import { useEffect, useState } from "react"; import { useSearchParams } from "react-router-dom"; import type { Service } from "@groombook/types"; import { ANALYTICS_EVENTS, fireAnalyticsEvent } from "../lib/analytics"; // ─── Types ─────────────────────────────────────────────────────────────────── interface BookingBody { serviceId: string; startTime: string; clientName: string; clientEmail: string; clientPhone: string; petName: string; petSpecies: string; petBreed: string; petSizeCategory: string; petCoatType: string; notes: string; } interface BookingResult { appointment: { id: string; startTime: string; endTime: string }; client: { id: string; name: string; email: string | null }; pet: { id: string; name: string }; } // ─── Helpers ───────────────────────────────────────────────────────────────── function fmtPrice(cents: number): string { return `$${(cents / 100).toFixed(2)}`; } function fmtDuration(minutes: number): string { if (minutes < 60) return `${minutes} min`; const h = Math.floor(minutes / 60); const m = minutes % 60; return m > 0 ? `${h}h ${m}m` : `${h}h`; } function fmtTime(iso: string): string { return new Date(iso).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }); } function fmtDateLong(isoDate: string): string { const d = new Date(isoDate + "T12:00:00Z"); return d.toLocaleDateString([], { weekday: "long", year: "numeric", month: "long", day: "numeric" }); } function todayIso(): string { return new Date().toISOString().slice(0, 10); } // ─── Sub-components ─────────────────────────────────────────────────────────── function StepIndicator({ step }: { step: number }) { const steps = ["Service", "Date & Time", "Your Info", "Confirm"]; return (
Schedule a grooming appointment for your pet in minutes.
Loading services…
} {!servicesLoading && services.length === 0 && (No services available. Please contact us to book.
)}{selectedService.name} — {fmtDuration(selectedService.durationMinutes)} — {fmtPrice(selectedService.basePriceCents)}
{dateError}
)}Checking availability…
} {!slotsLoading && slots.length === 0 && (No available slots on this date. Please try another day.
)} {!slotsLoading && slots.length > 0 && ({formError}
)}{submitError}
)}We've booked {result.pet.name} in for{" "} {selectedService?.name} on {fmtDateLong(date)} at{" "} {fmtTime(result.appointment.startTime)}.
A confirmation will be sent to {result.client.email}. If you need to reschedule or cancel, please contact us.