feat(eligibility-check) - appointment page redirecting to eligibility page
This commit is contained in:
@@ -131,6 +131,40 @@ router.get(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /api/appointments/:id/patient
|
||||||
|
*/
|
||||||
|
router.get(
|
||||||
|
"/:id/patient",
|
||||||
|
async (req: Request, res: Response): Promise<any> => {
|
||||||
|
try {
|
||||||
|
const rawId = req.params.id;
|
||||||
|
if (!rawId) {
|
||||||
|
return res.status(400).json({ message: "Appointment ID is required" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const apptId = parseInt(rawId, 10);
|
||||||
|
if (Number.isNaN(apptId) || apptId <= 0) {
|
||||||
|
return res.status(400).json({ message: "Invalid appointment ID" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const patient = await storage.getPatientFromAppointmentId(apptId);
|
||||||
|
|
||||||
|
if (!patient) {
|
||||||
|
return res
|
||||||
|
.status(404)
|
||||||
|
.json({ message: "Patient not found for the given appointment" });
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.json(patient);
|
||||||
|
} catch (err) {
|
||||||
|
return res
|
||||||
|
.status(500)
|
||||||
|
.json({ message: "Failed to retrieve patient for appointment" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// Create a new appointment
|
// Create a new appointment
|
||||||
router.post(
|
router.post(
|
||||||
"/upsert",
|
"/upsert",
|
||||||
|
|||||||
@@ -70,6 +70,9 @@ export interface IStorage {
|
|||||||
getAllAppointments(): Promise<Appointment[]>;
|
getAllAppointments(): Promise<Appointment[]>;
|
||||||
getAppointmentsByUserId(userId: number): Promise<Appointment[]>;
|
getAppointmentsByUserId(userId: number): Promise<Appointment[]>;
|
||||||
getAppointmentsByPatientId(patientId: number): Promise<Appointment[]>;
|
getAppointmentsByPatientId(patientId: number): Promise<Appointment[]>;
|
||||||
|
getPatientFromAppointmentId(
|
||||||
|
appointmentId: number
|
||||||
|
): Promise<Patient | undefined>;
|
||||||
getRecentAppointments(limit: number, offset: number): Promise<Appointment[]>;
|
getRecentAppointments(limit: number, offset: number): Promise<Appointment[]>;
|
||||||
getAppointmentsOnRange(start: Date, end: Date): Promise<Appointment[]>;
|
getAppointmentsOnRange(start: Date, end: Date): Promise<Appointment[]>;
|
||||||
createAppointment(appointment: InsertAppointment): Promise<Appointment>;
|
createAppointment(appointment: InsertAppointment): Promise<Appointment>;
|
||||||
@@ -393,6 +396,16 @@ export const storage: IStorage = {
|
|||||||
return await db.appointment.findMany({ where: { patientId } });
|
return await db.appointment.findMany({ where: { patientId } });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async getPatientFromAppointmentId(
|
||||||
|
appointmentId: number
|
||||||
|
): Promise<Patient | undefined> {
|
||||||
|
const appointment = await db.appointment.findUnique({
|
||||||
|
where: { id: appointmentId },
|
||||||
|
include: { patient: true },
|
||||||
|
});
|
||||||
|
return appointment?.patient ?? undefined;
|
||||||
|
},
|
||||||
|
|
||||||
async getAppointmentsOnRange(start: Date, end: Date): Promise<Appointment[]> {
|
async getAppointmentsOnRange(start: Date, end: Date): Promise<Appointment[]> {
|
||||||
return db.appointment.findMany({
|
return db.appointment.findMany({
|
||||||
where: {
|
where: {
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ import {
|
|||||||
ChevronRight,
|
ChevronRight,
|
||||||
Move,
|
Move,
|
||||||
Trash2,
|
Trash2,
|
||||||
ShieldCheck,
|
|
||||||
FileText,
|
|
||||||
CreditCard,
|
CreditCard,
|
||||||
ClipboardList,
|
ClipboardList,
|
||||||
StickyNote,
|
StickyNote,
|
||||||
@@ -95,6 +93,8 @@ export default function AppointmentsPage() {
|
|||||||
appointmentId?: number;
|
appointmentId?: number;
|
||||||
}>({ open: false });
|
}>({ open: false });
|
||||||
|
|
||||||
|
const [, setLocation] = useLocation();
|
||||||
|
|
||||||
// Create context menu hook
|
// Create context menu hook
|
||||||
const { show } = useContextMenu({
|
const { show } = useContextMenu({
|
||||||
id: APPOINTMENT_CONTEXT_MENU_ID,
|
id: APPOINTMENT_CONTEXT_MENU_ID,
|
||||||
@@ -652,7 +652,7 @@ export default function AppointmentsPage() {
|
|||||||
|
|
||||||
// -------------------
|
// -------------------
|
||||||
const handleCheckEligibility = (appointmentId: number) => {
|
const handleCheckEligibility = (appointmentId: number) => {
|
||||||
console.log(`Checking eligibility for appointment: ${appointmentId}`);
|
setLocation(`/insurance-status?appointmentId=${appointmentId}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClaimsPreAuth = (appointmentId: number) => {
|
const handleClaimsPreAuth = (appointmentId: number) => {
|
||||||
|
|||||||
@@ -26,8 +26,9 @@ import { InsertPatient, Patient } from "@repo/db/types";
|
|||||||
import { DateInput } from "@/components/ui/dateInput";
|
import { DateInput } from "@/components/ui/dateInput";
|
||||||
import { QK_PATIENTS_BASE } from "@/components/patients/patient-table";
|
import { QK_PATIENTS_BASE } from "@/components/patients/patient-table";
|
||||||
import { PdfPreviewModal } from "@/components/insurance-status/pdf-preview-modal";
|
import { PdfPreviewModal } from "@/components/insurance-status/pdf-preview-modal";
|
||||||
|
import { useLocation } from "wouter";
|
||||||
|
|
||||||
export default function EligibilityClaimStatusPage() {
|
export default function InsuranceStatusPage() {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
@@ -35,6 +36,7 @@ export default function EligibilityClaimStatusPage() {
|
|||||||
(state) => state.seleniumEligibilityCheckTask
|
(state) => state.seleniumEligibilityCheckTask
|
||||||
);
|
);
|
||||||
const [selectedPatient, setSelectedPatient] = useState<Patient | null>(null);
|
const [selectedPatient, setSelectedPatient] = useState<Patient | null>(null);
|
||||||
|
const [location] = useLocation();
|
||||||
|
|
||||||
// Insurance eligibility and claim check form fields
|
// Insurance eligibility and claim check form fields
|
||||||
const [memberId, setMemberId] = useState("");
|
const [memberId, setMemberId] = useState("");
|
||||||
@@ -303,6 +305,60 @@ export default function EligibilityClaimStatusPage() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
const appointmentId = params.get("appointmentId");
|
||||||
|
if (!appointmentId) return;
|
||||||
|
|
||||||
|
const id = Number(appointmentId);
|
||||||
|
if (Number.isNaN(id) || id <= 0) return;
|
||||||
|
|
||||||
|
let cancelled = false;
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const res = await apiRequest("GET", `/api/appointments/${id}/patient`);
|
||||||
|
if (!res.ok) {
|
||||||
|
// try to read body for a helpful error message, otherwise show generic
|
||||||
|
let body: any = null;
|
||||||
|
try {
|
||||||
|
body = await res.json();
|
||||||
|
} catch {}
|
||||||
|
if (!cancelled) {
|
||||||
|
toast({
|
||||||
|
title: "Failed to load patient",
|
||||||
|
description:
|
||||||
|
body?.message ??
|
||||||
|
body?.error ??
|
||||||
|
`Could not fetch patient for appointment ${id}.`,
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
// endpoint may return either { patient } or patient object directly
|
||||||
|
const patient = data?.patient ?? data;
|
||||||
|
if (!cancelled && patient) setSelectedPatient(patient as Patient);
|
||||||
|
} catch (err: any) {
|
||||||
|
if (!cancelled) {
|
||||||
|
console.error("Error fetching patient for appointment:", err);
|
||||||
|
toast({
|
||||||
|
title: "Error",
|
||||||
|
description:
|
||||||
|
err?.message ?? "An error occurred while fetching patient.",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
cancelled = true;
|
||||||
|
};
|
||||||
|
}, [location]); // re-run when wouter location changes
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<SeleniumTaskBanner
|
<SeleniumTaskBanner
|
||||||
|
|||||||
Reference in New Issue
Block a user