Added opaque join-token support across backend and frontend: new migration/model/service/endpoints, guest controllers now resolve tokens, and the demo seeder seeds a token. Tenant event details list/manage tokens with copy/revoke actions, and the guest PWA uses tokens end-to-end (routing, storage, uploads, achievements, etc.). Docs TODO updated to reflect completed steps.
This commit is contained in:
@@ -7,6 +7,7 @@ export interface EventData {
|
||||
default_locale: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
join_token?: string | null;
|
||||
type?: {
|
||||
slug: string;
|
||||
name: string;
|
||||
@@ -33,14 +34,14 @@ export interface EventStats {
|
||||
latestPhotoAt: string | null;
|
||||
}
|
||||
|
||||
export async function fetchEvent(slug: string): Promise<EventData> {
|
||||
const res = await fetch(`/api/v1/events/${slug}`);
|
||||
export async function fetchEvent(eventKey: string): Promise<EventData> {
|
||||
const res = await fetch(`/api/v1/events/${encodeURIComponent(eventKey)}`);
|
||||
if (!res.ok) throw new Error('Event fetch failed');
|
||||
return await res.json();
|
||||
}
|
||||
|
||||
export async function fetchStats(slug: string): Promise<EventStats> {
|
||||
const res = await fetch(`/api/v1/events/${slug}/stats`, {
|
||||
export async function fetchStats(eventKey: string): Promise<EventStats> {
|
||||
const res = await fetch(`/api/v1/events/${encodeURIComponent(eventKey)}/stats`, {
|
||||
headers: {
|
||||
'X-Device-Id': getDeviceId(),
|
||||
},
|
||||
@@ -48,17 +49,17 @@ export async function fetchStats(slug: string): Promise<EventStats> {
|
||||
if (!res.ok) throw new Error('Stats fetch failed');
|
||||
const json = await res.json();
|
||||
return {
|
||||
onlineGuests: json.onlineGuests ?? 0,
|
||||
tasksSolved: json.tasksSolved ?? 0,
|
||||
latestPhotoAt: json.latestPhotoAt ?? null,
|
||||
onlineGuests: json.online_guests ?? json.onlineGuests ?? 0,
|
||||
tasksSolved: json.tasks_solved ?? json.tasksSolved ?? 0,
|
||||
latestPhotoAt: json.latest_photo_at ?? json.latestPhotoAt ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
export async function getEventPackage(slug: string): Promise<EventPackage | null> {
|
||||
const res = await fetch(`/api/v1/events/${slug}/package`);
|
||||
const res = await fetch(`/api/v1/events/${encodeURIComponent(slug)}/package`);
|
||||
if (!res.ok) {
|
||||
if (res.status === 404) return null;
|
||||
throw new Error('Failed to load event package');
|
||||
}
|
||||
return await res.json();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ export async function uploadPhoto(slug: string, file: File, taskId?: number, emo
|
||||
if (emotionSlug) formData.append('emotion_slug', emotionSlug);
|
||||
formData.append('device_id', getDeviceId());
|
||||
|
||||
const res = await fetch(`/api/v1/events/${slug}/upload`, {
|
||||
const res = await fetch(`/api/v1/events/${encodeURIComponent(slug)}/upload`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: formData,
|
||||
@@ -99,4 +99,3 @@ export async function uploadPhoto(slug: string, file: File, taskId?: number, emo
|
||||
const json = await res.json();
|
||||
return json.photo_id ?? json.id ?? json.data?.id ?? 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user