feat: batch eligibility, batch claim, and batch check+claim from AI chat

- Add batch_eligibility, batch_claim, and batch_check_and_claim intents
  to AI classifier so multiple patients can be processed one by one
- Add queue processing on insurance-status and claims pages to auto-start
  the next patient after each check/claim completes
- Make patient schema firstName, lastName, phone optional so patients can
  be created with just member ID + DOB from eligibility checks
- Cancel buttons now preserve chat history instead of clearing it
- Patient-found card shows Check Eligibility, Eligibility & Appointment
  Today, and Cancel buttons
- Claim service date asks user to pick between latest appointment and
  today when they differ
- Login page subtitle styled with animated gradient

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
ff
2026-06-18 23:41:56 -04:00
parent a2e5c157ad
commit a52ff2d723
9 changed files with 710 additions and 66 deletions

View File

@@ -26,11 +26,14 @@ type Step =
| "ai-loading"
| "patient-found"
| "eligibility-id-ready"
| "batch-eligibility-ready"
| "check-and-claim-ready"
| "need-insurance-clarification"
| "need-appointment-selection"
| "need-cdt-clarification"
| "claim-ready"
| "batch-claim-ready"
| "batch-check-and-claim-ready"
| "preauth-ready";
interface Message {
@@ -160,6 +163,7 @@ export function ChatbotButton() {
const [freeTextInput, setFreeTextInput] = useState("");
const [patientResult, setPatientResult] = useState<PatientResult | null>(null);
const [eligibilityIdData, setEligibilityIdData] = useState<{ memberId: string; dob: string; siteKey: string; autoCheck: string; patient: PatientResult | null; appointmentDate?: string | null } | null>(null);
const [batchEligibilityData, setBatchEligibilityData] = useState<{ memberId: string; dob: string; siteKey: string; autoCheck: string; patient: PatientResult | null }[] | null>(null);
const [checkAndClaimData, setCheckAndClaimData] = useState<CheckAndClaimData | null>(null);
const [clarificationData, setClarificationData] = useState<{ memberId: string; dob: string; patient: PatientResult | null; procedureNames: string[]; options: string[] } | null>(null);
const [apptSelectionData, setApptSelectionData] = useState<{
@@ -181,6 +185,16 @@ export function ChatbotButton() {
appointmentId: number | null;
renderingProvider: string | null;
} | null>(null);
const [batchCheckAndClaimData, setBatchCheckAndClaimData] = useState<{
queue: { memberId: string; dob: string; siteKey: string; autoCheck: string; patient: PatientResult | null }[];
matchedCodes: { code: string; description: string; toothNumber?: string; toothSurface?: string; quad?: string }[];
renderingProvider: string | null;
} | null>(null);
const [batchClaimData, setBatchClaimData] = useState<{
queue: { patient: PatientResult; siteKey: string; serviceDate: string | null; appointmentId: number | null }[];
matchedCodes: { code: string; description: string; toothNumber?: string; toothSurface?: string; quad?: string }[];
renderingProvider: string | null;
} | null>(null);
const [preauthReadyData, setPreauthReadyData] = useState<{
patient: PatientResult | null;
matchedCodes: { code: string; description: string; toothNumber?: string }[];
@@ -257,11 +271,14 @@ export function ChatbotButton() {
setFreeTextInput("");
setPatientResult(null);
setEligibilityIdData(null);
setBatchEligibilityData(null);
setCheckAndClaimData(null);
setClarificationData(null);
setApptSelectionData(null);
setCdtClarificationData(null);
setClaimReadyData(null);
setBatchClaimData(null);
setBatchCheckAndClaimData(null);
setPreauthReadyData(null);
setPendingFiles([]);
};
@@ -326,18 +343,30 @@ export function ChatbotButton() {
};
const handleEligibilityFromPatient = () => {
if (!patientResult) return;
if (!patientResult?.insuranceId || !patientResult?.dateOfBirth) return;
addMsg("user", "Check eligibility now");
addMsg("bot", "Opening the eligibility check page...");
if (patientResult.insuranceId && patientResult.dateOfBirth) {
sessionStorage.setItem("chatbot_eligibility", JSON.stringify({
memberId: patientResult.insuranceId,
dob: patientResult.dateOfBirth,
autoCheck: getAutoCheck(patientResult.dateOfBirth),
}));
window.dispatchEvent(new CustomEvent("chatbot:eligibility-prefill"));
prefillAndNavigate(patientResult.insuranceId, patientResult.dateOfBirth, getAutoCheck(patientResult.dateOfBirth));
};
const handleEligibilityAndAppointmentFromPatient = async () => {
if (!patientResult?.insuranceId || !patientResult?.dateOfBirth) return;
addMsg("user", "Check eligibility & add to schedule (today)");
addMsg("bot", "Creating appointment for today...", true);
try {
const res = await apiRequest("POST", "/api/ai/create-appointment-today", {
patientId: patientResult.id,
});
const data = await res.json();
if (!res.ok) {
replaceLastMsg(data.message ?? "Could not create appointment.");
return;
}
replaceLastMsg(`Appointment added at ${data.startTime} (${data.column ?? "Column A"}) — opening eligibility check page...`);
} catch {
replaceLastMsg("Could not create appointment — opening eligibility check page...");
}
setTimeout(() => { setLocation("/insurance-status"); setOpen(false); resetStep(); }, 600);
prefillAndNavigate(patientResult.insuranceId, patientResult.dateOfBirth, getAutoCheck(patientResult.dateOfBirth));
};
const prefillAndNavigate = (memberId: string, dobISO: string, autoCheck: string) => {
@@ -354,6 +383,17 @@ export function ChatbotButton() {
prefillAndNavigate(eligibilityIdData.memberId, eligibilityIdData.dob, eligibilityIdData.autoCheck);
};
const handleBatchEligibilityRun = () => {
if (!batchEligibilityData || batchEligibilityData.length === 0) return;
addMsg("user", `Check all ${batchEligibilityData.length} patients`);
addMsg("bot", `Checking ${batchEligibilityData.length} patients one by one...`);
const [first, ...rest] = batchEligibilityData;
if (rest.length > 0) {
sessionStorage.setItem("chatbot_eligibility_queue", JSON.stringify(rest));
}
prefillAndNavigate(first!.memberId, first!.dob, first!.autoCheck);
};
const handleEligibilityAndAppointment = async (targetDate?: string) => {
if (!eligibilityIdData) return;
const dateLabel = targetDate
@@ -445,6 +485,12 @@ export function ChatbotButton() {
return;
}
if (data.action === "batch_eligibility_ready" && data.actionData?.queue) {
setBatchEligibilityData(data.actionData.queue);
setStep("batch-eligibility-ready");
return;
}
if (data.action === "eligibility_id_ready" && data.actionData) {
setEligibilityIdData({
memberId: data.actionData.memberId,
@@ -510,6 +556,26 @@ export function ChatbotButton() {
return;
}
if (data.action === "batch_check_and_claim_ready" && data.actionData) {
setBatchCheckAndClaimData({
queue: data.actionData.queue ?? [],
matchedCodes: data.actionData.matchedCodes ?? [],
renderingProvider: data.actionData.renderingProvider ?? null,
});
setStep("batch-check-and-claim-ready");
return;
}
if (data.action === "batch_claim_ready" && data.actionData) {
setBatchClaimData({
queue: data.actionData.queue ?? [],
matchedCodes: data.actionData.matchedCodes ?? [],
renderingProvider: data.actionData.renderingProvider ?? null,
});
setStep("batch-claim-ready");
return;
}
if (data.action === "claim_only_ready" && data.actionData) {
const { patient, matchedCodes, siteKey, serviceDate, appointmentId, renderingProvider } = data.actionData;
setClaimReadyData({
@@ -556,7 +622,10 @@ export function ChatbotButton() {
step === "ai-loading" ||
step === "patient-found" ||
step === "eligibility-id-ready" ||
step === "batch-eligibility-ready" ||
step === "check-and-claim-ready" ||
step === "batch-claim-ready" ||
step === "batch-check-and-claim-ready" ||
step === "need-insurance-clarification" ||
step === "need-appointment-selection";
@@ -684,7 +753,7 @@ export function ChatbotButton() {
>
Continue <ChevronRight className="h-3 w-3 ml-1" />
</Button>
<Button size="sm" variant="ghost" className="h-8 text-xs" onClick={reset}>
<Button size="sm" variant="ghost" className="h-8 text-xs" onClick={resetStep}>
Cancel
</Button>
</div>
@@ -726,19 +795,29 @@ export function ChatbotButton() {
{patientResult.dateOfBirth && (
<p className="text-xs text-gray-500">DOB: {patientResult.dateOfBirth}</p>
)}
<div className="flex gap-2 pt-1">
{patientResult.insuranceId && (
<Button
size="sm"
className="flex-1 h-8 text-xs bg-primary hover:bg-primary/90"
onClick={handleEligibilityFromPatient}
>
<Stethoscope className="h-3 w-3 mr-1" />
Check Eligibility
</Button>
<div className="flex flex-col gap-2 pt-1">
{patientResult.insuranceId && patientResult.dateOfBirth && (
<>
<Button
size="sm"
className="w-full h-8 text-xs bg-primary hover:bg-primary/90"
onClick={handleEligibilityFromPatient}
>
<Stethoscope className="h-3 w-3 mr-1" />
Check Eligibility
</Button>
<Button
size="sm"
className="w-full h-8 text-xs bg-emerald-600 hover:bg-emerald-700 text-white"
onClick={handleEligibilityAndAppointmentFromPatient}
>
<Calendar className="h-3 w-3 mr-1" />
Eligibility &amp; Appointment Today
</Button>
</>
)}
<Button size="sm" variant="ghost" className="h-8 text-xs" onClick={reset}>
Done
<Button size="sm" variant="ghost" className="w-full h-8 text-xs" onClick={resetStep}>
Cancel
</Button>
</div>
</div>
@@ -785,7 +864,39 @@ export function ChatbotButton() {
{new Date(eligibilityIdData.appointmentDate + "T00:00:00").toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })}
</Button>
)}
<Button size="sm" variant="ghost" className="w-full h-8 text-xs" onClick={reset}>
<Button size="sm" variant="ghost" className="w-full h-8 text-xs" onClick={resetStep}>
Cancel
</Button>
</div>
</div>
)}
{/* Batch eligibility ready */}
{step === "batch-eligibility-ready" && batchEligibilityData && (
<div className="bg-indigo-50 border border-indigo-200 rounded-xl p-3 space-y-2">
<p className="text-xs font-semibold text-indigo-800">
{batchEligibilityData.length} patients to check:
</p>
{batchEligibilityData.map((item, i) => {
const name = item.patient
? `${item.patient.firstName ?? ""} ${item.patient.lastName ?? ""}`.trim()
: `ID: ${item.memberId}`;
return (
<p key={i} className="text-xs text-indigo-600 pl-2">
{i + 1}. {name} DOB: {item.dob}
</p>
);
})}
<div className="flex flex-col gap-2 pt-1">
<Button
size="sm"
className="w-full h-8 text-xs bg-indigo-600 hover:bg-indigo-700 text-white"
onClick={handleBatchEligibilityRun}
>
<Stethoscope className="h-3 w-3 mr-1" />
Check All ({batchEligibilityData.length} patients)
</Button>
<Button size="sm" variant="ghost" className="w-full h-8 text-xs" onClick={resetStep}>
Cancel
</Button>
</div>
@@ -820,7 +931,7 @@ export function ChatbotButton() {
<Stethoscope className="h-3 w-3 mr-1" />
Check &amp; Claim
</Button>
<Button size="sm" variant="ghost" className="h-8 text-xs" onClick={reset}>
<Button size="sm" variant="ghost" className="h-8 text-xs" onClick={resetStep}>
Cancel
</Button>
</div>
@@ -884,7 +995,7 @@ export function ChatbotButton() {
</button>
))}
</div>
<Button size="sm" variant="ghost" className="h-7 text-xs w-full" onClick={reset}>
<Button size="sm" variant="ghost" className="h-7 text-xs w-full" onClick={resetStep}>
Cancel
</Button>
</div>
@@ -931,6 +1042,135 @@ export function ChatbotButton() {
</div>
)}
{/* Batch check & claim ready */}
{step === "batch-check-and-claim-ready" && batchCheckAndClaimData && (
<div className="bg-purple-50 border border-purple-200 rounded-xl p-3 space-y-2">
<p className="text-xs font-semibold text-purple-800">
Check &amp; Claim for {batchCheckAndClaimData.queue.length} patients:
</p>
{batchCheckAndClaimData.queue.map((item, i) => {
const name = item.patient
? `${item.patient.firstName ?? ""} ${item.patient.lastName ?? ""}`.trim()
: `ID: ${item.memberId}`;
return (
<p key={i} className="text-xs text-purple-600 pl-2">
{i + 1}. {name} DOB: {item.dob}
</p>
);
})}
{batchCheckAndClaimData.matchedCodes.length > 0 && (
<div className="space-y-0.5 pt-0.5">
<p className="text-xs font-medium text-purple-700">Claim after ACTIVE:</p>
{batchCheckAndClaimData.matchedCodes.map((c) => (
<p key={c.code} className="text-xs text-gray-700 pl-2">
<span className="font-medium">{c.code}</span> {c.description}
</p>
))}
</div>
)}
<div className="flex flex-col gap-2 pt-1">
<Button
size="sm"
className="w-full h-8 text-xs bg-purple-600 hover:bg-purple-700 text-white"
onClick={() => {
const { queue, matchedCodes, renderingProvider } = batchCheckAndClaimData;
addMsg("user", `Check & claim all ${queue.length} patients`);
addMsg("bot", `Checking eligibility and claiming for ${queue.length} patients one by one...`);
const [first, ...rest] = queue;
if (rest.length > 0) {
sessionStorage.setItem("chatbot_check_claim_queue", JSON.stringify({
remaining: rest,
matchedCodes,
renderingProvider,
}));
}
sessionStorage.setItem("chatbot_claim_codes", JSON.stringify({
codes: matchedCodes,
siteKey: first!.siteKey,
patientId: first!.patient?.id ?? null,
memberId: first!.memberId,
dob: first!.dob,
serviceDate: null,
renderingProvider,
}));
prefillAndNavigate(first!.memberId, first!.dob, first!.autoCheck);
}}
>
<Stethoscope className="h-3 w-3 mr-1" />
Check &amp; Claim All ({batchCheckAndClaimData.queue.length} patients)
</Button>
<Button size="sm" variant="ghost" className="w-full h-8 text-xs" onClick={resetStep}>
Cancel
</Button>
</div>
</div>
)}
{/* Batch claim ready */}
{step === "batch-claim-ready" && batchClaimData && (
<div className="bg-orange-50 border border-orange-200 rounded-xl p-3 space-y-2">
<p className="text-xs font-semibold text-orange-800">
Claim for {batchClaimData.queue.length} patients:
</p>
{batchClaimData.queue.map((item, i) => (
<p key={i} className="text-xs text-orange-600 pl-2">
{i + 1}. {item.patient.firstName} {item.patient.lastName}
</p>
))}
{batchClaimData.matchedCodes.length > 0 && (
<div className="space-y-0.5 pt-0.5">
<p className="text-xs font-medium text-orange-700">Procedures:</p>
{batchClaimData.matchedCodes.map((c) => (
<p key={c.code} className="text-xs text-gray-700 pl-2">
<span className="font-medium">{c.code}</span> {c.description}
</p>
))}
</div>
)}
<div className="flex flex-col gap-2 pt-1">
<Button
size="sm"
className="w-full h-8 text-xs bg-orange-600 hover:bg-orange-700 text-white"
onClick={() => {
const { queue, matchedCodes, renderingProvider } = batchClaimData;
addMsg("user", `Claim all ${queue.length} patients`);
addMsg("bot", `Claiming ${queue.length} patients one by one...`);
const [first, ...rest] = queue;
if (rest.length > 0) {
sessionStorage.setItem("chatbot_claim_queue", JSON.stringify({
remaining: rest,
matchedCodes,
renderingProvider,
}));
}
if (first!.patient.id && matchedCodes.length > 0) {
sessionStorage.setItem("chatbot_claim_prefill", JSON.stringify({
codes: matchedCodes,
siteKey: first!.siteKey,
serviceDate: first!.serviceDate,
autoSubmit: true,
renderingProvider: renderingProvider ?? null,
dob: first!.patient.dateOfBirth ?? null,
}));
}
setChatbotPendingFiles(pendingFiles);
markJobStarted();
const url = first!.appointmentId
? `/claims?appointmentId=${first!.appointmentId}`
: `/claims?newPatient=${first!.patient.id}`;
setTimeout(() => { setLocation(url); setOpen(false); resetStep(); }, 600);
}}
>
<FileText className="h-3 w-3 mr-1" />
Claim All ({batchClaimData.queue.length} patients)
</Button>
<Button size="sm" variant="ghost" className="w-full h-8 text-xs" onClick={resetStep}>
Cancel
</Button>
</div>
</div>
)}
{/* Claim ready — confirm before submitting */}
{step === "claim-ready" && claimReadyData && (() => {
const [sy, sm, sd] = (claimReadyData.serviceDate ?? "").split("-");

View File

@@ -110,3 +110,13 @@
min-width: 6rem; /* Prevent shrinking */
appearance: none; /* Removes native styling */
}
@keyframes gradient-flash {
0% { background-position: 100% 50%; }
50% { background-position: 0% 50%; }
100% { background-position: 100% 50%; }
}
.animate-gradient-flash {
animation: gradient-flash 6s ease-in-out infinite;
}

View File

@@ -90,8 +90,9 @@ export default function AuthPage() {
<h1 className="text-3xl font-bold text-primary mb-3 tracking-tight">
My Dental Office Management
</h1>
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-gray-400">
Driven by multiple AI agents
<p className="text-sm font-semibold tracking-[0.15em] bg-clip-text text-transparent animate-gradient-flash"
style={{ backgroundImage: "linear-gradient(90deg, #7c3aed, #d946ef, #06b6d4, #7c3aed)", backgroundSize: "200% 100%" }}>
Driven By Multiple AI Agents
</p>
</div>

View File

@@ -911,6 +911,79 @@ export default function ClaimsPage() {
}
}
} catch {}
// If a chatbot batch check+claim queue is pending, navigate to eligibility for the next patient
try {
const raw = sessionStorage.getItem("chatbot_check_claim_queue");
if (raw) {
const parsed = JSON.parse(raw);
const remaining = parsed?.remaining as any[] | undefined;
const matchedCodes = parsed?.matchedCodes ?? [];
const renderingProvider = parsed?.renderingProvider ?? null;
if (remaining && remaining.length > 0) {
const [next, ...rest] = remaining;
if (rest.length > 0) {
sessionStorage.setItem("chatbot_check_claim_queue", JSON.stringify({ remaining: rest, matchedCodes, renderingProvider }));
} else {
sessionStorage.removeItem("chatbot_check_claim_queue");
}
sessionStorage.setItem("chatbot_claim_codes", JSON.stringify({
codes: matchedCodes,
siteKey: next.siteKey,
patientId: next.patient?.id ?? null,
memberId: next.memberId,
dob: next.dob,
serviceDate: null,
renderingProvider,
}));
sessionStorage.setItem("chatbot_eligibility", JSON.stringify({
memberId: next.memberId,
dob: next.dob,
autoCheck: next.autoCheck,
}));
setTimeout(() => {
window.dispatchEvent(new CustomEvent("chatbot:eligibility-prefill"));
setWouterLocation("/insurance-status");
}, 500);
return;
}
sessionStorage.removeItem("chatbot_check_claim_queue");
}
} catch {}
// If a chatbot batch claim queue is pending, open the next patient
try {
const raw = sessionStorage.getItem("chatbot_claim_queue");
if (raw) {
const parsed = JSON.parse(raw);
const remaining = parsed?.remaining as any[] | undefined;
const matchedCodes = parsed?.matchedCodes ?? [];
const renderingProvider = parsed?.renderingProvider ?? null;
if (remaining && remaining.length > 0) {
const [next, ...rest] = remaining;
if (rest.length > 0) {
sessionStorage.setItem("chatbot_claim_queue", JSON.stringify({ remaining: rest, matchedCodes, renderingProvider }));
} else {
sessionStorage.removeItem("chatbot_claim_queue");
}
if (next.patient?.id && matchedCodes.length > 0) {
sessionStorage.setItem("chatbot_claim_prefill", JSON.stringify({
codes: matchedCodes,
siteKey: next.siteKey,
serviceDate: next.serviceDate,
autoSubmit: true,
renderingProvider,
dob: next.patient.dateOfBirth ?? null,
}));
}
setTimeout(() => {
setWouterLocation(`/claims?newPatient=${next.patient.id}`);
}, 500);
return;
}
sessionStorage.removeItem("chatbot_claim_queue");
}
} catch {}
};
// Pre Auth section

View File

@@ -385,6 +385,7 @@ export default function InsuranceStatusPage() {
setPreviewFallbackFilename(jobResult.pdfFilename ?? `eligibility_${memberId}.pdf`);
setPreviewOpen(true);
}
processNextInQueue();
} catch (error: any) {
dispatch(setTaskStatus({ key: "eligibilityCheck", status: "error", message: error.message || "Selenium submission failed" }));
toast({ title: "Selenium service error", description: error.message || "An error occurred.", variant: "destructive" });
@@ -574,6 +575,7 @@ export default function InsuranceStatusPage() {
if (claimed) return;
setSelectedPatient(null);
await queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE });
processNextInQueue();
// Open all PDFs side by side in the modal
if (jobResult.pdfFileId || jobResult.memberDetailsPdfFileId || jobResult.historyPdfFileId) {
@@ -643,6 +645,7 @@ export default function InsuranceStatusPage() {
setSelectedPatient(null);
await queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE });
processNextInQueue();
// Open 4-panel modal
if (jobResult.pdfFileId || jobResult.memberDetailsPdfFileId || jobResult.historyPdfFileId || jobResult.accumulatorPdfFileId) {
@@ -773,6 +776,29 @@ export default function InsuranceStatusPage() {
} catch {}
};
const processNextInQueue = () => {
try {
const raw = sessionStorage.getItem("chatbot_eligibility_queue");
if (!raw) return;
const queue = JSON.parse(raw) as { memberId: string; dob: string; autoCheck: string }[];
if (!queue.length) {
sessionStorage.removeItem("chatbot_eligibility_queue");
return;
}
const [next, ...rest] = queue;
if (rest.length > 0) {
sessionStorage.setItem("chatbot_eligibility_queue", JSON.stringify(rest));
} else {
sessionStorage.removeItem("chatbot_eligibility_queue");
}
toast({ title: `${rest.length + 1} patient${rest.length > 0 ? "s" : ""} remaining`, description: `Starting next: ${next!.memberId}` });
setTimeout(() => {
sessionStorage.setItem("chatbot_eligibility", JSON.stringify({ memberId: next!.memberId, dob: next!.dob, autoCheck: next!.autoCheck }));
window.dispatchEvent(new CustomEvent("chatbot:eligibility-prefill"));
}, 1500);
} catch {}
};
// Redirect from schedule page "Check Eligibility": prefill patient + optionally auto-trigger or scroll
useEffect(() => {
const params = new URLSearchParams(window.location.search);
@@ -1018,6 +1044,7 @@ export default function InsuranceStatusPage() {
setPreviewFallbackFilename(fallbackFilename ?? `eligibility_ddma_${memberId}.pdf`);
setPreviewOpen(true);
}
processNextInQueue();
}}
/>
</div>
@@ -1039,6 +1066,7 @@ export default function InsuranceStatusPage() {
setPreviewFallbackFilename(fallbackFilename ?? `eligibility_deltains_${memberId}.pdf`);
setPreviewOpen(true);
}
processNextInQueue();
}}
/>
</div>
@@ -1057,6 +1085,7 @@ export default function InsuranceStatusPage() {
fallbackFilename ?? `eligibility_bcbs_ma_${memberId}.pdf`,
);
setPreviewOpen(true);
processNextInQueue();
}}
/>
</div>
@@ -1081,6 +1110,7 @@ export default function InsuranceStatusPage() {
setPreviewFallbackFilename(fallbackFilename ?? `eligibility_tuftssco_${memberId}.pdf`);
setPreviewOpen(true);
}
processNextInQueue();
}}
/>
</div>
@@ -1102,6 +1132,7 @@ export default function InsuranceStatusPage() {
setPreviewFallbackFilename(fallbackFilename ?? `eligibility_unitedsco_${memberId}.pdf`);
setPreviewOpen(true);
}
processNextInQueue();
}}
/>
</div>
@@ -1123,6 +1154,7 @@ export default function InsuranceStatusPage() {
setPreviewFallbackFilename(fallbackFilename ?? `eligibility_cca_${memberId}.pdf`);
setPreviewOpen(true);
}
processNextInQueue();
}}
/>
</div>