import { createFileRoute, redirect } from "@tanstack/react-router"; import { useState, useCallback } from "react"; import type { GameSession, GameRequest, AnswerResult } from "@lila/shared"; import { QuestionCard } from "../components/game/QuestionCard"; import { ScoreScreen } from "../components/game/ScoreScreen"; import { GameSetup } from "../components/game/GameSetup"; import { authClient } from "../lib/auth-client"; type GameStartResponse = { success: true; data: GameSession }; type GameAnswerResponse = { success: true; data: AnswerResult }; const API_URL = (import.meta.env["VITE_API_URL"] as string) || ""; function Play() { const [gameSession, setGameSession] = useState(null); const [isLoading, setIsLoading] = useState(false); const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0); const [results, setResults] = useState([]); const [currentResult, setCurrentResult] = useState(null); const startGame = useCallback(async (settings: GameRequest) => { setIsLoading(true); const response = await fetch(`${API_URL}/api/v1/game/start`, { method: "POST", headers: { "Content-Type": "application/json" }, credentials: "include", body: JSON.stringify(settings), }); const data = (await response.json()) as GameStartResponse; setGameSession(data.data); setCurrentQuestionIndex(0); setResults([]); setCurrentResult(null); setIsLoading(false); }, []); const resetToSetup = useCallback(() => { setGameSession(null); setIsLoading(false); setCurrentQuestionIndex(0); setResults([]); setCurrentResult(null); }, []); const handleAnswer = async (optionId: number) => { if (!gameSession || currentResult) return; const question = gameSession.questions[currentQuestionIndex]; if (!question) return; const response = await fetch(`${API_URL}/api/v1/game/answer`, { method: "POST", headers: { "Content-Type": "application/json" }, credentials: "include", body: JSON.stringify({ sessionId: gameSession.sessionId, questionId: question.questionId, selectedOptionId: optionId, }), }); const data = (await response.json()) as GameAnswerResponse; setCurrentResult(data.data); }; const handleNext = () => { if (!currentResult) return; setResults((prev) => [...prev, currentResult]); setCurrentQuestionIndex((prev) => prev + 1); setCurrentResult(null); }; // Phase: setup if (!gameSession && !isLoading) { return (
{ void startGame(settings).catch((err) => { console.error("Start game error:", err); }); }} />
); } // Phase: loading if (isLoading || !gameSession) { return (

Loading...

); } // Phase: finished if (currentQuestionIndex >= gameSession.questions.length) { return (
); } // Phase: playing const question = gameSession.questions[currentQuestionIndex]!; return (
{ void handleAnswer(optionId).catch((err) => { console.error("Answer error:", err); }); }} question={question} questionNumber={currentQuestionIndex + 1} totalQuestions={gameSession.questions.length} currentResult={currentResult} onNext={handleNext} />
); } export const Route = createFileRoute("/play")({ component: Play, beforeLoad: async () => { const { data: session } = await authClient.getSession(); if (!session) { throw redirect({ to: "/login" }); } }, });