import { useState, useRef } from "react"; import { useQuery, useMutation } from "@tanstack/react-query"; import { format, parse, parseISO } from "date-fns"; import { TopAppBar } from "@/components/layout/top-app-bar"; import { Sidebar } from "@/components/layout/sidebar"; import { StatCard } from "@/components/ui/stat-card"; import { PatientTable } from "@/components/patients/patient-table"; import { AddPatientModal } from "@/components/patients/add-patient-modal"; import { AddAppointmentModal } from "@/components/appointments/add-appointment-modal"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { useToast } from "@/hooks/use-toast"; import { useAuth } from "@/hooks/use-auth"; import { apiRequest, queryClient } from "@/lib/queryClient"; import { AppointmentsByDay } from "@/components/analytics/appointments-by-day"; import { NewPatients } from "@/components/analytics/new-patients"; import { AppointmentUncheckedCreateInputObjectSchema, PatientUncheckedCreateInputObjectSchema, } from "@repo/db/shared/schemas"; import { Users, Calendar, CheckCircle, CreditCard, Plus, Clock, } from "lucide-react"; import { Link } from "wouter"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { z } from "zod"; import { DeleteConfirmationDialog } from "@/components/ui/deleteDialog"; //creating types out of schema auto generated. type Appointment = 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; // Type for the ref to access modal methods type AddPatientModalRef = { shouldSchedule: boolean; navigateToSchedule: (patientId: number) => void; }; export default function Dashboard() { const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); const [isAddPatientOpen, setIsAddPatientOpen] = useState(false); const [isViewPatientOpen, setIsViewPatientOpen] = useState(false); const [isDeletePatientOpen, setIsDeletePatientOpen] = useState(false); const [isAddAppointmentOpen, setIsAddAppointmentOpen] = useState(false); const [currentPatient, setCurrentPatient] = useState( undefined ); const [selectedAppointment, setSelectedAppointment] = useState< Appointment | undefined >(undefined); const { toast } = useToast(); const { user } = useAuth(); const addPatientModalRef = useRef(null); // Fetch patients const { data: patients = [], isLoading: isLoadingPatients } = useQuery< Patient[] >({ queryKey: ["/api/patients/"], queryFn: async () => { const res = await apiRequest("GET", "/api/patients/"); return res.json(); }, enabled: !!user, }); // Fetch appointments const { data: appointments = [] as Appointment[], isLoading: isLoadingAppointments, } = useQuery({ queryKey: ["/api/appointments/all"], queryFn: async () => { const res = await apiRequest("GET", "/api/appointments/all"); return res.json(); }, enabled: !!user, }); // Add patient mutation const addPatientMutation = useMutation({ mutationFn: async (patient: InsertPatient) => { const res = await apiRequest("POST", "/api/patients/", patient); return res.json(); }, onSuccess: (newPatient) => { setIsAddPatientOpen(false); queryClient.invalidateQueries({ queryKey: ["/api/patients/"] }); toast({ title: "Success", description: "Patient added successfully!", variant: "default", }); if (addPatientModalRef.current?.shouldSchedule) { addPatientModalRef.current.navigateToSchedule(newPatient.id); } }, 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: () => { setIsAddPatientOpen(false); 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", }); }, }); const deletePatientMutation = useMutation({ mutationFn: async (id: number) => { const res = await apiRequest("DELETE", `/api/patients/${id}`); return; }, onSuccess: () => { setIsDeletePatientOpen(false); queryClient.invalidateQueries({ queryKey: ["/api/patients/"] }); toast({ title: "Success", description: "Patient deleted successfully!", variant: "default", }); }, onError: (error) => { console.log(error); toast({ title: "Error", description: `Failed to delete patient: ${error.message}`, variant: "destructive", }); }, }); const toggleMobileMenu = () => { setIsMobileMenuOpen(!isMobileMenuOpen); }; const handleAddPatient = (patient: InsertPatient) => { if (user) { addPatientMutation.mutate({ ...patient, userId: user.id, }); } }; const handleUpdatePatient = (patient: UpdatePatient & { id?: number }) => { if (currentPatient && user) { const { id, ...sanitizedPatient } = patient; updatePatientMutation.mutate({ id: currentPatient.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", }); } }; const handleEditPatient = (patient: Patient) => { setCurrentPatient(patient); setIsAddPatientOpen(true); }; const handleViewPatient = (patient: Patient) => { setCurrentPatient(patient); setIsViewPatientOpen(true); }; const handleDeletePatient = (patient: Patient) => { setCurrentPatient(patient); setIsDeletePatientOpen(true); }; const handleConfirmDeletePatient = async () => { if (currentPatient) { deletePatientMutation.mutate(currentPatient.id); } else { toast({ title: "Error", description: "No patient selected for deletion.", variant: "destructive", }); } }; const isLoading = isLoadingPatients || addPatientMutation.isPending || updatePatientMutation.isPending; // Create appointment mutation const createAppointmentMutation = useMutation({ mutationFn: async (appointment: InsertAppointment) => { const res = await apiRequest("POST", "/api/appointments/", appointment); return await res.json(); }, onSuccess: () => { setIsAddAppointmentOpen(false); 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: () => { setIsAddAppointmentOpen(false); toast({ title: "Success", description: "Appointment updated 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 update appointment: ${error.message}`, variant: "destructive", }); }, }); // Handle appointment submission (create or update) const handleAppointmentSubmit = ( appointmentData: InsertAppointment | UpdateAppointment ) => { if (selectedAppointment && typeof selectedAppointment.id === "number") { updateAppointmentMutation.mutate({ id: selectedAppointment.id, appointment: appointmentData as UpdateAppointment, }); } else { if (user) { createAppointmentMutation.mutate({ ...(appointmentData as InsertAppointment), userId: user.id, }); } } }; // Since we removed filters, just return all patients const filteredPatients = patients; const now = new Date(); const todayUTC = `${now.getUTCFullYear()}-${String(now.getUTCMonth() + 1).padStart(2, "0")}-${String(now.getUTCDate()).padStart(2, "0")}`; const todaysAppointments = appointments.filter((appointment) => { const dateObj = typeof appointment.date === "string" ? parseISO(appointment.date) : appointment.date; // Extract UTC year, month, day from appointment date const year = dateObj.getUTCFullYear(); const month = dateObj.getUTCMonth(); const day = dateObj.getUTCDate(); const appointmentUTCDate = `${year}-${String(month + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`; return appointmentUTCDate === todayUTC; }); // Count completed appointments today const completedTodayCount = todaysAppointments.filter((appointment) => { return appointment.status === "completed"; }).length; return (
{/* Quick Stats */}
{/* Today's Appointments Section */}

Today's Appointments

{todaysAppointments.length > 0 ? (
{todaysAppointments.map((appointment) => { const patient = patients.find( (p) => p.id === appointment.patientId ); return (

{patient ? `${patient.firstName} ${patient.lastName}` : "Unknown Patient"}

{`${format( parse( `${format(new Date(appointment.date), "yyyy-MM-dd")} ${appointment.startTime}`, "yyyy-MM-dd HH:mm", new Date() ), "hh:mm a" )} - ${format( parse( `${format(new Date(appointment.date), "yyyy-MM-dd")} ${appointment.endTime}`, "yyyy-MM-dd HH:mm", new Date() ), "hh:mm a" )}`} {appointment.type.charAt(0).toUpperCase() + appointment.type.slice(1)}
{appointment.status ? appointment.status.charAt(0).toUpperCase() + appointment.status.slice(1) : "Scheduled"} View All
); })}
) : (

No appointments today

You don't have any appointments scheduled for today.

)}
{/* Analytics Dashboard Section */}
{/* Patient Management Section */}
{/* Patient Header */}

Patient Management

{/* Patient Table */} setIsDeletePatientOpen(false)} entityName={currentPatient?.name} />
{/* Add/Edit Patient Modal */} {/* View Patient Modal */} Patient Details Complete information about the patient. {currentPatient && (
{currentPatient.firstName.charAt(0)} {currentPatient.lastName.charAt(0)}

{currentPatient.firstName} {currentPatient.lastName}

Patient ID: {currentPatient.id.toString().padStart(4, "0")}

Personal Information

Date of Birth:{" "} Date of Birth:{" "} {format( parse( currentPatient.dateOfBirth, "yyyy-MM-dd", new Date() ), "PPP" )}

Gender:{" "} {currentPatient.gender.charAt(0).toUpperCase() + currentPatient.gender.slice(1)}

Status:{" "} {currentPatient.status.charAt(0).toUpperCase() + currentPatient.status.slice(1)}

Contact Information

Phone:{" "} {currentPatient.phone}

Email:{" "} {currentPatient.email || "N/A"}

Address:{" "} {currentPatient.address ? ( <> {currentPatient.address} {currentPatient.city && `, ${currentPatient.city}`} {currentPatient.zipCode && ` ${currentPatient.zipCode}`} ) : ( "N/A" )}

Insurance

Provider:{" "} {currentPatient.insuranceProvider ? currentPatient.insuranceProvider === "delta" ? "Delta Dental" : currentPatient.insuranceProvider === "metlife" ? "MetLife" : currentPatient.insuranceProvider === "cigna" ? "Cigna" : currentPatient.insuranceProvider === "aetna" ? "Aetna" : currentPatient.insuranceProvider : "N/A"}

ID:{" "} {currentPatient.insuranceId || "N/A"}

Group Number:{" "} {currentPatient.groupNumber || "N/A"}

Policy Holder:{" "} {currentPatient.policyHolder || "Self"}

Medical Information

Allergies:{" "} {currentPatient.allergies || "None reported"}

Medical Conditions:{" "} {currentPatient.medicalConditions || "None reported"}

)}
{/* Add/Edit Appointment Modal */}
); }