dramaling-vocab-learning/詞卡詳情頁重構計劃.md

15 KiB
Raw Blame History

詞卡詳情頁重構計劃

📋 現況分析

問題分析

frontend/app/flashcards/[id]/page.tsx 檔案存在以下問題:

  • 檔案過大: 543行代碼單一檔案責任過重
  • UI邏輯混雜: 業務邏輯與UI渲染代碼混合在一起
  • 重複代碼: 大量內聯樣式和重複的UI區塊
  • 可維護性差: 業務邏輯分散,難以測試和修改
  • 組件功能不清晰: 單一組件處理過多功能

現有組件狀況

已存在的組件:

  • FlashcardDetailHeader - 詞卡標題區域
  • FlashcardContentBlocks - 內容區塊179行已部分重構

需要新建的組件:

  • 詞卡資訊區塊組件
  • 操作按鈕組組件
  • 編輯模式UI組件
  • 載入與錯誤狀態組件

🎯 重構目標

主要目標

  1. 模組化分離: 將單一大檔案拆分為多個專職組件
  2. 職責分離: 將業務邏輯、UI邏輯、狀態管理分離
  3. 可重用性: 創建可在其他地方重用的原子級組件
  4. 可測試性: 每個組件功能單一,便於單元測試
  5. 可維護性: 降低代碼複雜度,提高可讀性

效能目標

  • 減少主檔案代碼量至 < 200 行
  • 提高組件重用率
  • 改善開發者體驗

🏗️ 重構策略

第一階段UI組件拆分

1.1 建立基礎UI組件

  • FlashcardInfoBlock - 詞卡基本資訊顯示
  • FlashcardActions - 底部操作按鈕組
  • EditingControls - 編輯模式專用控制元件

1.2 建立狀態組件

  • LoadingState - 載入狀態顯示
  • ErrorState - 錯誤狀態顯示

第二階段:邏輯抽取與優化

2.1 Custom Hook 強化

  • 完善 useFlashcardActions - 收藏、編輯、刪除操作
  • 建立 useImageGeneration - 圖片生成邏輯
  • 優化 useFlashcardDetailData - 數據管理

2.2 工具函數抽取

  • 編輯表單驗證邏輯
  • 確認對話框邏輯
  • 圖片處理邏輯

第三階段:主頁面重構

3.1 簡化主組件結構

// 目標結構
export default function FlashcardDetailPage({ params }) {
  return (
    <ProtectedRoute>
      <FlashcardDetailContent cardId={use(params).id} />
    </ProtectedRoute>
  )
}

function FlashcardDetailContent({ cardId }) {
  // 僅保留核心狀態管理和組件組合邏輯
  // 將具體UI實現委託給子組件
}

3.2 組件組合優化

  • 使用組合模式而非繼承
  • 實現懶載入提升效能
  • 優化re-render機制

📦 新組件結構設計

組件層次結構

FlashcardDetailPage (路由頁面)
├── ProtectedRoute
└── FlashcardDetailContent (主容器)
    ├── LoadingState / ErrorState
    ├── Navigation (返回按鈕)
    ├── FlashcardDetailCard (主卡片)
    │   ├── FlashcardDetailHeader (現有)
    │   ├── FlashcardContentBlocks (現有)
    │   ├── FlashcardInfoBlock (新建)
    │   └── EditingControls (新建)
    └── FlashcardActions (新建)

新組件詳細設計

FlashcardInfoBlock

interface FlashcardInfoBlockProps {
  flashcard: Flashcard
  isEditing: boolean
  editedCard?: Partial<Flashcard>
  onEditChange: (field: string, value: string) => void
}

功能: 顯示詞性、創建時間、下次複習、複習次數等資訊

FlashcardActions

interface FlashcardActionsProps {
  flashcard: Flashcard
  isEditing: boolean
  onToggleFavorite: () => void
  onToggleEdit: () => void
  onDelete: () => void
}

功能: 收藏、編輯、刪除按鈕組

EditingControls

interface EditingControlsProps {
  onSave: () => void
  onCancel: () => void
  isSaving?: boolean
}

功能: 編輯模式的保存/取消按鈕

LoadingState & ErrorState

interface LoadingStateProps {
  message?: string
}

interface ErrorStateProps {
  error: string
  onRetry?: () => void
  onGoBack?: () => void
}

功能: 統一的載入與錯誤狀態處理

Custom Hooks 設計

useFlashcardActions

interface UseFlashcardActionsReturn {
  toggleFavorite: () => Promise<void>
  saveEdit: () => Promise<void>
  deleteFlashcard: () => Promise<void>
  isLoading: boolean
}

useImageGeneration

interface UseImageGenerationReturn {
  generateImage: () => Promise<void>
  isGenerating: boolean
  progress: string
}

🔧 實施步驟

Step 1: 建立基礎組件 (預估1-2小時)

  1. 建立 LoadingStateErrorState 組件
  2. 建立 FlashcardInfoBlock 組件
  3. 建立 FlashcardActions 組件
  4. 建立 EditingControls 組件

Step 2: 抽取業務邏輯 (預估2-3小時)

  1. 建立 useFlashcardActions hook
  2. 建立 useImageGeneration hook
  3. 重構現有的 useFlashcardDetailData hook

Step 3: 重構主組件 (預估1-2小時)

  1. 更新 FlashcardDetailContent 使用新組件
  2. 移除重複代碼
  3. 優化props傳遞

Step 4: 測試與優化 (預估1小時)

  1. 功能測試確保無回歸
  2. 效能測試
  3. 代碼審查與優化

📏 成功指標

量化指標

  • 主檔案代碼行數543行 → 實際 193行 (減少 64%)
  • 組件檔案數量2個 → 實際 7個 (增加 250%)
  • 平均組件代碼行數:< 90行
  • 重複代碼減少率:> 60%

質化指標

  • 代碼可讀性提升
  • 組件重用性增強
  • 維護成本降低
  • 新功能開發效率提升

🚧 注意事項

重構原則

  1. 漸進式重構: 不影響現有功能
  2. 向後相容: 保持API介面穩定
  3. 測試驅動: 每次修改都要驗證功能正常
  4. 文檔同步: 及時更新組件文檔

風險控制

  • 重構前建立功能測試檢查清單
  • 分階段提交,確保每個階段都可回滾
  • 保留原始檔案備份
  • 充分測試邊緣案例

📅 時間規劃

階段 時間 主要任務
Phase 1 2小時 基礎組件開發
Phase 2 3小時 業務邏輯抽取
Phase 3 2小時 主組件重構
Phase 4 1小時 測試優化
總計 8小時 完整重構

🎉 重構完成摘要

📊 實際成果

已成功完成詞卡詳情頁重構,超額達成所有目標指標:

新建組件

  1. LoadingState (21行) - 統一載入狀態
  2. ErrorState (45行) - 統一錯誤處理
  3. FlashcardInfoBlock (89行) - 詞卡資訊區塊
  4. FlashcardActions (73行) - 操作按鈕組
  5. EditingControls (34行) - 編輯模式控制

新建 Custom Hooks

  1. useFlashcardActions (106行) - 詞卡操作邏輯
  2. useImageGeneration (63行) - 圖片生成邏輯

重構效果

  • 主檔案縮減543行 → 193行 (減少64%)
  • 組件數量增加2個 → 7個 (增加250%)
  • TypeScript類型安全 編譯無錯誤
  • 代碼複用性 大幅提升
  • 維護性 顯著改善

🔧 技術優化

  • 業務邏輯與UI完全分離
  • 統一的錯誤處理機制
  • 一致的載入狀態顯示
  • 模組化的組件設計
  • 強化的類型安全

重構完成後預期效果

  • 代碼結構清晰,職責分明
  • 組件可重用性大幅提升
  • 維護成本顯著降低
  • 新功能開發效率提升
  • 測試覆蓋率改善

重構完成日期2025年10月1日


🔄 後續重構計劃

📊 其他頁面重構優先級

根據代碼行數分析,按優先級排序:

頁面 代碼行數 優先級 預估工時 重構理由
generate/page.tsx 625行 極高 4-6小時 代碼量最大,功能複雜
flashcards/page.tsx 305行 2-3小時 搜尋邏輯複雜UI重複
review-design/page.tsx 279行 中高 2小時 設計頁面UI元素多
dashboard/page.tsx 256行 2小時 數據展示邏輯
review/page.tsx 253行 2小時 複習邏輯重複

🎯 下階段重構目標

第一優先generate/page.tsx

問題分析

  • 代碼行數過多 (625行)
  • 可能包含複雜的生成邏輯
  • UI與業務邏輯混雜

重構策略

  1. 分析主要功能模組
  2. 抽取生成邏輯到 Custom Hooks
  3. 分離UI組件
  4. 建立通用的表單元件

第二優先flashcards/page.tsx

預期問題

  • 搜尋功能複雜
  • 列表渲染邏輯重複
  • 狀態管理分散

組件重用性優化

已完成

  • LoadingState 移至 shared (通用載入狀態)
  • ErrorState 移至 shared (通用錯誤處理)

計劃重用

  • FlashcardActions 可用於其他詞卡操作頁面
  • EditingControls 可用於其他編輯功能

📋 下一步行動項目

  1. 立即執行:重構 generate/page.tsx
  2. 短期目標:完成 flashcards/page.tsx 重構
  3. 中期目標:建立可重用組件庫
  4. 長期目標:全站組件架構統一

🔧 重構規範

  • 單一檔案不超過 250行
  • 組件職責單一化
  • 業務邏輯抽取到 Custom Hooks
  • UI組件優先考慮重用性
  • 保持向後相容性

🚀 Generate頁面重構分析

📊 分析結果 (625行 → 目標 200行)

主要功能區塊:

  1. 文字輸入區 (243-274行) - 複雜驗證邏輯
  2. 分析處理引擎 (49-140行) - AI API調用邏輯
  3. 語法修正面板 (334-374行) - 條件渲染邏輯
  4. 詞彙統計卡片 (378-405行) - 重複統計UI模式
  5. 互動式句子顯示 (407-481行) - 複雜條件渲染
  6. 成語彈窗 (497-611行) - 大型內聯Modal實作
  7. 詞彙保存邏輯 (194-232行) - API整合邏輯

🔍 發現問題:

  • ClickableTextV2.tsx (15,692行!) - 超大組件需優先重構
  • 重複UI模式 - ContentBlock模式重複6+次
  • 統計卡片模式 - 重複4次
  • 內聯Modal - 可用現有Modal組件替換

🎯 重構策略

Phase 1: 建立可重用基礎組件

  1. ContentBlock - 通用內容區塊 (利用現有FlashcardContentBlocks模式)
  2. StatisticsCard - 統計卡片組件 (4處重複使用)
  3. ValidatedTextInput - 驗證文字輸入組件

Phase 2: 重構複雜UI組件

  1. GrammarCorrectionPanel - 語法修正面板
  2. VocabularyStatsGrid - 詞彙統計網格
  3. IdiomDetailContent - 成語詳情內容 (配合現有Modal)

Phase 3: 抽取業務邏輯

  1. useSentenceAnalysis - 句子分析Hook
  2. useVocabularySave - 詞彙保存Hook
  3. useVocabularyStats - 統計計算Hook

📋 組件重用評估結果

可重用現有組件:

  • Modal (ui/) - 替換自訂成語彈窗
  • LoadingState (shared/) - 替換內聯載入狀態
  • TTSButton (shared/) - 已在使用
  • ContentBlock 模式 - 參考 FlashcardContentBlocks

需新建組件:

  • StatisticsCard - 4處統計卡片重複
  • ValidatedTextInput - 複雜驗證邏輯
  • GrammarCorrectionPanel - 語法修正UI

⚠️ 重要發現

ClickableTextV2.tsx (15,692行) 也需要緊急重構!這是比 generate/page.tsx 更嚴重的問題。

📅 執行順序

  1. 立即:重構 generate/page.tsx (625行)
  2. 緊急:重構 ClickableTextV2.tsx (15,692行)
  3. 後續:其他頁面按優先級順序

🛠️ Generate頁面重構執行進度

Phase 1: 基礎組件建立

已完成組件:

  1. StatisticsCard (shared/) - 通用統計卡片支援6種顏色變體
  2. ContentBlock (shared/) - 通用內容區塊支援7種顏色變體
  3. ValidatedTextInput (shared/) - 驗證文字輸入,支援字數限制與視覺回饋
  4. VocabularyStatsGrid (generate/) - 詞彙統計網格組合4個StatisticsCard

重用現有組件:

  • Modal (ui/) - 將用於成語彈窗
  • LoadingState (shared/) - 用於分析載入狀態
  • TTSButton (shared/) - 已在成語彈窗中使用

Phase 2: 待執行組件 (進行中)

  1. GrammarCorrectionPanel - 語法修正面板
  2. IdiomDetailContent - 成語詳情內容
  3. SentenceAnalysisDisplay - 句子分析顯示

Phase 3: 待執行業務邏輯抽取

  1. useSentenceAnalysis Hook
  2. useVocabularySave Hook
  3. useVocabularyStats Hook

📊 目前進度

  • 基礎組件: 4/4 完成
  • 複雜組件: 0/3 完成
  • 業務邏輯: 0/3 完成
  • 主檔案重構: 待執行

預期效果: 625行 → 200行 (減少68%)


📋 Flashcards列表頁重構進度

📊 分析結果 (305行 → 目標 200行)

已完成優化:

  1. LoadingState重用 - 替換內聯載入狀態 (減少8行)
  2. ErrorState重用 - 替換內聯錯誤狀態 (減少8行)
  3. TabNavigation組件 - 新建通用標籤導航 (減少26行)

現有組件評估:

已有完善組件

  • SearchControls (8.4KB) - 搜尋控制面板
  • SearchResults (2.5KB) - 搜尋結果顯示
  • FlashcardCard (9.5KB) - 詞卡卡片組件
  • PaginationControls (4KB) - 分頁控制

新建通用組件

  • TabNavigation (shared/) - 通用標籤導航,可重用於其他頁面

📊 重構效果:

  • 代碼減少: 305行 → 277行 (減少9%)
  • 新增通用組件: 1個 (TabNavigation)
  • 編譯狀態: 成功
  • Bundle大小: flashcards頁面從12.1KB → 10.4KB (減少14%)

🔧 ClickableTextV2組件重構完成

📊 重構成果 (413行 → 114行減少72%)

🎯 重構前問題:

  • 單一組件過大: 413行代碼功能混雜
  • 重複UI邏輯: popup、內容區塊等重複實作
  • 邏輯分散: 詞彙分析、樣式計算、彈窗控制混合

重構完成:

新建組件架構:
  1. types.ts - 統一類型定義
  2. useWordAnalysis Hook - 詞彙分析邏輯抽取
  3. WordPopup組件 - 使用現有Modal + ContentBlock
  4. ClickableTextV2 - 簡化主組件邏輯
組件重用成果:
  • Modal組件重用 - 替換自訂popup實作
  • ContentBlock重用 - 替換內聯樣式區塊
  • Hook模式採用 - 業務邏輯分離

📈 技術優化:

  • 代碼減少: 413行 → 114行 (減少72%)
  • 組件分離: 1個大組件 → 4個模組化組件
  • 可重用性: 新建的word組件可用於其他詞彙功能
  • 可維護性: 單一職責,便於測試
  • Bundle優化: generate頁面從8.28KB → 9.11KB (輕微增加,但結構更好)