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

128 lines
4.6 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.

import { useState } from 'react'
import AudioPlayer from '@/components/AudioPlayer'
import { ChoiceTestProps } from '@/types/review'
import { ErrorReportButton } from '@/components/review/shared'
interface VocabChoiceTestProps extends ChoiceTestProps {
// VocabChoiceTest specific props (if any)
}
export const VocabChoiceTest: React.FC<VocabChoiceTestProps> = ({
cardData,
options,
onAnswer,
onReportError,
disabled = false
}) => {
const [selectedAnswer, setSelectedAnswer] = useState<string | null>(null)
const [showResult, setShowResult] = useState(false)
const handleAnswerSelect = (answer: string) => {
if (disabled || showResult) return
setSelectedAnswer(answer)
setShowResult(true)
onAnswer(answer)
}
const isCorrect = selectedAnswer === cardData.word
return (
<div className="relative">
<ErrorReportButton onClick={onReportError} />
<div className="bg-white rounded-xl shadow-lg p-8">
{/* 標題區 */}
<div className="flex justify-between items-start mb-6">
<h2 className="text-2xl font-bold text-gray-900"></h2>
<span className="bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded-full">
{cardData.difficultyLevel}
</span>
</div>
{/* 指示文字 */}
<p className="text-lg text-gray-700 mb-6 text-left">
</p>
{/* 定義顯示區 */}
<div className="text-center mb-8">
<div className="bg-gray-50 rounded-lg p-4 mb-6">
<h3 className="font-semibold text-gray-900 mb-2 text-left"></h3>
<p className="text-gray-700 text-left">{cardData.definition}</p>
</div>
{/* 同義詞顯示 */}
{cardData.synonyms && cardData.synonyms.length > 0 && (
<div className="bg-blue-50 rounded-lg p-4 mb-6">
<h3 className="font-semibold text-gray-900 mb-2 text-left"></h3>
<div className="flex flex-wrap gap-2 justify-start">
{cardData.synonyms.map((synonym, index) => (
<span
key={index}
className="px-3 py-1 bg-blue-100 text-blue-700 text-sm rounded-full font-medium"
>
{synonym}
</span>
))}
</div>
</div>
)}
</div>
{/* 選項區域 - 響應式網格布局 */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 mb-6">
{options.map((option, idx) => (
<button
key={idx}
onClick={() => handleAnswerSelect(option)}
disabled={disabled || showResult}
className={`p-4 text-center rounded-lg border-2 transition-all ${
showResult
? option === cardData.word
? 'border-green-500 bg-green-50 text-green-700'
: option === selectedAnswer
? 'border-red-500 bg-red-50 text-red-700'
: 'border-gray-200 bg-gray-50 text-gray-500'
: 'border-gray-200 hover:border-blue-300 hover:bg-blue-50'
}`}
>
<div className="text-lg font-medium">{option}</div>
</button>
))}
</div>
{/* 結果反饋區 */}
{showResult && (
<div className={`p-6 rounded-lg w-full mb-6 ${
isCorrect
? 'bg-green-50 border border-green-200'
: 'bg-red-50 border border-red-200'
}`}>
<p className={`font-semibold text-left text-xl mb-4 ${
isCorrect ? 'text-green-700' : 'text-red-700'
}`}>
{isCorrect ? '正確!' : '錯誤!'}
</p>
{!isCorrect && (
<div className="mb-4">
<p className="text-gray-700 text-left">
<strong className="text-lg">{cardData.word}</strong>
</p>
</div>
)}
<div className="space-y-3">
<div className="text-left">
<div className="flex items-center text-gray-600">
{cardData.pronunciation && <span className="mx-2">{cardData.pronunciation}</span>}
<AudioPlayer text={cardData.word} />
</div>
</div>
</div>
</div>
)}
</div>
</div>
)
}