"use client"; import { Plus, RefreshCw, X } from "lucide-react"; import { type FormEvent, type ReactNode, useState } from "react"; import { Button } from "@/components/ui/button"; import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { cn } from "@/lib/utils"; import { addPatient, type AllergySeverity, generateFileNumber, type Patient, } from "@/lib/patients"; type AddPatientDialogProps = { open: boolean; onOpenChange: (open: boolean) => void; onCreated: (fileNumber: string) => void; }; type AllergyDraft = { substance: string; reaction: string; severity: AllergySeverity }; type MedicationDraft = { name: string; dose: string; frequency: string }; const controlClass = "h-9 w-full rounded-3xl border border-transparent bg-input/50 px-3 text-sm text-foreground outline-none transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/30"; function Field({ label, children }: { label: string; children: ReactNode }) { return ( ); } function SectionHeader({ label, onAdd, }: { label: string; onAdd: () => void; }) { return (
{label}
); } function initialsFromName(name: string): string { const parts = name.trim().split(/\s+/).filter(Boolean); if (parts.length === 0) { return "?"; } return parts .slice(0, 2) .map((part) => part[0]) .join("") .toUpperCase(); } const today = () => new Date().toLocaleDateString("en-US", { month: "short", day: "2-digit", year: "numeric", }); export function AddPatientDialog({ open, onOpenChange, onCreated, }: AddPatientDialogProps) { // Lazily generate the file number on mount. The dialog is remounted (via a // `key`) each time it opens, so this gives a fresh number + cleared form // without a reset effect. const [fileNumber, setFileNumber] = useState(generateFileNumber); const [name, setName] = useState(""); const [age, setAge] = useState(""); const [sex, setSex] = useState("F"); const [status, setStatus] = useState("active"); const [pcp, setPcp] = useState(""); const [bp, setBp] = useState(""); const [hr, setHr] = useState(""); const [temp, setTemp] = useState(""); const [spo2, setSpo2] = useState(""); const [allergies, setAllergies] = useState([]); const [medications, setMedications] = useState([]); const handleSubmit = (event: FormEvent) => { event.preventDefault(); if (!name.trim()) { return; } const patient: Patient = { fileNumber, name: name.trim(), age: Number(age) || 0, sex, pcp: pcp.trim() || "—", status, initials: initialsFromName(name), allergies: allergies.filter((a) => a.substance.trim()), alerts: [], medications: medications.filter((m) => m.name.trim()), problems: [], vitals: { bp: bp.trim() || "—", hr: hr.trim() || "—", temp: temp.trim() || "—", spo2: spo2.trim() || "—", takenAt: today(), }, vitalsTrend: { label: "Heart rate", unit: "bpm", points: [] }, labs: [], labTrend: { label: "—", unit: "", points: [] }, encounters: [], }; addPatient(patient); onCreated(fileNumber); onOpenChange(false); }; return ( Add patient Create a new chart. A file number has been generated for you.
setName(event.target.value)} placeholder="e.g. Jordan Pierce" required value={name} />
setAge(event.target.value)} placeholder="—" value={age} />
setPcp(event.target.value)} placeholder="e.g. Dr. Lena Ortiz" value={pcp} />
Current vitals
setBp(event.target.value)} placeholder="BP" value={bp} /> setHr(event.target.value)} placeholder="HR" value={hr} /> setTemp(event.target.value)} placeholder="Temp" value={temp} /> setSpo2(event.target.value)} placeholder="SpO₂" value={spo2} />
setAllergies((prev) => [ ...prev, { substance: "", reaction: "", severity: "mild" }, ]) } /> {allergies.map((allergy, index) => (
setAllergies((prev) => prev.map((row, i) => i === index ? { ...row, substance: event.target.value } : row ) ) } placeholder="Substance" value={allergy.substance} /> setAllergies((prev) => prev.map((row, i) => i === index ? { ...row, reaction: event.target.value } : row ) ) } placeholder="Reaction" value={allergy.reaction} />
))}
setMedications((prev) => [ ...prev, { name: "", dose: "", frequency: "" }, ]) } /> {medications.map((med, index) => (
setMedications((prev) => prev.map((row, i) => i === index ? { ...row, name: event.target.value } : row ) ) } placeholder="Name" value={med.name} /> setMedications((prev) => prev.map((row, i) => i === index ? { ...row, dose: event.target.value } : row ) ) } placeholder="Dose" value={med.dose} /> setMedications((prev) => prev.map((row, i) => i === index ? { ...row, frequency: event.target.value } : row ) ) } placeholder="Frequency" value={med.frequency} />
))}
}> Cancel
); }