'use client' import { useState, useEffect } from 'react' import { useRouter } from 'next/navigation' import { Navigation } from '@/components/Navigation' import VoiceRecorder from '@/components/VoiceRecorder' import LearningComplete from '@/components/LearningComplete' import SegmentedProgressBar from '@/components/SegmentedProgressBar' import { studySessionService, type StudySession, type CurrentTest, type Progress } from '@/lib/services/studySession' export default function NewLearnPage() { const router = useRouter() const [mounted, setMounted] = useState(false) // 會話狀態 const [session, setSession] = useState(null) const [currentTest, setCurrentTest] = useState(null) const [progress, setProgress] = useState(null) // UI狀態 const [isLoading, setIsLoading] = useState(false) const [selectedAnswer, setSelectedAnswer] = useState(null) const [showResult, setShowResult] = useState(false) const [fillAnswer, setFillAnswer] = useState('') const [showHint, setShowHint] = useState(false) const [showComplete, setShowComplete] = useState(false) const [showTaskListModal, setShowTaskListModal] = useState(false) // 例句重組狀態 const [shuffledWords, setShuffledWords] = useState([]) const [arrangedWords, setArrangedWords] = useState([]) const [reorderResult, setReorderResult] = useState(null) // 分數狀態 const [score, setScore] = useState({ correct: 0, total: 0 }) // Client-side mounting useEffect(() => { setMounted(true) startNewSession() }, []) // 開始新的學習會話 const startNewSession = async () => { try { setIsLoading(true) console.log('🎯 開始新的學習會話...') const sessionResult = await studySessionService.startSession() if (sessionResult.success && sessionResult.data) { const newSession = sessionResult.data setSession(newSession) console.log('✅ 學習會話創建成功:', newSession) // 載入第一個測驗和詳細進度 await loadCurrentTest(newSession.sessionId) await loadProgress(newSession.sessionId) } else { console.error('❌ 創建學習會話失敗:', sessionResult.error) if (sessionResult.error === 'No due cards available for study') { setShowComplete(true) } } } catch (error) { console.error('💥 創建學習會話異常:', error) } finally { setIsLoading(false) } } // 載入當前測驗 const loadCurrentTest = async (sessionId: string) => { try { const testResult = await studySessionService.getCurrentTest(sessionId) if (testResult.success && testResult.data) { setCurrentTest(testResult.data) resetTestStates() console.log('🎯 載入當前測驗:', testResult.data.testType, 'for', testResult.data.card.word) } else { console.error('❌ 載入測驗失敗:', testResult.error) } } catch (error) { console.error('💥 載入測驗異常:', error) } } // 載入詳細進度 const loadProgress = async (sessionId: string) => { try { const progressResult = await studySessionService.getProgress(sessionId) if (progressResult.success && progressResult.data) { setProgress(progressResult.data) console.log('📊 載入進度成功:', progressResult.data) } else { console.error('❌ 載入進度失敗:', progressResult.error) } } catch (error) { console.error('💥 載入進度異常:', error) } } // 提交測驗結果 const submitTest = async (isCorrect: boolean, userAnswer?: string, confidenceLevel?: number) => { if (!session || !currentTest) return try { const result = await studySessionService.submitTest(session.sessionId, { testType: currentTest.testType, isCorrect, userAnswer, confidenceLevel, responseTimeMs: 2000 // 簡化時間計算 }) if (result.success && result.data) { console.log('✅ 測驗結果提交成功:', result.data) // 更新分數 setScore(prev => ({ correct: isCorrect ? prev.correct + 1 : prev.correct, total: prev.total + 1 })) // 更新本地進度顯示 if (progress && result.data) { setProgress(prev => prev ? { ...prev, completedTests: result.data!.progress.completedTests, completedCards: result.data!.progress.completedCards } : null) } // 重新載入完整進度數據 await loadProgress(session.sessionId) // 檢查是否有下一個測驗 setTimeout(async () => { await loadNextTest() }, 1500) // 顯示結果1.5秒後自動進入下一題 } else { console.error('❌ 提交測驗結果失敗:', result.error) } } catch (error) { console.error('💥 提交測驗結果異常:', error) } } // 載入下一個測驗 const loadNextTest = async () => { if (!session) return try { const nextResult = await studySessionService.getNextTest(session.sessionId) if (nextResult.success && nextResult.data) { const nextTest = nextResult.data if (nextTest.hasNextTest) { // 載入下一個測驗 await loadCurrentTest(session.sessionId) } else { // 會話完成 console.log('🎉 學習會話完成!') await studySessionService.completeSession(session.sessionId) setShowComplete(true) } } } catch (error) { console.error('💥 載入下一個測驗異常:', error) } } // 重置測驗狀態 const resetTestStates = () => { setSelectedAnswer(null) setShowResult(false) setFillAnswer('') setShowHint(false) setShuffledWords([]) setArrangedWords([]) setReorderResult(null) } // 測驗處理函數 const handleQuizAnswer = async (answer: string) => { if (showResult || !currentTest) return setSelectedAnswer(answer) setShowResult(true) const isCorrect = answer === currentTest.card.word await submitTest(isCorrect, answer) } const handleFillAnswer = async () => { if (showResult || !currentTest) return setShowResult(true) const isCorrect = fillAnswer.toLowerCase().trim() === currentTest.card.word.toLowerCase() await submitTest(isCorrect, fillAnswer) } const handleConfidenceLevel = async (level: number) => { if (!currentTest) return await submitTest(true, undefined, level) // 翻卡記憶以信心等級為準 } const handleReorderAnswer = async () => { if (!currentTest) return const userSentence = arrangedWords.join(' ') const correctSentence = currentTest.card.example const isCorrect = userSentence.toLowerCase().trim() === correctSentence.toLowerCase().trim() setReorderResult(isCorrect) setShowResult(true) await submitTest(isCorrect, userSentence) } const handleSpeakingAnswer = async (transcript: string) => { if (!currentTest) return setShowResult(true) const isCorrect = transcript.toLowerCase().includes(currentTest.card.word.toLowerCase()) await submitTest(isCorrect, transcript) } // 初始化例句重組 useEffect(() => { if (currentTest && currentTest.testType === 'sentence-reorder') { const words = currentTest.card.example.split(/\s+/).filter(word => word.length > 0) const shuffled = [...words].sort(() => Math.random() - 0.5) setShuffledWords(shuffled) setArrangedWords([]) setReorderResult(null) } }, [currentTest]) // 例句重組處理 const handleWordClick = (word: string) => { setShuffledWords(prev => prev.filter(w => w !== word)) setArrangedWords(prev => [...prev, word]) setReorderResult(null) } const handleRemoveFromArranged = (word: string) => { setArrangedWords(prev => prev.filter(w => w !== word)) setShuffledWords(prev => [...prev, word]) setReorderResult(null) } const handleResetReorder = () => { if (!currentTest) return const words = currentTest.card.example.split(/\s+/).filter(word => word.length > 0) const shuffled = [...words].sort(() => Math.random() - 0.5) setShuffledWords(shuffled) setArrangedWords([]) setReorderResult(null) } // 重新開始 const handleRestart = async () => { setScore({ correct: 0, total: 0 }) setShowComplete(false) await startNewSession() } // Loading screen if (!mounted || isLoading) { return (
載入中...
) } // No session or complete if (!session || showComplete) { return (
{showComplete ? ( router.push('/dashboard')} /> ) : (
📚

今日學習已完成!

目前沒有到期需要複習的詞卡。

)}
) } // No current test if (!currentTest) { return (
載入測驗中...
) } return (
{/* 分段式進度條 */}
學習進度
{progress && ( setShowTaskListModal(true)} /> )}
{/* 測驗內容渲染 */} {currentTest.testType === 'flip-memory' && ( )} {currentTest.testType === 'vocab-choice' && ( )} {currentTest.testType === 'sentence-fill' && ( )} {currentTest.testType === 'sentence-reorder' && ( )} {currentTest.testType === 'sentence-speaking' && ( )} {/* 任務清單模態框 */} {showTaskListModal && progress && ( setShowTaskListModal(false)} /> )}
) } // 測驗組件定義 interface TestComponentProps { card: any showResult: boolean } function FlipMemoryTest({ card, onConfidenceSelect, showResult }: TestComponentProps & { onConfidenceSelect: (level: number) => void }) { const [isFlipped, setIsFlipped] = useState(false) return (

翻卡記憶

setIsFlipped(!isFlipped)}> {!isFlipped ? (

{card.word}

{card.pronunciation}

) : (

{card.definition}

"{card.example}"

"{card.exampleTranslation}"

)}
{isFlipped && !showResult && (
{[1, 2, 3, 4, 5].map(level => ( ))}
)}
) } function VocabChoiceTest({ card, onAnswer, selectedAnswer, showResult }: TestComponentProps & { onAnswer: (answer: string) => void selectedAnswer: string | null }) { const options = [card.word, 'example1', 'example2', 'example3'].sort(() => Math.random() - 0.5) return (

詞彙選擇

{card.definition}

{options.map((option, idx) => ( ))}
{showResult && (

{selectedAnswer === card.word ? '正確!' : '錯誤!'}

{selectedAnswer !== card.word && (

正確答案: {card.word}

)}
)}
) } function SentenceFillTest({ card, fillAnswer, setFillAnswer, onSubmit, showHint, setShowHint, showResult }: TestComponentProps & { fillAnswer: string setFillAnswer: (value: string) => void onSubmit: () => void showHint: boolean setShowHint: (show: boolean) => void }) { return (

例句填空

{card.example.split(new RegExp(`(${card.word})`, 'gi')).map((part: string, index: number) => { const isTargetWord = part.toLowerCase() === card.word.toLowerCase() return isTargetWord ? ( setFillAnswer(e.target.value)} placeholder="____" disabled={showResult} className="inline-block px-2 py-1 mx-1 border-b-2 border-blue-500 focus:outline-none" style={{ width: `${Math.max(60, card.word.length * 12)}px` }} /> ) : ( {part} ) })}
{!showResult && fillAnswer.trim() && ( )}
{showHint && (

{card.definition}

)} {showResult && (

{fillAnswer.toLowerCase().trim() === card.word.toLowerCase() ? '正確!' : '錯誤!'}

)}
) } function SentenceReorderTest({ card, shuffledWords, arrangedWords, onWordClick, onRemoveWord, onCheckAnswer, onReset, showResult, result }: TestComponentProps & { shuffledWords: string[] arrangedWords: string[] onWordClick: (word: string) => void onRemoveWord: (word: string) => void onCheckAnswer: () => void onReset: () => void result: boolean | null }) { return (

例句重組

{/* 重組區域 */}

重組區域:

{arrangedWords.length === 0 ? (
將單字拖到這裡
) : (
{arrangedWords.map((word, index) => ( ))}
)}
{/* 可用單字 */}

可用單字:

{shuffledWords.map((word, index) => ( ))}
{arrangedWords.length > 0 && !showResult && ( )}
{result !== null && (

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

{!result && (

正確答案: "{card.example}"

)}
)}
) } function SentenceSpeakingTest({ card, onComplete, showResult }: TestComponentProps & { onComplete: (transcript: string) => void }) { return (

例句口說

onComplete(card.example)} /> {showResult && (

錄音完成!

系統正在評估發音...

)}
) } function TaskListModal({ progress, onClose }: { progress: Progress onClose: () => void }) { return (

📚 學習進度

整體進度: {progress.completedTests} / {progress.totalTests} ({Math.round((progress.completedTests / progress.totalTests) * 100)}%) 詞卡: {progress.completedCards} / {progress.totalCards}
{progress.cards.map((card, index) => (
詞卡{index + 1}: {card.word} {card.completedTestsCount}/{card.plannedTests.length} 測驗
{card.plannedTests.map(testType => { const isCompleted = card.tests.some(t => t.testType === testType) return (
{isCompleted ? '✅' : '⚪'} {testType}
) })}
))}
) }