import React, { useState, useEffect } from 'react'; import { Box, Typography, Radio, RadioGroup, FormControlLabel, TextField, Button, Alert, Collapse, Stack, Paper, Divider } from '@mui/material'; import LightbulbIcon from '@mui/icons-material/Lightbulb'; import NavigateNextIcon from '@mui/icons-material/NavigateNext'; import axios from 'axios'; function Exercise({ exercise, onSubmit, onNextExercise, selectedAnswer: externalSelectedAnswer, onAnswerSelect, result: externalResult }) { const [localSelectedAnswer, setLocalSelectedAnswer] = useState(''); const [showHints, setShowHints] = useState(false); const [currentHintIndex, setCurrentHintIndex] = useState(0); const [localResult, setLocalResult] = useState(null); // 使用外部傳入的 selectedAnswer 和 result,如果有的話 const selectedAnswer = externalSelectedAnswer || localSelectedAnswer; const result = externalResult || localResult; // 當外部 selectedAnswer 變化時更新本地狀態 useEffect(() => { if (externalSelectedAnswer) { setLocalSelectedAnswer(externalSelectedAnswer); } }, [externalSelectedAnswer]); // 當外部 result 變化時更新本地狀態 useEffect(() => { if (externalResult) { setLocalResult(externalResult); } }, [externalResult]); const handleOptionClick = (value) => { setLocalSelectedAnswer(value); // 找到選中選項的文本 if (exercise.type === 'multiple_choice' && exercise.options) { const optionIndex = parseInt(value, 10); const optionText = exercise.options[optionIndex]; // 通知父組件選擇變化 if (onAnswerSelect) { onAnswerSelect(value, optionText); } } else { // 對於文本輸入,直接傳遞值 if (onAnswerSelect) { onAnswerSelect(value, value); } } }; const handleSubmit = async () => { try { if (!selectedAnswer.trim()) { return; } // 找到選中選項的文本 let answerText = selectedAnswer; if (exercise.type === 'multiple_choice' && exercise.options) { const optionIndex = parseInt(selectedAnswer, 10); answerText = exercise.options[optionIndex]; } // 通知父組件 if (onSubmit) { await onSubmit(selectedAnswer, answerText); } else { // 如果沒有提供 onSubmit,則使用本地邏輯 const response = await axios.post(`/api/exercises/check/${exercise.id}`, { answer: selectedAnswer }); setLocalResult(response.data); } } catch (error) { console.error('Error submitting answer:', error); setLocalResult({ correct: false, explanation: "檢查答案時發生錯誤" }); } }; const handleNextExercise = () => { setLocalSelectedAnswer(''); setShowHints(false); setCurrentHintIndex(0); setLocalResult(null); if (onNextExercise) { onNextExercise(); } }; const showNextHint = () => { if (currentHintIndex < exercise.hints.length - 1) { setCurrentHintIndex(prev => prev + 1); } setShowHints(true); }; return ( {/* 左側:題目和作答區域 */} 題目 {exercise.question} {/* 作答區域整合到題目下方 */} {exercise.type === 'multiple_choice' ? ( { // 只有在還沒有結果或答錯的情況下才允許更改答案 if (!result?.correct) { handleOptionClick(e.target.value); } }} > {exercise.options.map((option, index) => { const isSelected = selectedAnswer === index.toString(); const isWrongAnswer = result && !result.correct && isSelected; return ( } label={`${String.fromCharCode(65 + index)}. ${option}`} sx={{ mb: 1, color: isWrongAnswer ? 'error.main' : 'text.primary', '&.Mui-disabled': { color: result?.correct ? 'success.main' : 'text.disabled' } }} disabled={result?.correct} /> ); })} ) : ( { // 只有在還沒有結果或答錯的情況下才允許更改答案 if (!result?.correct) { handleOptionClick(e.target.value); } }} placeholder="請輸入答案" variant="outlined" size="small" disabled={result?.correct} error={result && !result.correct} helperText={result && !result.correct ? "答案不正確" : ""} /> )} {/* 右側:操作和反饋區域 */} 操作區 {/* 按鈕組 */} {onNextExercise && ( )} {/* 提示和結果區域 */} {exercise.hints.slice(0, currentHintIndex + 1).map((hint, index) => ( 提示 {index + 1}: {hint} ))} {result && ( {result.correct ? '答對了!' : '再試一次!'} {result.explanation && ( 解釋:{result.explanation} )} )} ); } export default Exercise;