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

96 lines
2.9 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 React, { useState, useCallback, memo } from 'react'
import {
SpeakingTestContainer
} from '@/components/review/shared'
import { BaseReviewProps } from '@/types/review'
interface SentenceSpeakingTestProps extends BaseReviewProps {
exampleImage?: string
onImageClick?: (image: string) => void
}
const SentenceSpeakingTestComponent: React.FC<SentenceSpeakingTestProps> = ({
cardData,
exampleImage,
onAnswer,
onReportError,
onImageClick,
disabled = false
}) => {
const [showResult, setShowResult] = useState(false)
// 判斷是否已答題(錄音提交後設定 hasAnswered = true
const hasAnswered = showResult
const handleRecordingComplete = useCallback(() => {
if (disabled || showResult) return
setShowResult(true)
onAnswer(cardData.example) // 語音測驗通常都算正確
}, [disabled, showResult, cardData.example, onAnswer])
// 提示區域
const promptArea = (
<div className="text-center">
<p className="text-lg text-gray-700 text-left mb-4">
</p>
{exampleImage && (
<div className="bg-gray-50 rounded-lg p-4">
<img
src={exampleImage}
alt="Example illustration"
className="w-full max-w-md mx-auto rounded-lg cursor-pointer"
onClick={() => onImageClick?.(exampleImage)}
/>
</div>
)}
</div>
)
// 錄音區域
const recordingArea = (
<div className="w-full text-center">
<div className="bg-gray-50 rounded-lg p-6 border border-gray-200">
<p className="text-gray-600 mb-4"></p>
<button
onClick={handleRecordingComplete}
disabled={disabled || showResult}
className="bg-red-500 hover:bg-red-600 text-white px-6 py-3 rounded-full disabled:opacity-50 disabled:cursor-not-allowed"
>
🎤
</button>
<p className="text-sm text-gray-500 mt-2">
{cardData.example}
</p>
</div>
</div>
)
// 結果顯示區域
const resultArea = showResult ? (
<div className="p-6 rounded-lg bg-blue-50 border border-blue-200 w-full">
<p className="text-blue-700 text-left text-xl font-semibold mb-2">
</p>
<p className="text-gray-600 text-left">
...
</p>
</div>
) : null
return (
<SpeakingTestContainer
cardData={cardData}
testTitle="例句口說"
promptArea={promptArea}
recordingArea={recordingArea}
resultArea={resultArea}
onAnswer={onAnswer}
onReportError={onReportError}
disabled={disabled}
/>
)
}
export const SentenceSpeakingTest = memo(SentenceSpeakingTestComponent)
SentenceSpeakingTest.displayName = 'SentenceSpeakingTest'