'use client' import { useState, useEffect } from 'react' import Link from 'next/link' import { ProtectedRoute } from '@/components/ProtectedRoute' import { Navigation } from '@/components/Navigation' import { FlashcardForm } from '@/components/FlashcardForm' import { useToast } from '@/components/Toast' // import { flashcardsService, type CardSet, type Flashcard } from '@/lib/services/flashcards' import { flashcardsService, type Flashcard } from '@/lib/services/flashcards' // 移除不需要的型別定義,直接使用 import 的 Flashcard 型別 import { useRouter } from 'next/navigation' function FlashcardsContent() { const router = useRouter() const toast = useToast() const [activeTab, setActiveTab] = useState('all-cards') // const [selectedSet, setSelectedSet] = useState(null) // 移除 CardSets 相關 const [searchTerm, setSearchTerm] = useState('') const [showAdvancedSearch, setShowAdvancedSearch] = useState(false) const [searchFilters, setSearchFilters] = useState({ cefrLevel: '', partOfSpeech: '', masteryLevel: '', onlyFavorites: false }) // Real data from API // const [cardSets, setCardSets] = useState([]) // 移除 CardSets 狀態 const [flashcards, setFlashcards] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [totalCounts, setTotalCounts] = useState({ all: 0, favorites: 0 }) // 臨時使用學習功能的例句圖片作為測試 const getExampleImage = (word: string): string => { const availableImages = [ '/images/examples/bring_up.png', '/images/examples/instinct.png', '/images/examples/warrant.png' ] const imageMap: {[key: string]: string} = { 'brought': '/images/examples/bring_up.png', 'instincts': '/images/examples/instinct.png', 'warrants': '/images/examples/warrant.png', 'hello': '/images/examples/bring_up.png', 'beautiful': '/images/examples/instinct.png', 'understand': '/images/examples/warrant.png', 'elaborate': '/images/examples/bring_up.png', 'sophisticated': '/images/examples/instinct.png', 'ubiquitous': '/images/examples/warrant.png' } // 根據詞彙返回對應圖片,如果沒有則根據字母分配 const mappedImage = imageMap[word?.toLowerCase()] if (mappedImage) return mappedImage // 根據首字母分配圖片 const firstChar = (word || 'a')[0].toLowerCase() const charCode = firstChar.charCodeAt(0) - 97 // a=0, b=1, c=2... const imageIndex = charCode % availableImages.length return availableImages[imageIndex] } // Form states const [showForm, setShowForm] = useState(false) const [editingCard, setEditingCard] = useState(null) // 移除假資料,現在完全使用真實 API 資料 // 載入總數統計 const loadTotalCounts = async () => { try { // 載入所有詞卡數量 const allResult = await flashcardsService.getFlashcards() const allCount = allResult.success && allResult.data ? allResult.data.count : 0 // 載入收藏詞卡數量 const favoritesResult = await flashcardsService.getFlashcards(undefined, true) const favoritesCount = favoritesResult.success && favoritesResult.data ? favoritesResult.data.count : 0 setTotalCounts({ all: allCount, favorites: favoritesCount }) } catch (err) { console.error('載入統計失敗:', err) } } // Load data from API useEffect(() => { // 載入詞卡和統計 loadFlashcards() loadTotalCounts() }, []) // 監聽搜尋和篩選條件變化,重新載入資料 useEffect(() => { const timeoutId = setTimeout(() => { loadFlashcards() }, 300) // 300ms 防抖 return () => clearTimeout(timeoutId) }, [searchTerm, searchFilters, activeTab]) // 暫時移除 CardSets 功能,直接設定空陣列 // const loadCardSets = async () => { // setCardSets([]) // } const loadFlashcards = async () => { try { setLoading(true) setError(null) // 清除之前的錯誤 // 使用進階篩選參數呼叫 API const result = await flashcardsService.getFlashcards( searchTerm || undefined, activeTab === 'favorites', searchFilters.cefrLevel || undefined, searchFilters.partOfSpeech || undefined, searchFilters.masteryLevel || undefined ) if (result.success && result.data) { setFlashcards(result.data.flashcards) console.log('✅ 詞卡載入成功:', result.data.flashcards.length, '個詞卡') } else { setError(result.error || 'Failed to load flashcards') console.error('❌ 詞卡載入失敗:', result.error) } } catch (err) { const errorMessage = 'Failed to load flashcards' setError(errorMessage) console.error('❌ 詞卡載入異常:', err) } finally { setLoading(false) } } // 移除 selectedSet 依賴的 useEffect // useEffect(() => { // loadFlashcards() // }, [selectedSet]) // Handle form operations const handleFormSuccess = async () => { setShowForm(false) setEditingCard(null) await loadFlashcards() await loadTotalCounts() // 移除 loadCardSets() 調用 } const handleEdit = (card: Flashcard) => { setEditingCard(card) setShowForm(true) } const handleDelete = async (card: Flashcard) => { if (!confirm(`確定要刪除詞卡「${card.word}」嗎?`)) { return } try { const result = await flashcardsService.deleteFlashcard(card.id) if (result.success) { await loadFlashcards() await loadTotalCounts() toast.success(`詞卡「${card.word}」已刪除`) } else { toast.error(result.error || '刪除失敗') } } catch (err) { toast.error('刪除失敗,請重試') } } const handleToggleFavorite = async (card: any) => { try { // 如果是假資料,只更新本地狀態 if (card.id.startsWith('mock')) { // 模擬資料暫時只顯示提示,實際狀態更新需要實作 toast.success(`${card.isFavorite ? '已取消收藏' : '已加入收藏'}「${card.word}」`) return } // 真實API調用 const result = await flashcardsService.toggleFavorite(card.id) if (result.success) { // 重新載入詞卡以反映最新的收藏狀態 await loadFlashcards() // 重新載入統計數量 await loadTotalCounts() toast.success(`${card.isFavorite ? '已取消收藏' : '已加入收藏'}「${card.word}」`) } else { toast.error(result.error || '操作失敗') } } catch (err) { toast.error('操作失敗,請重試') } } // 獲取CEFR等級顏色 const getCEFRColor = (level: string) => { switch (level) { case 'A1': return 'bg-green-100 text-green-700 border-green-200' // 淺綠 - 最基礎 case 'A2': return 'bg-blue-100 text-blue-700 border-blue-200' // 淺藍 - 基礎 case 'B1': return 'bg-yellow-100 text-yellow-700 border-yellow-200' // 淺黃 - 中級 case 'B2': return 'bg-orange-100 text-orange-700 border-orange-200' // 淺橙 - 中高級 case 'C1': return 'bg-red-100 text-red-700 border-red-200' // 淺紅 - 高級 case 'C2': return 'bg-purple-100 text-purple-700 border-purple-200' // 淺紫 - 精通 default: return 'bg-gray-100 text-gray-700 border-gray-200' // 預設灰色 } } // 由於後端已處理篩選,直接使用 API 回傳的結果 const filteredCards = flashcards // 直接使用從 API 取得的已篩選結果 // 清除所有篩選 const clearAllFilters = () => { setSearchTerm('') setSearchFilters({ cefrLevel: '', partOfSpeech: '', masteryLevel: '', onlyFavorites: false }) } // 檢查是否有活動篩選 const hasActiveFilters = searchTerm || searchFilters.cefrLevel || searchFilters.partOfSpeech || searchFilters.masteryLevel || searchFilters.onlyFavorites // 搜尋結果高亮函數 const highlightSearchTerm = (text: string, searchTerm: string) => { if (!searchTerm || !text) return text const regex = new RegExp(`(${searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi') const parts = text.split(regex) return parts.map((part, index) => regex.test(part) ? ( {part} ) : ( part ) ) } // Add loading and error states if (loading) { return (
載入中...
) } if (error) { return (
{error}
) } return (
{/* Navigation */} {/* Main Content */}
{/* Page Header */}

我的詞卡

AI 生成詞卡
{/* 簡化的Tabs - 移除卡組功能 */}
{/* 進階搜尋區域 */}

搜尋詞卡

{/* 主要搜尋框 */}
setSearchTerm(e.target.value)} placeholder="搜尋詞彙、翻譯或定義..." className="w-full pl-12 pr-20 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent text-base" onKeyDown={(e) => { if (e.key === 'Escape') { setSearchTerm('') } }} />
{(searchTerm || hasActiveFilters) && (
{filteredCards.length} 結果
)}
{/* 進階篩選選項 */} {showAdvancedSearch && (
{/* CEFR等級篩選 */}
{/* 詞性篩選 */}
{/* 掌握度篩選 */}
{/* 收藏篩選 */}
{/* 快速篩選按鈕 */}
快速篩選: {hasActiveFilters && ( )}
)} {/* 搜尋結果統計 */} {(searchTerm || hasActiveFilters) && (
找到 {filteredCards.length} 個詞卡 {searchTerm && ( ,包含 "{searchTerm}" )}
{hasActiveFilters && ( )}
)}
{/* Favorites Tab */} {activeTab === 'favorites' && (

共 {filteredCards.length} 個詞卡

{filteredCards.length === 0 ? (

還沒有收藏的詞卡

在詞卡列表中點擊星星按鈕來收藏重要的詞彙

) : (
{filteredCards.map(card => (
{/* 收藏詞卡內容 - 與普通詞卡相同的佈局 */}
{(card as any).difficultyLevel || 'A1'}
{`${card.word} { const target = e.target as HTMLImageElement target.style.display = 'none' target.parentElement!.innerHTML = `
例句圖
` }} />

{searchTerm ? highlightSearchTerm(card.word || '未設定', searchTerm) : (card.word || '未設定')}

{card.partOfSpeech || 'unknown'}
{searchTerm ? highlightSearchTerm(card.translation || '未設定', searchTerm) : (card.translation || '未設定')} {card.pronunciation && (
{card.pronunciation}
)}
創建: {new Date(card.createdAt).toLocaleDateString()} 掌握度: {card.masteryLevel}%
{/* 右側:重新設計的操作按鈕區 */}
{/* 收藏按鈕 */} {/* 編輯按鈕 */} {/* 刪除按鈕 */} {/* 查看詳情按鈕 - 導航到詳細頁面 */}
))}
)}
)} {/* All Cards Tab */} {activeTab === 'all-cards' && (

共 {filteredCards.length} 個詞卡

{filteredCards.length === 0 ? (

沒有找到詞卡

創建新詞卡
) : (
{filteredCards.map(card => (
{/* 詞卡右上角CEFR標註 */}
{(card as any).difficultyLevel || 'A1'}
{/* 左側:詞彙基本信息 */}
{/* 例句圖片 - 超大尺寸 */}
{`${card.word} { // 圖片載入失敗時顯示佔位符 const target = e.target as HTMLImageElement target.style.display = 'none' target.parentElement!.innerHTML = `
例句圖
` }} />

{searchTerm ? highlightSearchTerm(card.word || '未設定', searchTerm) : (card.word || '未設定')}

{card.partOfSpeech || 'unknown'}
{searchTerm ? highlightSearchTerm(card.translation || '未設定', searchTerm) : (card.translation || '未設定')} {card.pronunciation && (
{card.pronunciation}
)}
{/* 簡要統計 */}
創建: {new Date(card.createdAt).toLocaleDateString()} 掌握度: {card.masteryLevel}%
{/* 右側:操作按鈕 */}
{/* 重新設計的操作按鈕區 */}
{/* 收藏按鈕 */} {/* 編輯按鈕 */} {/* 刪除按鈕 */} {/* 查看詳情按鈕 - 導航到詳細頁面 */}
))}
)}
)}
{/* Flashcard Form Modal */} {showForm && ( { setShowForm(false) setEditingCard(null) }} /> )} {/* Toast 通知系統 */}
) } export default function FlashcardsPage() { return ( ) }