EventBuzz_Website/src/lib/games.ts

46 lines
4.0 KiB
TypeScript

function apiBase(): string {
const configured = import.meta.env.VITE_API_BASE_URL || import.meta.env.VITE_API_URL || 'http://localhost:3001';
const base = String(configured).trim().replace(/\/$/, '');
return base.endsWith('/api') ? base : `${base}/api`;
}
async function call<T>(path: string, init?: RequestInit): Promise<T> {
const response = await fetch(`${apiBase()}${path}`, { ...init, headers: { 'Content-Type': 'application/json', ...(init?.headers || {}) } });
const body = await response.json().catch(() => null);
if (!response.ok || !body?.success) throw new Error(body?.error?.message || 'Game unavailable');
return body.data as T;
}
export interface PublicMatchUpItem { _id: string; text: string; imageUrl?: string; }
export interface PublicMatchUpGroup { _id: string; title: string; description?: string; items: PublicMatchUpItem[]; }
export interface PublicMatchUp {
name: string;
backgroundImage: string;
backgroundSize?: "cover" | "contain" | "auto";
backgroundRepeat?: "no" | "repeat" | "repeat-x" | "repeat-y";
backgroundWidth?: string | number;
gridSize: 3 | 4 | 5;
attempts?: number;
groups: PublicMatchUpGroup[];
publicToken: string;
eventId?: string;
accessMode?: "open" | "login";
eventName?: string;
event?: import('./api').PhotoWallPublicEvent | null;
eventHeader?: import('./api').PhotoWallEventHeaderDisplay | null;
}
export interface PublicQuizOption { text: string; imageUrl?: string; }
export interface PublicQuizQuestion { _id: string; question: string; imageUrl?: string; type?: "single" | "multiple"; points?: number; timeLimit?: number; options: Array<string | PublicQuizOption>; }
export interface PublicQuizSettings { showResults?: boolean; timeRestricted?: boolean; timeLimit?: number; displayMode?: string; }
export interface PublicQuiz { name: string; backgroundImage: string; settings?: PublicQuizSettings; questions: PublicQuizQuestion[]; publicToken: string; eventId?: string; accessMode?: "open" | "login"; eventName?: string; event?: import('./api').PhotoWallPublicEvent | null; eventHeader?: import('./api').PhotoWallEventHeaderDisplay | null; }
export interface QuizAnswerFeedback { correct: boolean | null; correctIndex: number; correctIndexes?: number[]; points: number; }
export interface QuizResult { displayName: string; score: number; total: number; correct: number; questionCount?: number; timeSpent: number; }
export interface QuizLeaderboardEntry extends QuizResult { _id: string; }
export function getMatchUp(token: string) { return call<PublicMatchUp>(`/public/games/match-up/${encodeURIComponent(token)}`); }
export function guessMatchUp(token: string, itemIds: string[], participantId?: string) { return call<{ correct: boolean; group: { _id: string; title: string; description: string; itemIds: string[] } | null }>(`/public/games/match-up/${encodeURIComponent(token)}/guess`, { method: 'POST', body: JSON.stringify({ itemIds, participantId }) }); }
export function completeMatchUp(token: string, groups: string[][], participantId?: string) { return call<{ completed: boolean; groups: number }>(`/public/games/match-up/${encodeURIComponent(token)}/complete`, { method: 'POST', body: JSON.stringify({ groups, participantId }) }); }
export function getGameQuiz(token: string) { return call<PublicQuiz>(`/public/games/quiz/${encodeURIComponent(token)}`); }
export function answerGameQuiz(token: string, questionIndex: number, answer: number | number[], participantId?: string) { return call<QuizAnswerFeedback>(`/public/games/quiz/${encodeURIComponent(token)}/answer`, { method: 'POST', body: JSON.stringify(Array.isArray(answer) ? { questionIndex, answerIndexes: answer, participantId } : { questionIndex, answerIndex: answer, participantId }) }); }
export function submitGameQuiz(token: string, payload: { displayName: string; answers: Array<number | number[]>; timeSpent: number; participantId?: string }) { return call<{ result: QuizResult; leaderboard: QuizLeaderboardEntry[] }>(`/public/games/quiz/${encodeURIComponent(token)}/submit`, { method: 'POST', body: JSON.stringify(payload) }); }