diff --git a/frontend/app/generate/page.tsx b/frontend/app/generate/page.tsx index ce88051..4f63cb0 100644 --- a/frontend/app/generate/page.tsx +++ b/frontend/app/generate/page.tsx @@ -1,27 +1,55 @@ 'use client' -import { useState } from 'react' +import { useState, useMemo, useCallback } from 'react' import { ProtectedRoute } from '@/components/ProtectedRoute' import { Navigation } from '@/components/Navigation' import { ClickableTextV2 } from '@/components/ClickableTextV2' import { flashcardsService } from '@/lib/services/flashcards' import Link from 'next/link' +// 常數定義 +const CEFR_LEVELS = ['A1', 'A2', 'B1', 'B2', 'C1', 'C2'] as const +const MAX_MANUAL_INPUT_LENGTH = 300 +const MAX_SCREENSHOT_INPUT_LENGTH = 5000 + +// 工具函數 +const getLevelIndex = (level: string): number => { + return CEFR_LEVELS.indexOf(level as typeof CEFR_LEVELS[number]) +} + +const getTargetLearningRange = (userLevel: string): string => { + const ranges: Record = { + 'A1': 'A2-B1', 'A2': 'B1-B2', 'B1': 'B2-C1', + 'B2': 'C1-C2', 'C1': 'C2', 'C2': 'C2' + } + return ranges[userLevel] || 'B1-B2' +} + function GenerateContent() { const [mode, setMode] = useState<'manual' | 'screenshot'>('manual') const [textInput, setTextInput] = useState('') const [isAnalyzing, setIsAnalyzing] = useState(false) const [showAnalysisView, setShowAnalysisView] = useState(false) - const [sentenceAnalysis, setSentenceAnalysis] = useState(null) + const [sentenceAnalysis, setSentenceAnalysis] = useState | null>(null) const [sentenceMeaning, setSentenceMeaning] = useState('') - const [grammarCorrection, setGrammarCorrection] = useState(null) + const [grammarCorrection, setGrammarCorrection] = useState<{ + hasErrors: boolean; + originalText: string; + correctedText: string; + corrections: Array<{ + error: string; + correction: string; + type: string; + explanation: string; + }>; + } | null>(null) const [finalText, setFinalText] = useState('') - const [usageCount, setUsageCount] = useState(0) + const [usageCount] = useState(0) const [isPremium] = useState(true) const [phrasePopup, setPhrasePopup] = useState<{ phrase: string analysis: any - position: { x: number, y: number } + position: { x: number; y: number } } | null>(null) @@ -309,20 +337,53 @@ function GenerateContent() { - const handleAcceptCorrection = () => { + const handleAcceptCorrection = useCallback(() => { if (grammarCorrection?.correctedText) { setFinalText(grammarCorrection.correctedText) alert('✅ 已採用修正版本,後續學習將基於正確的句子進行!') } - } + }, [grammarCorrection?.correctedText]) - const handleRejectCorrection = () => { + const handleRejectCorrection = useCallback(() => { setFinalText(grammarCorrection?.originalText || textInput) alert('📝 已保持原始版本,將基於您的原始輸入進行學習。') - } + }, [grammarCorrection?.originalText, textInput]) + + // 詞彙統計計算 - 移到組件頂層避免Hooks順序問題 + const vocabularyStats = useMemo(() => { + if (!sentenceAnalysis) return null + + const userLevel = localStorage.getItem('userEnglishLevel') || 'A2' + let simpleCount = 0 + let moderateCount = 0 + let difficultCount = 0 + let phraseCount = 0 + + Object.entries(sentenceAnalysis).forEach(([, wordData]: [string, any]) => { + const isPhrase = wordData?.isPhrase || wordData?.IsPhrase + const difficultyLevel = wordData?.difficultyLevel || 'A1' + + if (isPhrase) { + phraseCount++ + } else { + const userIndex = getLevelIndex(userLevel) + const wordIndex = getLevelIndex(difficultyLevel) + + if (userIndex > wordIndex) { + simpleCount++ + } else if (userIndex === wordIndex) { + moderateCount++ + } else { + difficultCount++ + } + } + }) + + return { simpleCount, moderateCount, difficultCount, phraseCount } + }, [sentenceAnalysis]) // 保存單個詞彙 - const handleSaveWord = async (word: string, analysis: any) => { + const handleSaveWord = useCallback(async (word: string, analysis: any) => { try { const cardData = { word: word, @@ -344,7 +405,7 @@ function GenerateContent() { console.error('Save word error:', error) throw error // 重新拋出錯誤讓組件處理 } - } + }, []) return (
@@ -355,76 +416,37 @@ function GenerateContent() {

AI 智能生成詞卡

- {/* Input Mode Selection */} -
-

原始例句類型

-
- - -
-
- {/* Content Input */} -
+

輸入英文文本