dramaling-vocab-learning/frontend/app/review-simple/components/SimpleProgress.tsx

135 lines
5.4 KiB
TypeScript

import { CardState } from '../data'
interface SimpleProgressProps {
current: number
total: number
score: { correct: number; total: number }
cards?: CardState[] // 可選:用於顯示延遲統計
sortedCards?: CardState[] // 智能排序後的卡片
currentCard?: CardState // 當前正在練習的卡片
}
export function SimpleProgress({ current, total, score, cards, sortedCards, currentCard }: SimpleProgressProps) {
const progress = (current - 1) / total * 100
const accuracy = score.total > 0 ? Math.round((score.correct / score.total) * 100) : 0
// 延遲統計計算
const delayStats = cards ? {
totalSkips: cards.reduce((sum, card) => sum + card.skipCount, 0),
totalWrongs: cards.reduce((sum, card) => sum + card.wrongCount, 0),
delayedCards: cards.filter(card => card.skipCount + card.wrongCount > 0).length
} : null
return (
<div className="mb-8">
<div className="flex justify-between items-center mb-3">
<span className="text-sm font-medium text-gray-600"></span>
<div className="flex items-center gap-4 text-sm">
<span className="text-gray-600">
{current}/{total}
</span>
{score.total > 0 && (
<span className="text-green-600 font-medium">
{accuracy}%
</span>
)}
</div>
</div>
{/* 進度條 */}
<div className="w-full bg-gray-200 rounded-full h-3">
<div
className="bg-blue-500 h-3 rounded-full transition-all duration-300"
style={{ width: `${progress}%` }}
/>
</div>
{/* 詳細統計 */}
<div className="flex justify-center gap-4 mt-3 text-sm">
{score.total > 0 && (
<>
<div className="flex items-center gap-1">
<span className="w-2 h-2 bg-green-500 rounded-full"></span>
<span className="text-green-700"> {score.correct}</span>
</div>
<div className="flex items-center gap-1">
<span className="w-2 h-2 bg-red-500 rounded-full"></span>
<span className="text-red-700"> {score.total - score.correct}</span>
</div>
</>
)}
{/* 延遲統計 */}
{delayStats && (delayStats.totalSkips > 0 || delayStats.totalWrongs > 0) && (
<>
{score.total > 0 && <span className="text-gray-400">|</span>}
<div className="flex items-center gap-1">
<span className="w-2 h-2 bg-yellow-500 rounded-full"></span>
<span className="text-yellow-700"> {delayStats.totalSkips}</span>
</div>
<div className="flex items-center gap-1">
<span className="w-2 h-2 bg-blue-500 rounded-full"></span>
<span className="text-blue-700"> {delayStats.delayedCards}</span>
</div>
</>
)}
</div>
{/* 詞彙順序可視化 - 便於驗證延遲計數系統 */}
{sortedCards && currentCard && (
<div className="mt-4">
<div className="bg-white/50 rounded-lg p-3">
<p className="text-sm text-gray-600 mb-2"> ():</p>
<div className="flex flex-wrap gap-2">
{sortedCards.map((card, index) => {
const isCompleted = card.isCompleted
const delayScore = card.skipCount + card.wrongCount
// 狀態顏色
let cardStyle = ''
let statusText = ''
if (isCompleted) {
cardStyle = 'bg-green-100 text-green-700 border-green-300'
statusText = '✓'
} else if (delayScore > 0) {
if (card.skipCount > 0 && card.wrongCount > 0) {
cardStyle = 'bg-red-100 text-red-700 border-red-300'
statusText = `${card.skipCount}${card.wrongCount}`
} else if (card.skipCount > 0) {
cardStyle = 'bg-yellow-100 text-yellow-700 border-yellow-300'
statusText = `${card.skipCount}`
} else {
cardStyle = 'bg-orange-100 text-orange-700 border-orange-300'
statusText = `${card.wrongCount}`
}
} else {
cardStyle = 'bg-gray-100 text-gray-600 border-gray-300'
statusText = ''
}
return (
<div
key={card.id}
className={`px-3 py-2 rounded-lg border text-sm font-medium ${cardStyle}`}
>
<div className="flex items-center gap-1">
<span>{index + 1}.</span>
<span className="font-semibold">{card.word}</span>
{statusText && (
<span className="text-xs">({statusText})</span>
)}
</div>
</div>
)
})}
</div>
<p className="text-xs text-gray-500 mt-2 text-right">
🟢🟡🟠🔴+
</p>
</div>
</div>
)}
</div>
)
}