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

@@ -0,0 +1,70 @@
import { NextRequest, NextResponse } from 'next/server';
import { bookingApi } from '@/lib/pocketbase';
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const { id: bookingTypeId } = await params;
// Get booking type details to get the actual capacity
const bookingTypes = await bookingApi.getBookingTypes();
const bookingType = bookingTypes.find(bt => bt.id === bookingTypeId);
if (!bookingType) {
return NextResponse.json({ error: 'Booking type not found' }, { status: 404 });
}
const bookingCapacity = bookingType.booking_capacity;
// Get time slots for this booking type
const timeSlots = await bookingApi.getTimeSlotsForBookingType(bookingTypeId);
// Generate all available dates based on recurrence patterns
const availableSlotsByDate = await bookingApi.generateAvailableTimeSlots(timeSlots);
// Get all dates and check capacity for each
const availableDates: string[] = [];
for (const date of Object.keys(availableSlotsByDate)) {
// Get bookings for this date
const bookings = await bookingApi.getBookingsForDate(date, [bookingTypeId]);
// Check if any time slots have capacity available
const slotsForDate = availableSlotsByDate[date];
const hasAvailableSlots = slotsForDate.some(slot => {
const slotStart = new Date(slot.start_time);
const slotEnd = new Date(slot.end_time);
const overlappingBookings = bookings.filter(booking => {
const bookingStart = new Date(booking.start_time);
const bookingEnd = new Date(booking.end_time);
return bookingStart < slotEnd && bookingEnd > slotStart;
});
const totalParticipants = overlappingBookings.reduce((sum, booking) =>
sum + (booking.participants_count || 0), 0
);
return totalParticipants < bookingCapacity;
});
if (hasAvailableSlots) {
availableDates.push(date);
}
}
return NextResponse.json({
bookingTypeId,
availableDates: availableDates.sort()
});
} catch (error) {
console.error('Error fetching available dates:', error);
return NextResponse.json(
{ error: 'Failed to fetch available dates' },
{ status: 500 }
);
}
}

View File

@@ -0,0 +1,102 @@
import { NextRequest, NextResponse } from 'next/server';
import { bookingApi } from '@/lib/pocketbase';
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const { id: bookingTypeId } = await params;
const { searchParams } = new URL(request.url);
const date = searchParams.get('date');
if (!date) {
return NextResponse.json({ error: 'Date parameter required' }, { status: 400 });
}
// Get booking type details to get the actual capacity
const bookingTypes = await bookingApi.getBookingTypes();
const bookingType = bookingTypes.find(bt => bt.id === bookingTypeId);
if (!bookingType) {
return NextResponse.json({ error: 'Booking type not found' }, { status: 404 });
}
const bookingCapacity = bookingType.booking_capacity;
// Get time slots for this booking type
const timeSlots = await bookingApi.getTimeSlotsForBookingType(bookingTypeId);
// Generate available slots for all dates
const availableSlotsByDate = await bookingApi.generateAvailableTimeSlots(timeSlots);
const slotsForDate = availableSlotsByDate[date] || [];
if (slotsForDate.length === 0) {
return NextResponse.json({
date,
bookingTypeId,
timeSlots: []
});
}
// Get existing bookings for this date
const bookings = await bookingApi.getBookingsForDate(date, [bookingTypeId]);
console.log(`\n=== Bookings for ${date} and booking type ${bookingTypeId} ===`);
console.log('Number of bookings found:', bookings.length);
bookings.forEach((booking, i) => {
console.log(`Booking ${i+1}: ${booking.start_time} - ${booking.end_time}, participants: ${booking.participants_count}`);
});
// Calculate capacity for each slot
const slotsWithCapacity = slotsForDate.map((slot, index) => {
const slotStart = new Date(slot.start_time);
const slotEnd = new Date(slot.end_time);
console.log(`\n=== Checking slot ${slot.start_time} - ${slot.end_time} ===`);
console.log('Available bookings for date:', bookings.length);
const overlappingBookings = bookings.filter(booking => {
const bookingStart = new Date(booking.start_time);
const bookingEnd = new Date(booking.end_time);
const overlaps = bookingStart < slotEnd && bookingEnd > slotStart;
console.log(`Booking ${booking.start_time} - ${booking.end_time}: overlaps = ${overlaps}`);
return overlaps;
});
const totalParticipants = overlappingBookings.reduce((sum, booking) =>
sum + (booking.participants_count || 0), 0
);
const availableCapacity = Math.max(0, bookingCapacity - totalParticipants);
console.log(`Total participants: ${totalParticipants}, Capacity: ${bookingCapacity}, Available: ${availableCapacity}`);
return {
id: `slot-${date}-${index}`,
start_time: slot.start_time,
end_time: slot.end_time,
availableCapacity,
totalBookings: totalParticipants,
maxCapacity: bookingCapacity,
is_active: availableCapacity > 0
};
});
// Filter out fully booked slots
const availableTimeSlots = slotsWithCapacity.filter(slot => slot.availableCapacity > 0);
return NextResponse.json({
date,
bookingTypeId,
timeSlots: availableTimeSlots
});
} catch (error) {
console.error('Error fetching time slots:', error);
return NextResponse.json(
{ error: 'Failed to fetch time slots' },
{ status: 500 }
);
}
}