Spaces:
Running
Running
File size: 2,884 Bytes
ebab432 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | import { useCallback, useEffect, useRef, useState } from 'react'
export default function useTestAnswerState({
current,
questions,
currentQuestion,
answersRef,
timingsRef,
}) {
const [answers, setAnswers] = useState({})
const [timings, setTimings] = useState({})
const [marked, setMarked] = useState(new Set())
const [visited, setVisited] = useState(new Set())
const [natInput, setNatInput] = useState('')
const questionStartRef = useRef(Date.now())
// Per-question elapsed timing effect
useEffect(() => {
const q = questions[current]
if (!q) return
questionStartRef.current = Date.now()
return () => {
const elapsed = Math.floor((Date.now() - questionStartRef.current) / 1000)
if (elapsed > 0) {
setTimings(t => {
const updated = { ...t, [q.id]: (t[q.id] || 0) + elapsed }
timingsRef.current = updated
return updated
})
}
}
}, [current, questions, timingsRef])
// Visited tracking effect
useEffect(() => {
const q = questions[current]
if (q) setVisited(v => new Set([...v, q.id]))
}, [current, questions])
// NAT input sync effect
useEffect(() => {
const q = questions[current]
if (q?.question_type === 'nat') setNatInput(answers[q.id] || '')
}, [current, questions, answers])
const setMCQ = useCallback((letter) => {
if (!currentQuestion) return
setAnswers(a => {
const updated = { ...a, [currentQuestion.id]: a[currentQuestion.id] === letter ? undefined : letter }
answersRef.current = updated
return updated
})
}, [currentQuestion, answersRef])
const toggleMSQ = useCallback((letter) => {
if (!currentQuestion) return
setAnswers(a => {
const cur = (a[currentQuestion.id] || '').split(',').filter(Boolean)
const next = cur.includes(letter) ? cur.filter(l => l !== letter) : [...cur, letter].sort()
const updated = { ...a, [currentQuestion.id]: next.join(',') || undefined }
answersRef.current = updated
return updated
})
}, [currentQuestion, answersRef])
const commitNAT = useCallback(() => {
if (!currentQuestion) return
setAnswers(a => {
const updated = { ...a, [currentQuestion.id]: natInput.trim() || undefined }
answersRef.current = updated
return updated
})
}, [currentQuestion, natInput, answersRef])
const clearResponse = useCallback(() => {
if (!currentQuestion) return
setAnswers(a => {
const n = { ...a }
delete n[currentQuestion.id]
answersRef.current = n
return n
})
setNatInput('')
}, [currentQuestion, answersRef])
return {
answers,
setAnswers,
timings,
setTimings,
marked,
setMarked,
visited,
setVisited,
natInput,
setNatInput,
setMCQ,
toggleMSQ,
commitNAT,
clearResponse,
questionStartRef,
}
} |