From d0b6e9e75790d230a2f7c73d28734356e7b9019a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=84=AD=E6=B2=9B=E8=BB=92?= Date: Tue, 7 Oct 2025 02:21:13 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=BB=BA=E7=AB=8B=E9=96=8B=E7=99=BC/?= =?UTF-8?q?=E6=AD=A3=E5=BC=8F=E7=89=88=E6=9C=AC=E5=88=86=E9=9B=A2=E7=9A=84?= =?UTF-8?q?=E9=80=B2=E5=BA=A6=E7=B5=84=E4=BB=B6=E6=9E=B6=E6=A7=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 組件重組 - 創建 QuizProgressDev.tsx:給 /review-dev 使用,保留完整開發功能 - 修改 QuizProgress.tsx:給 /review 使用,移除開發測試資訊 - 頁面獨立:兩個頁面使用不同組件,互不影響 ## TypeScript 修復 - 完善 CardState interface 類型兼容性 - 修復 primaryImageUrl, updatedAt, exampleTranslation 類型匹配 - 確保所有必需屬性都有預設值 ## 頁面功能 - /review: 使用簡化版 QuizProgress,適合正式使用 - /review-dev: 使用完整版 QuizProgressDev,保留所有調試功能 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- frontend/app/review-dev/page.tsx | 4 +- frontend/app/review/page.tsx | 3 +- .../components/review/ui/QuizProgress.tsx | 16 ----- .../components/review/ui/QuizProgressDev.tsx | 67 +++++++++++++++++++ frontend/hooks/review/useReviewSession.ts | 19 ++++-- 5 files changed, 82 insertions(+), 27 deletions(-) create mode 100644 frontend/components/review/ui/QuizProgressDev.tsx diff --git a/frontend/app/review-dev/page.tsx b/frontend/app/review-dev/page.tsx index 9cb9158..eb644a2 100644 --- a/frontend/app/review-dev/page.tsx +++ b/frontend/app/review-dev/page.tsx @@ -3,7 +3,7 @@ import { Navigation } from '@/components/shared/Navigation' import { FlipMemory } from '@/components/review/quiz/FlipMemory' import { VocabChoiceQuiz } from '@/components/review/quiz/VocabChoiceQuiz' -import { QuizProgress } from '@/components/review/ui/QuizProgress' +import { QuizProgressDev } from '@/components/review/ui/QuizProgressDev' import { QuizResult } from '@/components/review/quiz/QuizResult' import { useReviewSession } from '@/hooks/review/useReviewSession' @@ -115,7 +115,7 @@ export default function ReviewDevPage() {
{/* 使用修改後的 SimpleProgress 組件 */} -
- {/* 使用修改後的 SimpleProgress 組件 */} + {/* 使用簡化的 ReviewProgress 組件 */} {/* 根據當前測驗項目類型渲染對應組件 */} diff --git a/frontend/components/review/ui/QuizProgress.tsx b/frontend/components/review/ui/QuizProgress.tsx index 1df3a65..452cbb1 100644 --- a/frontend/components/review/ui/QuizProgress.tsx +++ b/frontend/components/review/ui/QuizProgress.tsx @@ -22,23 +22,7 @@ export function QuizProgress({ currentQuizItem, totalQuizItems, completedQuizIte return (
-
- 線性複習進度 - {currentQuizItem && ( -
- - {currentQuizItem.quizType === 'flip-card' ? '🔄' : '🎯'} - - - {currentQuizItem.quizType === 'flip-card' ? '翻卡記憶' : '詞彙選擇'} • {currentQuizItem.cardData.word} - -
- )} -
- - {completedQuizItems}/{totalQuizItems} 項目 - {score.total > 0 && ( 準確率 {accuracy}% diff --git a/frontend/components/review/ui/QuizProgressDev.tsx b/frontend/components/review/ui/QuizProgressDev.tsx new file mode 100644 index 0000000..ba05ef6 --- /dev/null +++ b/frontend/components/review/ui/QuizProgressDev.tsx @@ -0,0 +1,67 @@ +import { QuizItem } from '@/lib/data/reviewSimpleData' + +interface ReviewProgressProps { + currentQuizItem?: QuizItem + totalQuizItems: number + completedQuizItems: number + score: { correct: number; total: number } +} + +export function QuizProgressDev({ currentQuizItem, totalQuizItems, completedQuizItems, score }: ReviewProgressProps) { + const progress = (completedQuizItems / totalQuizItems) * 100 + const accuracy = score.total > 0 ? Math.round((score.correct / score.total) * 100) : 0 + + return ( +
+
+
+ 複習進度 + {currentQuizItem && ( +
+ + {currentQuizItem.quizType === 'flip-card' ? '🔄' : '🎯'} + + + {currentQuizItem.quizType === 'flip-card' ? '翻卡記憶' : '詞彙選擇'} • {currentQuizItem.cardData.word} + +
+ )} +
+
+ + {completedQuizItems}/{totalQuizItems} 項目 + + {score.total > 0 && ( + + 準確率 {accuracy}% + + )} +
+
+ + {/* 進度條 */} +
+
+
+ + {/* 基本統計 */} +
+ {score.total > 0 && ( + <> +
+ + 答對 {score.correct} +
+
+ + 答錯 {score.total - score.correct} +
+ + )} +
+
+ ) +} \ No newline at end of file diff --git a/frontend/hooks/review/useReviewSession.ts b/frontend/hooks/review/useReviewSession.ts index 77b943a..cf459d1 100644 --- a/frontend/hooks/review/useReviewSession.ts +++ b/frontend/hooks/review/useReviewSession.ts @@ -1,14 +1,17 @@ import { useReducer, useEffect, useMemo, useState } from 'react' import { flashcardsService, Flashcard } from '@/lib/services/flashcards' -// 重新定義所需的介面 +// 重新定義所需的介面,確保與 reviewSimpleData.CardState 完全兼容 interface CardState extends Flashcard { skipCount: number wrongCount: number isCompleted: boolean originalOrder: number - synonyms?: string[] - difficultyLevelNumeric: number // 添加缺少的屬性 + synonyms: string[] // 改為必需的數組 + difficultyLevelNumeric: number // 必需屬性 + exampleTranslation: string // 覆蓋 Flashcard 的可選定義,改為必需 + updatedAt: string // 覆蓋 Flashcard 的可選定義,改為必需 + primaryImageUrl: string | null // 確保類型匹配(null 而非 undefined) } interface QuizItem { @@ -89,16 +92,18 @@ const generateQuizItemsFromFlashcards = (flashcards: Flashcard[]): QuizItem[] => let order = 0 flashcards.forEach((card) => { - // 轉換 Flashcard 為 CardState 格式 + // 轉換 Flashcard 為 CardState 格式,確保所有屬性都有值 const cardState: CardState = { ...card, - exampleTranslation: card.exampleTranslation || '', // 確保 exampleTranslation 不為 undefined + exampleTranslation: card.exampleTranslation || '', // 確保為 string,不是 undefined + updatedAt: card.updatedAt || card.createdAt, // 確保 updatedAt 為 string + primaryImageUrl: card.primaryImageUrl || null, // 確保為 null 而非 undefined skipCount: 0, wrongCount: 0, isCompleted: false, originalOrder: order / 2, // 原始詞卡的順序 - synonyms: [], - difficultyLevelNumeric: card.masteryLevel || 1 // 添加缺少的屬性 + synonyms: [], // 確保為空數組而非 undefined + difficultyLevelNumeric: card.masteryLevel || 1 // 使用 masteryLevel 或預設值 1 } // 為每張詞卡生成兩種測驗模式