diff --git a/apps/pocketbase/pb_data/auxiliary.db b/apps/pocketbase/pb_data/auxiliary.db
index e1b3286..515babc 100644
Binary files a/apps/pocketbase/pb_data/auxiliary.db and b/apps/pocketbase/pb_data/auxiliary.db differ
diff --git a/apps/pocketbase/pb_data/data.db b/apps/pocketbase/pb_data/data.db
index 293ae71..a58edb1 100644
Binary files a/apps/pocketbase/pb_data/data.db and b/apps/pocketbase/pb_data/data.db differ
diff --git a/apps/pocketbase/pb_migrations/1756241295_updated_timeSlots.js b/apps/pocketbase/pb_migrations/1756241295_updated_timeSlots.js
new file mode 100644
index 0000000..8b0b815
--- /dev/null
+++ b/apps/pocketbase/pb_migrations/1756241295_updated_timeSlots.js
@@ -0,0 +1,38 @@
+///
+migrate((app) => {
+ const collection = app.findCollectionByNameOrId("pbc_586073990")
+
+ // update field
+ collection.fields.addAt(7, new Field({
+ "hidden": false,
+ "id": "number3301820327",
+ "max": null,
+ "min": 1,
+ "name": "max_booking_capacity",
+ "onlyInt": false,
+ "presentable": false,
+ "required": true,
+ "system": false,
+ "type": "number"
+ }))
+
+ return app.save(collection)
+}, (app) => {
+ const collection = app.findCollectionByNameOrId("pbc_586073990")
+
+ // update field
+ collection.fields.addAt(7, new Field({
+ "hidden": false,
+ "id": "number3301820327",
+ "max": null,
+ "min": 1,
+ "name": "max_capacity",
+ "onlyInt": false,
+ "presentable": false,
+ "required": true,
+ "system": false,
+ "type": "number"
+ }))
+
+ return app.save(collection)
+})
diff --git a/apps/pocketbase/pb_migrations/1756241390_updated_bookingTypes.js b/apps/pocketbase/pb_migrations/1756241390_updated_bookingTypes.js
new file mode 100644
index 0000000..00bd671
--- /dev/null
+++ b/apps/pocketbase/pb_migrations/1756241390_updated_bookingTypes.js
@@ -0,0 +1,66 @@
+///
+migrate((app) => {
+ const collection = app.findCollectionByNameOrId("pbc_43114331")
+
+ // update field
+ collection.fields.addAt(9, new Field({
+ "hidden": false,
+ "id": "number1421793101",
+ "max": null,
+ "min": null,
+ "name": "min_participants_capacity",
+ "onlyInt": false,
+ "presentable": false,
+ "required": false,
+ "system": false,
+ "type": "number"
+ }))
+
+ // update field
+ collection.fields.addAt(10, new Field({
+ "hidden": false,
+ "id": "number3301820327",
+ "max": null,
+ "min": null,
+ "name": "max_participants_capacity",
+ "onlyInt": false,
+ "presentable": false,
+ "required": false,
+ "system": false,
+ "type": "number"
+ }))
+
+ return app.save(collection)
+}, (app) => {
+ const collection = app.findCollectionByNameOrId("pbc_43114331")
+
+ // update field
+ collection.fields.addAt(9, new Field({
+ "hidden": false,
+ "id": "number1421793101",
+ "max": null,
+ "min": null,
+ "name": "min_capacity",
+ "onlyInt": false,
+ "presentable": false,
+ "required": false,
+ "system": false,
+ "type": "number"
+ }))
+
+ // update field
+ collection.fields.addAt(10, new Field({
+ "hidden": false,
+ "id": "number3301820327",
+ "max": null,
+ "min": null,
+ "name": "max_capacity",
+ "onlyInt": false,
+ "presentable": false,
+ "required": false,
+ "system": false,
+ "type": "number"
+ }))
+
+ return app.save(collection)
+})
diff --git a/apps/pocketbase/pb_migrations/1756242359_updated_timeSlots.js b/apps/pocketbase/pb_migrations/1756242359_updated_timeSlots.js
new file mode 100644
index 0000000..515f381
--- /dev/null
+++ b/apps/pocketbase/pb_migrations/1756242359_updated_timeSlots.js
@@ -0,0 +1,27 @@
+///
+migrate((app) => {
+ const collection = app.findCollectionByNameOrId("pbc_586073990")
+
+ // remove field
+ collection.fields.removeById("number3301820327")
+
+ return app.save(collection)
+}, (app) => {
+ const collection = app.findCollectionByNameOrId("pbc_586073990")
+
+ // add field
+ collection.fields.addAt(7, new Field({
+ "hidden": false,
+ "id": "number3301820327",
+ "max": null,
+ "min": 1,
+ "name": "max_booking_capacity",
+ "onlyInt": false,
+ "presentable": false,
+ "required": true,
+ "system": false,
+ "type": "number"
+ }))
+
+ return app.save(collection)
+})
diff --git a/apps/pocketbase/pb_migrations/1756242388_updated_bookingTypes.js b/apps/pocketbase/pb_migrations/1756242388_updated_bookingTypes.js
new file mode 100644
index 0000000..c51eac8
--- /dev/null
+++ b/apps/pocketbase/pb_migrations/1756242388_updated_bookingTypes.js
@@ -0,0 +1,27 @@
+///
+migrate((app) => {
+ const collection = app.findCollectionByNameOrId("pbc_43114331")
+
+ // add field
+ collection.fields.addAt(12, new Field({
+ "hidden": false,
+ "id": "number2396794873",
+ "max": null,
+ "min": null,
+ "name": "booking_capacity",
+ "onlyInt": false,
+ "presentable": false,
+ "required": true,
+ "system": false,
+ "type": "number"
+ }))
+
+ return app.save(collection)
+}, (app) => {
+ const collection = app.findCollectionByNameOrId("pbc_43114331")
+
+ // remove field
+ collection.fields.removeById("number2396794873")
+
+ return app.save(collection)
+})
diff --git a/apps/pocketbase/pb_migrations/1756243147_updated_bookings.js b/apps/pocketbase/pb_migrations/1756243147_updated_bookings.js
new file mode 100644
index 0000000..c839e41
--- /dev/null
+++ b/apps/pocketbase/pb_migrations/1756243147_updated_bookings.js
@@ -0,0 +1,22 @@
+///
+migrate((app) => {
+ const collection = app.findCollectionByNameOrId("pbc_986407980")
+
+ // update collection data
+ unmarshal({
+ "listRule": "",
+ "viewRule": ""
+ }, collection)
+
+ return app.save(collection)
+}, (app) => {
+ const collection = app.findCollectionByNameOrId("pbc_986407980")
+
+ // update collection data
+ unmarshal({
+ "listRule": null,
+ "viewRule": null
+ }, collection)
+
+ return app.save(collection)
+})
diff --git a/apps/web/components/BookingForm.tsx b/apps/web/components/BookingForm.tsx
index 4ce1370..98f2829 100644
--- a/apps/web/components/BookingForm.tsx
+++ b/apps/web/components/BookingForm.tsx
@@ -119,21 +119,58 @@ const BookingInterface = () => {
}
};
- const handleDateChange = (date: string) => {
+ const handleDateChange = async (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) => ({
+ // Get bookings for this date filtered by booking type IDs
+ let bookingOverlapCounts: { [key: string]: number } = {};
+ try {
+ const bookings = await bookingApi.getBookingsForDate(date, [selectedBookingType]);
+
+ // Count overlapping bookings for each time slot
+ slotsForDate.forEach(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);
+
+ // 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);
+ } catch (error) {
+ console.error('Error fetching bookings for date:', error);
+ }
+
+ // 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,
- max_capacity: 8,
+ booking_capacity: bookingTypeCapacity,
booking_types: [selectedBookingType],
is_reccuring: false,
recurrence_pattern: undefined,
diff --git a/apps/web/components/DateSelector.tsx b/apps/web/components/DateSelector.tsx
index 5a4660e..f5ae5c1 100644
--- a/apps/web/components/DateSelector.tsx
+++ b/apps/web/components/DateSelector.tsx
@@ -35,11 +35,14 @@ const DateSelector: React.FC = ({
date.setDate(today.getDate() + i);
const dateString = date.toISOString().split('T')[0] || '';
+ // Create date object from the ISO string to avoid timezone issues
+ const displayDate = new Date(dateString + 'T12:00:00.000Z');
+
days.push({
date: dateString,
- day: date.getDate(),
- month: date.toLocaleDateString('en', { month: 'short' }),
- dayName: date.toLocaleDateString('en', { weekday: 'short' }),
+ day: parseInt(dateString.split('-')[2]),
+ month: displayDate.toLocaleDateString('en', { month: 'short', timeZone: 'UTC' }),
+ dayName: displayDate.toLocaleDateString('en', { weekday: 'short', timeZone: 'UTC' }),
available: availableDates.includes(dateString)
});
}
diff --git a/apps/web/lib/pocketbase.ts b/apps/web/lib/pocketbase.ts
index 63c28be..7c7233e 100644
--- a/apps/web/lib/pocketbase.ts
+++ b/apps/web/lib/pocketbase.ts
@@ -1,5 +1,5 @@
import PocketBase from 'pocketbase';
-import { BookingType, TimeSlot } from '@/types/bookings';
+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');
@@ -122,4 +122,26 @@ export const bookingApi = {
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 [];
+ }
+ },
};
\ No newline at end of file
diff --git a/apps/web/types/bookings.ts b/apps/web/types/bookings.ts
index eb6fe27..974305e 100644
--- a/apps/web/types/bookings.ts
+++ b/apps/web/types/bookings.ts
@@ -9,7 +9,7 @@ export interface BaseRecord {
export interface Resource extends BaseRecord {
name: string;
type: 'wheel' | 'workstation';
- capacity: number;
+ usage_capacity: number;
is_active: boolean;
}
@@ -23,9 +23,10 @@ export interface BookingType extends BaseRecord {
min_duration: number;
price_per_person: number;
resources: string; // relation to Resource
- min_capacity: number;
- max_capacity: number;
+ min_participants_capacity: number;
+ max_participants_capacity: number;
is_active: boolean;
+ booking_capacity: number;
}
// Time Slot entity
@@ -36,7 +37,6 @@ export interface TimeSlot extends BaseRecord {
is_active: boolean;
is_reccuring?: boolean;
recurrence_pattern?: RecurrencePattern;
- max_capacity: number;
}
// Recurrence pattern structure