import { UserSolution } from "@/interfaces/exam"; import useExamStore from "@/stores/exam"; import axios from "axios"; import { useEffect, useRef } from "react"; import { useRouter } from "next/router"; const useEvaluationPolling = (sessionIds: string[], mode: "exam" | "records", userId: string) => { const { setUserSolutions, userSolutions } = useExamStore(); const pollingTimeoutsRef = useRef>(new Map()); const router = useRouter(); const poll = async (sessionId: string) => { try { const { data: statusData } = await axios.get('/api/evaluate/status', { params: { op: 'pending', userId, sessionId } }); if (!statusData.hasPendingEvaluation) { let solutionsOrStats = userSolutions; if (mode === "records") { const res = await axios.get(`/api/stats/session/${sessionId}`) solutionsOrStats = res.data; } const { data: completedSolutions } = await axios.post('/api/evaluate/fetchSolutions?op=session', { sessionId, userId, stats: solutionsOrStats, }); await axios.post('/api/stats/disabled', { sessionId, userId, solutions: completedSolutions, }); const timeout = pollingTimeoutsRef.current.get(sessionId); if (timeout) clearTimeout(timeout); pollingTimeoutsRef.current.delete(sessionId); if (mode === "exam") { const updatedSolutions = userSolutions.map(solution => { const completed = completedSolutions.find( (c: UserSolution) => c.exercise === solution.exercise ); return completed || solution; }); setUserSolutions(updatedSolutions); } else { router.reload(); } } else { if (pollingTimeoutsRef.current.has(sessionId)) { clearTimeout(pollingTimeoutsRef.current.get(sessionId)); } pollingTimeoutsRef.current.set( sessionId, setTimeout(() => poll(sessionId), 5000) ); } } catch (error) { if (pollingTimeoutsRef.current.has(sessionId)) { clearTimeout(pollingTimeoutsRef.current.get(sessionId)); } pollingTimeoutsRef.current.set( sessionId, setTimeout(() => poll(sessionId), 5000) ); } }; useEffect(() => { if (mode === "exam") { const hasDisabledSolutions = userSolutions.some(s => s.isDisabled); if (hasDisabledSolutions && sessionIds.length > 0) { poll(sessionIds[0]); } else { pollingTimeoutsRef.current.forEach((timeout) => { clearTimeout(timeout); }); pollingTimeoutsRef.current.clear(); } } // eslint-disable-next-line react-hooks/exhaustive-deps }, [mode, sessionIds, userSolutions]); useEffect(() => { if (mode === "records" && sessionIds.length > 0) { sessionIds.forEach(sessionId => { poll(sessionId); }); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [mode, sessionIds]); useEffect(() => { const timeouts = pollingTimeoutsRef.current; return () => { timeouts.forEach((timeout) => { clearTimeout(timeout); }); timeouts.clear(); }; }, []); return { isPolling: pollingTimeoutsRef.current.size > 0 }; }; export default useEvaluationPolling;