diff --git a/Learn重命名為Review計劃.md b/Learn重命名為Review計劃.md new file mode 100644 index 0000000..dbe1ae8 --- /dev/null +++ b/Learn重命名為Review計劃.md @@ -0,0 +1,171 @@ +# Learn → Review 重命名計劃 + +**建立日期**: 2025-09-27 +**目的**: 將所有 learn 相關命名改為 review,使程式碼語義更清晰準確 + +--- + +## 📋 需要重命名的項目盤點 + +### **1. 目錄結構重命名** + +#### **主要目錄** +``` +FROM TO +/frontend/app/learn/ → /frontend/app/review/ +/frontend/components/learn/ → /frontend/components/review/ +/frontend/hooks/learn/ → /frontend/hooks/review/ +/frontend/lib/services/learn/ → /frontend/lib/services/review/ +``` + +#### **子目錄重命名** +``` +FROM TO +/components/learn/tests/ → /components/review/review-tests/ +``` + +### **2. 檔案重命名** + +#### **核心檔案** +``` +FROM TO +useLearnStore.ts → useReviewStore.ts +learnService.ts → reviewService.ts +TestRunner.tsx → ReviewRunner.tsx +``` + +#### **組件檔案 (可選重命名)** +``` +FROM TO +ProgressTracker.tsx → ReviewProgressTracker.tsx +TaskListModal.tsx → ReviewTaskListModal.tsx +LoadingStates.tsx → ReviewLoadingStates.tsx +``` + +### **3. 程式碼內容修改** + +#### **Import 路徑修改** +需要更新以下檔案中的import: +- `/app/learn/page.tsx` (8個import) +- `/components/learn/TestRunner.tsx` (2個import) +- `/lib/services/learn/learnService.ts` (1個import) + +```typescript +// FROM +import { ProgressTracker } from '@/components/learn/ProgressTracker' +import { useLearnStore } from '@/store/useLearnStore' +import { LearnService } from '@/lib/services/learn/learnService' + +// TO +import { ReviewProgressTracker } from '@/components/review/ReviewProgressTracker' +import { useReviewStore } from '@/store/useReviewStore' +import { ReviewService } from '@/lib/services/review/reviewService' +``` + +#### **類別和介面重命名** +```typescript +// FROM → TO +useLearnStore → useReviewStore +LearnState → ReviewState +LearnService → ReviewService +TestRunner → ReviewRunner + +// 函數名稱 +initializeLearnSession → initializeReviewSession +loadDueCards → loadDueReviewCards (可選) +``` + +#### **註解和文字更新** +所有註解中的 "learn" 改為 "review": +```typescript +// FROM +// 學習會話狀態 +// 載入到期詞卡 +// 初始化學習會話 + +// TO +// 複習會話狀態 +// 載入到期複習詞卡 +// 初始化複習會話 +``` + +### **4. 特殊考量** + +#### **URL路由保持不變** +- **用戶訪問**: 仍然是 `http://localhost:3000/learn` +- **檔案路徑**: `/app/review/page.tsx` (內部重命名) +- **Next.js**: 需要考慮路由映射問題 + +#### **外部引用檢查** +需要檢查是否有其他檔案引用了learn相關組件: +- Navigation.tsx 中的 learn 連結 +- Dashboard.tsx 中的 learn 按鈕 +- 其他頁面的跳轉邏輯 + +--- + +## 🚀 執行順序 + +### **階段一:目錄和檔案重命名** (15分鐘) +1. 重命名主要目錄結構 +2. 重命名核心檔案 +3. 更新檔案的export名稱 + +### **階段二:程式碼內容更新** (20分鐘) +1. 更新所有import路徑 +2. 重命名類別和介面 +3. 更新函數和變數名稱 +4. 更新註解和字串 + +### **階段三:路由配置** (10分鐘) +1. 確認Next.js路由正常運作 +2. 檢查外部引用是否正確 +3. 測試頁面是否正常載入 + +### **階段四:測試和驗證** (15分鐘) +1. 檢查編譯是否通過 +2. 測試功能是否正常 +3. 確認沒有遺漏的引用 + +--- + +## ⚠️ 風險評估 + +### **低風險項目** +- 內部檔案重命名 +- 註解和字串更新 +- 組件內部邏輯 + +### **中風險項目** +- Import路徑更新 (可能遺漏) +- Store狀態管理 (需要仔細測試) + +### **注意事項** +- URL路由 `/learn` 保持不變 +- 確保所有依賴關係正確更新 +- 備份重要檔案以防萬一 + +--- + +## 📝 驗證清單 + +### **重命名完成檢查** +- [ ] 所有目錄重命名完成 +- [ ] 所有檔案重命名完成 +- [ ] 所有import路徑更新 +- [ ] 所有類別名稱更新 +- [ ] 所有函數名稱更新 + +### **功能測試** +- [ ] 頁面可以正常載入 +- [ ] 測驗組件正常顯示 +- [ ] 狀態管理正常運作 +- [ ] API調用正常 +- [ ] 錯誤處理正常 + +### **外部整合測試** +- [ ] Navigation導航正常 +- [ ] Dashboard跳轉正常 +- [ ] 路由映射正確 + +這個重命名將讓程式碼語義更清晰,`review`(複習) 比 `learn`(學習) 更精確地描述這個功能的本質。 \ No newline at end of file diff --git a/frontend/app/learn/page.tsx b/frontend/app/learn/page.tsx index b5a3194..93cf57b 100644 --- a/frontend/app/learn/page.tsx +++ b/frontend/app/learn/page.tsx @@ -7,15 +7,15 @@ import LearningComplete from '@/components/LearningComplete' import { Modal } from '@/components/ui/Modal' // 新架構組件 -import { ProgressTracker } from '@/components/learn/ProgressTracker' -import { TaskListModal } from '@/components/learn/TaskListModal' -import { LoadingStates } from '@/components/learn/LoadingStates' -import { TestRunner } from '@/components/learn/TestRunner' +import { ProgressTracker } from '@/components/review/ProgressTracker' +import { TaskListModal } from '@/components/review/TaskListModal' +import { LoadingStates } from '@/components/review/LoadingStates' +import { ReviewRunner } from '@/components/review/ReviewRunner' // 狀態管理 -import { useLearnStore } from '@/store/useLearnStore' +import { useReviewStore } from '@/store/useReviewStore' import { useUIStore } from '@/store/useUIStore' -import { LearnService } from '@/lib/services/learn/learnService' +import { ReviewService } from '@/lib/services/review/reviewService' export default function LearnPage() { const router = useRouter() @@ -37,7 +37,7 @@ export default function LearnPage() { loadDueCards, initializeTestQueue, resetSession - } = useLearnStore() + } = useReviewStore() const { showTaskListModal, @@ -64,11 +64,11 @@ export default function LearnPage() { if (dueCards.length > 0) { const cardIds = dueCards.map(c => c.id) - const completedTests = await LearnService.loadCompletedTests(cardIds) + const completedTests = await ReviewService.loadCompletedTests(cardIds) initializeTestQueue(completedTests) } } catch (error) { - console.error('初始化學習會話失敗:', error) + console.error('初始化複習會話失敗:', error) } } @@ -114,7 +114,7 @@ export default function LearnPage() { /> {/* 測驗執行器 */} - + {/* 任務清單Modal */} { + setMounted(true) + initializeSession() + }, []) + + // 初始化學習會話 + const initializeSession = async () => { + try { + await loadDueCards() + + if (dueCards.length > 0) { + const cardIds = dueCards.map(c => c.id) + const completedTests = await ReviewService.loadCompletedTests(cardIds) + initializeTestQueue(completedTests) + } + } catch (error) { + console.error('初始化複習會話失敗:', error) + } + } + + // 重新開始 + const handleRestart = async () => { + resetSession() + await initializeSession() + } + + // 載入狀態 + if (!mounted || isLoading) { + return ( + + ) + } + + if (showNoDueCards) { + return ( + + ) + } + + if (!currentCard) { + return + } + + return ( + + + + + {/* 進度追蹤 */} + setShowTaskListModal(true)} + /> + + {/* 測驗執行器 */} + + + {/* 任務清單Modal */} + setShowTaskListModal(false)} + testItems={testItems} + completedTests={completedTests} + totalTests={totalTests} + /> + + {/* 學習完成 */} + {showComplete && ( + router.push('/dashboard')} + /> + )} + + {/* 圖片Modal */} + {modalImage && ( + + + + + ✕ + + + + )} + + {/* 錯誤回報Modal */} + + + + + 單字:{reportingCard?.word} + + + + + + 錯誤類型 + + setReportReason(e.target.value)} + className="w-full p-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500" + > + 請選擇錯誤類型 + 翻譯錯誤 + 定義錯誤 + 發音錯誤 + 例句錯誤 + 圖片錯誤 + 其他 + + + + + + 取消 + + { + console.log('Report submitted:', { card: reportingCard, reason: reportReason }) + closeReportModal() + }} + disabled={!reportReason} + className="flex-1 px-4 py-2 bg-red-600 text-white rounded-md hover:bg-red-700 disabled:opacity-50 disabled:cursor-not-allowed" + > + 送出回報 + + + + + + + ) +} \ No newline at end of file diff --git a/frontend/components/Navigation.tsx b/frontend/components/Navigation.tsx index 87cd0fe..a8fd633 100644 --- a/frontend/components/Navigation.tsx +++ b/frontend/components/Navigation.tsx @@ -5,12 +5,8 @@ import Link from 'next/link' import { usePathname } from 'next/navigation' import { useAuth } from '@/contexts/AuthContext' -interface NavigationProps { - showExitLearning?: boolean - onExitLearning?: () => void -} -export function Navigation({ showExitLearning = false, onExitLearning }: NavigationProps = {}) { +export function Navigation() { const { user, logout } = useAuth() const pathname = usePathname() const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false) @@ -18,7 +14,7 @@ export function Navigation({ showExitLearning = false, onExitLearning }: Navigat const navItems = [ { href: '/dashboard', label: '儀表板' }, { href: '/flashcards', label: '詞卡' }, - { href: '/learn', label: '學習' }, + { href: '/learn', label: '複習' }, { href: '/generate', label: 'AI 生成' }, { href: '/settings', label: '⚙️ 設定' } ] @@ -64,17 +60,7 @@ export function Navigation({ showExitLearning = false, onExitLearning }: Navigat - {/* 學習模式的結束學習按鈕 */} - {showExitLearning ? ( - - × 結束學習 - - ) : ( - <> - {/* 通知按鈕 - 桌面和手機都顯示 */} + {/* 通知按鈕 - 桌面和手機都顯示 */} @@ -94,8 +80,6 @@ export function Navigation({ showExitLearning = false, onExitLearning }: Navigat 登出 - > - )} diff --git a/frontend/components/learn/LoadingStates.tsx b/frontend/components/review/LoadingStates.tsx similarity index 100% rename from frontend/components/learn/LoadingStates.tsx rename to frontend/components/review/LoadingStates.tsx diff --git a/frontend/components/learn/ProgressTracker.tsx b/frontend/components/review/ProgressTracker.tsx similarity index 100% rename from frontend/components/learn/ProgressTracker.tsx rename to frontend/components/review/ProgressTracker.tsx diff --git a/frontend/components/learn/ReviewContainer.tsx b/frontend/components/review/ReviewContainer.tsx similarity index 100% rename from frontend/components/learn/ReviewContainer.tsx rename to frontend/components/review/ReviewContainer.tsx diff --git a/frontend/components/learn/TestRunner.tsx b/frontend/components/review/ReviewRunner.tsx similarity index 92% rename from frontend/components/learn/TestRunner.tsx rename to frontend/components/review/ReviewRunner.tsx index 7a9f6ae..0a888b4 100644 --- a/frontend/components/learn/TestRunner.tsx +++ b/frontend/components/review/ReviewRunner.tsx @@ -1,5 +1,5 @@ import { useEffect } from 'react' -import { useLearnStore } from '@/store/useLearnStore' +import { useReviewStore } from '@/store/useReviewStore' import { useUIStore } from '@/store/useUIStore' import { FlipMemoryTest, @@ -9,20 +9,20 @@ import { VocabListeningTest, SentenceListeningTest, SentenceSpeakingTest -} from './tests' +} from './review-tests' interface TestRunnerProps { className?: string } -export const TestRunner: React.FC = ({ className }) => { +export const ReviewRunner: React.FC = ({ className }) => { const { currentCard, currentMode, updateScore, recordTestResult, error - } = useLearnStore() + } = useReviewStore() const { openReportModal, diff --git a/frontend/components/learn/TaskListModal.tsx b/frontend/components/review/TaskListModal.tsx similarity index 100% rename from frontend/components/learn/TaskListModal.tsx rename to frontend/components/review/TaskListModal.tsx diff --git a/frontend/components/learn/tests/FlipMemoryTest.tsx b/frontend/components/review/review-tests/FlipMemoryTest.tsx similarity index 100% rename from frontend/components/learn/tests/FlipMemoryTest.tsx rename to frontend/components/review/review-tests/FlipMemoryTest.tsx diff --git a/frontend/components/learn/tests/SentenceFillTest.tsx b/frontend/components/review/review-tests/SentenceFillTest.tsx similarity index 100% rename from frontend/components/learn/tests/SentenceFillTest.tsx rename to frontend/components/review/review-tests/SentenceFillTest.tsx diff --git a/frontend/components/learn/tests/SentenceListeningTest.tsx b/frontend/components/review/review-tests/SentenceListeningTest.tsx similarity index 100% rename from frontend/components/learn/tests/SentenceListeningTest.tsx rename to frontend/components/review/review-tests/SentenceListeningTest.tsx diff --git a/frontend/components/learn/tests/SentenceReorderTest.tsx b/frontend/components/review/review-tests/SentenceReorderTest.tsx similarity index 100% rename from frontend/components/learn/tests/SentenceReorderTest.tsx rename to frontend/components/review/review-tests/SentenceReorderTest.tsx diff --git a/frontend/components/learn/tests/SentenceSpeakingTest.tsx b/frontend/components/review/review-tests/SentenceSpeakingTest.tsx similarity index 100% rename from frontend/components/learn/tests/SentenceSpeakingTest.tsx rename to frontend/components/review/review-tests/SentenceSpeakingTest.tsx diff --git a/frontend/components/learn/tests/VocabChoiceTest.tsx b/frontend/components/review/review-tests/VocabChoiceTest.tsx similarity index 100% rename from frontend/components/learn/tests/VocabChoiceTest.tsx rename to frontend/components/review/review-tests/VocabChoiceTest.tsx diff --git a/frontend/components/learn/tests/VocabListeningTest.tsx b/frontend/components/review/review-tests/VocabListeningTest.tsx similarity index 100% rename from frontend/components/learn/tests/VocabListeningTest.tsx rename to frontend/components/review/review-tests/VocabListeningTest.tsx diff --git a/frontend/components/learn/tests/index.ts b/frontend/components/review/review-tests/index.ts similarity index 100% rename from frontend/components/learn/tests/index.ts rename to frontend/components/review/review-tests/index.ts diff --git a/frontend/hooks/learn/useProgressTracker.ts b/frontend/hooks/review/useProgressTracker.ts similarity index 100% rename from frontend/hooks/learn/useProgressTracker.ts rename to frontend/hooks/review/useProgressTracker.ts diff --git a/frontend/hooks/learn/useReviewSession.ts b/frontend/hooks/review/useReviewSession.ts similarity index 100% rename from frontend/hooks/learn/useReviewSession.ts rename to frontend/hooks/review/useReviewSession.ts diff --git a/frontend/hooks/learn/useTestAnswering.ts b/frontend/hooks/review/useTestAnswering.ts similarity index 100% rename from frontend/hooks/learn/useTestAnswering.ts rename to frontend/hooks/review/useTestAnswering.ts diff --git a/frontend/hooks/learn/useTestQueue.ts b/frontend/hooks/review/useTestQueue.ts similarity index 100% rename from frontend/hooks/learn/useTestQueue.ts rename to frontend/hooks/review/useTestQueue.ts diff --git a/frontend/lib/services/learn/learnService.ts b/frontend/lib/services/review/reviewService.ts similarity index 93% rename from frontend/lib/services/learn/learnService.ts rename to frontend/lib/services/review/reviewService.ts index 70eed42..4556990 100644 --- a/frontend/lib/services/learn/learnService.ts +++ b/frontend/lib/services/review/reviewService.ts @@ -1,8 +1,8 @@ import { flashcardsService } from '@/lib/services/flashcards' -import { ExtendedFlashcard, TestItem } from '@/store/useLearnStore' +import { ExtendedFlashcard, TestItem } from '@/store/useReviewStore' -// 學習會話服務 -export class LearnService { +// 複習會話服務 +export class ReviewService { // 載入到期詞卡 static async loadDueCards(limit = 50): Promise { try { diff --git a/frontend/store/useLearnStore.ts b/frontend/store/useReviewStore.ts similarity index 95% rename from frontend/store/useLearnStore.ts rename to frontend/store/useReviewStore.ts index fa1b0b6..03189e1 100644 --- a/frontend/store/useLearnStore.ts +++ b/frontend/store/useReviewStore.ts @@ -30,8 +30,8 @@ export interface TestItem { order: number } -// 學習會話狀態 -interface LearnState { +// 複習會話狀態 +interface ReviewState { // 核心狀態 mounted: boolean isLoading: boolean @@ -69,7 +69,7 @@ interface LearnState { setError: (error: string | null) => void } -export const useLearnStore = create()( +export const useReviewStore = create()( subscribeWithSelector((set, get) => ({ // 初始狀態 mounted: false,
+ 單字:{reportingCard?.word} +