feat(redirect via aptmnt page) - added feature
This commit is contained in:
@@ -147,7 +147,7 @@ export default function ClaimsPage() {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// helper
|
// helpers
|
||||||
const getPatientByInsuranceId = async (insuranceId: string) => {
|
const getPatientByInsuranceId = async (insuranceId: string) => {
|
||||||
const res = await apiRequest(
|
const res = await apiRequest(
|
||||||
"GET",
|
"GET",
|
||||||
@@ -163,7 +163,26 @@ export default function ClaimsPage() {
|
|||||||
return res.json();
|
return res.json();
|
||||||
};
|
};
|
||||||
|
|
||||||
// workflow starts from there - this params are set by pdf extraction/patient page. then used in claim page here.
|
// small helper: remove given query params from the current URL (silent, no reload)
|
||||||
|
const clearUrlParams = (params: string[]) => {
|
||||||
|
try {
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
let changed = false;
|
||||||
|
for (const p of params) {
|
||||||
|
if (url.searchParams.has(p)) {
|
||||||
|
url.searchParams.delete(p);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
window.history.replaceState({}, document.title, url.toString());
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// ignore (URL API or history.replaceState might throw in very old envs)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// case1: - this params are set by pdf extraction/patient page. then used in claim page here.
|
||||||
const [location] = useLocation();
|
const [location] = useLocation();
|
||||||
const { name, memberId, dob, newPatient } = useMemo(() => {
|
const { name, memberId, dob, newPatient } = useMemo(() => {
|
||||||
const search = window.location.search;
|
const search = window.location.search;
|
||||||
@@ -180,27 +199,35 @@ export default function ClaimsPage() {
|
|||||||
setSelectedPatientId(patientId);
|
setSelectedPatientId(patientId);
|
||||||
setIsClaimFormOpen(true);
|
setIsClaimFormOpen(true);
|
||||||
};
|
};
|
||||||
// ✅ FIRST: if ?newPatient=<id> is present, open claim form directly
|
|
||||||
|
// case2: redirect from patient-add-form. if ?newPatient=<id> is present, open claim form directly
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (newPatient) {
|
if (!newPatient) return;
|
||||||
|
|
||||||
const id = Number(newPatient);
|
const id = Number(newPatient);
|
||||||
if (Number.isFinite(id) && id > 0) {
|
if (!Number.isFinite(id) || id <= 0) return;
|
||||||
|
|
||||||
handleNewClaim(id);
|
handleNewClaim(id);
|
||||||
}
|
clearUrlParams(["newPatient"]);
|
||||||
}
|
|
||||||
}, [newPatient]);
|
}, [newPatient]);
|
||||||
|
|
||||||
// existing flow: only runs when there is no ?newPatient and we have memberId+dob
|
// case3: only runs when there is no ?newPatient and we have memberId+dob
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (memberId && dob) {
|
if (!memberId || !dob) return;
|
||||||
|
|
||||||
|
let cancelled = false;
|
||||||
|
|
||||||
// if matching patient found then simply send its id to claim form,
|
// if matching patient found then simply send its id to claim form,
|
||||||
// if not then create new patient then send its id to claim form.
|
// if not then create new patient then send its id to claim form.
|
||||||
const fetchMatchingPatient = async () => {
|
const fetchMatchingPatient = async () => {
|
||||||
try {
|
try {
|
||||||
const matchingPatient = await getPatientByInsuranceId(memberId);
|
const matchingPatient = await getPatientByInsuranceId(memberId);
|
||||||
|
|
||||||
|
if (cancelled) return;
|
||||||
|
|
||||||
if (matchingPatient) {
|
if (matchingPatient) {
|
||||||
handleNewClaim(matchingPatient.id);
|
handleNewClaim(matchingPatient.id);
|
||||||
|
clearUrlParams(["memberId", "dob", "name"]);
|
||||||
} else {
|
} else {
|
||||||
const [firstName, ...rest] = name.trim().split(" ");
|
const [firstName, ...rest] = name.trim().split(" ");
|
||||||
const lastName = rest.join(" ") || "";
|
const lastName = rest.join(" ") || "";
|
||||||
@@ -219,18 +246,93 @@ export default function ClaimsPage() {
|
|||||||
|
|
||||||
addPatientMutation.mutate(newPatient, {
|
addPatientMutation.mutate(newPatient, {
|
||||||
onSuccess: (created) => {
|
onSuccess: (created) => {
|
||||||
|
if (cancelled) return;
|
||||||
handleNewClaim(created.id);
|
handleNewClaim(created.id);
|
||||||
|
clearUrlParams(["memberId", "dob", "name"]);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
if (!cancelled) {
|
||||||
console.error("Error checking/creating patient:", err);
|
console.error("Error checking/creating patient:", err);
|
||||||
|
toast({
|
||||||
|
title: "Error",
|
||||||
|
description: "Error checking/creating patient from URL params.",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchMatchingPatient();
|
fetchMatchingPatient();
|
||||||
}
|
|
||||||
|
return () => {
|
||||||
|
cancelled = true;
|
||||||
|
};
|
||||||
}, [memberId]);
|
}, [memberId]);
|
||||||
|
|
||||||
|
// case4 - redirect from appointment page:
|
||||||
|
// If ?appointmentId= is present (and no ?newPatient param), fetch appointment->patient and open claim form
|
||||||
|
useEffect(() => {
|
||||||
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
const appointmentIdParam = params.get("appointmentId");
|
||||||
|
|
||||||
|
// If newPatient flow is present, prefer it and do nothing here
|
||||||
|
if (newPatient) return;
|
||||||
|
if (!appointmentIdParam) return;
|
||||||
|
|
||||||
|
const appointmentId = Number(appointmentIdParam);
|
||||||
|
if (!Number.isFinite(appointmentId) || appointmentId <= 0) return;
|
||||||
|
|
||||||
|
let cancelled = false;
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const res = await apiRequest(
|
||||||
|
"GET",
|
||||||
|
`/api/appointments/${appointmentId}/patient`
|
||||||
|
);
|
||||||
|
if (!res.ok) {
|
||||||
|
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 ${appointmentId}.`,
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
const patient = data?.patient ?? data;
|
||||||
|
if (!cancelled && patient && patient.id) {
|
||||||
|
handleNewClaim(patient.id);
|
||||||
|
clearUrlParams(["appointmentId"]);
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
if (!cancelled) {
|
||||||
|
console.error("Error fetching patient for appointment:", err);
|
||||||
|
toast({
|
||||||
|
title: "Error",
|
||||||
|
description: err?.message ?? "Failed to fetch patient.",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
cancelled = true;
|
||||||
|
};
|
||||||
|
}, [location, newPatient]);
|
||||||
|
|
||||||
// 1. upsert appointment.
|
// 1. upsert appointment.
|
||||||
const handleAppointmentSubmit = async (
|
const handleAppointmentSubmit = async (
|
||||||
appointmentData: InsertAppointment | UpdateAppointment
|
appointmentData: InsertAppointment | UpdateAppointment
|
||||||
|
|||||||
Reference in New Issue
Block a user