diff --git a/apps/Frontend/src/components/claims/claim-form-handler.tsx b/apps/Frontend/src/components/claims/claim-form-handler.tsx deleted file mode 100644 index 048c217..0000000 --- a/apps/Frontend/src/components/claims/claim-form-handler.tsx +++ /dev/null @@ -1,409 +0,0 @@ -import { AppDispatch } from "@/redux/store"; -import { useState, useEffect, useMemo } from "react"; -import { useMutation, useQuery } from "@tanstack/react-query"; -import { TopAppBar } from "@/components/layout/top-app-bar"; -import { Sidebar } from "@/components/layout/sidebar"; -import { - Card, - CardHeader, - CardTitle, - CardContent, - CardDescription, -} from "@/components/ui/card"; -import { ClaimForm } from "@/components/claims/claim-form"; -import { useToast } from "@/hooks/use-toast"; -import { useAuth } from "@/hooks/use-auth"; -import { - PatientUncheckedCreateInputObjectSchema, - AppointmentUncheckedCreateInputObjectSchema, - ClaimUncheckedCreateInputObjectSchema, -} from "@repo/db/usedSchemas"; -import { FileCheck } from "lucide-react"; -import { parse } from "date-fns"; -import { z } from "zod"; -import { apiRequest, queryClient } from "@/lib/queryClient"; -import { useLocation } from "wouter"; -import { useAppDispatch, useAppSelector } from "@/redux/hooks"; -import { - setTaskStatus, - clearTaskStatus, -} from "@/redux/slices/seleniumClaimSubmitTaskSlice"; -import { SeleniumTaskBanner } from "@/components/ui/selenium-task-banner"; -import { formatLocalDate, parseLocalDate } from "@/utils/dateUtils"; -import ClaimsRecentTable from "@/components/claims/claims-recent-table"; -import ClaimsOfPatientModal from "@/components/claims/claims-of-patient-table"; - -//creating types out of schema auto generated. -type Appointment = z.infer; -type Claim = z.infer; - -const insertAppointmentSchema = ( - AppointmentUncheckedCreateInputObjectSchema as unknown as z.ZodObject -).omit({ - id: true, - createdAt: true, -}); -type InsertAppointment = z.infer; - -const updateAppointmentSchema = ( - AppointmentUncheckedCreateInputObjectSchema as unknown as z.ZodObject -) - .omit({ - id: true, - createdAt: true, - }) - .partial(); -type UpdateAppointment = z.infer; - -const PatientSchema = ( - PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject -).omit({ - appointments: true, -}); -type Patient = z.infer; - -const insertPatientSchema = ( - PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject -).omit({ - id: true, - createdAt: true, -}); -type InsertPatient = z.infer; - -const updatePatientSchema = ( - PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject -) - .omit({ - id: true, - createdAt: true, - userId: true, - }) - .partial(); - -type UpdatePatient = z.infer; - -const { toast } = useToast(); - -// Add patient mutation -const addPatientMutation = useMutation({ - mutationFn: async (patient: InsertPatient) => { - const res = await apiRequest("POST", "/api/patients/", patient); - return res.json(); - }, - onSuccess: (newPatient) => { - queryClient.invalidateQueries({ queryKey: ["/api/patients/"] }); - toast({ - title: "Success", - description: "Patient added successfully!", - variant: "default", - }); - }, - onError: (error) => { - toast({ - title: "Error", - description: `Failed to add patient: ${error.message}`, - variant: "destructive", - }); - }, -}); - -// Update patient mutation -const updatePatientMutation = useMutation({ - mutationFn: async ({ - id, - patient, - }: { - id: number; - patient: UpdatePatient; - }) => { - const res = await apiRequest("PUT", `/api/patients/${id}`, patient); - return res.json(); - }, - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: ["/api/patients/"] }); - toast({ - title: "Success", - description: "Patient updated successfully!", - variant: "default", - }); - }, - onError: (error) => { - toast({ - title: "Error", - description: `Failed to update patient: ${error.message}`, - variant: "destructive", - }); - }, -}); - -// Create/upsert appointment mutation -const createAppointmentMutation = useMutation({ - mutationFn: async (appointment: InsertAppointment) => { - const res = await apiRequest("POST", "/api/appointments/upsert", appointment); - return await res.json(); - }, - onSuccess: () => { - toast({ - title: "Success", - description: "Appointment created successfully.", - }); - // Invalidate both appointments and patients queries - queryClient.invalidateQueries({ queryKey: ["/api/appointments/all"] }); - queryClient.invalidateQueries({ queryKey: ["/api/patients/"] }); - }, - onError: (error: Error) => { - toast({ - title: "Error", - description: `Failed to create appointment: ${error.message}`, - variant: "destructive", - }); - }, -}); - -// Update appointment mutation -const updateAppointmentMutation = useMutation({ - mutationFn: async ({ - id, - appointment, - }: { - id: number; - appointment: UpdateAppointment; - }) => { - const res = await apiRequest("PUT", `/api/appointments/${id}`, appointment); - return await res.json(); - }, - onSuccess: () => { - toast({ - title: "Success", - description: "Appointment updated successfully.", - }); - queryClient.invalidateQueries({ queryKey: ["/api/appointments/all"] }); - queryClient.invalidateQueries({ queryKey: ["/api/patients/"] }); - }, - onError: (error: Error) => { - toast({ - title: "Error", - description: `Failed to update appointment: ${error.message}`, - variant: "destructive", - }); - }, -}); - -const createClaimMutation = useMutation({ - mutationFn: async (claimData: any) => { - const res = await apiRequest("POST", "/api/claims/", claimData); - return res.json(); - }, - onSuccess: () => { - toast({ - title: "Claim created successfully", - variant: "default", - }); - }, - onError: (error: any) => { - toast({ - title: "Error submitting claim", - description: error.message, - variant: "destructive", - }); - }, -}); - -function handleClaimSubmit(claimData: any): Promise { - return createClaimMutation.mutateAsync(claimData).then((data) => { - return data; - }); -} - -const handleAppointmentSubmit = async ( - appointmentData: InsertAppointment | UpdateAppointment -): Promise => { - const rawDate = parseLocalDate(appointmentData.date); - const formattedDate = formatLocalDate(rawDate); - - // Prepare minimal data to update/create - const minimalData = { - date: rawDate.toLocaleDateString("en-CA"), // "YYYY-MM-DD" format - startTime: appointmentData.startTime || "09:00", - endTime: appointmentData.endTime || "09:30", - staffId: appointmentData.staffId, - }; - - // Find existing appointment for this patient on the same date - const existingAppointment = appointments.find( - (a) => - a.patientId === appointmentData.patientId && - formatLocalDate(parseLocalDate(a.date)) === formattedDate - ); - - if (existingAppointment && typeof existingAppointment.id === "number") { - // Update appointment with only date - updateAppointmentMutation.mutate({ - id: existingAppointment.id, - appointment: minimalData, - }); - return existingAppointment.id; - } - - return new Promise((resolve, reject) => { - createAppointmentMutation.mutate( - { - ...minimalData, - patientId: appointmentData.patientId, - userId: user?.id, - title: "Scheduled Appointment", - type: "checkup", - }, - { - onSuccess: (newAppointment) => { - resolve(newAppointment.id); - }, - onError: (error) => { - toast({ - title: "Error", - description: "Could not create appointment", - variant: "destructive", - }); - reject(error); - }, - } - ); - }); -}; - -// Update Patient ( for insuranceId and Insurance Provider) -const handleUpdatePatient = (patient: UpdatePatient & { id?: number }) => { - if (patient) { - const { id, ...sanitizedPatient } = patient; - updatePatientMutation.mutate({ - id: Number(patient.id), - patient: sanitizedPatient, - }); - } else { - console.error("No current patient or user found for update"); - toast({ - title: "Error", - description: "Cannot update patient: No patient or user found", - variant: "destructive", - }); - } -}; - -// handle selenium sybmiting Mass Health claim -export const handleMHClaimSubmitSelenium = async ( - data: any, - dispatch: AppDispatch, - selectedPatient: number | null -) => { - const formData = new FormData(); - formData.append("data", JSON.stringify(data)); - const uploadedFiles: File[] = data.uploadedFiles ?? []; - - uploadedFiles.forEach((file: File) => { - if (file.type === "application/pdf") { - formData.append("pdfs", file); - } else if (file.type.startsWith("image/")) { - formData.append("images", file); - } - }); - - try { - dispatch( - setTaskStatus({ - status: "pending", - message: "Submitting claim to Selenium...", - }) - ); - const response = await apiRequest("POST", "/api/claims/selenium", formData); - const result1 = await response.json(); - if (result1.error) throw new Error(result1.error); - - dispatch( - setTaskStatus({ - status: "pending", - message: "Submitted to Selenium. Awaiting PDF...", - }) - ); - - toast({ - title: "Selenium service notified", - description: - "Your claim data was successfully sent to Selenium, Waitinig for its response.", - variant: "default", - }); - - const result2 = await handleSeleniumPdfDownload( - result1, - dispatch, - selectedPatient - ); - return result2; - } catch (error: any) { - dispatch( - setTaskStatus({ - status: "error", - message: error.message || "Selenium submission failed", - }) - ); - toast({ - title: "Selenium service error", - description: error.message || "An error occurred.", - variant: "destructive", - }); - } -}; - -// selenium pdf download handler -export const handleSeleniumPdfDownload = async ( - data: any, - dispatch: AppDispatch, - selectedPatient: number | null -) => { - try { - if (!selectedPatient) { - throw new Error("Missing patientId"); - } - - dispatch( - setTaskStatus({ - status: "pending", - message: "Downloading PDF from Selenium...", - }) - ); - - const res = await apiRequest("POST", "/api/claims/selenium/fetchpdf", { - patientId: selectedPatient, - pdf_url: data.pdf_url, - }); - const result = await res.json(); - if (result.error) throw new Error(result.error); - - dispatch( - setTaskStatus({ - status: "success", - message: "Claim submitted & PDF downloaded successfully.", - }) - ); - - toast({ - title: "Success", - description: "Claim Submitted and Pdf Downloaded completed.", - }); - - // setSelectedPatient(null); - - return result; - } catch (error: any) { - dispatch( - setTaskStatus({ - status: "error", - message: error.message || "Failed to download PDF", - }) - ); - toast({ - title: "Error", - description: error.message || "Failed to fetch PDF", - variant: "destructive", - }); - } -}; diff --git a/apps/Frontend/src/components/claims/claim-modal.tsx b/apps/Frontend/src/components/claims/claim-modal.tsx deleted file mode 100644 index ae69646..0000000 --- a/apps/Frontend/src/components/claims/claim-modal.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { useState, useEffect } from "react"; -import { ClaimForm } from "./claim-form"; -import { PatientUncheckedCreateInputObjectSchema } from "@repo/db/usedSchemas"; -import {z} from "zod"; - -const PatientSchema = (PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject).omit({ - appointments: true, -}); -type Patient = z.infer; - -interface ClaimModalProps { - open: boolean; - onClose: () => void; - patientId: number; - appointmentId: number; -} - -export function ClaimModal({ - open, - onClose, - patientId, - appointmentId -}: ClaimModalProps) { - const [patient, setPatient] = useState(null); - const [loading, setLoading] = useState(false); - - useEffect(() => { - // Fetch patient data - const fetchPatient = async () => { - try { - setLoading(true); - const response = await fetch(`/api/patients/${patientId}`); - if (!response.ok) { - throw new Error("Failed to fetch patient data"); - } - const data = await response.json(); - setPatient(data); - } catch (error) { - console.error("Error fetching patient:", error); - } finally { - setLoading(false); - } - }; - - if (open && patientId) { - fetchPatient(); - } - }, [patientId, open]); - - if (!open) return null; - - const patientName = patient ? `${patient.firstName} ${patient.lastName}` : `Patient #${patientId}`; - - return ( - - ); -} \ No newline at end of file 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 15c1c51..184d350 100644 --- a/apps/Frontend/src/components/claims/claims-of-patient-table.tsx +++ b/apps/Frontend/src/components/claims/claims-of-patient-table.tsx @@ -1,10 +1,4 @@ import { useState } from "react"; -import { - Dialog, - DialogContent, - DialogHeader, - DialogTitle, -} from "@/components/ui/dialog"; import ClaimsRecentTable from "./claims-recent-table"; import { PatientTable } from "../patients/patient-table"; import { PatientUncheckedCreateInputObjectSchema } from "@repo/db/usedSchemas"; diff --git a/apps/Frontend/src/pages/appointments-page.tsx b/apps/Frontend/src/pages/appointments-page.tsx index c882882..c5dac88 100644 --- a/apps/Frontend/src/pages/appointments-page.tsx +++ b/apps/Frontend/src/pages/appointments-page.tsx @@ -4,12 +4,10 @@ import { format, addDays, startOfToday, addMinutes } from "date-fns"; import { parseLocalDate, formatLocalDate, - normalizeToISOString, } from "@/utils/dateUtils"; import { TopAppBar } from "@/components/layout/top-app-bar"; import { Sidebar } from "@/components/layout/sidebar"; import { AddAppointmentModal } from "@/components/appointments/add-appointment-modal"; -import { ClaimModal } from "@/components/claims/claim-modal"; import { Button } from "@/components/ui/button"; import { Calendar as CalendarIcon, @@ -19,7 +17,6 @@ import { RefreshCw, Move, Trash2, - FileText, } from "lucide-react"; import { useToast } from "@/hooks/use-toast"; import { z } from "zod"; @@ -705,40 +702,6 @@ export default function AppointmentsPage() { Edit Appointment - { - const fullAppointment = appointments.find( - (a) => a.id === props.appointmentId - ); - if (fullAppointment) { - // Set the appointment and patient IDs for the claim modal - setClaimAppointmentId(fullAppointment.id ?? null); - setClaimPatientId(fullAppointment.patientId); - - // Find the patient name for the toast notification - const patient = patients.find( - (p) => p.id === fullAppointment.patientId - ); - const patientName = patient - ? `${patient.firstName} ${patient.lastName}` - : `Patient #${fullAppointment.patientId}`; - - // Show a toast notification - toast({ - title: "Claim Services Initiated", - description: `Started insurance claim process for ${patientName}`, - }); - - // Open the claim modal - setIsClaimModalOpen(true); - } - }} - > - - - Claim Services - - handleDeleteAppointment(props.appointmentId) @@ -936,20 +899,6 @@ export default function AppointmentsPage() { onCancel={() => setConfirmDeleteState({ open: false })} entityName={confirmDeleteState.appointmentTitle} /> - - {/* Claim Services Modal */} - {claimPatientId && claimAppointmentId && ( - { - setIsClaimModalOpen(false); - setClaimPatientId(null); - setClaimAppointmentId(null); - }} - patientId={claimPatientId} - appointmentId={claimAppointmentId} - /> - )} ); } diff --git a/apps/Frontend/src/pages/claims-page.tsx b/apps/Frontend/src/pages/claims-page.tsx index 861542f..336c767 100644 --- a/apps/Frontend/src/pages/claims-page.tsx +++ b/apps/Frontend/src/pages/claims-page.tsx @@ -1,5 +1,5 @@ import { useState, useEffect, useMemo } from "react"; -import { useMutation, useQuery } from "@tanstack/react-query"; +import { useMutation} from "@tanstack/react-query"; import { TopAppBar } from "@/components/layout/top-app-bar"; import { Sidebar } from "@/components/layout/sidebar"; import { @@ -17,7 +17,6 @@ import { AppointmentUncheckedCreateInputObjectSchema, ClaimUncheckedCreateInputObjectSchema, } from "@repo/db/usedSchemas"; -import { FileCheck } from "lucide-react"; import { parse } from "date-fns"; import { z } from "zod"; import { apiRequest, queryClient } from "@/lib/queryClient"; @@ -28,7 +27,7 @@ import { clearTaskStatus, } from "@/redux/slices/seleniumClaimSubmitTaskSlice"; import { SeleniumTaskBanner } from "@/components/ui/selenium-task-banner"; -import { formatLocalDate, parseLocalDate } from "@/utils/dateUtils"; +import { formatLocalDate} from "@/utils/dateUtils"; import ClaimsRecentTable from "@/components/claims/claims-recent-table"; import ClaimsOfPatientModal from "@/components/claims/claims-of-patient-table";