patient creation done
This commit is contained in:
@@ -144,7 +144,7 @@ router.get("/search", async (req: Request, res: Response): Promise<any> => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const [patients, totalCount] = await Promise.all([
|
const [patients, totalCount] = await Promise.all([
|
||||||
storage.searchPatients({
|
storage.searchPatients({
|
||||||
filters,
|
filters,
|
||||||
limit: parseInt(limit),
|
limit: parseInt(limit),
|
||||||
offset: parseInt(offset),
|
offset: parseInt(offset),
|
||||||
@@ -201,6 +201,18 @@ router.post("/", async (req: Request, res: Response): Promise<any> => {
|
|||||||
userId: req.user!.id,
|
userId: req.user!.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Check for duplicate insuranceId if it's provided
|
||||||
|
if (patientData.insuranceId) {
|
||||||
|
const existingPatient = await storage.getPatientByInsuranceId(
|
||||||
|
patientData.insuranceId
|
||||||
|
);
|
||||||
|
|
||||||
|
if (existingPatient) {
|
||||||
|
return res.status(409).json({
|
||||||
|
message: "A patient with this insurance ID already exists.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const patient = await storage.createPatient(patientData);
|
const patient = await storage.createPatient(patientData);
|
||||||
|
|
||||||
@@ -244,8 +256,26 @@ router.put(
|
|||||||
// Validate request body
|
// Validate request body
|
||||||
const patientData = updatePatientSchema.parse(req.body);
|
const patientData = updatePatientSchema.parse(req.body);
|
||||||
|
|
||||||
|
// If updating insuranceId, check for uniqueness (excluding self)
|
||||||
|
if (
|
||||||
|
patientData.insuranceId &&
|
||||||
|
patientData.insuranceId !== existingPatient.insuranceId
|
||||||
|
) {
|
||||||
|
const duplicatePatient = await storage.getPatientByInsuranceId(
|
||||||
|
patientData.insuranceId
|
||||||
|
);
|
||||||
|
if (duplicatePatient && duplicatePatient.id !== patientId) {
|
||||||
|
return res.status(409).json({
|
||||||
|
message: "Another patient with this insurance ID already exists.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update patient
|
// Update patient
|
||||||
const updatedPatient = await storage.updatePatient(patientId, patientData);
|
const updatedPatient = await storage.updatePatient(
|
||||||
|
patientId,
|
||||||
|
patientData
|
||||||
|
);
|
||||||
res.json(updatedPatient);
|
res.json(updatedPatient);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof z.ZodError) {
|
if (error instanceof z.ZodError) {
|
||||||
|
|||||||
@@ -165,6 +165,7 @@ export interface IStorage {
|
|||||||
|
|
||||||
// Patient methods
|
// Patient methods
|
||||||
getPatient(id: number): Promise<Patient | undefined>;
|
getPatient(id: number): Promise<Patient | undefined>;
|
||||||
|
getPatientByInsuranceId(insuranceId: string): Promise<Patient | null>;
|
||||||
getPatientsByUserId(userId: number): Promise<Patient[]>;
|
getPatientsByUserId(userId: number): Promise<Patient[]>;
|
||||||
getRecentPatients(limit: number, offset: number): Promise<Patient[]>;
|
getRecentPatients(limit: number, offset: number): Promise<Patient[]>;
|
||||||
getTotalPatientCount(): Promise<number>;
|
getTotalPatientCount(): Promise<number>;
|
||||||
@@ -315,6 +316,12 @@ export const storage: IStorage = {
|
|||||||
return await db.patient.findMany({ where: { userId } });
|
return await db.patient.findMany({ where: { userId } });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async getPatientByInsuranceId(insuranceId: string): Promise<Patient | null> {
|
||||||
|
return db.patient.findFirst({
|
||||||
|
where: { insuranceId },
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
async getRecentPatients(limit: number, offset: number): Promise<Patient[]> {
|
async getRecentPatients(limit: number, offset: number): Promise<Patient[]> {
|
||||||
return db.patient.findMany({
|
return db.patient.findMany({
|
||||||
skip: offset,
|
skip: offset,
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ const API_BASE_URL = import.meta.env.VITE_API_BASE_URL_BACKEND ?? "";
|
|||||||
|
|
||||||
async function throwIfResNotOk(res: Response) {
|
async function throwIfResNotOk(res: Response) {
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
|
|
||||||
if (res.status === 401 || res.status === 403) {
|
if (res.status === 401 || res.status === 403) {
|
||||||
localStorage.removeItem("token");
|
localStorage.removeItem("token");
|
||||||
if (!window.location.pathname.startsWith("/auth")) {
|
if (!window.location.pathname.startsWith("/auth")) {
|
||||||
@@ -13,7 +12,19 @@ async function throwIfResNotOk(res: Response) {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new Error(`${res.status}: ${res.statusText}`);
|
|
||||||
|
// Try to parse the response as JSON for a more meaningful error message
|
||||||
|
let message = `${res.status}: ${res.statusText}`;
|
||||||
|
try {
|
||||||
|
const errorBody = await res.json();
|
||||||
|
if (errorBody?.message) {
|
||||||
|
message = errorBody.message;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// ignore JSON parse errors, keep default message
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import {
|
|||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from "@/components/ui/popover";
|
} from "@/components/ui/popover";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
import { apiRequest, queryClient } from "@/lib/queryClient";
|
||||||
|
|
||||||
const PatientSchema = (
|
const PatientSchema = (
|
||||||
PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
|
PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
|
||||||
@@ -34,6 +35,15 @@ const PatientSchema = (
|
|||||||
});
|
});
|
||||||
type Patient = z.infer<typeof PatientSchema>;
|
type Patient = z.infer<typeof PatientSchema>;
|
||||||
|
|
||||||
|
const insertPatientSchema = (
|
||||||
|
PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
|
||||||
|
).omit({
|
||||||
|
id: true,
|
||||||
|
createdAt: true,
|
||||||
|
userId: true,
|
||||||
|
});
|
||||||
|
type InsertPatient = z.infer<typeof insertPatientSchema>;
|
||||||
|
|
||||||
export default function InsuranceEligibilityPage() {
|
export default function InsuranceEligibilityPage() {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
@@ -53,23 +63,55 @@ export default function InsuranceEligibilityPage() {
|
|||||||
|
|
||||||
// Populate fields from selected patient
|
// Populate fields from selected patient
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedPatient) {
|
if (selectedPatient) {
|
||||||
setMemberId(selectedPatient.insuranceId ?? "");
|
setMemberId(selectedPatient.insuranceId ?? "");
|
||||||
setFirstName(selectedPatient.firstName ?? "");
|
setFirstName(selectedPatient.firstName ?? "");
|
||||||
setLastName(selectedPatient.lastName ?? "");
|
setLastName(selectedPatient.lastName ?? "");
|
||||||
|
|
||||||
const dob = selectedPatient.dateOfBirth
|
const dob = selectedPatient.dateOfBirth
|
||||||
? new Date(selectedPatient.dateOfBirth)
|
? new Date(selectedPatient.dateOfBirth)
|
||||||
: undefined;
|
: undefined;
|
||||||
setDateOfBirth(dob);
|
setDateOfBirth(dob);
|
||||||
} else {
|
} else {
|
||||||
setMemberId("");
|
setMemberId("");
|
||||||
setFirstName("");
|
setFirstName("");
|
||||||
setLastName("");
|
setLastName("");
|
||||||
setDateOfBirth(undefined);
|
setDateOfBirth(undefined);
|
||||||
}
|
}
|
||||||
}, [selectedPatient]);
|
}, [selectedPatient]);
|
||||||
|
|
||||||
|
// Add patient mutation
|
||||||
|
const addPatientMutation = useMutation({
|
||||||
|
mutationFn: async (patient: InsertPatient) => {
|
||||||
|
const res = await apiRequest("POST", "/api/patients/", patient);
|
||||||
|
return res.json();
|
||||||
|
},
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["patients"] });
|
||||||
|
toast({
|
||||||
|
title: "Success",
|
||||||
|
description: "Patient added successfully!",
|
||||||
|
variant: "default",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onError: (error: any) => {
|
||||||
|
const msg = error.message;
|
||||||
|
|
||||||
|
if (msg === "A patient with this insurance ID already exists.") {
|
||||||
|
toast({
|
||||||
|
title: "Patient already exists",
|
||||||
|
description: msg,
|
||||||
|
variant: "default",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
toast({
|
||||||
|
title: "Error",
|
||||||
|
description: `Failed to add patient: ${msg}`,
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// Insurance eligibility check mutation
|
// Insurance eligibility check mutation
|
||||||
const checkInsuranceMutation = useMutation({
|
const checkInsuranceMutation = useMutation({
|
||||||
@@ -114,16 +156,34 @@ export default function InsuranceEligibilityPage() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Handle insurance provider button clicks
|
// Handle insurance provider button clicks
|
||||||
const handleMHButton= () => {
|
const handleMHButton = () => {
|
||||||
|
// Form Fields check
|
||||||
if (!memberId || !dateOfBirth || !firstName) {
|
if (!memberId || !dateOfBirth || !firstName) {
|
||||||
toast({
|
toast({
|
||||||
title: "Missing Fields",
|
title: "Missing Fields",
|
||||||
description:
|
description:
|
||||||
"Please fill in all the required fields: Member ID, Date of Birth, First Name.",
|
"Please fill in all the required fields: Member ID, Date of Birth, First Name.",
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adding patient if same patient exists then it will skip.
|
||||||
|
const newPatient: InsertPatient = {
|
||||||
|
firstName,
|
||||||
|
lastName,
|
||||||
|
dateOfBirth: dateOfBirth,
|
||||||
|
gender: "",
|
||||||
|
phone: "",
|
||||||
|
userId: user?.id ?? 1,
|
||||||
|
status: "active",
|
||||||
|
insuranceId: memberId,
|
||||||
|
};
|
||||||
|
addPatientMutation.mutate(newPatient);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user