import { useState, useMemo } from 'react' import AudioPlayer from '@/components/AudioPlayer' import { getCorrectAnswer } from '@/utils/answerExtractor' interface SentenceFillTestProps { word: string definition: string example: string filledQuestionText?: string exampleTranslation: string pronunciation?: string synonyms?: string[] difficultyLevel: string exampleImage?: string onAnswer: (answer: string) => void onReportError: () => void onImageClick?: (image: string) => void disabled?: boolean } export const SentenceFillTest: React.FC = ({ word, definition, example, filledQuestionText, exampleTranslation, pronunciation, synonyms = [], difficultyLevel, exampleImage, onAnswer, onReportError, onImageClick, disabled = false }) => { const [fillAnswer, setFillAnswer] = useState('') const [showResult, setShowResult] = useState(false) const [showHint, setShowHint] = useState(false) const handleSubmit = () => { if (disabled || showResult || !fillAnswer.trim()) return setShowResult(true) onAnswer(fillAnswer) } const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && !showResult && fillAnswer.trim()) { handleSubmit() } } // 🆕 動態計算正確答案:從例句和挖空題目推導 const correctAnswer = useMemo(() => { return getCorrectAnswer(example, filledQuestionText, word); }, [example, filledQuestionText, word]); const isCorrect = fillAnswer.toLowerCase().trim() === correctAnswer.toLowerCase().trim() const targetWordLength = correctAnswer.length const inputWidth = Math.max(100, Math.max(targetWordLength * 12, fillAnswer.length * 12 + 20)) // 🆕 智能填空渲染:優先使用後端提供的挖空題目 const renderFilledSentence = () => { if (!filledQuestionText) { // 降級處理:使用原有的前端挖空邏輯 return renderSentenceWithInput(); } // 使用後端提供的挖空題目 const parts = filledQuestionText.split('____'); return (
{parts.map((part, index) => ( {part} {index < parts.length - 1 && ( setFillAnswer(e.target.value)} onKeyDown={handleKeyDown} placeholder="" disabled={disabled || showResult} className={`inline-block px-2 py-1 text-center bg-transparent focus:outline-none disabled:bg-gray-100 ${ fillAnswer ? 'border-b-2 border-blue-500' : 'border-b-2 border-dashed border-gray-400 focus:border-blue-400 focus:border-solid' }`} style={{ width: `${inputWidth}px` }} /> {!fillAnswer && ( ____ )} )} ))}
); } // 將例句中的目標詞替換為輸入框 const renderSentenceWithInput = () => { const parts = example.split(new RegExp(`\\b${word}\\b`, 'gi')) const matches = example.match(new RegExp(`\\b${word}\\b`, 'gi')) || [] return (
{parts.map((part, index) => ( {part} {index < matches.length && ( setFillAnswer(e.target.value)} onKeyDown={handleKeyDown} placeholder="" disabled={disabled || showResult} className={`inline-block px-2 py-1 text-center bg-transparent focus:outline-none disabled:bg-gray-100 ${ fillAnswer ? 'border-b-2 border-blue-500' : 'border-b-2 border-dashed border-gray-400 focus:border-blue-400 focus:border-solid' }`} style={{ width: `${inputWidth}px` }} /> {!fillAnswer && ( ____ )} )} ))}
) } return (
{/* 錯誤回報按鈕 */}
{/* 標題區 */}

例句填空

{difficultyLevel}
{/* 圖片區(如果有) */} {exampleImage && (
Example illustration onImageClick?.(exampleImage)} />
)} {/* 指示文字 */}

請點擊例句中的空白處輸入正確的單字:

{/* 填空句子區域 */}
{renderFilledSentence()}
{/* 操作按鈕 */}
{/* 提示區域 */} {showHint && (

詞彙定義:

{definition}

{/* 同義詞顯示 */} {synonyms && synonyms.length > 0 && (

同義詞提示:

{synonyms.map((synonym, index) => ( {synonym} ))}
)}
)} {/* 結果反饋區 */} {showResult && (

{isCorrect ? '正確!' : '錯誤!'}

{!isCorrect && (

正確答案是:{correctAnswer}

)}

{word && {word}} {pronunciation && {pronunciation}}

{example}

{exampleTranslation}

)}
) }