import { useRef, useState } from "react"; import { Button } from "@/components/ui/button"; import { CheckCircle, LoaderCircleIcon } from "lucide-react"; import { useToast } from "@/hooks/use-toast"; import { apiRequest, queryClient } from "@/lib/queryClient"; import { useAppDispatch } from "@/redux/hooks"; import { setTaskStatus } from "@/redux/slices/seleniumTaskSlice"; import { formatLocalDate } from "@/utils/dateUtils"; import { socket } from "@/lib/socket"; import { QK_PATIENTS_BASE } from "@/components/patients/patient-table"; // ─── Main component ─────────────────────────────────────────────────────────── interface CCAEligibilityButtonProps { memberId: string; dateOfBirth: Date | null; firstName?: string; lastName?: string; isFormIncomplete: boolean; onPdfReady: (pdfId: number, fallbackFilename: string | null) => void; } export function CCAEligibilityButton({ memberId, dateOfBirth, firstName, lastName, isFormIncomplete, onPdfReady, }: CCAEligibilityButtonProps) { const { toast } = useToast(); const dispatch = useAppDispatch(); const sessionIdRef = useRef(null); const [isStarting, setIsStarting] = useState(false); const handleStart = async () => { if (!memberId || !dateOfBirth) { toast({ title: "Missing fields", description: "Member ID and Date of Birth are required.", variant: "destructive", }); return; } const formattedDob = formatLocalDate(dateOfBirth); const payload = { memberId, dateOfBirth: formattedDob, firstName, lastName, insuranceSiteKey: "CCA", }; setIsStarting(true); try { dispatch( setTaskStatus({ key: "eligibilityCheck", status: "pending", message: "Starting CCA eligibility check…", }) ); const response = await apiRequest( "POST", "/api/insurance-status-cca/cca-eligibility", { data: JSON.stringify(payload), socketId: socket.id } ); const result = await response.json(); if (!response.ok || result.error) { throw new Error(result.error || `Server error (${response.status})`); } const jobId: string = result.jobId; if (!jobId) throw new Error("No jobId returned from server"); dispatch( setTaskStatus({ key: "eligibilityCheck", status: "pending", message: "CCA job queued. Waiting for browser session…", }) ); const onSessionStarted = (data: any) => { if (String(data?.jobId) !== String(jobId)) return; sessionIdRef.current = data.session_id ?? null; dispatch( setTaskStatus({ key: "eligibilityCheck", status: "pending", message: "Browser session started. Running eligibility check…", }) ); }; socket.on("selenium:cca_session_started", onSessionStarted); function cleanup() { clearTimeout(safetyTimer); socket.off("selenium:cca_session_started", onSessionStarted); socket.off("job:update", onJobUpdate); } const onJobUpdate = (data: any) => { if (String(data?.jobId) !== String(jobId)) return; if (data.status === "active") { dispatch( setTaskStatus({ key: "eligibilityCheck", status: "pending", message: data.message ?? "Selenium browser starting…", }) ); return; } cleanup(); if (data.status === "completed") { dispatch( setTaskStatus({ key: "eligibilityCheck", status: "success", message: "CCA eligibility updated and PDF attached to patient documents.", }) ); toast({ title: "CCA eligibility complete", description: "Patient status was updated and the eligibility PDF was saved.", }); queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE }); const pdfId = data.result?.pdfFileId; if (pdfId) { onPdfReady(Number(pdfId), data.result?.pdfFilename ?? `eligibility_cca_${memberId}.pdf`); } } else if (data.status === "failed") { const msg = data.error ?? "CCA eligibility job failed."; dispatch(setTaskStatus({ key: "eligibilityCheck", status: "error", message: msg })); toast({ title: "CCA selenium error", description: msg, variant: "destructive" }); } setIsStarting(false); }; socket.on("job:update", onJobUpdate); const safetyTimer = setTimeout(() => { cleanup(); setIsStarting(false); dispatch( setTaskStatus({ key: "eligibilityCheck", status: "error", message: "CCA job timed out waiting for completion.", }) ); }, 6 * 60 * 1000); } catch (err: any) { console.error("CCAEligibilityButton error:", err); dispatch( setTaskStatus({ key: "eligibilityCheck", status: "error", message: err?.message || "Failed to start CCA eligibility", }) ); toast({ title: "CCA selenium error", description: err?.message || "Failed to start CCA eligibility", variant: "destructive", }); setIsStarting(false); } }; return ( ); }