Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | 1x 1x 1x 9x 18x 18x 18x 18x 18x 7x 7x 7x 7x 7x 7x 2x 2x 2x 90x | 'use client'
import { useState } from 'react'
import {
Box,
Typography,
Container,
Paper,
LinearProgress,
Stack,
Chip,
} from '@mui/material'
import { VocabularyItem } from '@/core/domain/VocabularyItem'
import { QuizSession } from '@/core/domain/QuizSession'
import { QuizOption } from './QuizOption'
interface QuizPhaseProps {
session: QuizSession
currentQuestion: VocabularyItem
shuffledOptions: string[]
onAnswer: (word: string) => boolean
}
/**
* QuizPhase Component
* Displays the quiz interface with questions and answer options.
*/
export function QuizPhase({
session,
currentQuestion,
shuffledOptions,
onAnswer,
}: QuizPhaseProps) {
const [selectedAnswer, setSelectedAnswer] = useState<string | null>(null)
const [isCorrect, setIsCorrect] = useState<boolean | null>(null)
const [isAnimating, setIsAnimating] = useState(false)
const progress = ((session.currentStep) / session.vocabularyItems.length) * 100
const handleOptionClick = (word: string) => {
Iif (isAnimating) return
setSelectedAnswer(word)
const correct = onAnswer(word)
setIsCorrect(correct)
setIsAnimating(true)
// Reset for next question after animation
setTimeout(() => {
setSelectedAnswer(null)
setIsCorrect(null)
setIsAnimating(false)
}, 1000)
}
return (
<Container maxWidth="md" sx={{ py: 4 }}>
<Paper sx={{ p: 4 }}>
<Box sx={{ mb: 4 }}>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
<Typography variant="h5" component="h1" sx={{ fontWeight: 600 }}>
Quiz Time
</Typography>
<Chip
label={`Questão ${session.currentStep + 1} de ${session.vocabularyItems.length}`}
color="primary"
variant="outlined"
/>
</Box>
<LinearProgress
variant="determinate"
value={progress}
sx={{ height: 8, borderRadius: 4 }}
/>
</Box>
<Paper
elevation={0}
sx={{
p: 4,
mb: 4,
bgcolor: 'grey.100',
borderRadius: 2,
textAlign: 'center',
}}
>
<Typography variant="body2" color="text.secondary" gutterBottom>
Qual palavra inglesa corresponde a esta descrição?
</Typography>
<Typography
variant="h5"
component="p"
sx={{ fontWeight: 500, color: 'text.primary' }}
data-testid="quiz-description"
>
{currentQuestion.description}
</Typography>
</Paper>
<Stack spacing={2}>
{shuffledOptions.map((word) => (
<QuizOption
key={word}
word={word}
onClick={handleOptionClick}
disabled={isAnimating}
selected={selectedAnswer === word}
isCorrect={
selectedAnswer === word
? isCorrect
: isCorrect === false && word === currentQuestion.word
? true
: null
}
/>
))}
</Stack>
<Box sx={{ mt: 4, textAlign: 'center' }}>
<Typography variant="body2" color="text.secondary">
Score: {session.score} / {session.currentStep}
</Typography>
</Box>
</Paper>
</Container>
)
}
|