import PocketBase from 'pocketbase'; import { BookingType, Resource, TimeSlot, Booking } from '@/types/booking'; // 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 available resources async getResources(): Promise { try { const records = await pb.collection('resources').getFullList({ filter: 'is_active = true', sort: 'type', }); return records; } catch (error) { console.error('Error fetching resources:', error); throw error; } }, // Get available time slots for a specific booking type and date range async getAvailableTimeSlots( bookingTypeId: string, startDate: Date, endDate: Date ): Promise { try { const startDateStr = startDate.toISOString().split('T')[0]; const endDateStr = endDate.toISOString().split('T')[0]; const records = await pb.collection('timeSlots').getFullList({ filter: `is_active = true && booking_types ~ "${bookingTypeId}" && start_time >= "${startDateStr}" && start_time <= "${endDateStr}"`, sort: 'start_time', }); return records; } catch (error) { console.error('Error fetching time slots:', error); throw error; } }, // Check if a time slot has availability async checkTimeSlotAvailability( timeSlotId: string, startTime: string, endTime: string, participantsCount: number ): Promise<{ available: boolean; currentBookings: number }> { try { // Get existing confirmed bookings for this time slot const existingBookings = await pb.collection('bookings').getFullList({ filter: `status = "confirmed" && start_time >= "${startTime}" && end_time <= "${endTime}"`, }); // Get the time slot to check max capacity const timeSlot = await pb.collection('timeSlots').getOne(timeSlotId); const currentBookings = existingBookings.reduce((sum, booking) => sum + (booking.participants_count || 0), 0 ); const availableSpots = timeSlot.max_capacity - currentBookings; const available = availableSpots >= participantsCount; return { available, currentBookings, }; } catch (error) { console.error('Error checking availability:', error); throw error; } }, // Create a new booking async createBooking(bookingData: { booking_type: string; customer_name: string; customer_email: string; start_time: string; end_time: string; participants_count: number; internal_notes?: string; }): Promise { try { const record = await pb.collection('bookings').create({ ...bookingData, status: 'confirmed', payment_status: 'not_required', // We'll handle payment logic later payment_required: false, }); return record; } catch (error) { console.error('Error creating booking:', error); throw error; } }, // Get booking by cancellation token (for cancellation flow) async getBookingByToken(token: string): Promise { try { const records = await pb.collection('bookings').getFullList({ filter: `cancellation_token = "${token}"`, }); return records[0] || null; } catch (error) { console.error('Error fetching booking by token:', error); return null; } }, // Cancel booking async cancelBooking(bookingId: string): Promise { try { await pb.collection('bookings').update(bookingId, { status: 'cancelled', }); return true; } catch (error) { console.error('Error cancelling booking:', error); return false; } }, };