feat: AI chat Eligibility & Appointment button with 15-min slots and Column B fallback
- Add "Eligibility & Appointment" button to chatbot eligibility-id-ready card - For known patients: creates today's appointment immediately, then opens eligibility page - For unknown patients: navigates to eligibility page; after Selenium creates the patient, auto-creates appointment via tryAppointmentFromChatbot on the insurance-status page - Update MH Eligibility & Appointment button to create a today's schedule slot instead of navigating to the appointments page; shows PDF preview on completion - createAppointmentToday falls back from Column A to Column B when Column A is full; returns column label in response so UI can display it - Set AI-scheduled appointment duration to 15 minutes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -593,7 +593,7 @@ async function handleClaimOnly(
|
|||||||
// ─── schedule_appointment ─────────────────────────────────────────────────────
|
// ─── schedule_appointment ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
const DEFAULT_STAFF_ID = 1; // Column A
|
const DEFAULT_STAFF_ID = 1; // Column A
|
||||||
const SLOT_DURATION = 30; // minutes
|
const SLOT_DURATION = 15; // minutes
|
||||||
|
|
||||||
/** Convert "HH:MM" to total minutes since midnight */
|
/** Convert "HH:MM" to total minutes since midnight */
|
||||||
function toMinutes(t: string): number {
|
function toMinutes(t: string): number {
|
||||||
@@ -736,6 +736,68 @@ async function handleScheduleAppointment(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─── Standalone helper: create today's appointment for a known patientId ─────
|
||||||
|
|
||||||
|
export async function createAppointmentToday(
|
||||||
|
patientId: number,
|
||||||
|
userId: number,
|
||||||
|
storage: StorageLike
|
||||||
|
): Promise<{ startTime: string; endTime: string; dateStr: string; dateLabel: string; column: string } | { error: string }> {
|
||||||
|
const today = new Date();
|
||||||
|
const dateStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, "0")}-${String(today.getDate()).padStart(2, "0")}`;
|
||||||
|
const dateLabel = today.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
|
||||||
|
const localDate = new Date(today.getFullYear(), today.getMonth(), today.getDate());
|
||||||
|
|
||||||
|
const dayNames = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
|
||||||
|
const dayName = dayNames[today.getDay()]!;
|
||||||
|
|
||||||
|
const officeHours = await storage.getOfficeHours(userId);
|
||||||
|
const dayHours = officeHours?.data?.doctors?.[dayName] ?? {
|
||||||
|
amStart: "09:00", amEnd: "12:00", pmStart: "13:00", pmEnd: "17:00", enabled: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!dayHours.enabled) {
|
||||||
|
return { error: `The office is closed today (${dayName}). Cannot create appointment.` };
|
||||||
|
}
|
||||||
|
|
||||||
|
const allSlots = buildSlots(dayHours);
|
||||||
|
const allAppointments = await storage.getAppointmentsByDateForUser(dateStr, userId);
|
||||||
|
|
||||||
|
for (const { staffId, label } of [
|
||||||
|
{ staffId: DEFAULT_STAFF_ID, label: "Column A" },
|
||||||
|
{ staffId: 2, label: "Column B" },
|
||||||
|
]) {
|
||||||
|
const booked = allAppointments
|
||||||
|
.filter((a: any) => a.staffId === staffId)
|
||||||
|
.map((a: any) => ({ start: toMinutes(a.startTime), end: toMinutes(a.endTime) }));
|
||||||
|
|
||||||
|
const availableStart = allSlots.find((slotStart) => {
|
||||||
|
const slotEnd = slotStart + SLOT_DURATION;
|
||||||
|
return !booked.some((b) => slotStart < b.end && slotEnd > b.start);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (availableStart !== undefined) {
|
||||||
|
const startTime = fromMinutes(availableStart);
|
||||||
|
const endTime = fromMinutes(availableStart + SLOT_DURATION);
|
||||||
|
await storage.createAppointment({
|
||||||
|
patientId,
|
||||||
|
userId,
|
||||||
|
staffId,
|
||||||
|
title: dateLabel,
|
||||||
|
date: localDate,
|
||||||
|
startTime,
|
||||||
|
endTime,
|
||||||
|
type: "recall",
|
||||||
|
status: "scheduled",
|
||||||
|
movedByAi: true,
|
||||||
|
});
|
||||||
|
return { startTime, endTime, dateStr, dateLabel, column: label };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { error: `Both Column A and Column B are fully booked today. Please add the appointment manually.` };
|
||||||
|
}
|
||||||
|
|
||||||
// ─── Insurance resolution helper ──────────────────────────────────────────────
|
// ─── Insurance resolution helper ──────────────────────────────────────────────
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import express, { Request, Response } from "express";
|
import express, { Request, Response } from "express";
|
||||||
import { storage } from "../storage";
|
import { storage } from "../storage";
|
||||||
import { classifyInternalChat } from "../ai/internal-chat-graph";
|
import { classifyInternalChat } from "../ai/internal-chat-graph";
|
||||||
import { runInternalChatWorkflow } from "../ai/internal-chat-workflow";
|
import { runInternalChatWorkflow, createAppointmentToday } from "../ai/internal-chat-workflow";
|
||||||
import { resolveAiProvider } from "../ai/llm-factory";
|
import { resolveAiProvider } from "../ai/llm-factory";
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
@@ -309,4 +309,18 @@ router.post("/internal-chat", async (req: Request, res: Response): Promise<any>
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.post("/create-appointment-today", async (req: Request, res: Response): Promise<any> => {
|
||||||
|
try {
|
||||||
|
const userId = req.user?.id;
|
||||||
|
if (!userId) return res.status(401).json({ message: "Unauthorized" });
|
||||||
|
const { patientId } = req.body;
|
||||||
|
if (!patientId) return res.status(400).json({ message: "patientId is required" });
|
||||||
|
const result = await createAppointmentToday(Number(patientId), userId, storage);
|
||||||
|
if ("error" in result) return res.status(409).json({ message: result.error });
|
||||||
|
return res.status(200).json(result);
|
||||||
|
} catch (err) {
|
||||||
|
return res.status(500).json({ error: "Failed to create appointment", details: String(err) });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
@@ -299,6 +299,35 @@ export function ChatbotButton() {
|
|||||||
prefillAndNavigate(eligibilityIdData.memberId, eligibilityIdData.dob, eligibilityIdData.autoCheck);
|
prefillAndNavigate(eligibilityIdData.memberId, eligibilityIdData.dob, eligibilityIdData.autoCheck);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleEligibilityAndAppointment = async () => {
|
||||||
|
if (!eligibilityIdData) return;
|
||||||
|
addMsg("user", "Check eligibility & add to today's schedule");
|
||||||
|
|
||||||
|
if (!eligibilityIdData.patient) {
|
||||||
|
// Patient not yet in DB — eligibility check will create them; flag for post-check appointment
|
||||||
|
addMsg("bot", "Running eligibility check — will add patient and create today's appointment after...");
|
||||||
|
sessionStorage.setItem("chatbot_appt_after_eligibility", JSON.stringify({ memberId: eligibilityIdData.memberId }));
|
||||||
|
prefillAndNavigate(eligibilityIdData.memberId, eligibilityIdData.dob, eligibilityIdData.autoCheck);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
addMsg("bot", "Creating appointment for today...", true);
|
||||||
|
try {
|
||||||
|
const res = await apiRequest("POST", "/api/ai/create-appointment-today", {
|
||||||
|
patientId: eligibilityIdData.patient.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...`);
|
||||||
|
prefillAndNavigate(eligibilityIdData.memberId, eligibilityIdData.dob, eligibilityIdData.autoCheck);
|
||||||
|
} catch {
|
||||||
|
replaceLastMsg("Could not create appointment. Please try again.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleCheckAndClaimRun = () => {
|
const handleCheckAndClaimRun = () => {
|
||||||
if (!checkAndClaimData) return;
|
if (!checkAndClaimData) return;
|
||||||
addMsg("user", "Run check & claim");
|
addMsg("user", "Run check & claim");
|
||||||
@@ -653,16 +682,24 @@ export function ChatbotButton() {
|
|||||||
{eligibilityIdData.patient?.insuranceProvider && (
|
{eligibilityIdData.patient?.insuranceProvider && (
|
||||||
<p className="text-xs text-gray-500">{eligibilityIdData.patient.insuranceProvider}</p>
|
<p className="text-xs text-gray-500">{eligibilityIdData.patient.insuranceProvider}</p>
|
||||||
)}
|
)}
|
||||||
<div className="flex gap-2 pt-1">
|
<div className="flex flex-col gap-2 pt-1">
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
className="flex-1 h-8 text-xs bg-primary hover:bg-primary/90"
|
className="w-full h-8 text-xs bg-primary hover:bg-primary/90"
|
||||||
onClick={handleEligibilityIdRun}
|
onClick={handleEligibilityIdRun}
|
||||||
>
|
>
|
||||||
<Stethoscope className="h-3 w-3 mr-1" />
|
<Stethoscope className="h-3 w-3 mr-1" />
|
||||||
Check Eligibility
|
Check Eligibility
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="sm" variant="ghost" className="h-8 text-xs" onClick={reset}>
|
<Button
|
||||||
|
size="sm"
|
||||||
|
className="w-full h-8 text-xs bg-emerald-600 hover:bg-emerald-700 text-white"
|
||||||
|
onClick={handleEligibilityAndAppointment}
|
||||||
|
>
|
||||||
|
<Calendar className="h-3 w-3 mr-1" />
|
||||||
|
Eligibility & Appointment
|
||||||
|
</Button>
|
||||||
|
<Button size="sm" variant="ghost" className="w-full h-8 text-xs" onClick={reset}>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -363,6 +363,7 @@ export default function InsuranceStatusPage() {
|
|||||||
|
|
||||||
setSelectedPatient(null);
|
setSelectedPatient(null);
|
||||||
await queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE });
|
await queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE });
|
||||||
|
void tryAppointmentFromChatbot();
|
||||||
|
|
||||||
if (jobResult.pdfFileId) {
|
if (jobResult.pdfFileId) {
|
||||||
setPreviewPdfId(Number(jobResult.pdfFileId));
|
setPreviewPdfId(Number(jobResult.pdfFileId));
|
||||||
@@ -377,7 +378,7 @@ export default function InsuranceStatusPage() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// MH Eligibility & Appointment — check eligibility, save to DB, navigate to appointments
|
// MH Eligibility & Appointment — check eligibility, save to DB, create appointment for today
|
||||||
const handleMHEligibilityAppointmentButton = async () => {
|
const handleMHEligibilityAppointmentButton = async () => {
|
||||||
if (!memberId || !dateOfBirth) {
|
if (!memberId || !dateOfBirth) {
|
||||||
toast({
|
toast({
|
||||||
@@ -399,34 +400,60 @@ export default function InsuranceStatusPage() {
|
|||||||
setTaskStatus({
|
setTaskStatus({
|
||||||
key: "eligibilityCheck",
|
key: "eligibilityCheck",
|
||||||
status: "error",
|
status: "error",
|
||||||
message: "Insurance is inactive. Staying on Eligibility page.",
|
message: "Insurance is inactive. No appointment created.",
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
toast({
|
toast({
|
||||||
title: "Insurance Inactive",
|
title: "Insurance Inactive",
|
||||||
description: "Patient insurance is inactive. Staying on Eligibility page.",
|
description: "Patient insurance is inactive. No appointment was created.",
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
});
|
});
|
||||||
await queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE });
|
await queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE });
|
||||||
|
|
||||||
|
// Look up the patient (created/updated by the Selenium worker) then create today's appointment
|
||||||
|
let apptTime: string | null = null;
|
||||||
|
try {
|
||||||
|
const lookupRes = await apiRequest("GET", `/api/patients/by-insurance-id?insuranceId=${encodeURIComponent(memberId)}`);
|
||||||
|
if (lookupRes.ok) {
|
||||||
|
const patient = await lookupRes.json();
|
||||||
|
if (patient?.id) {
|
||||||
|
const apptRes = await apiRequest("POST", "/api/ai/create-appointment-today", { patientId: patient.id });
|
||||||
|
if (apptRes.ok) {
|
||||||
|
const apptData = await apptRes.json();
|
||||||
|
apptTime = apptData.startTime ? `${apptData.startTime} (${apptData.column ?? "Column A"})` : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
|
||||||
dispatch(
|
dispatch(
|
||||||
setTaskStatus({
|
setTaskStatus({
|
||||||
key: "eligibilityCheck",
|
key: "eligibilityCheck",
|
||||||
status: "success",
|
status: "success",
|
||||||
message: "Eligibility checked and saved. Redirecting to Appointments...",
|
message: apptTime
|
||||||
|
? `Eligibility checked. Appointment created at ${apptTime}.`
|
||||||
|
: "Eligibility checked. Could not create appointment — please add manually.",
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
toast({
|
toast({
|
||||||
title: "Eligibility checked.",
|
title: "Eligibility checked.",
|
||||||
description: "Patient eligibility saved. Redirecting to Appointments.",
|
description: apptTime
|
||||||
|
? `Patient added to today's schedule at ${apptTime}.`
|
||||||
|
: "Eligibility saved. Could not create appointment — Column A may be full.",
|
||||||
variant: "default",
|
variant: "default",
|
||||||
});
|
});
|
||||||
|
|
||||||
setSelectedPatient(null);
|
setSelectedPatient(null);
|
||||||
await queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE });
|
|
||||||
setLocation("/appointments");
|
if (jobResult.pdfFileId) {
|
||||||
|
setPreviewPdfId(Number(jobResult.pdfFileId));
|
||||||
|
setPreviewFallbackFilename(jobResult.pdfFilename ?? `eligibility_${memberId}.pdf`);
|
||||||
|
setPreviewOpen(true);
|
||||||
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
dispatch(setTaskStatus({ key: "eligibilityCheck", status: "error", message: error.message || "Selenium submission failed" }));
|
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" });
|
toast({ title: "Selenium service error", description: error.message || "An error occurred.", variant: "destructive" });
|
||||||
@@ -523,6 +550,7 @@ export default function InsuranceStatusPage() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const claimed = await tryClaimFromChatbot(selectedPatient?.id);
|
const claimed = await tryClaimFromChatbot(selectedPatient?.id);
|
||||||
|
void tryAppointmentFromChatbot();
|
||||||
if (claimed) return;
|
if (claimed) return;
|
||||||
setSelectedPatient(null);
|
setSelectedPatient(null);
|
||||||
await queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE });
|
await queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE });
|
||||||
@@ -686,6 +714,38 @@ export default function InsuranceStatusPage() {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// After any eligibility check succeeds, check if chatbot wanted an appointment created.
|
||||||
|
// Patient was just created/updated in DB by the Selenium worker before this is called.
|
||||||
|
const tryAppointmentFromChatbot = async (): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const raw = sessionStorage.getItem("chatbot_appt_after_eligibility");
|
||||||
|
if (!raw) return;
|
||||||
|
const { memberId: storedMemberId } = JSON.parse(raw);
|
||||||
|
sessionStorage.removeItem("chatbot_appt_after_eligibility");
|
||||||
|
if (!storedMemberId) return;
|
||||||
|
|
||||||
|
const lookupRes = await apiRequest("GET", `/api/patients/by-insurance-id?insuranceId=${encodeURIComponent(storedMemberId)}`);
|
||||||
|
if (!lookupRes.ok) return;
|
||||||
|
const patient = await lookupRes.json();
|
||||||
|
if (!patient?.id) return;
|
||||||
|
|
||||||
|
const apptRes = await apiRequest("POST", "/api/ai/create-appointment-today", { patientId: patient.id });
|
||||||
|
const apptData = await apptRes.json();
|
||||||
|
if (apptRes.ok) {
|
||||||
|
toast({
|
||||||
|
title: "Appointment created",
|
||||||
|
description: `${patient.firstName ?? ""} ${patient.lastName ?? ""} added to today's schedule at ${apptData.startTime} (${apptData.column ?? "Column A"}).`.trim(),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
toast({
|
||||||
|
title: "Could not create appointment",
|
||||||
|
description: apptData.message ?? "Please add manually.",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
};
|
||||||
|
|
||||||
// Redirect from schedule page "Check Eligibility": prefill patient + optionally auto-trigger or scroll
|
// Redirect from schedule page "Check Eligibility": prefill patient + optionally auto-trigger or scroll
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
@@ -925,6 +985,7 @@ export default function InsuranceStatusPage() {
|
|||||||
onAutoTriggered={() => setTriggerTarget(null)}
|
onAutoTriggered={() => setTriggerTarget(null)}
|
||||||
onPdfReady={async (pdfId, fallbackFilename) => {
|
onPdfReady={async (pdfId, fallbackFilename) => {
|
||||||
const claimed = await tryClaimFromChatbot(selectedPatient?.id);
|
const claimed = await tryClaimFromChatbot(selectedPatient?.id);
|
||||||
|
void tryAppointmentFromChatbot();
|
||||||
if (!claimed) {
|
if (!claimed) {
|
||||||
setPreviewPdfId(pdfId);
|
setPreviewPdfId(pdfId);
|
||||||
setPreviewFallbackFilename(fallbackFilename ?? `eligibility_ddma_${memberId}.pdf`);
|
setPreviewFallbackFilename(fallbackFilename ?? `eligibility_ddma_${memberId}.pdf`);
|
||||||
@@ -945,6 +1006,7 @@ export default function InsuranceStatusPage() {
|
|||||||
onAutoTriggered={() => setTriggerTarget(null)}
|
onAutoTriggered={() => setTriggerTarget(null)}
|
||||||
onPdfReady={async (pdfId, fallbackFilename) => {
|
onPdfReady={async (pdfId, fallbackFilename) => {
|
||||||
const claimed = await tryClaimFromChatbot(selectedPatient?.id);
|
const claimed = await tryClaimFromChatbot(selectedPatient?.id);
|
||||||
|
void tryAppointmentFromChatbot();
|
||||||
if (!claimed) {
|
if (!claimed) {
|
||||||
setPreviewPdfId(pdfId);
|
setPreviewPdfId(pdfId);
|
||||||
setPreviewFallbackFilename(fallbackFilename ?? `eligibility_deltains_${memberId}.pdf`);
|
setPreviewFallbackFilename(fallbackFilename ?? `eligibility_deltains_${memberId}.pdf`);
|
||||||
@@ -961,7 +1023,8 @@ export default function InsuranceStatusPage() {
|
|||||||
firstName={firstName}
|
firstName={firstName}
|
||||||
lastName={lastName}
|
lastName={lastName}
|
||||||
isFormIncomplete={isFormIncomplete}
|
isFormIncomplete={isFormIncomplete}
|
||||||
onPdfReady={(pdfId, fallbackFilename) => {
|
onPdfReady={async (pdfId, fallbackFilename) => {
|
||||||
|
void tryAppointmentFromChatbot();
|
||||||
setPreviewPdfId(pdfId);
|
setPreviewPdfId(pdfId);
|
||||||
setPreviewFallbackFilename(
|
setPreviewFallbackFilename(
|
||||||
fallbackFilename ?? `eligibility_bcbs_ma_${memberId}.pdf`,
|
fallbackFilename ?? `eligibility_bcbs_ma_${memberId}.pdf`,
|
||||||
@@ -985,6 +1048,7 @@ export default function InsuranceStatusPage() {
|
|||||||
onAutoTriggered={() => setTriggerTarget(null)}
|
onAutoTriggered={() => setTriggerTarget(null)}
|
||||||
onPdfReady={async (pdfId, fallbackFilename) => {
|
onPdfReady={async (pdfId, fallbackFilename) => {
|
||||||
const claimed = await tryClaimFromChatbot(selectedPatient?.id);
|
const claimed = await tryClaimFromChatbot(selectedPatient?.id);
|
||||||
|
void tryAppointmentFromChatbot();
|
||||||
if (!claimed) {
|
if (!claimed) {
|
||||||
setPreviewPdfId(pdfId);
|
setPreviewPdfId(pdfId);
|
||||||
setPreviewFallbackFilename(fallbackFilename ?? `eligibility_tuftssco_${memberId}.pdf`);
|
setPreviewFallbackFilename(fallbackFilename ?? `eligibility_tuftssco_${memberId}.pdf`);
|
||||||
@@ -1005,6 +1069,7 @@ export default function InsuranceStatusPage() {
|
|||||||
onAutoTriggered={() => setTriggerTarget(null)}
|
onAutoTriggered={() => setTriggerTarget(null)}
|
||||||
onPdfReady={async (pdfId, fallbackFilename) => {
|
onPdfReady={async (pdfId, fallbackFilename) => {
|
||||||
const claimed = await tryClaimFromChatbot(selectedPatient?.id);
|
const claimed = await tryClaimFromChatbot(selectedPatient?.id);
|
||||||
|
void tryAppointmentFromChatbot();
|
||||||
if (!claimed) {
|
if (!claimed) {
|
||||||
setPreviewPdfId(pdfId);
|
setPreviewPdfId(pdfId);
|
||||||
setPreviewFallbackFilename(fallbackFilename ?? `eligibility_unitedsco_${memberId}.pdf`);
|
setPreviewFallbackFilename(fallbackFilename ?? `eligibility_unitedsco_${memberId}.pdf`);
|
||||||
@@ -1025,6 +1090,7 @@ export default function InsuranceStatusPage() {
|
|||||||
onAutoTriggered={() => setTriggerTarget(null)}
|
onAutoTriggered={() => setTriggerTarget(null)}
|
||||||
onPdfReady={async (pdfId, fallbackFilename) => {
|
onPdfReady={async (pdfId, fallbackFilename) => {
|
||||||
const claimed = await tryClaimFromChatbot(selectedPatient?.id);
|
const claimed = await tryClaimFromChatbot(selectedPatient?.id);
|
||||||
|
void tryAppointmentFromChatbot();
|
||||||
if (!claimed) {
|
if (!claimed) {
|
||||||
setPreviewPdfId(pdfId);
|
setPreviewPdfId(pdfId);
|
||||||
setPreviewFallbackFilename(fallbackFilename ?? `eligibility_cca_${memberId}.pdf`);
|
setPreviewFallbackFilename(fallbackFilename ?? `eligibility_cca_${memberId}.pdf`);
|
||||||
|
|||||||
Reference in New Issue
Block a user