11'use client' ;
2- import { Ban , Clock , FileText , TriangleAlert } from 'lucide-react' ;
2+ import { Ban , FileText , TriangleAlert , UserRound } from 'lucide-react' ;
33import { useRouter , useSearchParams } from 'next/navigation' ;
44import { useLocale , useTranslations } from 'next-intl' ;
55import {
@@ -19,6 +19,7 @@ import type { QuizQuestionClient } from '@/db/queries/quiz';
1919import { useAntiCheat } from '@/hooks/useAntiCheat' ;
2020import { useQuizGuards } from '@/hooks/useQuizGuards' ;
2121import { useQuizSession } from '@/hooks/useQuizSession' ;
22+ import { Link } from '@/i18n/routing' ;
2223import { savePendingQuizResult } from '@/lib/quiz/guest-quiz' ;
2324import {
2425 clearQuizSession ,
@@ -160,12 +161,14 @@ export function QuizContainer({
160161 onBackToTopics,
161162} : QuizContainerProps ) {
162163 const tRules = useTranslations ( 'quiz.rules' ) ;
164+ const tResult = useTranslations ( 'quiz.result' ) ;
163165 const tExit = useTranslations ( 'quiz.exitModal' ) ;
164166 const tQuestion = useTranslations ( 'quiz.question' ) ;
165167 const categoryStyle = categorySlug
166168 ? categoryTabStyles [ categorySlug as keyof typeof categoryTabStyles ]
167169 : null ;
168170 const accentColor = categoryStyle ?. accent ?? '#3B82F6' ;
171+ const [ isStarting , setIsStarting ] = useState ( false ) ;
169172 const [ isPending , startTransition ] = useTransition ( ) ;
170173 const [ state , dispatch ] = useReducer ( quizReducer , {
171174 status : 'rules' ,
@@ -219,18 +222,21 @@ export function QuizContainer({
219222 } , [ seed , searchParams , router ] ) ;
220223
221224 const handleStart = async ( ) => {
225+ setIsStarting ( true ) ;
222226 try {
223227 const result = await initializeQuizCache ( quizId ) ;
224228
225229 if ( ! result . success ) {
226230 toast . error ( 'Failed to start quiz session' ) ;
231+ setIsStarting ( false ) ;
227232 return ;
228233 }
229234
230235 window . history . pushState ( { quizGuard : true } , '' ) ;
231236 dispatch ( { type : 'START_QUIZ' } ) ;
232237 } catch {
233238 toast . error ( 'Failed to start quiz session' ) ;
239+ setIsStarting ( false ) ;
234240 }
235241 } ;
236242
@@ -242,6 +248,7 @@ export function QuizContainer({
242248 questionId : currentQuestion . id ,
243249 selectedAnswerId : answerId ,
244250 quizId,
251+ timeLimitSeconds,
245252 } ) ,
246253 } ) ;
247254
@@ -370,6 +377,7 @@ export function QuizContainer({
370377 const handleRestart = ( ) => {
371378 clearQuizSession ( quizId ) ;
372379 resetViolations ( ) ;
380+ setIsStarting ( false ) ;
373381 dispatch ( { type : 'RESTART' } ) ;
374382 } ;
375383
@@ -446,22 +454,50 @@ export function QuizContainer({
446454 </ p >
447455 </ div >
448456 </ div >
449- < div className = "flex gap-3" >
450- < Clock
451- className = "mt-0.5 h-5 w-5 shrink-0 text-blue-500 dark:text-blue-400"
452- aria-hidden = "true"
453- />
454- < div >
455- < p className = "font-medium" > { tRules ( 'time.title' ) } </ p >
456- < p className = "text-sm text-gray-600 dark:text-gray-400" >
457- { tRules ( 'time.description' , { seconds : totalQuestions * 3 } ) }
457+ </ div >
458+ { isGuest ? (
459+ < >
460+ < div className = "flex gap-3 rounded-lg border border-amber-200 bg-amber-50 p-4 dark:border-amber-800 dark:bg-amber-900/20" >
461+ < UserRound
462+ className = "mt-0.5 h-5 w-5 shrink-0 text-amber-500 dark:text-amber-400"
463+ aria-hidden = "true"
464+ />
465+ < p className = "text-sm font-medium text-amber-800 dark:text-amber-200" >
466+ { tRules ( 'guestWarning' ) }
458467 </ p >
459468 </ div >
460- </ div >
461- </ div >
469+ < div className = "flex flex-col gap-3 sm:flex-row" >
470+ < Link
471+ href = { `/login?returnTo=/${ locale } /quiz/${ quizSlug } ` }
472+ className = "flex-1 inline-flex items-center justify-center rounded-xl font-medium transition-colors px-6 py-3 text-base bg-[var(--accent-primary)] text-white hover:bg-[var(--accent-hover)] active:brightness-90 text-center"
473+ >
474+ { tResult ( 'loginButton' ) }
475+ </ Link >
476+ < Link
477+ href = { `/signup?returnTo=/${ locale } /quiz/${ quizSlug } ` }
478+ className = "flex-1 inline-flex items-center justify-center rounded-xl font-medium transition-colors px-6 py-3 text-base bg-gray-200 text-gray-900 hover:bg-gray-300 dark:bg-gray-800 dark:text-gray-100 dark:hover:bg-gray-700 text-center"
479+ >
480+ { tResult ( 'signupButton' ) }
481+ </ Link >
482+ < button
483+ onClick = { handleStart }
484+ disabled = { isStarting }
485+ className = "disabled:opacity-50 disabled:cursor-not-allowed flex-1 rounded-xl border px-6 py-3 text-center text-base font-semibold transition-all duration-300"
486+ style = { {
487+ borderColor : `${ accentColor } 50` ,
488+ backgroundColor : `${ accentColor } 15` ,
489+ color : accentColor ,
490+ } }
491+ >
492+ { tRules ( 'continueAsGuest' ) }
493+ </ button >
494+ </ div >
495+ </ >
496+ ) : (
462497 < button
463498 onClick = { handleStart }
464- className = "group relative w-full overflow-hidden rounded-xl border px-6 py-3 text-center text-base font-semibold transition-all duration-300"
499+ disabled = { isStarting }
500+ className = "disabled:opacity-50 disabled:cursor-not-allowed group relative w-full overflow-hidden rounded-xl border px-6 py-3 text-center text-base font-semibold transition-all duration-300"
465501 style = { {
466502 borderColor : `${ accentColor } 50` ,
467503 backgroundColor : `${ accentColor } 15` ,
@@ -474,6 +510,7 @@ export function QuizContainer({
474510 style = { { backgroundColor : accentColor } }
475511 />
476512 </ button >
513+ ) }
477514 </ div >
478515 ) ;
479516 }
0 commit comments