129 lines
4.7 KiB
TypeScript
129 lines
4.7 KiB
TypeScript
interface TestItem {
|
|
id: string
|
|
cardId: string
|
|
word: string
|
|
testType: string
|
|
testName: string
|
|
isCompleted: boolean
|
|
isCurrent: boolean
|
|
order: number
|
|
}
|
|
|
|
interface TaskListModalProps {
|
|
isOpen: boolean
|
|
onClose: () => void
|
|
testItems: TestItem[]
|
|
completedTests: number
|
|
totalTests: number
|
|
}
|
|
|
|
export const TaskListModal: React.FC<TaskListModalProps> = ({
|
|
isOpen,
|
|
onClose,
|
|
testItems,
|
|
completedTests,
|
|
totalTests
|
|
}) => {
|
|
if (!isOpen) return null
|
|
|
|
const progressPercentage = totalTests > 0 ? Math.round((completedTests / totalTests) * 100) : 0
|
|
const completedCount = testItems.filter(item => item.isCompleted).length
|
|
const currentCount = testItems.filter(item => item.isCurrent).length
|
|
const pendingCount = testItems.filter(item => !item.isCompleted && !item.isCurrent).length
|
|
|
|
return (
|
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
|
<div className="bg-white rounded-xl shadow-2xl max-w-4xl w-full mx-4 max-h-[80vh] overflow-hidden">
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between p-6 border-b border-gray-200">
|
|
<h2 className="text-2xl font-bold text-gray-900 flex items-center gap-2">
|
|
📚 學習任務清單
|
|
</h2>
|
|
<button
|
|
onClick={onClose}
|
|
className="text-gray-400 hover:text-gray-600 text-2xl"
|
|
>
|
|
✕
|
|
</button>
|
|
</div>
|
|
|
|
{/* Content */}
|
|
<div className="p-6 overflow-y-auto max-h-[60vh]">
|
|
{/* 進度統計 */}
|
|
<div className="mb-6 bg-blue-50 rounded-lg p-4">
|
|
<div className="flex items-center justify-between text-sm">
|
|
<span className="text-blue-900 font-medium">
|
|
測驗進度: {completedTests} / {totalTests} ({progressPercentage}%)
|
|
</span>
|
|
<div className="flex items-center gap-4 text-blue-800">
|
|
<span>✅ 已完成: {completedCount}</span>
|
|
<span>⏳ 進行中: {currentCount}</span>
|
|
<span>⚪ 待完成: {pendingCount}</span>
|
|
</div>
|
|
</div>
|
|
<div className="mt-3 w-full bg-blue-200 rounded-full h-2">
|
|
<div
|
|
className="bg-blue-600 h-2 rounded-full transition-all"
|
|
style={{ width: `${progressPercentage}%` }}
|
|
></div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 測驗清單 */}
|
|
<div className="space-y-4">
|
|
{testItems.length > 0 ? (
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
|
|
{testItems.map((item) => (
|
|
<div
|
|
key={item.id}
|
|
className={`flex items-center gap-3 p-3 rounded-lg transition-all ${
|
|
item.isCompleted
|
|
? 'bg-green-50 border border-green-200'
|
|
: item.isCurrent
|
|
? 'bg-blue-50 border border-blue-300 shadow-sm'
|
|
: 'bg-gray-50 border border-gray-200'
|
|
}`}
|
|
>
|
|
{/* 狀態圖標 */}
|
|
<span className="text-lg">
|
|
{item.isCompleted ? '✅' : item.isCurrent ? '⏳' : '⚪'}
|
|
</span>
|
|
|
|
{/* 測驗資訊 */}
|
|
<div className="flex-1">
|
|
<div className="font-medium text-sm">
|
|
{item.order}. {item.word} - {item.testName}
|
|
</div>
|
|
<div className={`text-xs ${
|
|
item.isCompleted ? 'text-green-600' :
|
|
item.isCurrent ? 'text-blue-600' : 'text-gray-500'
|
|
}`}>
|
|
{item.isCompleted ? '已完成' :
|
|
item.isCurrent ? '進行中' : '待完成'}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
) : (
|
|
<div className="text-center py-8 text-gray-500">
|
|
<div className="text-4xl mb-2">📚</div>
|
|
<p>還沒有生成任務清單</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Footer */}
|
|
<div className="px-6 py-4 border-t border-gray-200 bg-gray-50">
|
|
<button
|
|
onClick={onClose}
|
|
className="w-full py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
|
|
>
|
|
關閉
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
} |