'use client'; import React, { useState, useEffect } from 'react'; import { useForm } from 'react-hook-form'; import { useTranslations } from 'next-intl'; import { BookingService } from '@/lib/bookingService'; import { bookingApi } from '@/lib/pocketbase'; import { BookingType, TimeSlot } from '@/types/bookings'; import BookingTypeSelector from './BookingTypeSelector'; import DateSelector from './DateSelector'; import TimeSlotSelector from './TimeSlotSelector'; import CustomerDetails from './CustomerDetails'; import BookingSummary from './BookingSummary'; interface FormData { customerName: string; customerEmail: string; participantsCount: number; } const BookingInterface = () => { const t = useTranslations('bookingForm'); const [selectedDate, setSelectedDate] = useState(''); const [selectedTimeSlot, setSelectedTimeSlot] = useState(''); const [selectedBookingType, setSelectedBookingType] = useState(''); const [participantsCount, setParticipantsCount] = useState(1); const [bookingTypes, setBookingTypes] = useState([]); const [timeSlots, setTimeSlots] = useState([]); const [availableDates, setAvailableDates] = useState([]); const [availableSlotsByDate, setAvailableSlotsByDate] = useState<{ [date: string]: { start_time: string; end_time: string }[] }>({}); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const { register, handleSubmit, formState: { errors, isValid }, setValue, trigger } = useForm({ mode: 'onChange', defaultValues: { customerName: '', customerEmail: '', participantsCount: 1 } }); const selectedBookingTypeData = bookingTypes.find(bt => bt.id === selectedBookingType); // Fetch booking types on mount useEffect(() => { const fetchBookingTypes = async () => { try { setLoading(true); setError(null); const types = await BookingService.getBookingTypes(); setBookingTypes(types); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load booking types'); } finally { setLoading(false); } }; fetchBookingTypes(); }, []); // Available dates are now handled in handleBookingTypeChange // Time slots are now handled in handleDateChange useEffect(() => { setValue('participantsCount', participantsCount); trigger('participantsCount'); }, [participantsCount, setValue, trigger]); const onSubmit = (data: FormData) => { const selectedTimeSlotData = timeSlots.find(slot => slot.id === selectedTimeSlot); const formData = { bookingTypeId: selectedBookingType, customerName: data.customerName, customerEmail: data.customerEmail, startTime: selectedDate && selectedTimeSlotData ? `${selectedDate}T${selectedTimeSlotData.start_time}` : '', endTime: selectedDate && selectedTimeSlotData ? `${selectedDate}T${selectedTimeSlotData.end_time}` : '', participantsCount: data.participantsCount, }; console.log(formData); }; const handleParticipantsCountChange = (count: number) => { setParticipantsCount(count); }; const handleBookingTypeChange = async (typeId: string) => { setSelectedBookingType(typeId); setSelectedDate(''); setSelectedTimeSlot(''); setTimeSlots([]); // Set participants count to booking type's minimum capacity const bookingType = bookingTypes.find(bt => bt.id === typeId); if (bookingType) { setParticipantsCount(bookingType.min_capacity); } // Fetch time slots for the selected booking type try { const timeSlots = await bookingApi.getTimeSlotsForBookingType(typeId); // Generate available time slots grouped by date const generatedSlotsByDate = bookingApi.generateAvailableTimeSlots(timeSlots); const availableDatesFromAPI = Object.keys(generatedSlotsByDate).sort(); // Update available dates and slots data for the date selector setAvailableDates(availableDatesFromAPI); setAvailableSlotsByDate(generatedSlotsByDate); } catch (error) { console.error('Error fetching time slots:', error); } }; const handleDateChange = (date: string) => { setSelectedDate(date); setSelectedTimeSlot(''); // Get time slots for the selected date from availableSlotsByDate const slotsForDate = availableSlotsByDate[date] || []; console.log(`Time slots for ${date}:`, slotsForDate); // Convert to TimeSlot format for TimeSlotSelector const formattedTimeSlots: TimeSlot[] = slotsForDate.map((slot, index) => ({ id: `slot-${date}-${index}`, start_time: slot.start_time, end_time: slot.end_time, is_active: true, max_capacity: 8, booking_types: [selectedBookingType], is_reccuring: false, recurrence_pattern: undefined, resources: [], created: new Date().toISOString(), updated: new Date().toISOString() })); setTimeSlots(formattedTimeSlots); }; return (
{/* Header */}

{t('title')}

{t('subtitle')}

{/* Loading State */} {loading && (

{t('loading')}

)} {/* Error State */} {error && (
⚠️

{t('noBookings')}

{error}

)} {/* Booking Type Selection */} {!loading && !error && bookingTypes.length === 0 && (

{t('noBookings')}

{t('checkBackLater')}

)} {!loading && !error && bookingTypes.length > 0 && ( )} {/* Date Selection */} {selectedBookingType && ( )} {/* Time Slot Selection */} {selectedDate && ( )} {/* Customer Details */} {selectedTimeSlot && selectedBookingTypeData && (
{/* Summary & Submit */} {isValid && (
)} )}
); }; export default BookingInterface;