119 lines
4.1 KiB
TypeScript
119 lines
4.1 KiB
TypeScript
import React, { useState } from 'react'
|
|
import { useTestQueueStore } from '@/store/useTestQueueStore'
|
|
import { useTestResultStore } from '@/store/useTestResultStore'
|
|
import { mockFlashcards, getTestStatistics, generateTestQueue } from '@/data/mockTestData'
|
|
|
|
interface TestDebugPanelProps {
|
|
className?: string
|
|
}
|
|
|
|
export const TestDebugPanel: React.FC<TestDebugPanelProps> = ({ className }) => {
|
|
const [isVisible, setIsVisible] = useState(false)
|
|
const { testItems, currentTestIndex, addTestItems, resetQueue } = useTestQueueStore()
|
|
const { totalCorrect, totalIncorrect, resetScore } = useTestResultStore()
|
|
|
|
const stats = getTestStatistics(mockFlashcards)
|
|
|
|
const handleLoadMockData = () => {
|
|
const queue = generateTestQueue(mockFlashcards)
|
|
addTestItems(queue.map(item => ({
|
|
flashcardId: item.card.id,
|
|
mode: item.mode,
|
|
priority: item.priority,
|
|
attempts: item.card.testAttempts || 0,
|
|
completed: false
|
|
})))
|
|
}
|
|
|
|
const handleResetAll = () => {
|
|
resetQueue()
|
|
resetScore()
|
|
}
|
|
|
|
if (!isVisible) {
|
|
return (
|
|
<button
|
|
onClick={() => setIsVisible(true)}
|
|
className="fixed bottom-4 right-4 bg-blue-600 text-white px-3 py-2 rounded-lg shadow-lg text-sm z-50"
|
|
>
|
|
🔧 調試
|
|
</button>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className={`fixed bottom-4 right-4 bg-white border border-gray-200 rounded-lg shadow-xl p-4 z-50 w-80 ${className}`}>
|
|
<div className="flex justify-between items-center mb-4">
|
|
<h3 className="font-semibold text-gray-800">測試調試面板</h3>
|
|
<button
|
|
onClick={() => setIsVisible(false)}
|
|
className="text-gray-500 hover:text-gray-700"
|
|
>
|
|
✕
|
|
</button>
|
|
</div>
|
|
|
|
{/* 當前進度 */}
|
|
<div className="mb-4 p-3 bg-gray-50 rounded">
|
|
<h4 className="font-medium text-sm mb-2">當前進度</h4>
|
|
<div className="text-xs space-y-1">
|
|
<div>隊列長度: {testItems.length}</div>
|
|
<div>當前位置: {currentTestIndex + 1}/{testItems.length}</div>
|
|
<div>正確: {totalCorrect} | 錯誤: {totalIncorrect}</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 測試數據統計 */}
|
|
<div className="mb-4 p-3 bg-blue-50 rounded">
|
|
<h4 className="font-medium text-sm mb-2">模擬數據統計</h4>
|
|
<div className="text-xs space-y-1">
|
|
<div>總卡片: {stats.total}</div>
|
|
<div>未測試: {stats.untested}</div>
|
|
<div>答錯: {stats.incorrect}</div>
|
|
<div>跳過: {stats.skipped}</div>
|
|
<div className="mt-2 text-gray-600">
|
|
優先級 - 高:{stats.priorities.high} 中:{stats.priorities.medium} 低:{stats.priorities.low}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 操作按鈕 */}
|
|
<div className="space-y-2">
|
|
<button
|
|
onClick={handleLoadMockData}
|
|
className="w-full bg-green-600 text-white py-2 px-3 rounded text-sm hover:bg-green-700"
|
|
>
|
|
載入真實測試數據 ({mockFlashcards.length} 卡片)
|
|
</button>
|
|
|
|
<button
|
|
onClick={handleResetAll}
|
|
className="w-full bg-red-600 text-white py-2 px-3 rounded text-sm hover:bg-red-700"
|
|
>
|
|
重置所有數據
|
|
</button>
|
|
</div>
|
|
|
|
{/* 隊列預覽 */}
|
|
{testItems.length > 0 && (
|
|
<div className="mt-4 p-3 bg-yellow-50 rounded">
|
|
<h4 className="font-medium text-sm mb-2">當前隊列預覽</h4>
|
|
<div className="text-xs max-h-32 overflow-y-auto">
|
|
{testItems.slice(0, 10).map((item, index) => (
|
|
<div
|
|
key={index}
|
|
className={`flex justify-between ${index === currentTestIndex ? 'font-bold text-blue-600' : ''}`}
|
|
>
|
|
<span>{item.mode}</span>
|
|
<span>P:{item.priority}</span>
|
|
</div>
|
|
))}
|
|
{testItems.length > 10 && (
|
|
<div className="text-gray-500">...還有 {testItems.length - 10} 項</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
} |