import PocketBase from 'pocketbase'; import { BookingType, TimeSlot, Booking } from '@/types/bookings'; // Initialize PocketBase client export const pb = new PocketBase(process.env.NEXT_PUBLIC_POCKETBASE_URL || 'http://127.0.0.1:8090'); // Disable auto cancellation for SSR pb.autoCancellation(false); // API functions for booking system export const bookingApi = { // Get all active booking types async getBookingTypes(): Promise { try { const records = await pb.collection('bookingTypes').getFullList({ sort: 'created', expand: 'resources', }); return records; } catch (error) { console.error('Error fetching booking types:', error); throw error; } }, // Get time slots for a specific booking type async getTimeSlotsForBookingType(bookingTypeId: string): Promise { try { const today = new Date(); const oneMonthFromToday = new Date(); oneMonthFromToday.setMonth(today.getMonth() + 1); const todayStr = today.toISOString().split('T')[0]; const oneMonthStr = oneMonthFromToday.toISOString().split('T')[0]; const records = await pb.collection('timeSlots').getFullList({ filter: `is_active = true && booking_types ~ "${bookingTypeId}" && start_time >= "${todayStr}" && end_time <= "${oneMonthStr}"`, sort: 'start_time', }); return records; } catch (error) { console.error('Error fetching time slots for booking type:', error); throw error; } }, // Generate available time slots grouped by date generateAvailableTimeSlots(timeSlots: TimeSlot[]): { [date: string]: { start_time: string; end_time: string }[] } { const today = new Date(); const oneMonthFromToday = new Date(); oneMonthFromToday.setMonth(today.getMonth() + 1); // Step 1: Generate massive array of individual time slots with specific dates const allTimeSlots: { start_time: string; end_time: string }[] = []; timeSlots.forEach(slot => { if (!slot.is_reccuring || !slot.recurrence_pattern) { // Handle non-recurring slots - use as is allTimeSlots.push({ start_time: slot.start_time, end_time: slot.end_time }); return; } // Handle recurring slots - generate dates based on recurrence pattern const pattern = slot.recurrence_pattern; const endDate = pattern.end_date ? new Date(pattern.end_date) : oneMonthFromToday; const finalEndDate = endDate < oneMonthFromToday ? endDate : oneMonthFromToday; // Extract time from original start_time and end_time const originalStartTime = new Date(slot.start_time); const originalEndTime = new Date(slot.end_time); const startHours = originalStartTime.getHours(); const startMinutes = originalStartTime.getMinutes(); const endHours = originalEndTime.getHours(); const endMinutes = originalEndTime.getMinutes(); let currentDate = new Date(today); while (currentDate <= finalEndDate) { const dayOfWeek = currentDate.getDay(); // Convert Sunday (0) to 6, Monday (1) to 0, etc. to match pattern format const patternDay = dayOfWeek === 0 ? 6 : dayOfWeek - 1; if (pattern.days && pattern.days.includes(patternDay)) { // Create specific datetime for this occurrence const specificStartTime = new Date(currentDate); specificStartTime.setHours(startHours, startMinutes, 0, 0); const specificEndTime = new Date(currentDate); specificEndTime.setHours(endHours, endMinutes, 0, 0); allTimeSlots.push({ start_time: specificStartTime.toISOString(), end_time: specificEndTime.toISOString() }); } currentDate.setDate(currentDate.getDate() + 1); } }); // Step 2: Group time slots by date (without time) const availableSlotsByDate: { [date: string]: { start_time: string; end_time: string }[] } = {}; allTimeSlots.forEach(timeSlot => { const dateStr = timeSlot.start_time.split('T')[0]; if (dateStr) { if (!availableSlotsByDate[dateStr]) { availableSlotsByDate[dateStr] = []; } availableSlotsByDate[dateStr].push(timeSlot); } }); // Step 3: Sort time slots within each date Object.keys(availableSlotsByDate).forEach(date => { availableSlotsByDate[date]?.sort((a, b) => a.start_time.localeCompare(b.start_time)); }); return availableSlotsByDate; }, // Get all bookings for a specific date filtered by booking type IDs async getBookingsForDate( date: string, bookingTypeIds: string[] ): Promise { try { // Create filter for booking type IDs const bookingTypeFilter = bookingTypeIds.map(id => `booking_type = "${id}"`).join(' || '); const bookings = await pb.collection('bookings').getFullList({ filter: `status = "confirmed" && start_time ~ "${date}" && (${bookingTypeFilter})`, sort: 'start_time' }); console.log(`Bookings for ${date}:`, bookings); return bookings; } catch (error) { console.error('Error fetching bookings for date:', error); return []; } }, };