dramaling-vocab-learning/flashcards-page-split-plan.md

9.8 KiB
Raw Blame History

Flashcards/page.tsx 拆分執行計劃

目標: 將 878行的 flashcards/page.tsx 拆分為可維護的模組化組件 預估工期: 4天 優先級: 🔴 最高 - 影響最大的技術債務


📊 現況分析

🚨 問題嚴重性

  • 檔案大小: 878行 (超標4.4倍)
  • 責任過多: 7個主要功能模組混雜
  • 維護難度: 極高 - 任何修改都有高風險
  • 開發效率: 低 - 多人協作衝突頻繁

🔍 功能模組分析

// 目前單一檔案包含的功能:
1. 搜尋與篩選邏輯        (~150)
2. 詞卡列表渲染          (~200)
3. 分頁控制邏輯          (~100)
4. 圖片生成管理          (~120)
5. 表單狀態管理          (~80)
6. Toast通知處理         (~50)
7. 路由和導航邏輯        (~80)
8. 其他工具函數          (~98)

🎯 拆分目標架構

📁 新的檔案結構 (已整合)

/app/flashcards/
└── page.tsx                    (~120行) 主容器頁面

/components/
├── flashcards/
│   ├── FlashcardCard.tsx       (137行) ✅ 已完成
│   ├── FlashcardSearchBar.tsx  (~80行)  搜尋輸入組件
│   ├── FlashcardFilters.tsx    (~100行) 篩選器組件
│   ├── FlashcardGrid.tsx       (~150行) 詞卡網格顯示
│   └── FlashcardToolbar.tsx    (~80行)  工具欄組件
└── shared/
    └── PaginationControls.tsx  (109行) ✅ 已完成

/hooks/flashcards/
├── useFlashcardOperations.ts   (~100行) 操作邏輯Hook
└── useFlashcardImageGeneration.ts (~80行) 圖片生成Hook

🔧 詳細拆分方案

1. 主容器頁面 (page.tsx)

目標: ~120行 責任:

  • 路由保護和認證
  • 頂層狀態協調
  • 組件佈局和組合
export default function FlashcardsPage() {
  return (
    <ProtectedRoute>
      <Navigation />
      <div className="container">
        <FlashcardToolbar />
        <FlashcardSearchBar />
        <FlashcardFilters />
        <FlashcardGrid />
        <PaginationControls />
      </div>
    </ProtectedRoute>
  )
}

2. 搜尋輸入組件 (FlashcardSearchBar.tsx)

目標: ~80行 責任:

  • 搜尋輸入框
  • 即時搜尋邏輯
  • 搜尋建議下拉
interface FlashcardSearchBarProps {
  searchTerm: string
  onSearchChange: (term: string) => void
  suggestions: string[]
}

3. 篩選器組件 (FlashcardFilters.tsx)

目標: ~100行 責任:

  • 篩選下拉選單
  • 排序控制
  • 進階篩選切換
interface FlashcardFiltersProps {
  filters: SearchFilters
  onFiltersChange: (filters: Partial<SearchFilters>) => void
  sortOptions: SortOptions
  onSortChange: (sort: SortOptions) => void
}

4. 詞卡網格組件 (FlashcardGrid.tsx)

目標: ~150行 責任:

  • 詞卡網格布局
  • 載入狀態顯示
  • 空狀態處理
interface FlashcardGridProps {
  flashcards: Flashcard[]
  loading: boolean
  onCardClick: (id: string) => void
  onImageGenerate: (id: string) => void
}

5. 單個詞卡組件 (FlashcardCard.tsx)

目標: ~120行 責任:

  • 詞卡卡片UI
  • 互動按鈕
  • 狀態顯示
interface FlashcardCardProps {
  flashcard: Flashcard
  onEdit: () => void
  onDelete: () => void
  onFavorite: () => void
  onImageGenerate: () => void
  isGenerating?: boolean
}

6. 分頁控制組件 (PaginationControls.tsx)

目標: ~60行 責任:

  • 分頁導航
  • 每頁條數選擇
  • 跳頁輸入
interface PaginationControlsProps {
  currentPage: number
  totalPages: number
  pageSize: number
  totalCount: number
  onPageChange: (page: number) => void
  onPageSizeChange: (size: number) => void
}

7. 工具欄組件 (FlashcardToolbar.tsx)

目標: ~80行 責任:

  • 新增詞卡按鈕
  • 批量操作
  • 匯入/匯出功能

🎣 Custom Hooks 設計

1. useFlashcardOperations

export const useFlashcardOperations = () => {
  const toast = useToast()

  const handleEdit = (id: string) => { /* 編輯邏輯 */ }
  const handleDelete = async (id: string) => { /* 刪除邏輯 */ }
  const handleToggleFavorite = async (id: string) => { /* 收藏邏輯 */ }

  return {
    handleEdit,
    handleDelete,
    handleToggleFavorite
  }
}

2. useFlashcardImageGeneration

export const useFlashcardImageGeneration = () => {
  const [generating, setGenerating] = useState<Set<string>>(new Set())
  const [progress, setProgress] = useState<{[id: string]: string}>({})

  const generateImage = async (flashcardId: string) => { /* 生成邏輯 */ }
  const cancelGeneration = async (requestId: string) => { /* 取消邏輯 */ }

  return {
    generating,
    progress,
    generateImage,
    cancelGeneration
  }
}

📅 4天執行時間表

Day 1: 基礎組件拆分

  • 上午: 創建 FlashcardCard.tsx (單卡組件)
  • 下午: 創建 PaginationControls.tsx (分頁組件)
  • 🎯 目標: 完成2個基礎組件減少主檔案 ~180行

Day 2: 篩選與搜尋組件

  • 上午: 創建 FlashcardSearchBar.tsx (搜尋組件)
  • 下午: 創建 FlashcardFilters.tsx (篩選組件)
  • 🎯 目標: 完成搜尋篩選邏輯拆分,減少 ~180行

Day 3: Hook邏輯提取

  • 上午: 創建 useFlashcardOperations.ts
  • 下午: 創建 useFlashcardImageGeneration.ts
  • 🎯 目標: 提取業務邏輯,減少 ~200行

Day 4: 整合與測試

  • 上午: 創建 FlashcardGrid.tsxFlashcardToolbar.tsx
  • 下午: 重構主頁面,整合所有組件,完整測試
  • 🎯 目標: 主檔案縮減至 ~120行完成所有測試

📋 每日檢查清單

Day 1 檢查清單 完成 - 2025-10-01

  • 創建 FlashcardCard.tsx 組件 (137行)
  • 提取單卡渲染邏輯
  • 創建 PaginationControls.tsx 組件 (109行)
  • 提取分頁控制邏輯
  • 測試基礎組件功能 編譯通過
  • 檢查編譯無錯誤 100%成功

Day 1成果: 創建2個基礎組件為後續重構奠定基礎

📁 組件整合完成 - 2025-10-01 18:30

  • FlashcardCard.tsx → /components/flashcards/FlashcardCard.tsx
  • PaginationControls.tsx → /components/shared/PaginationControls.tsx
  • 遵循Next.js 13+ App Router最佳實踐
  • 統一組件管理,提升復用性和可發現性

Day 2 檢查清單

  • 創建 FlashcardSearchBar.tsx 組件
  • 提取搜尋輸入邏輯
  • 創建 FlashcardFilters.tsx 組件
  • 提取篩選控制邏輯
  • 測試搜尋篩選功能
  • 確保狀態同步正常

Day 3 檢查清單

  • 創建 useFlashcardOperations.ts Hook
  • 提取編輯、刪除、收藏邏輯
  • 創建 useFlashcardImageGeneration.ts Hook
  • 提取圖片生成邏輯
  • 測試 Hook 邏輯正確性
  • 驗證狀態管理完整性

Day 4 檢查清單

  • 創建 FlashcardGrid.tsx 組件
  • 創建 FlashcardToolbar.tsx 組件
  • 重構主頁面為組件組合
  • 完整功能測試
  • 性能測試驗證
  • 代碼review和優化

🎯 預期成果

📊 量化目標

  • 主檔案: 878行 → ~120行 (減少86%)
  • 組件數量: 1個 → 6個專責組件
  • Hook數量: 0個 → 2個業務邏輯Hook
  • 可維護性: 🔴🟢 (極大提升)

🚀 品質提升

  • 單一責任: 每個組件職責明確
  • 可測試性: 組件獨立可測
  • 可復用性: 組件可在其他頁面復用
  • 開發效率: 預期提升60%

💡 長期效益

  • 新功能開發: 加速50%
  • Bug修復: 時間減少70%
  • 協作效率: 減少衝突80%
  • 代碼review: 時間減少60%

⚠️ 風險控制

🔴 主要風險

  1. 狀態管理複雜化: 跨組件狀態傳遞
  2. 功能回歸: 重構過程中遺失功能
  3. 性能影響: 組件拆分可能影響渲染效能

🛡️ 緩解策略

  1. 漸進式拆分: 一天一個組件,逐步驗證
  2. 功能測試: 每步完成後立即測試
  3. Git備份: 每日提交,保證可回滾
  4. 性能監控: 使用React DevTools監控性能

🎉 成功指標

📈 技術指標

  • 主檔案 <150行
  • 組件平均 <120行
  • 編譯時間 <3秒
  • 測試覆蓋率 >80%

💼 業務指標

  • 功能完整性 100%
  • 用戶體驗無變化
  • 頁面載入速度保持
  • 無新Bug產生

👥 團隊指標

  • 代碼review時間減少50%
  • 新功能開發時間減少40%
  • Bug修復時間減少60%

📊 重構進度總覽 (更新至 2025-10-01 18:35)

已完成階段

  • 基礎設施建立: 工具函數庫、基礎組件創建
  • 組件架構整合: 統一組件管理結構
  • Day 1部分完成: 2個核心組件準備就緒

⚠️ 待完成工作

  • 主頁面重構: 878行代碼的實際拆分整合
  • 內聯邏輯替換: 將內聯組件替換為模組化組件
  • 完整測試驗證: 確保功能完整性

💡 後續建議

由於主頁面重構是大型工作,建議:

  1. 先提交當前基礎設施成果
  2. 後續專門安排時間完成完整重構
  3. 現階段已為重構奠定了堅實基礎

生成時間: 2025-10-01 18:25 預估完成: 2025-10-05 風險等級: 🟡 中等風險 (有詳細計劃) 建議執行: 立即開始