gorombo-payload-appointments 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +308 -0
  3. package/dist/collections/Appointments.d.ts +2 -0
  4. package/dist/collections/Appointments.js +165 -0
  5. package/dist/collections/Appointments.js.map +1 -0
  6. package/dist/collections/GuestCustomers.d.ts +2 -0
  7. package/dist/collections/GuestCustomers.js +106 -0
  8. package/dist/collections/GuestCustomers.js.map +1 -0
  9. package/dist/collections/Services.d.ts +2 -0
  10. package/dist/collections/Services.js +147 -0
  11. package/dist/collections/Services.js.map +1 -0
  12. package/dist/collections/TeamMembers.d.ts +2 -0
  13. package/dist/collections/TeamMembers.js +184 -0
  14. package/dist/collections/TeamMembers.js.map +1 -0
  15. package/dist/components/BeforeDashboardClient.d.ts +2 -0
  16. package/dist/components/BeforeDashboardClient.js +162 -0
  17. package/dist/components/BeforeDashboardClient.js.map +1 -0
  18. package/dist/components/BeforeDashboardServer.d.ts +2 -0
  19. package/dist/components/BeforeDashboardServer.js +22 -0
  20. package/dist/components/BeforeDashboardServer.js.map +1 -0
  21. package/dist/components/BeforeDashboardServer.module.css +5 -0
  22. package/dist/components/calendar/Calendar.module.css +506 -0
  23. package/dist/components/calendar/CalendarContainer.d.ts +3 -0
  24. package/dist/components/calendar/CalendarContainer.js +246 -0
  25. package/dist/components/calendar/CalendarContainer.js.map +1 -0
  26. package/dist/components/calendar/DayView.d.ts +3 -0
  27. package/dist/components/calendar/DayView.js +192 -0
  28. package/dist/components/calendar/DayView.js.map +1 -0
  29. package/dist/components/calendar/EventPopover.d.ts +3 -0
  30. package/dist/components/calendar/EventPopover.js +257 -0
  31. package/dist/components/calendar/EventPopover.js.map +1 -0
  32. package/dist/components/calendar/EventRenderer.d.ts +3 -0
  33. package/dist/components/calendar/EventRenderer.js +76 -0
  34. package/dist/components/calendar/EventRenderer.js.map +1 -0
  35. package/dist/components/calendar/WeekView.d.ts +3 -0
  36. package/dist/components/calendar/WeekView.js +203 -0
  37. package/dist/components/calendar/WeekView.js.map +1 -0
  38. package/dist/components/calendar/index.d.ts +6 -0
  39. package/dist/components/calendar/index.js +7 -0
  40. package/dist/components/calendar/index.js.map +1 -0
  41. package/dist/components/calendar/types.d.ts +69 -0
  42. package/dist/components/calendar/types.js +3 -0
  43. package/dist/components/calendar/types.js.map +1 -0
  44. package/dist/endpoints/customEndpointHandler.d.ts +2 -0
  45. package/dist/endpoints/customEndpointHandler.js +7 -0
  46. package/dist/endpoints/customEndpointHandler.js.map +1 -0
  47. package/dist/endpoints/getAvailableSlots.d.ts +12 -0
  48. package/dist/endpoints/getAvailableSlots.js +291 -0
  49. package/dist/endpoints/getAvailableSlots.js.map +1 -0
  50. package/dist/exports/client.d.ts +3 -0
  51. package/dist/exports/client.js +4 -0
  52. package/dist/exports/client.js.map +1 -0
  53. package/dist/exports/rsc.d.ts +1 -0
  54. package/dist/exports/rsc.js +3 -0
  55. package/dist/exports/rsc.js.map +1 -0
  56. package/dist/globals/OpeningTimes.d.ts +2 -0
  57. package/dist/globals/OpeningTimes.js +196 -0
  58. package/dist/globals/OpeningTimes.js.map +1 -0
  59. package/dist/hooks/addAdminTitle.d.ts +7 -0
  60. package/dist/hooks/addAdminTitle.js +86 -0
  61. package/dist/hooks/addAdminTitle.js.map +1 -0
  62. package/dist/hooks/sendCustomerEmail.d.ts +6 -0
  63. package/dist/hooks/sendCustomerEmail.js +351 -0
  64. package/dist/hooks/sendCustomerEmail.js.map +1 -0
  65. package/dist/hooks/setEndDateTime.d.ts +6 -0
  66. package/dist/hooks/setEndDateTime.js +44 -0
  67. package/dist/hooks/setEndDateTime.js.map +1 -0
  68. package/dist/hooks/validateCustomerOrGuest.d.ts +6 -0
  69. package/dist/hooks/validateCustomerOrGuest.js +21 -0
  70. package/dist/hooks/validateCustomerOrGuest.js.map +1 -0
  71. package/dist/index.d.ts +23 -0
  72. package/dist/index.js +183 -0
  73. package/dist/index.js.map +1 -0
  74. package/package.json +135 -0
@@ -0,0 +1,69 @@
1
+ export interface CalendarEvent {
2
+ blockoutReason?: string;
3
+ customerId?: string;
4
+ customerName?: string;
5
+ end: Date;
6
+ guestId?: string;
7
+ guestName?: string;
8
+ id: string;
9
+ notes?: string;
10
+ serviceColor?: string;
11
+ serviceId?: string;
12
+ serviceName?: string;
13
+ start: Date;
14
+ status?: 'cancelled' | 'completed' | 'confirmed' | 'no-show' | 'scheduled';
15
+ teamMemberColor?: string;
16
+ teamMemberId?: string;
17
+ teamMemberName?: string;
18
+ title: string;
19
+ type: 'appointment' | 'blockout';
20
+ }
21
+ export interface TeamMember {
22
+ color: string;
23
+ id: string;
24
+ name: string;
25
+ takingAppointments: boolean;
26
+ }
27
+ export interface Service {
28
+ color: string;
29
+ duration: number;
30
+ id: string;
31
+ isActive: boolean;
32
+ name: string;
33
+ }
34
+ export type CalendarViewMode = 'day' | 'week';
35
+ export interface CalendarProps {
36
+ endHour?: number;
37
+ events: CalendarEvent[];
38
+ onDateChange?: (date: Date) => void;
39
+ onEventClick?: (event: CalendarEvent) => void;
40
+ onEventDrop?: (event: CalendarEvent, newStart: Date) => void;
41
+ onSlotClick?: (start: Date, end: Date, teamMemberId?: string) => void;
42
+ onViewModeChange?: (mode: CalendarViewMode) => void;
43
+ selectedDate?: Date;
44
+ slotDuration?: number;
45
+ startHour?: number;
46
+ teamMembers?: TeamMember[];
47
+ viewMode?: CalendarViewMode;
48
+ }
49
+ export interface WeekViewProps extends Omit<CalendarProps, 'onViewModeChange' | 'viewMode'> {
50
+ weekStart: Date;
51
+ }
52
+ export interface DayViewProps extends Omit<CalendarProps, 'onViewModeChange' | 'viewMode'> {
53
+ date: Date;
54
+ }
55
+ export interface EventRendererProps {
56
+ event: CalendarEvent;
57
+ onClick?: (event: CalendarEvent) => void;
58
+ style: React.CSSProperties;
59
+ }
60
+ export interface EventPopoverProps {
61
+ event: CalendarEvent;
62
+ onClose: () => void;
63
+ onDelete?: (event: CalendarEvent) => void;
64
+ onEdit?: (event: CalendarEvent) => void;
65
+ position: {
66
+ left: number;
67
+ top: number;
68
+ };
69
+ }
@@ -0,0 +1,3 @@
1
+ export { };
2
+
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/calendar/types.ts"],"sourcesContent":["export interface CalendarEvent {\n blockoutReason?: string\n customerId?: string\n customerName?: string\n end: Date\n guestId?: string\n guestName?: string\n id: string\n notes?: string\n serviceColor?: string\n serviceId?: string\n serviceName?: string\n start: Date\n status?: 'cancelled' | 'completed' | 'confirmed' | 'no-show' | 'scheduled'\n teamMemberColor?: string\n teamMemberId?: string\n teamMemberName?: string\n title: string\n type: 'appointment' | 'blockout'\n}\n\nexport interface TeamMember {\n color: string\n id: string\n name: string\n takingAppointments: boolean\n}\n\nexport interface Service {\n color: string\n duration: number\n id: string\n isActive: boolean\n name: string\n}\n\nexport type CalendarViewMode = 'day' | 'week'\n\nexport interface CalendarProps {\n endHour?: number\n events: CalendarEvent[]\n onDateChange?: (date: Date) => void\n onEventClick?: (event: CalendarEvent) => void\n onEventDrop?: (event: CalendarEvent, newStart: Date) => void\n onSlotClick?: (start: Date, end: Date, teamMemberId?: string) => void\n onViewModeChange?: (mode: CalendarViewMode) => void\n selectedDate?: Date\n slotDuration?: number // in minutes\n startHour?: number\n teamMembers?: TeamMember[]\n viewMode?: CalendarViewMode\n}\n\nexport interface WeekViewProps extends Omit<CalendarProps, 'onViewModeChange' | 'viewMode'> {\n weekStart: Date\n}\n\nexport interface DayViewProps extends Omit<CalendarProps, 'onViewModeChange' | 'viewMode'> {\n date: Date\n}\n\nexport interface EventRendererProps {\n event: CalendarEvent\n onClick?: (event: CalendarEvent) => void\n style: React.CSSProperties\n}\n\nexport interface EventPopoverProps {\n event: CalendarEvent\n onClose: () => void\n onDelete?: (event: CalendarEvent) => void\n onEdit?: (event: CalendarEvent) => void\n position: { left: number; top: number }\n}\n"],"names":[],"mappings":"AAmEA,WAMC"}
@@ -0,0 +1,2 @@
1
+ import type { PayloadHandler } from 'payload';
2
+ export declare const customEndpointHandler: PayloadHandler;
@@ -0,0 +1,7 @@
1
+ export const customEndpointHandler = ()=>{
2
+ return Response.json({
3
+ message: 'Hello from custom endpoint'
4
+ });
5
+ };
6
+
7
+ //# sourceMappingURL=customEndpointHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/endpoints/customEndpointHandler.ts"],"sourcesContent":["import type { PayloadHandler } from 'payload'\n\nexport const customEndpointHandler: PayloadHandler = () => {\n return Response.json({ message: 'Hello from custom endpoint' })\n}\n"],"names":["customEndpointHandler","Response","json","message"],"mappings":"AAEA,OAAO,MAAMA,wBAAwC;IACnD,OAAOC,SAASC,IAAI,CAAC;QAAEC,SAAS;IAA6B;AAC/D,EAAC"}
@@ -0,0 +1,12 @@
1
+ import type { PayloadHandler } from 'payload';
2
+ /**
3
+ * GET /api/appointments/available-slots
4
+ *
5
+ * Query params:
6
+ * - date: YYYY-MM-DD (required)
7
+ * - serviceId: string (required)
8
+ * - teamMemberId: string (optional)
9
+ *
10
+ * Returns available time slots for booking
11
+ */
12
+ export declare const getAvailableSlotsHandler: PayloadHandler;
@@ -0,0 +1,291 @@
1
+ /**
2
+ * GET /api/appointments/available-slots
3
+ *
4
+ * Query params:
5
+ * - date: YYYY-MM-DD (required)
6
+ * - serviceId: string (required)
7
+ * - teamMemberId: string (optional)
8
+ *
9
+ * Returns available time slots for booking
10
+ */ export const getAvailableSlotsHandler = async (req)=>{
11
+ try {
12
+ const url = new URL(req.url || '', 'http://localhost');
13
+ const dateParam = url.searchParams.get('date');
14
+ const serviceId = url.searchParams.get('serviceId');
15
+ const teamMemberId = url.searchParams.get('teamMemberId');
16
+ // Validate required params
17
+ if (!dateParam) {
18
+ return Response.json({
19
+ error: 'Missing required parameter: date (YYYY-MM-DD format)'
20
+ }, {
21
+ status: 400
22
+ });
23
+ }
24
+ if (!serviceId) {
25
+ return Response.json({
26
+ error: 'Missing required parameter: serviceId'
27
+ }, {
28
+ status: 400
29
+ });
30
+ }
31
+ // Parse date
32
+ const requestedDate = new Date(dateParam);
33
+ if (isNaN(requestedDate.getTime())) {
34
+ return Response.json({
35
+ error: 'Invalid date format. Use YYYY-MM-DD'
36
+ }, {
37
+ status: 400
38
+ });
39
+ }
40
+ // Get service details
41
+ const service = await req.payload.findByID({
42
+ id: serviceId,
43
+ collection: 'services'
44
+ });
45
+ if (!service) {
46
+ return Response.json({
47
+ error: 'Service not found'
48
+ }, {
49
+ status: 404
50
+ });
51
+ }
52
+ if (!service.isActive) {
53
+ return Response.json({
54
+ error: 'Service is not available for booking'
55
+ }, {
56
+ status: 400
57
+ });
58
+ }
59
+ // Get opening times settings
60
+ const openingTimes = await req.payload.findGlobal({
61
+ slug: 'opening-times'
62
+ });
63
+ // Check booking window
64
+ const now = new Date();
65
+ const maxBookingDate = new Date(now);
66
+ maxBookingDate.setDate(maxBookingDate.getDate() + (openingTimes?.maxAdvanceBookingDays || 30));
67
+ const minBookingDate = new Date(now);
68
+ minBookingDate.setHours(minBookingDate.getHours() + (openingTimes?.minAdvanceBookingHours || 1));
69
+ if (requestedDate > maxBookingDate) {
70
+ return Response.json({
71
+ error: `Cannot book more than ${openingTimes?.maxAdvanceBookingDays || 30} days in advance`
72
+ }, {
73
+ status: 400
74
+ });
75
+ }
76
+ if (requestedDate < minBookingDate) {
77
+ return Response.json({
78
+ error: `Must book at least ${openingTimes?.minAdvanceBookingHours || 1} hours in advance`
79
+ }, {
80
+ status: 400
81
+ });
82
+ }
83
+ // Get day of week
84
+ const dayNames = [
85
+ 'sunday',
86
+ 'monday',
87
+ 'tuesday',
88
+ 'wednesday',
89
+ 'thursday',
90
+ 'friday',
91
+ 'saturday'
92
+ ];
93
+ const dayOfWeek = dayNames[requestedDate.getDay()];
94
+ // Find business hours for this day
95
+ const daySchedule = openingTimes?.schedule?.find((s)=>s.day === dayOfWeek);
96
+ if (!daySchedule || !daySchedule.isOpen) {
97
+ return Response.json({
98
+ date: dateParam,
99
+ message: 'Business is closed on this day',
100
+ serviceId,
101
+ slots: [],
102
+ teamMemberId: teamMemberId || undefined
103
+ });
104
+ }
105
+ // Calculate slot duration (service duration + buffer)
106
+ const slotDuration = service.duration || 30;
107
+ const bufferBefore = service.bufferBefore || 0;
108
+ const bufferAfter = service.bufferAfter || 0;
109
+ const totalSlotTime = slotDuration + bufferBefore + bufferAfter;
110
+ // Parse business hours
111
+ const [openHour, openMin] = (daySchedule.openTime || '09:00').split(':').map(Number);
112
+ const [closeHour, closeMin] = (daySchedule.closeTime || '17:00').split(':').map(Number);
113
+ // Parse break times if set
114
+ let breakStart = null;
115
+ let breakEnd = null;
116
+ if (daySchedule.breakStart && daySchedule.breakEnd) {
117
+ const [breakStartHour, breakStartMin] = daySchedule.breakStart.split(':').map(Number);
118
+ const [breakEndHour, breakEndMin] = daySchedule.breakEnd.split(':').map(Number);
119
+ breakStart = breakStartHour * 60 + breakStartMin;
120
+ breakEnd = breakEndHour * 60 + breakEndMin;
121
+ }
122
+ // Get team member availability if specified
123
+ let teamMemberSchedule = null;
124
+ if (teamMemberId) {
125
+ const teamMember = await req.payload.findByID({
126
+ id: teamMemberId,
127
+ collection: 'team-members'
128
+ });
129
+ if (!teamMember) {
130
+ return Response.json({
131
+ error: 'Team member not found'
132
+ }, {
133
+ status: 404
134
+ });
135
+ }
136
+ if (!teamMember.takingAppointments) {
137
+ return Response.json({
138
+ error: 'Team member is not taking appointments'
139
+ }, {
140
+ status: 400
141
+ });
142
+ }
143
+ // Check if team member provides this service
144
+ const teamMemberServices = teamMember.services || [];
145
+ const serviceIds = teamMemberServices.map((s)=>typeof s === 'object' ? s.id : s);
146
+ if (serviceIds.length > 0 && !serviceIds.includes(serviceId)) {
147
+ return Response.json({
148
+ error: 'Team member does not provide this service'
149
+ }, {
150
+ status: 400
151
+ });
152
+ }
153
+ // Get team member's schedule for this day
154
+ teamMemberSchedule = teamMember.availability?.find((a)=>a.day === dayOfWeek);
155
+ if (teamMemberSchedule && !teamMemberSchedule.isAvailable) {
156
+ return Response.json({
157
+ date: dateParam,
158
+ message: 'Team member is not available on this day',
159
+ serviceId,
160
+ slots: [],
161
+ teamMemberId
162
+ });
163
+ }
164
+ }
165
+ // Get existing appointments for this day
166
+ const dayStart = new Date(requestedDate);
167
+ dayStart.setHours(0, 0, 0, 0);
168
+ const dayEnd = new Date(requestedDate);
169
+ dayEnd.setHours(23, 59, 59, 999);
170
+ const existingAppointments = await req.payload.find({
171
+ collection: 'appointments',
172
+ limit: 100,
173
+ where: {
174
+ and: [
175
+ {
176
+ startDateTime: {
177
+ greater_than_equal: dayStart.toISOString()
178
+ }
179
+ },
180
+ {
181
+ startDateTime: {
182
+ less_than: dayEnd.toISOString()
183
+ }
184
+ },
185
+ {
186
+ status: {
187
+ not_in: [
188
+ 'cancelled'
189
+ ]
190
+ }
191
+ },
192
+ ...teamMemberId ? [
193
+ {
194
+ teamMember: {
195
+ equals: teamMemberId
196
+ }
197
+ }
198
+ ] : []
199
+ ]
200
+ }
201
+ });
202
+ // Convert appointments to blocked time ranges (in minutes from midnight)
203
+ const blockedRanges = [];
204
+ for (const apt of existingAppointments.docs){
205
+ const aptStart = new Date(apt.startDateTime);
206
+ const aptEnd = apt.endDateTime ? new Date(apt.endDateTime) : new Date(aptStart.getTime() + 30 * 60000);
207
+ const startMinutes = aptStart.getHours() * 60 + aptStart.getMinutes();
208
+ const endMinutes = aptEnd.getHours() * 60 + aptEnd.getMinutes();
209
+ blockedRanges.push({
210
+ end: endMinutes + bufferAfter,
211
+ start: startMinutes - bufferBefore
212
+ });
213
+ }
214
+ // Determine effective working hours
215
+ let effectiveOpenMinutes = openHour * 60 + openMin;
216
+ let effectiveCloseMinutes = closeHour * 60 + closeMin;
217
+ // Apply team member schedule if available
218
+ if (teamMemberSchedule) {
219
+ const [tmOpenHour, tmOpenMin] = (teamMemberSchedule.startTime || '09:00').split(':').map(Number);
220
+ const [tmCloseHour, tmCloseMin] = (teamMemberSchedule.endTime || '17:00').split(':').map(Number);
221
+ effectiveOpenMinutes = Math.max(effectiveOpenMinutes, tmOpenHour * 60 + tmOpenMin);
222
+ effectiveCloseMinutes = Math.min(effectiveCloseMinutes, tmCloseHour * 60 + tmCloseMin);
223
+ // Apply team member break
224
+ if (teamMemberSchedule.breakStart && teamMemberSchedule.breakEnd) {
225
+ const [tmBreakStartHour, tmBreakStartMin] = teamMemberSchedule.breakStart.split(':').map(Number);
226
+ const [tmBreakEndHour, tmBreakEndMin] = teamMemberSchedule.breakEnd.split(':').map(Number);
227
+ // Use the more restrictive break
228
+ if (breakStart === null) {
229
+ breakStart = tmBreakStartHour * 60 + tmBreakStartMin;
230
+ breakEnd = tmBreakEndHour * 60 + tmBreakEndMin;
231
+ } else {
232
+ breakStart = Math.min(breakStart, tmBreakStartHour * 60 + tmBreakStartMin);
233
+ breakEnd = Math.max(breakEnd, tmBreakEndHour * 60 + tmBreakEndMin);
234
+ }
235
+ }
236
+ }
237
+ // Generate slots
238
+ const slots = [];
239
+ const slotInterval = openingTimes?.slotDuration || 30;
240
+ for(let minutes = effectiveOpenMinutes; minutes + totalSlotTime <= effectiveCloseMinutes; minutes += slotInterval){
241
+ const slotEnd = minutes + totalSlotTime;
242
+ // Check if slot is during break
243
+ if (breakStart !== null && breakEnd !== null) {
244
+ if (minutes < breakEnd && slotEnd > breakStart) {
245
+ continue; // Skip slots that overlap with break
246
+ }
247
+ }
248
+ // Check if slot conflicts with existing appointments
249
+ let isBlocked = false;
250
+ for (const blocked of blockedRanges){
251
+ if (minutes < blocked.end && slotEnd > blocked.start) {
252
+ isBlocked = true;
253
+ break;
254
+ }
255
+ }
256
+ // Create slot datetime
257
+ const slotStart = new Date(requestedDate);
258
+ slotStart.setHours(Math.floor(minutes / 60), minutes % 60, 0, 0);
259
+ const slotEndDate = new Date(requestedDate);
260
+ slotEndDate.setHours(Math.floor(slotEnd / 60), slotEnd % 60, 0, 0);
261
+ // Check if slot is in the past
262
+ if (slotStart < now) {
263
+ isBlocked = true;
264
+ }
265
+ slots.push({
266
+ available: !isBlocked,
267
+ end: slotEndDate.toISOString(),
268
+ start: slotStart.toISOString()
269
+ });
270
+ }
271
+ const response = {
272
+ date: dateParam,
273
+ serviceId,
274
+ slots,
275
+ teamMemberId: teamMemberId || undefined
276
+ };
277
+ return Response.json(response);
278
+ } catch (error) {
279
+ req.payload.logger.error({
280
+ error,
281
+ msg: 'Error getting available slots'
282
+ });
283
+ return Response.json({
284
+ error: 'Internal server error'
285
+ }, {
286
+ status: 500
287
+ });
288
+ }
289
+ };
290
+
291
+ //# sourceMappingURL=getAvailableSlots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/endpoints/getAvailableSlots.ts"],"sourcesContent":["import type { PayloadHandler } from 'payload'\n\ninterface TimeSlot {\n available: boolean\n end: string // ISO datetime\n start: string // ISO datetime\n}\n\ninterface AvailableSlotsResponse {\n date: string\n serviceId: string\n slots: TimeSlot[]\n teamMemberId?: string\n}\n\n/**\n * GET /api/appointments/available-slots\n *\n * Query params:\n * - date: YYYY-MM-DD (required)\n * - serviceId: string (required)\n * - teamMemberId: string (optional)\n *\n * Returns available time slots for booking\n */\nexport const getAvailableSlotsHandler: PayloadHandler = async (req) => {\n try {\n const url = new URL(req.url || '', 'http://localhost')\n const dateParam = url.searchParams.get('date')\n const serviceId = url.searchParams.get('serviceId')\n const teamMemberId = url.searchParams.get('teamMemberId')\n\n // Validate required params\n if (!dateParam) {\n return Response.json(\n { error: 'Missing required parameter: date (YYYY-MM-DD format)' },\n { status: 400 }\n )\n }\n\n if (!serviceId) {\n return Response.json(\n { error: 'Missing required parameter: serviceId' },\n { status: 400 }\n )\n }\n\n // Parse date\n const requestedDate = new Date(dateParam)\n if (isNaN(requestedDate.getTime())) {\n return Response.json(\n { error: 'Invalid date format. Use YYYY-MM-DD' },\n { status: 400 }\n )\n }\n\n // Get service details\n const service = await req.payload.findByID({\n id: serviceId,\n collection: 'services',\n })\n\n if (!service) {\n return Response.json(\n { error: 'Service not found' },\n { status: 404 }\n )\n }\n\n if (!service.isActive) {\n return Response.json(\n { error: 'Service is not available for booking' },\n { status: 400 }\n )\n }\n\n // Get opening times settings\n const openingTimes = await req.payload.findGlobal({\n slug: 'opening-times',\n })\n\n // Check booking window\n const now = new Date()\n const maxBookingDate = new Date(now)\n maxBookingDate.setDate(maxBookingDate.getDate() + (openingTimes?.maxAdvanceBookingDays || 30))\n\n const minBookingDate = new Date(now)\n minBookingDate.setHours(minBookingDate.getHours() + (openingTimes?.minAdvanceBookingHours || 1))\n\n if (requestedDate > maxBookingDate) {\n return Response.json(\n { error: `Cannot book more than ${openingTimes?.maxAdvanceBookingDays || 30} days in advance` },\n { status: 400 }\n )\n }\n\n if (requestedDate < minBookingDate) {\n return Response.json(\n { error: `Must book at least ${openingTimes?.minAdvanceBookingHours || 1} hours in advance` },\n { status: 400 }\n )\n }\n\n // Get day of week\n const dayNames = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday']\n const dayOfWeek = dayNames[requestedDate.getDay()]\n\n // Find business hours for this day\n const daySchedule = openingTimes?.schedule?.find(\n (s: any) => s.day === dayOfWeek\n )\n\n if (!daySchedule || !daySchedule.isOpen) {\n return Response.json({\n date: dateParam,\n message: 'Business is closed on this day',\n serviceId,\n slots: [],\n teamMemberId: teamMemberId || undefined,\n })\n }\n\n // Calculate slot duration (service duration + buffer)\n const slotDuration = service.duration || 30\n const bufferBefore = service.bufferBefore || 0\n const bufferAfter = service.bufferAfter || 0\n const totalSlotTime = slotDuration + bufferBefore + bufferAfter\n\n // Parse business hours\n const [openHour, openMin] = (daySchedule.openTime || '09:00').split(':').map(Number)\n const [closeHour, closeMin] = (daySchedule.closeTime || '17:00').split(':').map(Number)\n\n // Parse break times if set\n let breakStart: null | number = null\n let breakEnd: null | number = null\n if (daySchedule.breakStart && daySchedule.breakEnd) {\n const [breakStartHour, breakStartMin] = daySchedule.breakStart.split(':').map(Number)\n const [breakEndHour, breakEndMin] = daySchedule.breakEnd.split(':').map(Number)\n breakStart = breakStartHour * 60 + breakStartMin\n breakEnd = breakEndHour * 60 + breakEndMin\n }\n\n // Get team member availability if specified\n let teamMemberSchedule: any = null\n if (teamMemberId) {\n const teamMember = await req.payload.findByID({\n id: teamMemberId,\n collection: 'team-members',\n })\n\n if (!teamMember) {\n return Response.json(\n { error: 'Team member not found' },\n { status: 404 }\n )\n }\n\n if (!teamMember.takingAppointments) {\n return Response.json(\n { error: 'Team member is not taking appointments' },\n { status: 400 }\n )\n }\n\n // Check if team member provides this service\n const teamMemberServices = teamMember.services || []\n const serviceIds = teamMemberServices.map((s: any) =>\n typeof s === 'object' ? s.id : s\n )\n\n if (serviceIds.length > 0 && !serviceIds.includes(serviceId)) {\n return Response.json(\n { error: 'Team member does not provide this service' },\n { status: 400 }\n )\n }\n\n // Get team member's schedule for this day\n teamMemberSchedule = teamMember.availability?.find(\n (a: any) => a.day === dayOfWeek\n )\n\n if (teamMemberSchedule && !teamMemberSchedule.isAvailable) {\n return Response.json({\n date: dateParam,\n message: 'Team member is not available on this day',\n serviceId,\n slots: [],\n teamMemberId,\n })\n }\n }\n\n // Get existing appointments for this day\n const dayStart = new Date(requestedDate)\n dayStart.setHours(0, 0, 0, 0)\n const dayEnd = new Date(requestedDate)\n dayEnd.setHours(23, 59, 59, 999)\n\n const existingAppointments = await req.payload.find({\n collection: 'appointments',\n limit: 100,\n where: {\n and: [\n {\n startDateTime: {\n greater_than_equal: dayStart.toISOString(),\n },\n },\n {\n startDateTime: {\n less_than: dayEnd.toISOString(),\n },\n },\n {\n status: {\n not_in: ['cancelled'],\n },\n },\n ...(teamMemberId\n ? [{ teamMember: { equals: teamMemberId } }]\n : []),\n ],\n },\n })\n\n // Convert appointments to blocked time ranges (in minutes from midnight)\n const blockedRanges: Array<{ end: number; start: number }> = []\n for (const apt of existingAppointments.docs) {\n const aptStart = new Date(apt.startDateTime)\n const aptEnd = apt.endDateTime ? new Date(apt.endDateTime) : new Date(aptStart.getTime() + 30 * 60000)\n\n const startMinutes = aptStart.getHours() * 60 + aptStart.getMinutes()\n const endMinutes = aptEnd.getHours() * 60 + aptEnd.getMinutes()\n\n blockedRanges.push({\n end: endMinutes + bufferAfter,\n start: startMinutes - bufferBefore,\n })\n }\n\n // Determine effective working hours\n let effectiveOpenMinutes = openHour * 60 + openMin\n let effectiveCloseMinutes = closeHour * 60 + closeMin\n\n // Apply team member schedule if available\n if (teamMemberSchedule) {\n const [tmOpenHour, tmOpenMin] = (teamMemberSchedule.startTime || '09:00').split(':').map(Number)\n const [tmCloseHour, tmCloseMin] = (teamMemberSchedule.endTime || '17:00').split(':').map(Number)\n\n effectiveOpenMinutes = Math.max(effectiveOpenMinutes, tmOpenHour * 60 + tmOpenMin)\n effectiveCloseMinutes = Math.min(effectiveCloseMinutes, tmCloseHour * 60 + tmCloseMin)\n\n // Apply team member break\n if (teamMemberSchedule.breakStart && teamMemberSchedule.breakEnd) {\n const [tmBreakStartHour, tmBreakStartMin] = teamMemberSchedule.breakStart.split(':').map(Number)\n const [tmBreakEndHour, tmBreakEndMin] = teamMemberSchedule.breakEnd.split(':').map(Number)\n\n // Use the more restrictive break\n if (breakStart === null) {\n breakStart = tmBreakStartHour * 60 + tmBreakStartMin\n breakEnd = tmBreakEndHour * 60 + tmBreakEndMin\n } else {\n breakStart = Math.min(breakStart, tmBreakStartHour * 60 + tmBreakStartMin)\n breakEnd = Math.max(breakEnd!, tmBreakEndHour * 60 + tmBreakEndMin)\n }\n }\n }\n\n // Generate slots\n const slots: TimeSlot[] = []\n const slotInterval = openingTimes?.slotDuration || 30\n\n for (let minutes = effectiveOpenMinutes; minutes + totalSlotTime <= effectiveCloseMinutes; minutes += slotInterval) {\n const slotEnd = minutes + totalSlotTime\n\n // Check if slot is during break\n if (breakStart !== null && breakEnd !== null) {\n if (minutes < breakEnd && slotEnd > breakStart) {\n continue // Skip slots that overlap with break\n }\n }\n\n // Check if slot conflicts with existing appointments\n let isBlocked = false\n for (const blocked of blockedRanges) {\n if (minutes < blocked.end && slotEnd > blocked.start) {\n isBlocked = true\n break\n }\n }\n\n // Create slot datetime\n const slotStart = new Date(requestedDate)\n slotStart.setHours(Math.floor(minutes / 60), minutes % 60, 0, 0)\n\n const slotEndDate = new Date(requestedDate)\n slotEndDate.setHours(Math.floor(slotEnd / 60), slotEnd % 60, 0, 0)\n\n // Check if slot is in the past\n if (slotStart < now) {\n isBlocked = true\n }\n\n slots.push({\n available: !isBlocked,\n end: slotEndDate.toISOString(),\n start: slotStart.toISOString(),\n })\n }\n\n const response: AvailableSlotsResponse = {\n date: dateParam,\n serviceId,\n slots,\n teamMemberId: teamMemberId || undefined,\n }\n\n return Response.json(response)\n } catch (error) {\n req.payload.logger.error({\n error,\n msg: 'Error getting available slots',\n })\n\n return Response.json(\n { error: 'Internal server error' },\n { status: 500 }\n )\n }\n}\n"],"names":["getAvailableSlotsHandler","req","url","URL","dateParam","searchParams","get","serviceId","teamMemberId","Response","json","error","status","requestedDate","Date","isNaN","getTime","service","payload","findByID","id","collection","isActive","openingTimes","findGlobal","slug","now","maxBookingDate","setDate","getDate","maxAdvanceBookingDays","minBookingDate","setHours","getHours","minAdvanceBookingHours","dayNames","dayOfWeek","getDay","daySchedule","schedule","find","s","day","isOpen","date","message","slots","undefined","slotDuration","duration","bufferBefore","bufferAfter","totalSlotTime","openHour","openMin","openTime","split","map","Number","closeHour","closeMin","closeTime","breakStart","breakEnd","breakStartHour","breakStartMin","breakEndHour","breakEndMin","teamMemberSchedule","teamMember","takingAppointments","teamMemberServices","services","serviceIds","length","includes","availability","a","isAvailable","dayStart","dayEnd","existingAppointments","limit","where","and","startDateTime","greater_than_equal","toISOString","less_than","not_in","equals","blockedRanges","apt","docs","aptStart","aptEnd","endDateTime","startMinutes","getMinutes","endMinutes","push","end","start","effectiveOpenMinutes","effectiveCloseMinutes","tmOpenHour","tmOpenMin","startTime","tmCloseHour","tmCloseMin","endTime","Math","max","min","tmBreakStartHour","tmBreakStartMin","tmBreakEndHour","tmBreakEndMin","slotInterval","minutes","slotEnd","isBlocked","blocked","slotStart","floor","slotEndDate","available","response","logger","msg"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { BeforeDashboardClient } from '../components/BeforeDashboardClient.js';
2
+ export { CalendarContainer, DayView, EventPopover, EventRenderer, WeekView, } from '../components/calendar/index.js';
3
+ export type { CalendarEvent, CalendarProps, CalendarViewMode, DayViewProps, EventPopoverProps, EventRendererProps, Service, TeamMember, WeekViewProps, } from '../components/calendar/types.js';
@@ -0,0 +1,4 @@
1
+ export { BeforeDashboardClient } from '../components/BeforeDashboardClient.js';
2
+ export { CalendarContainer, DayView, EventPopover, EventRenderer, WeekView } from '../components/calendar/index.js';
3
+
4
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/exports/client.ts"],"sourcesContent":["export { BeforeDashboardClient } from '../components/BeforeDashboardClient.js'\nexport {\n CalendarContainer,\n DayView,\n EventPopover,\n EventRenderer,\n WeekView,\n} from '../components/calendar/index.js'\nexport type {\n CalendarEvent,\n CalendarProps,\n CalendarViewMode,\n DayViewProps,\n EventPopoverProps,\n EventRendererProps,\n Service,\n TeamMember,\n WeekViewProps,\n} from '../components/calendar/types.js'\n"],"names":["BeforeDashboardClient","CalendarContainer","DayView","EventPopover","EventRenderer","WeekView"],"mappings":"AAAA,SAASA,qBAAqB,QAAQ,yCAAwC;AAC9E,SACEC,iBAAiB,EACjBC,OAAO,EACPC,YAAY,EACZC,aAAa,EACbC,QAAQ,QACH,kCAAiC"}
@@ -0,0 +1 @@
1
+ export { BeforeDashboardServer } from '../components/BeforeDashboardServer.js';
@@ -0,0 +1,3 @@
1
+ export { BeforeDashboardServer } from '../components/BeforeDashboardServer.js';
2
+
3
+ //# sourceMappingURL=rsc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/exports/rsc.ts"],"sourcesContent":["export { BeforeDashboardServer } from '../components/BeforeDashboardServer.js'\n"],"names":["BeforeDashboardServer"],"mappings":"AAAA,SAASA,qBAAqB,QAAQ,yCAAwC"}
@@ -0,0 +1,2 @@
1
+ import type { GlobalConfig } from 'payload';
2
+ export declare const OpeningTimes: GlobalConfig;