import { useState, useEffect, useCallback } from 'react' import { useNavigate } from '@tanstack/react-router' import { cn } from '@/lib/utils' import { useTestStore } from '@/store/test-store' import { useRequireAuth } from '@/hooks/use-require-auth' import { TestSessionHeader } from './TestSessionHeader' import { TestSessionSidebar } from './TestSessionSidebar' import { TestSessionFooter } from './TestSessionFooter' import type { Question } from '@/types' const ANSWER_LABELS = ['A', 'B', 'C', 'D'] function QuestionCard({ question, globalNum, answer, onSelect, }: { question: Question globalNum: number answer: number | null onSelect: (idx: number) => void }) { return (
Câu {globalNum} {question.passageText && (
{question.passageText}
)} {question.audioUrl && (
) } export function TestSession() { const navigate = useNavigate() const { testName, parts, currentPartIndex, answers, totalSeconds, setAnswer, setCurrentPart, submitExam } = useTestStore() const { isAuthenticated, isLoading } = useRequireAuth() const [timeLeft, setTimeLeft] = useState(() => totalSeconds > 0 ? totalSeconds : -1) const [timeUsed, setTimeUsed] = useState(0) const handleSubmit = useCallback(() => { submitExam(totalSeconds > 0 ? totalSeconds - timeLeft : timeUsed) navigate({ to: '/toeic/result' }) }, [submitExam, navigate, totalSeconds, timeLeft, timeUsed]) // Timer useEffect(() => { if (parts.length === 0) return const id = setInterval(() => { if (timeLeft > 0) { setTimeLeft(t => { if (t <= 1) { clearInterval(id); handleSubmit(); return 0 } return t - 1 }) } else { setTimeUsed(t => t + 1) } }, 1000) return () => clearInterval(id) }, [parts.length, timeLeft, handleSubmit]) useEffect(() => { if (isLoading) return if (!isAuthenticated || parts.length === 0) navigate({ to: '/toeic' }) }, [isLoading, isAuthenticated, parts.length, navigate]) if (parts.length === 0) return null const currentPart = parts[currentPartIndex] // Compute global question offset for current part let globalOffset = 0 for (let i = 0; i < currentPartIndex; i++) globalOffset += parts[i].questions.length return (
{/* Main scrollable content */}

Part {currentPart.partNumber}: {currentPart.partName}

{currentPart.questions.map((q, idx) => ( setAnswer(q.id, i)} /> ))}
setCurrentPart(currentPartIndex - 1)} onNext={() => setCurrentPart(currentPartIndex + 1)} />
) }