"use client"; import { useState, useEffect } from "react"; import { Calendar } from "@/components/ui/calendar"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { useLanguage } from "@/contexts/LanguageContext"; import { useAuth } from "@/contexts/AuthContext"; import { listServices, formatDuration, ApiService } from "@/lib/api/services"; import { getAvailableSlots, createBooking, TimeSlotApi } from "@/lib/api/bookings"; import { ApiError } from "@/lib/api"; import { Check, Clock, CalendarDays } from "lucide-react"; import { toast } from "sonner"; function toDateStr(d: Date): string { return d.toISOString().slice(0, 10); } export default function Booking() { const { t, locale } = useLanguage(); const { user } = useAuth(); const [services, setServices] = useState([]); const [servicesLoading, setServicesLoading] = useState(true); const [selectedService, setSelectedService] = useState(null); const [selectedDate, setSelectedDate] = useState(); const [slots, setSlots] = useState([]); const [slotsLoading, setSlotsLoading] = useState(false); const [selectedSlot, setSelectedSlot] = useState(null); const [name, setName] = useState(user?.full_name ?? ""); const [email, setEmail] = useState(user?.email ?? ""); const [phone, setPhone] = useState(user?.phone ?? ""); const [submitting, setSubmitting] = useState(false); const [confirmed, setConfirmed] = useState(false); useEffect(() => { listServices() .then(setServices) .catch((e) => { console.error("[reservation] listServices failed:", e); setServices([]); }) .finally(() => setServicesLoading(false)); }, []); useEffect(() => { if (user) { setName(user.full_name ?? ""); setEmail(user.email ?? ""); setPhone(user.phone ?? ""); } }, [user]); useEffect(() => { if (!selectedDate) return; setSlotsLoading(true); setSelectedSlot(null); const dateStr = toDateStr(selectedDate); getAvailableSlots(dateStr, dateStr) .then(setSlots) .catch((e) => { console.error("[reservation] getAvailableSlots failed:", e); setSlots([]); }) .finally(() => setSlotsLoading(false)); }, [selectedDate]); const step = !selectedService ? 1 : !selectedDate ? 2 : !selectedSlot ? 3 : 4; const handleConfirm = async () => { if (!selectedSlot || !selectedService) return; setSubmitting(true); try { await createBooking({ slot_id: selectedSlot.id, service_note: selectedService.name, ...(user ? {} : { guest_name: name, guest_email: email, guest_phone: phone }), }); setConfirmed(true); toast.success(t("booking.success")); } catch (err) { const msg = err instanceof ApiError ? err.message : t("booking.error"); toast.error(msg); } finally { setSubmitting(false); } }; if (confirmed) { return (

{t("booking.confirmed_title")}

{selectedService?.name} — {selectedDate?.toLocaleDateString(locale)} {t("booking.confirmed_at")} {selectedSlot?.start_time.slice(0, 5)}

{t("booking.confirmed_desc")}

); } return (

{t("booking.title")}

{t("booking.subtitle")}

{[1, 2, 3, 4].map((s) => (
))}
{/* Step 1: Service */}

{t("booking.select_service")}

{servicesLoading ? (
{Array.from({ length: 4 }).map((_, i) => (
))}
) : services.length === 0 ? (

{t("booking.no_services")}

) : (
{services.map((service) => ( ))}
)}
{/* Step 2: Date */} {selectedService && (

{t("booking.select_date")}

date < new Date() || date.getDay() === 0} className="rounded-lg border border-border p-4" />
)} {/* Step 3: Time slot */} {selectedDate && (

{t("booking.select_time")}

{slotsLoading ? (
{Array.from({ length: 7 }).map((_, i) => (
))}
) : slots.length === 0 ? (

{t("booking.no_slots")}

) : (
{slots.map((slot) => ( ))}
)}
)} {/* Step 4: Contact */} {selectedSlot && (

{t("booking.confirm")}

{!user && ( <>
setName(e.target.value)} className="mt-1" required />
setEmail(e.target.value)} className="mt-1" required />
)} {user && (

{user.full_name}

{user.email}

)}
setPhone(e.target.value)} className="mt-1" />
)}
); }