import { useState, useEffect } from "react"; import { PawPrint, Heart, Scissors, Clock, Edit3, Loader2 } from "lucide-react"; import { PetForm } from "./PetForm.js"; interface Pet { id: string; name: string; breed: string; weight: number; birthDate: string; photoUrl: string | null; notes: string | null; } interface Appointment { id: string; startTime: string; endTime: string; status: string; confirmationStatus: string | null; customerNotes: string | null; groomerNotes: string | null; reportCardId: string | null; pet: { id: string; name: string; photo: string | null } | null; service: { id: string } | null; staff: { id: string; name: string } | null; } interface AppointmentsResponse { upcoming: Appointment[]; past: Appointment[]; } interface Props { sessionId: string | null; readOnly: boolean; } function buildHeaders(sessionId: string | null): Record { const headers: Record = {}; if (sessionId) { headers["X-Impersonation-Session-Id"] = sessionId; } return headers; } export function PetProfiles({ sessionId, readOnly }: Props) { const [pets, setPets] = useState([]); const [appointments, setAppointments] = useState({ upcoming: [], past: [] }); const [selectedPetId, setSelectedPetId] = useState(""); const [activeTab, setActiveTab] = useState<"info" | "medical" | "grooming" | "history">("info"); const [editingPetId, setEditingPetId] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { async function fetchData() { setLoading(true); setError(null); try { const [petsRes, apptsRes] = await Promise.all([ fetch("/api/portal/pets", { headers: buildHeaders(sessionId) }), fetch("/api/portal/appointments", { headers: buildHeaders(sessionId) }), ]); if (!petsRes.ok) { throw new Error("Failed to load pets"); } if (!apptsRes.ok) { throw new Error("Failed to load appointments"); } const petsData = await petsRes.json(); const apptsData: AppointmentsResponse = await apptsRes.json(); setPets(petsData); setAppointments(apptsData); if (petsData.length > 0 && !selectedPetId) { setSelectedPetId(petsData[0].id); } } catch (e) { setError(e instanceof Error ? e.message : "Failed to load data"); } finally { setLoading(false); } } fetchData(); }, [sessionId]); const selectedPet = pets.find(p => p.id === selectedPetId) ?? null; const petHistory = appointments.past.filter(a => a.pet?.id === selectedPetId); const editingPet = editingPetId ? pets.find(p => p.id === editingPetId) ?? null : null; function handlePetSave(updatedPet: Pet) { setPets(prev => prev.map(p => p.id === updatedPet.id ? updatedPet : p)); setEditingPetId(null); } if (editingPet) { return ( setEditingPetId(null)} /> ); } if (loading) { return (
); } if (error) { return (

{error}

); } if (pets.length === 0) { return (

No pets found

); } return (
{/* Pet Selector */}
{pets.map(p => ( ))}
{/* Profile Header */} {selectedPet && (
{selectedPet.photoUrl ? ( {selectedPet.name} ) : ( ๐Ÿพ )}

{selectedPet.name}

{selectedPet.breed} ยท {selectedPet.weight} lbs

Born {selectedPet.birthDate ? new Date(selectedPet.birthDate).toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" }) : "Unknown"}

{!readOnly && ( )}
)} {/* Tabs */}
{([ { id: "info", label: "Basic Info", icon: PawPrint }, { id: "medical", label: "Medical", icon: Heart }, { id: "grooming", label: "Grooming", icon: Scissors }, { id: "history", label: "History", icon: Clock }, ] as const).map(({ id, label, icon: Icon }) => ( ))}
{/* Tab Content */}
{activeTab === "info" && selectedPet && } {activeTab === "medical" && selectedPet && } {activeTab === "grooming" && selectedPet && } {activeTab === "history" && }
); } function InfoRow({ label, value }: { label: string; value: string }) { return (
{label} {value}
); } function BasicInfoTab({ pet, readOnly }: { pet: Pet; readOnly: boolean }) { return (
{!readOnly && ( )}
); } function MedicalTab({ pet, readOnly }: { pet: Pet; readOnly: boolean }) { return (
{!readOnly && (

Changes to medical notes will be flagged for staff review.

)}
); } function GroomingTab({ pet, readOnly }: { pet: Pet; readOnly: boolean }) { return (
{!readOnly && ( )}
); } function HistoryTab({ petHistory }: { petHistory: Appointment[] }) { return (
{petHistory.length === 0 ? (

No history yet

) : ( petHistory.map(appt => (

{appt.service ? "Grooming Service" : "Appointment"}

with {appt.staff?.name || "Unknown Groomer"}

{new Date(appt.startTime).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })} {appt.reportCardId && ( Report )}
)) )}
); }