fix the capacity and NaN participants issue

This commit is contained in:
Asya Vee
2025-08-27 02:50:13 +04:00
parent 459289df2d
commit ff6de00988
9 changed files with 248 additions and 68 deletions

View File

@@ -4,7 +4,6 @@ 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';
@@ -27,7 +26,6 @@ const BookingInterface = () => {
const [bookingTypes, setBookingTypes] = useState<BookingType[]>([]);
const [timeSlots, setTimeSlots] = useState<TimeSlot[]>([]);
const [availableDates, setAvailableDates] = useState<string[]>([]);
const [availableSlotsByDate, setAvailableSlotsByDate] = useState<{ [date: string]: { start_time: string; end_time: string }[] }>({});
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
@@ -100,22 +98,23 @@ const BookingInterface = () => {
// Set participants count to booking type's minimum capacity
const bookingType = bookingTypes.find(bt => bt.id === typeId);
if (bookingType) {
setParticipantsCount(bookingType.min_capacity);
setParticipantsCount(bookingType.min_participants_capacity);
}
// Fetch time slots for the selected booking type
// Fetch available dates from server API (with capacity pre-calculated)
try {
const timeSlots = await bookingApi.getTimeSlotsForBookingType(typeId);
const response = await fetch(`/api/booking-types/${typeId}/available-dates`);
const data = await response.json();
// 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);
if (response.ok) {
setAvailableDates(data.availableDates);
} else {
console.error('Error fetching available dates:', data.error);
setAvailableDates([]);
}
} catch (error) {
console.error('Error fetching time slots:', error);
console.error('Error fetching available dates:', error);
setAvailableDates([]);
}
};
@@ -123,63 +122,37 @@ const BookingInterface = () => {
setSelectedDate(date);
setSelectedTimeSlot('');
// Get time slots for the selected date from availableSlotsByDate
const slotsForDate = availableSlotsByDate[date] || [];
// Get bookings for this date filtered by booking type IDs
let bookingOverlapCounts: { [key: string]: number } = {};
// Fetch time slots with capacity from server API
try {
const bookings = await bookingApi.getBookingsForDate(date, [selectedBookingType]);
const response = await fetch(`/api/booking-types/${selectedBookingType}/time-slots?date=${date}`);
const data = await response.json();
// Count overlapping bookings for each time slot
slotsForDate.forEach(slot => {
const slotStart = new Date(slot.start_time);
const slotEnd = new Date(slot.end_time);
if (response.ok) {
// Convert server response to TimeSlot format
const formattedTimeSlots: TimeSlot[] = data.timeSlots.map((slot: any) => ({
id: slot.id,
start_time: slot.start_time,
end_time: slot.end_time,
is_active: slot.is_active,
booking_capacity: slot.maxCapacity,
booking_types: [selectedBookingType],
is_reccuring: false,
recurrence_pattern: undefined,
resources: [],
created: new Date().toISOString(),
updated: new Date().toISOString(),
availableCapacity: slot.availableCapacity // Add capacity info for UI
}));
const overlappingBookings = bookings.filter(booking => {
const bookingStart = new Date(booking.start_time);
const bookingEnd = new Date(booking.end_time);
// Check if bookings overlap with time slot
return bookingStart < slotEnd && bookingEnd > slotStart;
});
const totalParticipants = overlappingBookings.reduce((sum, booking) =>
sum + (booking.participants_count || 0), 0
);
const key = `${slot.start_time}-${slot.end_time}`;
bookingOverlapCounts[key] = totalParticipants;
});
console.log('Booking overlap counts:', bookingOverlapCounts);
setTimeSlots(formattedTimeSlots);
} else {
console.error('Error fetching time slots:', data.error);
setTimeSlots([]);
}
} catch (error) {
console.error('Error fetching bookings for date:', error);
console.error('Error fetching time slots:', error);
setTimeSlots([]);
}
// Convert to TimeSlot format and filter out fully booked slots
const bookingTypeCapacity = selectedBookingTypeData?.booking_capacity || 8;
const availableTimeSlots = slotsForDate.filter(slot => {
const key = `${slot.start_time}-${slot.end_time}`;
const overlappingCount = bookingOverlapCounts[key] || 0;
return overlappingCount < bookingTypeCapacity;
});
const formattedTimeSlots: TimeSlot[] = availableTimeSlots.map((slot, index) => ({
id: `slot-${date}-${index}`,
start_time: slot.start_time,
end_time: slot.end_time,
is_active: true,
booking_capacity: bookingTypeCapacity,
booking_types: [selectedBookingType],
is_reccuring: false,
recurrence_pattern: undefined,
resources: [],
created: new Date().toISOString(),
updated: new Date().toISOString()
}));
setTimeSlots(formattedTimeSlots);
};
return (