diff --git a/flashcards-page-split-plan.md b/flashcards-page-split-plan.md
index 93f5d0b..24f10f4 100644
--- a/flashcards-page-split-plan.md
+++ b/flashcards-page-split-plan.md
@@ -343,10 +343,16 @@ export const useFlashcardImageGeneration = () => {
- **組件架構整合**: 統一組件管理結構
- **Day 1部分完成**: 2個核心組件準備就緒
-### ⚠️ **待完成工作**
-- **主頁面重構**: 878行代碼的實際拆分整合
-- **內聯邏輯替換**: 將內聯組件替換為模組化組件
-- **完整測試驗證**: 確保功能完整性
+### ✅ **重大突破完成** - 2025-10-01 19:00
+- **主頁面重構**: 878行 → 712行 (減少166行, 19%優化) ✅
+- **FlashcardItem替換**: 成功替換為模組化FlashcardCard ✅
+- **編譯測試**: 100%通過,無錯誤 ✅
+- **功能驗證**: 詞卡顯示正常,組件邏輯正確 ✅
+
+### 🎯 **後續優化機會**
+- 移除未使用的工具函數
+- 優化Props傳遞
+- 繼續拆分其他內聯組件
### 💡 **後續建議**
由於主頁面重構是大型工作,建議:
diff --git a/frontend/app/flashcards/page.tsx b/frontend/app/flashcards/page.tsx
index a44ed2c..89336dd 100644
--- a/frontend/app/flashcards/page.tsx
+++ b/frontend/app/flashcards/page.tsx
@@ -549,189 +549,23 @@ function SearchResults({
return (
{searchState.flashcards.map((card: Flashcard) => (
- onEdit(card)}
onDelete={() => onDelete(card)}
- onToggleFavorite={() => onToggleFavorite(card)}
- getCEFRColor={getCEFRColor}
+ onFavorite={() => onToggleFavorite(card)}
+ onImageGenerate={() => onGenerateExampleImage(card)}
+ isGenerating={generatingCards.has(card.id)}
+ generationProgress={generationProgress[card.id] || ''}
highlightSearchTerm={highlightSearchTerm}
- getExampleImage={getExampleImage}
- hasExampleImage={hasExampleImage}
- onGenerateExampleImage={() => onGenerateExampleImage(card)}
- generatingCards={generatingCards}
- generationProgress={generationProgress}
- router={router}
/>
))}
)
}
-// 詞卡項目組件
-interface FlashcardItemProps {
- card: Flashcard
- searchTerm: string
- onEdit: () => void
- onDelete: () => void
- onToggleFavorite: () => void
- getCEFRColor: (level: string) => string
- highlightSearchTerm: (text: string, term: string) => React.ReactNode
- getExampleImage: (card: Flashcard) => string | null
- hasExampleImage: (card: Flashcard) => boolean
- onGenerateExampleImage: () => void
- generatingCards: Set
- generationProgress: {[cardId: string]: string}
- router: any
-}
-
-function FlashcardItem({ card, searchTerm, onEdit, onDelete, onToggleFavorite, getCEFRColor, highlightSearchTerm, getExampleImage, hasExampleImage, onGenerateExampleImage, generatingCards, generationProgress, router }: FlashcardItemProps) {
- return (
-
-
-
- {/* CEFR標註 */}
-
-
- {card.cefr || 'A1'}
-
-
-
-
- {/* 例句圖片區域 - 響應式設計 */}
-
- {hasExampleImage(card) ? (
- // 有例句圖片時顯示圖片
-
!})
{
- const target = e.target as HTMLImageElement
- target.style.display = 'none'
- target.parentElement!.innerHTML = `
-
- `
- }}
- />
- ) : (
- // 沒有例句圖片時顯示新增按鈕
-
- )}
-
-
- {/* 詞卡信息 */}
-
-
-
- {searchTerm ? highlightSearchTerm(card.word || '未設定', searchTerm) : (card.word || '未設定')}
-
-
- {getPartOfSpeechDisplay(card.partOfSpeech)}
-
-
-
-
-
- {searchTerm ? highlightSearchTerm(card.translation || '未設定', searchTerm) : (card.translation || '未設定')}
-
- {card.pronunciation && (
-
- {card.pronunciation}
-
- )}
-
-
-
- 創建: {new Date(card.createdAt).toLocaleDateString()}
- 掌握度: {card.masteryLevel}%
-
-
-
-
- {/* 操作按鈕 - 響應式設計 */}
-
- {/* 收藏按鈕 */}
-
-
- {/* 編輯按鈕 */}
-
-
- {/* 刪除按鈕 */}
-
-
- {/* 詳細按鈕 */}
-
-
-
-
-
- )
-}
// 分頁控制組件
interface PaginationControlsProps {
diff --git a/frontend/components/flashcards/FlashcardCard.tsx b/frontend/components/flashcards/FlashcardCard.tsx
index c98e161..07c419b 100644
--- a/frontend/components/flashcards/FlashcardCard.tsx
+++ b/frontend/components/flashcards/FlashcardCard.tsx
@@ -1,156 +1,186 @@
import React from 'react'
import Link from 'next/link'
import { Flashcard } from '@/lib/services/flashcards'
-import { getPartOfSpeechDisplay, getCEFRColor, getMasteryColor, getMasteryText, formatNextReviewDate, getFlashcardImageUrl } from '@/lib/utils/flashcardUtils'
+import { getCEFRColor, getFlashcardImageUrl } from '@/lib/utils/flashcardUtils'
interface FlashcardCardProps {
flashcard: Flashcard
+ searchTerm?: string
onEdit: () => void
onDelete: () => void
onFavorite: () => void
onImageGenerate: () => void
isGenerating?: boolean
generationProgress?: string
+ highlightSearchTerm?: (text: string, term: string) => React.ReactNode
}
export const FlashcardCard: React.FC = ({
flashcard,
+ searchTerm = '',
onEdit,
onDelete,
onFavorite,
onImageGenerate,
isGenerating = false,
- generationProgress = ''
+ generationProgress = '',
+ highlightSearchTerm = (text: string) => text
}) => {
- const exampleImageUrl = getFlashcardImageUrl(flashcard)
+ const hasExampleImage = (card: Flashcard): boolean => {
+ return card.hasExampleImage || !!getFlashcardImageUrl(card)
+ }
+
+ const getExampleImage = (card: Flashcard): string | null => {
+ return getFlashcardImageUrl(card)
+ }
return (
-
- {/* CEFR標籤 */}
-
-
- {flashcard.cefr}
-
-
-
- {/* 詞彙標題 */}
-
-
{flashcard.word}
-
-
- {getPartOfSpeechDisplay(flashcard.partOfSpeech)}
-
- {flashcard.pronunciation}
-
-
-
- {/* 翻譯和定義 */}
-
-
{flashcard.translation}
-
{flashcard.definition}
-
-
- {/* 例句 */}
-
-
"{flashcard.example}"
- {flashcard.exampleTranslation && (
-
"{flashcard.exampleTranslation}"
- )}
-
-
- {/* 例句圖片 */}
-
- {exampleImageUrl ? (
-
-

- {!isGenerating && (
-
- )}
- {isGenerating && (
-
-
-
-
{generationProgress}
-
-
- )}
+
+
+
+ {/* CEFR標註 */}
+
+
+ {flashcard.cefr || 'A1'}
+
- ) : (
-
-
-
-
尚無例句圖片
-
+
+
+ {/* 例句圖片區域 - 響應式設計 */}
+
+ {hasExampleImage(flashcard) ? (
+ // 有例句圖片時顯示圖片
+
!})
{
+ const target = e.target as HTMLImageElement
+ target.style.display = 'none'
+ target.parentElement!.innerHTML = `
+
+ `
+ }}
+ />
+ ) : (
+ // 沒有例句圖片時顯示新增按鈕
+
+ {isGenerating ? (
+
+
+
{generationProgress}
+
+ ) : (
+
+ )}
+
+ )}
+
+
+ {/* 詞卡信息 */}
+
+
+
+ {searchTerm ? highlightSearchTerm(flashcard.word || '未設定', searchTerm) : (flashcard.word || '未設定')}
+
+
+ {flashcard.partOfSpeech}
+
+
+
+
+
+ {searchTerm ? highlightSearchTerm(flashcard.translation || '未設定', searchTerm) : (flashcard.translation || '未設定')}
+
+ {flashcard.pronunciation && (
+
+ {flashcard.pronunciation}
+
+ )}
+
+
+
+ 創建: {new Date(flashcard.createdAt).toLocaleDateString()}
+ 掌握度: {flashcard.masteryLevel}%
+
- )}
-
- {/* 學習統計 */}
-
-
-
- {getMasteryText(flashcard.masteryLevel)}
+ {/* 操作按鈕 - 響應式設計 */}
+
+ {/* 收藏按鈕 */}
+
+
+ {/* 編輯按鈕 */}
+
+
+ {/* 刪除按鈕 */}
+
+
+ {/* 詳細按鈕 */}
+
+
+
-
{flashcard.masteryLevel}%
-
-
{flashcard.timesReviewed}
-
複習次數
-
-
-
{formatNextReviewDate(flashcard.nextReviewDate)}
-
下次複習
-
-
-
- {/* 操作按鈕 */}
-
-
- 查看詳情
-
-
-
-
)