diff options
Diffstat (limited to 'makima/frontend/src/contexts/SupervisorQuestionsContext.tsx')
| -rw-r--r-- | makima/frontend/src/contexts/SupervisorQuestionsContext.tsx | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/makima/frontend/src/contexts/SupervisorQuestionsContext.tsx b/makima/frontend/src/contexts/SupervisorQuestionsContext.tsx new file mode 100644 index 0000000..aa1bb12 --- /dev/null +++ b/makima/frontend/src/contexts/SupervisorQuestionsContext.tsx @@ -0,0 +1,94 @@ +import { createContext, useContext, useState, useEffect, useCallback, ReactNode } from "react"; +import { listPendingQuestions, answerQuestion, type PendingQuestion } from "../lib/api"; +import { useAuth } from "./AuthContext"; + +interface SupervisorQuestionsContextValue { + pendingQuestions: PendingQuestion[]; + loading: boolean; + error: string | null; + refreshQuestions: () => Promise<void>; + submitAnswer: (questionId: string, response: string) => Promise<boolean>; +} + +const SupervisorQuestionsContext = createContext<SupervisorQuestionsContextValue | null>(null); + +export function SupervisorQuestionsProvider({ children }: { children: ReactNode }) { + const { isAuthenticated } = useAuth(); + const [pendingQuestions, setPendingQuestions] = useState<PendingQuestion[]>([]); + const [loading, setLoading] = useState(false); + const [error, setError] = useState<string | null>(null); + + const refreshQuestions = useCallback(async () => { + if (!isAuthenticated) return; + + try { + setLoading(true); + const questions = await listPendingQuestions(); + if (questions.length > 0) { + console.log("[SupervisorQuestions] Received questions:", questions); + } + setPendingQuestions(questions); + setError(null); + } catch (err) { + // Log but don't spam + console.warn("[SupervisorQuestions] Failed to fetch:", err); + setError(err instanceof Error ? err.message : "Failed to load questions"); + } finally { + setLoading(false); + } + }, [isAuthenticated]); + + const submitAnswer = useCallback(async (questionId: string, response: string): Promise<boolean> => { + try { + const result = await answerQuestion(questionId, response); + if (result.success) { + // Remove the question from local state + setPendingQuestions(prev => prev.filter(q => q.questionId !== questionId)); + } + return result.success; + } catch (err) { + console.error("Failed to submit answer:", err); + return false; + } + }, []); + + // Poll for questions every 5 seconds when authenticated + useEffect(() => { + if (!isAuthenticated) { + setPendingQuestions([]); + return; + } + + // Initial fetch (delayed slightly to ensure auth is ready) + const initialTimeout = setTimeout(refreshQuestions, 500); + + // Poll periodically (every 5 seconds for responsiveness) + const interval = setInterval(refreshQuestions, 5000); + return () => { + clearTimeout(initialTimeout); + clearInterval(interval); + }; + }, [isAuthenticated, refreshQuestions]); + + return ( + <SupervisorQuestionsContext.Provider + value={{ + pendingQuestions, + loading, + error, + refreshQuestions, + submitAnswer, + }} + > + {children} + </SupervisorQuestionsContext.Provider> + ); +} + +export function useSupervisorQuestions() { + const context = useContext(SupervisorQuestionsContext); + if (!context) { + throw new Error("useSupervisorQuestions must be used within SupervisorQuestionsProvider"); + } + return context; +} |
