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[]; /** Questions that are pending but not dismissed from notifications */ notificationQuestions: PendingQuestion[]; loading: boolean; error: string | null; refreshQuestions: () => Promise; submitAnswer: (questionId: string, response: string) => Promise; /** Dismiss a question from the notification (but keep it pending in task output) */ dismissNotification: (questionId: string) => void; } const SupervisorQuestionsContext = createContext(null); export function SupervisorQuestionsProvider({ children }: { children: ReactNode }) { const { isAuthenticated } = useAuth(); const [pendingQuestions, setPendingQuestions] = useState([]); const [dismissedIds, setDismissedIds] = useState>(new Set()); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); // Questions that should show in notifications (not dismissed) const notificationQuestions = pendingQuestions.filter(q => !dismissedIds.has(q.questionId)); const dismissNotification = useCallback((questionId: string) => { setDismissedIds(prev => new Set(prev).add(questionId)); }, []); 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 => { try { const result = await answerQuestion(questionId, response); if (result.success) { // Remove the question from local state setPendingQuestions(prev => prev.filter(q => q.questionId !== questionId)); // Also clean up dismissed state setDismissedIds(prev => { const next = new Set(prev); next.delete(questionId); return next; }); } 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 ( {children} ); } export function useSupervisorQuestions() { const context = useContext(SupervisorQuestionsContext); if (!context) { throw new Error("useSupervisorQuestions must be used within SupervisorQuestionsProvider"); } return context; }