dramaling-vocab-learning/frontend/app/test-vocab-choice/page.tsx

124 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client'
import { useState } from 'react'
import { Navigation } from '@/components/shared/Navigation'
import { VocabChoiceTest } from '@/components/review/simple/VocabChoiceTest'
import { SIMPLE_CARDS, CardState } from '@/lib/data/reviewSimpleData'
export default function TestVocabChoicePage() {
const [currentCardIndex, setCurrentCardIndex] = useState(0)
const [score, setScore] = useState({ correct: 0, total: 0 })
const currentCard = SIMPLE_CARDS[currentCardIndex]
// 生成測驗選項 (包含正確答案和3個干擾項)
const generateOptions = (correctWord: string) => {
const allWords = SIMPLE_CARDS.map(card => card.word).filter(word => word !== correctWord)
const shuffledWords = allWords.sort(() => Math.random() - 0.5)
const distractors = shuffledWords.slice(0, 3)
const options = [correctWord, ...distractors]
return options.sort(() => Math.random() - 0.5) // 隨機排列選項
}
const handleAnswer = (confidence: number) => {
const isCorrect = confidence >= 2
setScore(prev => ({
correct: prev.correct + (isCorrect ? 1 : 0),
total: prev.total + 1
}))
// 移動到下一張卡片
setTimeout(() => {
if (currentCardIndex < SIMPLE_CARDS.length - 1) {
setCurrentCardIndex(prev => prev + 1)
} else {
alert(`測試完成!正確率: ${score.correct + (isCorrect ? 1 : 0)}/${score.total + 1}`)
}
}, 100)
}
const handleSkip = () => {
setScore(prev => ({ ...prev, total: prev.total + 1 }))
if (currentCardIndex < SIMPLE_CARDS.length - 1) {
setCurrentCardIndex(prev => prev + 1)
} else {
alert(`測試完成!正確率: ${score.correct}/${score.total + 1}`)
}
}
const handleRestart = () => {
setCurrentCardIndex(0)
setScore({ correct: 0, total: 0 })
}
if (!currentCard) {
return (
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100">
<Navigation />
<div className="py-8">
<div className="max-w-4xl mx-auto px-4 text-center">
<h1 className="text-2xl font-bold mb-4"></h1>
<button
onClick={handleRestart}
className="px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
>
</button>
</div>
</div>
</div>
)
}
return (
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100">
<Navigation />
<div className="py-8">
<div className="max-w-4xl mx-auto px-4">
{/* 進度顯示 */}
<div className="mb-6 bg-white rounded-lg shadow p-4">
<div className="flex justify-between items-center">
<h1 className="text-xl font-bold"></h1>
<div className="text-sm text-gray-600">
{currentCardIndex + 1} / {SIMPLE_CARDS.length}
</div>
</div>
<div className="mt-2">
<div className="text-sm text-gray-600 mb-1">
: {score.correct} / {score.total}
{score.total > 0 && ` (${Math.round(score.correct / score.total * 100)}%)`}
</div>
<div className="w-full bg-gray-200 rounded-full h-2">
<div
className="bg-blue-600 h-2 rounded-full transition-all duration-300"
style={{ width: `${((currentCardIndex) / SIMPLE_CARDS.length) * 100}%` }}
/>
</div>
</div>
</div>
{/* 測驗組件 */}
<VocabChoiceTest
card={currentCard}
options={generateOptions(currentCard.word)}
onAnswer={handleAnswer}
onSkip={handleSkip}
/>
{/* 控制按鈕 */}
<div className="mt-6 text-center">
<button
onClick={handleRestart}
className="px-4 py-2 bg-gray-500 text-white rounded-lg hover:bg-gray-600 mr-4"
>
</button>
</div>
</div>
</div>
</div>
)
}