'use client'; import { useEffect, useMemo, useState } from 'react'; import { Plus } from 'lucide-react'; import { Button } from '@/components/ui/Button'; import { patientsApi } from '@/lib/api/patients'; import { CreatePatientInput, CreateTreatmentHistoryInput, Patient, TreatmentHistoryItem, } from '@/types/patient'; import { PatientSearchSelect } from '@/components/patients/PatientSearchSelect'; import { CreatePatientModal } from '@/components/patients/CreatePatientModal'; import { PatientSummaryCard } from '@/components/patients/PatientSummaryCard'; import { TreatmentHistoryPreview } from '@/components/patients/TreatmentHistoryPreview'; const EMPTY_PATIENT_FORM: CreatePatientInput = { firstName: '', lastName: '', phone: '', email: '', }; export default function PatientsPage() { const [search, setSearch] = useState(''); const [patients, setPatients] = useState([]); const [selectedPatient, setSelectedPatient] = useState(); const [treatments, setTreatments] = useState([]); const [loadingPatients, setLoadingPatients] = useState(false); const [loadingTreatments, setLoadingTreatments] = useState(false); const [isCreateOpen, setIsCreateOpen] = useState(false); const [savingPatient, setSavingPatient] = useState(false); const [savingTreatment, setSavingTreatment] = useState(false); const [patientForm, setPatientForm] = useState(EMPTY_PATIENT_FORM); const [errorMessage, setErrorMessage] = useState(''); const [successMessage, setSuccessMessage] = useState(''); const sortedPatients = useMemo( () => [...patients].sort((a, b) => `${a.firstName} ${a.lastName}`.localeCompare(`${b.firstName} ${b.lastName}`), ), [patients], ); useEffect(() => { const timeout = setTimeout(() => { void loadPatients(search); }, 300); return () => clearTimeout(timeout); }, [search]); useEffect(() => { void loadPatients(''); }, []); useEffect(() => { if (!successMessage) { return; } const timeout = setTimeout(() => { setSuccessMessage(''); }, 3000); return () => clearTimeout(timeout); }, [successMessage]); async function loadPatients(q: string) { setLoadingPatients(true); setErrorMessage(''); try { const response = await patientsApi.list({ q, page: 1, limit: 25 }); const items = response.data.items; setPatients(items); if (selectedPatient) { const freshSelected = items.find((item) => item.id === selectedPatient.id); setSelectedPatient(freshSelected); } } catch (error: any) { const message = Array.isArray(error?.message) ? error.message.join(', ') : error?.message; setErrorMessage(message || 'Failed to load patients.'); } finally { setLoadingPatients(false); } } async function loadTreatments(patientId: string) { setLoadingTreatments(true); setErrorMessage(''); try { const response = await patientsApi.listTreatments(patientId); setTreatments(response.data); } catch (error: any) { const message = Array.isArray(error?.message) ? error.message.join(', ') : error?.message; setErrorMessage(message || 'Failed to load treatment history.'); } finally { setLoadingTreatments(false); } } async function handleCreatePatient() { setSavingPatient(true); setErrorMessage(''); setSuccessMessage(''); try { const response = await patientsApi.create(patientForm); setIsCreateOpen(false); setPatientForm(EMPTY_PATIENT_FORM); await loadPatients(search); setSelectedPatient(response.data); await loadTreatments(response.data.id); setSuccessMessage( `Patient ${response.data.firstName} ${response.data.lastName} was saved successfully.`, ); } catch (error: any) { const message = Array.isArray(error?.message) ? error.message.join(', ') : error?.message; setErrorMessage(message || 'Failed to save patient.'); } finally { setSavingPatient(false); } } async function handleQuickAddTreatment() { if (!selectedPatient) { return; } const payload: CreateTreatmentHistoryInput = { title: 'Initial consultation', status: 'scheduled', treatmentAt: new Date().toISOString(), notes: 'Created from quick action on patients page.', }; setSavingTreatment(true); setErrorMessage(''); setSuccessMessage(''); try { await patientsApi.addTreatment(selectedPatient.id, payload); await loadTreatments(selectedPatient.id); setSuccessMessage('Treatment entry added successfully.'); } catch (error: any) { const message = Array.isArray(error?.message) ? error.message.join(', ') : error?.message; setErrorMessage(message || 'Failed to add treatment entry.'); } finally { setSavingTreatment(false); } } return (

Patients

setPatientForm((prev) => ({ ...prev, ...patch }))} onSubmit={handleCreatePatient} onClose={() => setIsCreateOpen(false)} loading={savingPatient} />
{ setSelectedPatient(patient); void loadTreatments(patient.id); }} loading={loadingPatients} />
{(errorMessage || successMessage) && (
{errorMessage && (
{errorMessage}
)} {successMessage && (
{successMessage}
)}
)}
); }