dramaling-vocab-learning/frontend/components/review/simple/VocabChoiceTest.tsx

149 lines
5.3 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, useCallback } from 'react'
import { CardState } from '@/lib/data/reviewSimpleData'
import { SimpleTestHeader } from './SimpleTestHeader'
interface VocabChoiceTestProps {
card: CardState
options: string[]
onAnswer: (confidence: number) => void
onSkip: () => void
}
export function VocabChoiceTest({ card, options, onAnswer, onSkip }: VocabChoiceTestProps) {
const [selectedAnswer, setSelectedAnswer] = useState<string | null>(null)
const [showResult, setShowResult] = useState(false)
const handleAnswerSelect = useCallback((answer: string) => {
if (showResult) return
setSelectedAnswer(answer)
setShowResult(true)
// 判斷答案是否正確正確給3分錯誤給1分
const isCorrect = answer === card.word
const confidence = isCorrect ? 2 : 0
// 延遲一點再調用回調,讓用戶看到選擇結果
setTimeout(() => {
onAnswer(confidence)
// 重置狀態為下一題準備
setSelectedAnswer(null)
setShowResult(false)
}, 1500)
}, [showResult, card.word, onAnswer])
const handleSkipClick = useCallback(() => {
onSkip()
}, [onSkip])
const isCorrect = selectedAnswer === card.word
return (
<div>
<div className="bg-white rounded-xl shadow-lg p-8">
<SimpleTestHeader
title="詞彙選擇"
cefr={card.cefr}
/>
{/* 問題區域 */}
<div className="mb-8">
<div className="bg-gray-50 rounded-lg p-6 mb-4">
<h3 className="font-semibold text-gray-900 mb-3 text-left"></h3>
<p className="text-gray-700 text-left text-lg leading-relaxed">{card.definition}</p>
</div>
<p className="text-lg text-gray-700 text-left">
</p>
</div>
{/* 選項區域 */}
<div className="mb-6">
<div className="grid grid-cols-2 gap-3">
{options.map((option, index) => {
const isSelected = selectedAnswer === option
const isCorrectOption = option === card.word
let buttonClass = 'p-4 rounded-lg border-2 text-center font-medium transition-all duration-200 cursor-pointer active:scale-95'
if (showResult) {
if (isSelected && isCorrectOption) {
// 選中且正確
buttonClass += ' bg-green-100 text-green-700 border-green-200 ring-2 ring-green-400'
} else if (isSelected && !isCorrectOption) {
// 選中但錯誤
buttonClass += ' bg-red-100 text-red-700 border-red-200 ring-2 ring-red-400'
} else if (!isSelected && isCorrectOption) {
// 未選中但是正確答案
buttonClass += ' bg-green-50 text-green-600 border-green-200'
} else {
// 未選中且非正確答案
buttonClass += ' bg-gray-50 text-gray-500 border-gray-200'
}
} else {
// 未答題狀態
buttonClass += ' bg-blue-50 text-blue-700 border-blue-200 hover:bg-blue-100'
}
return (
<button
key={index}
onClick={() => handleAnswerSelect(option)}
disabled={showResult}
className={buttonClass}
>
{option}
</button>
)
})}
</div>
</div>
{/* 結果顯示區域 */}
{showResult && (
<div className="mb-6">
<div className={`p-4 rounded-lg ${isCorrect ? 'bg-green-50 border border-green-200' : 'bg-red-50 border border-red-200'}`}>
<div className="flex items-center mb-3">
<span className={`text-2xl mr-3 ${isCorrect ? 'text-green-600' : 'text-red-600'}`}>
{isCorrect ? '✅' : '❌'}
</span>
<h3 className={`text-lg font-semibold ${isCorrect ? 'text-green-800' : 'text-red-800'}`}>
{isCorrect ? '答對了!' : '答錯了'}
</h3>
</div>
<div className="space-y-2 text-left">
<p className="text-gray-700">
<strong></strong> {card.word}
</p>
<p className="text-gray-700">
<strong></strong> {card.pronunciation}
</p>
<p className="text-gray-700">
<strong></strong> "{card.example}"
</p>
<p className="text-gray-600 text-sm">
{card.exampleTranslation}
</p>
</div>
</div>
</div>
)}
</div>
{/* 跳過按鈕 - 移到卡片外面 */}
{!showResult && (
<div className="mt-6">
<button
onClick={handleSkipClick}
className="w-full border border-gray-300 text-gray-700 py-3 px-4 rounded-lg font-medium hover:bg-gray-50 transition-colors"
>
</button>
</div>
)}
</div>
)
}