From 0930b70bfd5b3f8bf4b4934ef2449a1f010ef935 Mon Sep 17 00:00:00 2001 From: Potenz Date: Mon, 28 Jul 2025 17:49:01 +0530 Subject: [PATCH] claim page done --- .../{appointements.ts => appointments.ts} | 106 +++++++--- apps/Backend/src/routes/index.ts | 2 +- apps/Backend/src/routes/patients.ts | 23 ++ .../claims/claims-of-patient-table.tsx | 13 +- .../components/claims/claims-recent-table.tsx | 1 - .../src/components/patients/patient-table.tsx | 17 +- apps/Frontend/src/pages/claims-page.tsx | 196 ++---------------- 7 files changed, 152 insertions(+), 206 deletions(-) rename apps/Backend/src/routes/{appointements.ts => appointments.ts} (78%) diff --git a/apps/Backend/src/routes/appointements.ts b/apps/Backend/src/routes/appointments.ts similarity index 78% rename from apps/Backend/src/routes/appointements.ts rename to apps/Backend/src/routes/appointments.ts index 64c6e83..3953238 100644 --- a/apps/Backend/src/routes/appointements.ts +++ b/apps/Backend/src/routes/appointments.ts @@ -183,6 +183,8 @@ router.post( }); const userId = req.user!.id; + const originalStartTime = appointmentData.startTime; + const MAX_END_TIME = "18:30"; // 1. Verify patient exists and belongs to user const patient = await storage.getPatient(appointmentData.patientId); @@ -196,39 +198,87 @@ router.post( }); } - // 2. Check if patient already has an appointment on the same date and time. - const sameDayAppointment = await storage.getPatientAppointmentByDateTime( - appointmentData.patientId, - appointmentData.date, - appointmentData.startTime - ); - // 3. Check if there's already an appointment at this time slot of Staff. - const staffConflict = await storage.getStaffAppointmentByDateTime( - appointmentData.staffId, - appointmentData.date, - appointmentData.startTime, - sameDayAppointment?.id - ); + // 2. Attempt to find the next available slot + let [hour, minute] = originalStartTime.split(":").map(Number); - if (staffConflict) { - return res.status(409).json({ - message: - "This time slot is already booked for the selected staff. Please choose another time or staff member.", - }); - } + const pad = (n: number) => n.toString().padStart(2, "0"); - // 4. If same-day appointment exists, update it - if (sameDayAppointment?.id !== undefined) { - const updatedAppointment = await storage.updateAppointment( - sameDayAppointment.id, - appointmentData + while (`${pad(hour)}:${pad(minute)}` <= MAX_END_TIME) { + const currentStartTime = `${pad(hour)}:${pad(minute)}`; + + // Check patient appointment at this time + const sameDayAppointment = + await storage.getPatientAppointmentByDateTime( + appointmentData.patientId, + appointmentData.date, + currentStartTime + ); + + // Check staff conflict at this time + const staffConflict = await storage.getStaffAppointmentByDateTime( + appointmentData.staffId, + appointmentData.date, + currentStartTime, + sameDayAppointment?.id // Ignore self if updating ); - return res.status(200).json(updatedAppointment); + + if (!staffConflict) { + const endMinute = minute + 30; + let endHour = hour + Math.floor(endMinute / 60); + let realEndMinute = endMinute % 60; + + const currentEndTime = `${pad(endHour)}:${pad(realEndMinute)}`; + + const payload = { + ...appointmentData, + startTime: currentStartTime, + endTime: currentEndTime, + }; + + let responseData; + + if (sameDayAppointment?.id !== undefined) { + const updated = await storage.updateAppointment( + sameDayAppointment.id, + payload + ); + responseData = { + ...updated, + originalRequestedTime: originalStartTime, + finalScheduledTime: currentStartTime, + message: + originalStartTime !== currentStartTime + ? `Your requested time (${originalStartTime}) was unavailable. Appointment was updated to ${currentStartTime}.` + : `Appointment successfully updated at ${currentStartTime}.`, + }; + return res.status(200).json(responseData); + } + + const created = await storage.createAppointment(payload); + responseData = { + ...created, + originalRequestedTime: originalStartTime, + finalScheduledTime: currentStartTime, + message: + originalStartTime !== currentStartTime + ? `Your requested time (${originalStartTime}) was unavailable. Appointment was scheduled at ${currentStartTime}.` + : `Appointment successfully scheduled at ${currentStartTime}.`, + }; + return res.status(201).json(responseData); + } + + // Move to next 30-min slot + minute += 30; + if (minute >= 60) { + hour += 1; + minute = 0; + } } - // 6. Otherwise, create a new appointment - const newAppointment = await storage.createAppointment(appointmentData); - return res.status(201).json(newAppointment); + return res.status(409).json({ + message: + "No available slots remaining until 6:30 PM for this Staff. Please choose another day.", + }); } catch (error) { console.error("Error in upsert appointment:", error); diff --git a/apps/Backend/src/routes/index.ts b/apps/Backend/src/routes/index.ts index 2c594a3..96a8059 100644 --- a/apps/Backend/src/routes/index.ts +++ b/apps/Backend/src/routes/index.ts @@ -1,6 +1,6 @@ import { Router } from 'express'; import patientRoutes from './patients'; -import appointmentRoutes from './appointements' +import appointmentRoutes from './appointments' import userRoutes from './users' import staffRoutes from './staffs' import pdfExtractionRoutes from './pdfExtraction'; diff --git a/apps/Backend/src/routes/patients.ts b/apps/Backend/src/routes/patients.ts index 936d0db..1e147ae 100644 --- a/apps/Backend/src/routes/patients.ts +++ b/apps/Backend/src/routes/patients.ts @@ -159,6 +159,29 @@ router.get("/search", async (req: Request, res: Response): Promise => { } }); + +// get patient by insurance id +router.get("/by-insurance-id", async (req: Request, res: Response): Promise => { + const insuranceId = req.query.insuranceId?.toString(); + + if (!insuranceId) { + return res.status(400).json({ error: "Missing insuranceId" }); + } + + try { + const patient = await storage.getPatientByInsuranceId(insuranceId); + + if (patient) { + return res.status(200).json(patient); + } else { + return res.status(404).json(null); + } + } catch (err) { + console.error("Failed to lookup patient:", err); + return res.status(500).json({ error: "Internal server error" }); + } +}); + // Get a single patient by ID router.get( "/:id", diff --git a/apps/Frontend/src/components/claims/claims-of-patient-table.tsx b/apps/Frontend/src/components/claims/claims-of-patient-table.tsx index b546def..15c1c51 100644 --- a/apps/Frontend/src/components/claims/claims-of-patient-table.tsx +++ b/apps/Frontend/src/components/claims/claims-of-patient-table.tsx @@ -24,7 +24,11 @@ const PatientSchema = ( }); type Patient = z.infer; -export default function ClaimsOfPatientModal() { +interface ClaimsOfPatientModalProps { + onNewClaim?: (patientId: number) => void; +} + +export default function ClaimsOfPatientModal({ onNewClaim }: ClaimsOfPatientModalProps) { const [selectedPatient, setSelectedPatient] = useState(null); const [isModalOpen, setIsModalOpen] = useState(false); const [claimsPage, setClaimsPage] = useState(1); @@ -70,13 +74,18 @@ export default function ClaimsOfPatientModal() { Patient Records - View and manage all patient information + Select any patient and View all their recent claims. + + + Also create new claim for any patients. diff --git a/apps/Frontend/src/components/claims/claims-recent-table.tsx b/apps/Frontend/src/components/claims/claims-recent-table.tsx index 7591729..7c7e6cb 100644 --- a/apps/Frontend/src/components/claims/claims-recent-table.tsx +++ b/apps/Frontend/src/components/claims/claims-recent-table.tsx @@ -94,7 +94,6 @@ export default function ClaimsRecentTable({ patientId, }: ClaimsRecentTableProps) { const { toast } = useToast(); - const { user } = useAuth(); const [isViewClaimOpen, setIsViewClaimOpen] = useState(false); const [isEditClaimOpen, setIsEditClaimOpen] = useState(false); diff --git a/apps/Frontend/src/components/patients/patient-table.tsx b/apps/Frontend/src/components/patients/patient-table.tsx index 08910f7..f007d78 100644 --- a/apps/Frontend/src/components/patients/patient-table.tsx +++ b/apps/Frontend/src/components/patients/patient-table.tsx @@ -8,7 +8,7 @@ import { TableRow, } from "@/components/ui/table"; import { Button } from "@/components/ui/button"; -import { Delete, Edit, Eye } from "lucide-react"; +import { Delete, Edit, Eye, FileCheck } from "lucide-react"; import { Avatar, AvatarFallback } from "@/components/ui/avatar"; import { Pagination, @@ -69,6 +69,8 @@ interface PatientTableProps { allowView?: boolean; allowDelete?: boolean; allowCheckbox?: boolean; + allowNewClaim?: boolean; + onNewClaim?: (patientId: number) => void; onSelectPatient?: (patient: Patient | null) => void; onPageChange?: (page: number) => void; onSearchChange?: (searchTerm: string) => void; @@ -79,6 +81,8 @@ export function PatientTable({ allowView, allowDelete, allowCheckbox, + allowNewClaim, + onNewClaim, onSelectPatient, onPageChange, onSearchChange, @@ -481,6 +485,17 @@ export function PatientTable({ )} + {allowNewClaim && ( + + )} {allowView && (