110 lines
3.1 KiB
TypeScript
110 lines
3.1 KiB
TypeScript
import { create } from 'zustand'
|
|
import { subscribeWithSelector } from 'zustand/middleware'
|
|
import { flashcardsService } from '@/lib/services/flashcards'
|
|
import { ReviewMode } from './useTestQueueStore'
|
|
|
|
// 測試結果狀態接口
|
|
interface TestResultState {
|
|
// 分數狀態
|
|
score: { correct: number; total: number }
|
|
|
|
// 測試進行狀態
|
|
isRecordingResult: boolean
|
|
recordingError: string | null
|
|
|
|
// Actions
|
|
updateScore: (isCorrect: boolean) => void
|
|
resetScore: () => void
|
|
recordTestResult: (params: {
|
|
flashcardId: string
|
|
testType: ReviewMode
|
|
isCorrect: boolean
|
|
userAnswer?: string
|
|
confidenceLevel?: number
|
|
responseTimeMs?: number
|
|
}) => Promise<boolean>
|
|
setRecordingResult: (isRecording: boolean) => void
|
|
setRecordingError: (error: string | null) => void
|
|
|
|
// 統計方法
|
|
getAccuracyPercentage: () => number
|
|
getTotalAttempts: () => number
|
|
}
|
|
|
|
export const useTestResultStore = create<TestResultState>()(
|
|
subscribeWithSelector((set, get) => ({
|
|
// 初始狀態
|
|
score: { correct: 0, total: 0 },
|
|
isRecordingResult: false,
|
|
recordingError: null,
|
|
|
|
// Actions
|
|
updateScore: (isCorrect) => {
|
|
set(state => ({
|
|
score: {
|
|
correct: isCorrect ? state.score.correct + 1 : state.score.correct,
|
|
total: state.score.total + 1
|
|
}
|
|
}))
|
|
},
|
|
|
|
resetScore: () => set({
|
|
score: { correct: 0, total: 0 },
|
|
recordingError: null
|
|
}),
|
|
|
|
recordTestResult: async (params) => {
|
|
const { setRecordingResult, setRecordingError } = get()
|
|
|
|
try {
|
|
setRecordingResult(true)
|
|
setRecordingError(null)
|
|
|
|
console.log('🔄 開始記錄測驗結果...', {
|
|
flashcardId: params.flashcardId,
|
|
testType: params.testType,
|
|
isCorrect: params.isCorrect
|
|
})
|
|
|
|
const result = await flashcardsService.recordTestCompletion({
|
|
flashcardId: params.flashcardId,
|
|
testType: params.testType,
|
|
isCorrect: params.isCorrect,
|
|
userAnswer: params.userAnswer,
|
|
confidenceLevel: params.confidenceLevel,
|
|
responseTimeMs: params.responseTimeMs || 2000
|
|
})
|
|
|
|
if (result.success) {
|
|
console.log('✅ 測驗結果已記錄')
|
|
return true
|
|
} else {
|
|
console.error('❌ 記錄測驗結果失敗:', result.error)
|
|
setRecordingError('記錄測驗結果失敗')
|
|
return false
|
|
}
|
|
} catch (error) {
|
|
console.error('💥 記錄測驗結果異常:', error)
|
|
setRecordingError('記錄測驗結果異常')
|
|
return false
|
|
} finally {
|
|
setRecordingResult(false)
|
|
}
|
|
},
|
|
|
|
setRecordingResult: (isRecording) => set({ isRecordingResult: isRecording }),
|
|
|
|
setRecordingError: (error) => set({ recordingError: error }),
|
|
|
|
// 統計方法
|
|
getAccuracyPercentage: () => {
|
|
const { score } = get()
|
|
return score.total > 0 ? Math.round((score.correct / score.total) * 100) : 0
|
|
},
|
|
|
|
getTotalAttempts: () => {
|
|
const { score } = get()
|
|
return score.total
|
|
}
|
|
}))
|
|
) |