import { useState } from "react"; import { Calendar, Clock, Plus, ChevronRight, ChevronDown, Search, Repeat } from "lucide-react"; import { UPCOMING_APPOINTMENTS, PAST_APPOINTMENTS, PETS, SERVICES, GROOMERS } from "../mockData.js"; import type { Appointment, Pet, Service, Groomer } from "../mockData.js"; interface Props { readOnly: boolean; } function formatDate(dateStr: string): string { return new Date(dateStr).toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric", year: "numeric" }); } const STATUS_COLORS: Record = { confirmed: "bg-green-100 text-green-700", pending: "bg-amber-100 text-amber-700", waitlisted: "bg-blue-100 text-blue-700", completed: "bg-stone-100 text-stone-600", cancelled: "bg-red-100 text-red-600", }; export function AppointmentsSection({ readOnly }: Props) { const [showBooking, setShowBooking] = useState(false); const [expandedId, setExpandedId] = useState(null); const [tab, setTab] = useState<"upcoming" | "past">("upcoming"); return (
{!readOnly && ( )}
{tab === "upcoming" && (
{UPCOMING_APPOINTMENTS.map(appt => ( setExpandedId(expandedId === appt.id ? null : appt.id)} readOnly={readOnly} /> ))} {UPCOMING_APPOINTMENTS.length === 0 && (

No upcoming appointments

)}
)} {tab === "past" && (
{PAST_APPOINTMENTS.map(appt => ( setExpandedId(expandedId === appt.id ? null : appt.id)} readOnly={readOnly} /> ))}
)} {showBooking && ( setShowBooking(false)} readOnly={readOnly} /> )}
); } function AppointmentCard({ appointment: appt, expanded, onToggle, readOnly, }: { appointment: Appointment; expanded: boolean; onToggle: () => void; readOnly: boolean; }) { return (
{expanded && (

Duration

{appt.duration} min

Estimated Price

${appt.price}

{appt.addOns.length > 0 && (

Add-ons

{appt.addOns.join(", ")}

)}
{appt.notes && (

{appt.notes}

)} {appt.status !== "completed" && appt.status !== "cancelled" && !readOnly && (
)} {appt.reportCardId && (
View Report Card โ†’
)}
)}
); } function BookingFlow({ onClose, readOnly }: { onClose: () => void; readOnly: boolean }) { const [step, setStep] = useState(1); const [selectedPet, setSelectedPet] = useState(null); const [selectedServices, setSelectedServices] = useState([]); const [selectedAddOns, setSelectedAddOns] = useState([]); const [selectedGroomer, setSelectedGroomer] = useState(null); const [selectedDate, setSelectedDate] = useState(""); const [selectedTime, setSelectedTime] = useState(""); const [notes, setNotes] = useState(""); const [recurring, setRecurring] = useState(""); const [confirmed, setConfirmed] = useState(false); const availableTimes = ["9:00 AM", "10:00 AM", "11:00 AM", "1:00 PM", "2:00 PM", "3:00 PM", "4:00 PM"]; const mainServices = SERVICES.filter(s => !s.isAddOn); const addOnServices = SERVICES.filter(s => s.isAddOn); if (readOnly) return null; return (

Book Appointment

{/* Step Indicator */}
{[1, 2, 3, 4, 5].map(s => (
))}
{confirmed ? (
๐ŸŽ‰

Appointment Booked!

{selectedPet?.name} with {selectedGroomer?.name || "First Available"} on {formatDate(selectedDate)} at {selectedTime}

) : ( <> {/* Step 1: Select Pet */} {step === 1 && (

Select Pet

{PETS.map(pet => ( ))}
)} {/* Step 2: Select Services */} {step === 2 && (

Select Services

{mainServices.map(svc => ( ))}
{selectedServices.length > 0 && ( <>

Add-ons (optional)

{addOnServices.map(svc => ( ))}
)}
)} {/* Step 3: Select Groomer */} {step === 3 && (

Select Groomer

{GROOMERS.map(g => ( ))}
)} {/* Step 4: Date & Time */} {step === 4 && (

Pick Date & Time

setSelectedDate(e.target.value)} min={new Date().toISOString().split("T")[0]} className="w-full border border-stone-300 rounded-lg px-3 py-2 text-sm mb-3" /> {selectedDate && (
{availableTimes.map(time => ( ))}
)}
)} {/* Step 5: Review & Confirm */} {step === 5 && (

Review & Confirm

Pet{selectedPet?.name}
Services{selectedServices.map(s => s.name).join(", ")}
{selectedAddOns.length > 0 && (
Add-ons{selectedAddOns.map(s => s.name).join(", ")}
)}
Groomer{selectedGroomer?.name || "First Available"}
Date & Time{formatDate(selectedDate)} at {selectedTime}
{recurring &&
RecurringEvery {recurring} weeks
}