import { useState } from "react"; import { X, Save, Plus, Star, Loader2 } from "lucide-react"; import type { Pet, MedicalAlert, CoatType, AlertSeverity } from "@groombook/types"; const COAT_TYPES: CoatType[] = ["double", "wire", "curly", "smooth", "long", "hairless"]; const SEVERITY_OPTIONS: AlertSeverity[] = ["low", "medium", "high"]; const SIZE_OPTIONS = ["small", "medium", "large", "xlarge"] as const; type SizeOption = typeof SIZE_OPTIONS[number]; interface Props { pet?: Pet; onSave: (pet: Pet) => void | Promise; onCancel: () => void; saving?: boolean; saveError?: string | null; } function newAlert(): Omit { return { type: "", description: "", severity: "low" }; } export function PetForm({ pet, onSave, onCancel, saving, saveError }: Props) { const [name, setName] = useState(pet?.name ?? ""); const [breed, setBreed] = useState(pet?.breed ?? ""); const [weight, setWeight] = useState(Number(pet?.weight ?? pet?.weightKg ?? 0)); const [notes, setNotes] = useState(pet?.healthAlerts ?? ""); const [coatType, setCoatType] = useState((pet?.coatType as CoatType) ?? ""); const [petSizeCategory, setPetSizeCategory] = useState(pet?.petSizeCategory as SizeOption ?? ""); const [preferredCuts, setPreferredCuts] = useState(pet?.preferredCuts ?? []); const [cutInput, setCutInput] = useState(""); const [alerts, setAlerts] = useState[]>( pet?.medicalAlerts?.map((alert: MedicalAlert) => ({ type: alert.type, description: alert.description, severity: alert.severity })) ?? [] ); const [alertErrors, setAlertErrors] = useState>({}); function addAlert() { setAlerts(prev => [...prev, newAlert()]); } function updateAlert(idx: number, field: keyof Omit, value: string) { setAlerts(prev => prev.map((a, i) => i === idx ? { ...a, [field]: value } : a)); setAlertErrors(prev => { const e = { ...prev }; delete e[idx]; return e; }); } function removeAlert(idx: number) { setAlerts(prev => prev.filter((_, i) => i !== idx)); setAlertErrors(prev => { const e = { ...prev }; delete e[idx]; return e; }); } function addCut() { const trimmed = cutInput.trim(); if (trimmed && !preferredCuts.includes(trimmed)) { setPreferredCuts(prev => [...prev, trimmed]); } setCutInput(""); } function removeCut(cut: string) { setPreferredCuts(prev => prev.filter(c => c !== cut)); } function handleCutKey(e: React.KeyboardEvent) { if (e.key === "Enter") { e.preventDefault(); addCut(); } } function validateAlerts(): boolean { const errors: Record = {}; alerts.forEach((a, i) => { if (!a.type.trim()) errors[i] = "Type is required"; else if (a.severity === "medium" && !a.description.trim()) errors[i] = "Description required at medium/high severity"; }); setAlertErrors(errors); return Object.keys(errors).length === 0; } function handleSubmit(e: React.FormEvent) { e.preventDefault(); if (!pet) return; if (!handleCutKey) {} // noop reference if (alerts.length > 0 && !validateAlerts()) return; const savedPet: Pet = { ...pet, name, breed: breed || null, weightKg: weight || null, healthAlerts: notes, coatType: coatType || null, petSizeCategory: petSizeCategory || null, preferredCuts, medicalAlerts: alerts.map((a, i) => ({ ...a, id: pet.medicalAlerts?.[i]?.id ?? crypto.randomUUID() })), }; onSave(savedPet); } const temperamentScore = pet?.temperamentScore; const temperamentFlags = pet?.temperamentFlags ?? []; return (

{pet?.id ? "Edit Pet" : "Add Pet"}

{/* Basic Info */}
setName(e.target.value)} required className="w-full border border-stone-200 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-(--color-accent)" />
setBreed(e.target.value)} className="w-full border border-stone-200 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-(--color-accent)" />
setWeight(Number(e.target.value))} min="0" step="0.1" className="w-full border border-stone-200 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-(--color-accent)" />