@wix/headless-bookings 0.0.20 → 0.0.22
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.
- package/cjs/dist/api/{time-slot-list → fetch-availability}/index.d.ts +4 -3
- package/cjs/dist/api/{time-slot-list → fetch-availability}/index.js +36 -15
- package/cjs/dist/api/index.d.ts +1 -1
- package/cjs/dist/api/index.js +1 -1
- package/cjs/dist/react/booking/Booking.d.ts +2 -1
- package/cjs/dist/react/booking/Booking.js +1 -1
- package/cjs/dist/react/core/booking/Booking.d.ts +3 -2
- package/cjs/dist/react/core/booking/Booking.js +5 -2
- package/cjs/dist/react/core/time-slot-list/TimeSlot.d.ts +4 -4
- package/cjs/dist/react/core/time-slot-list/TimeSlot.js +17 -7
- package/cjs/dist/react/core/time-slot-list/TimeSlotList.js +3 -2
- package/cjs/dist/react/time-slot-list/TimeSlot.d.ts +6 -6
- package/cjs/dist/react/time-slot-list/TimeSlot.js +6 -6
- package/cjs/dist/react/time-slot-list/TimeSlotList.d.ts +4 -4
- package/cjs/dist/services/booking/booking.d.ts +6 -0
- package/cjs/dist/services/booking/booking.js +21 -1
- package/cjs/dist/services/time-slot-list/time-slot-list.def.d.ts +12 -4
- package/cjs/dist/services/time-slot-list/time-slot-list.js +37 -34
- package/dist/api/{time-slot-list → fetch-availability}/index.d.ts +4 -3
- package/dist/api/{time-slot-list → fetch-availability}/index.js +36 -15
- package/dist/api/index.d.ts +1 -1
- package/dist/api/index.js +1 -1
- package/dist/react/booking/Booking.d.ts +2 -1
- package/dist/react/booking/Booking.js +1 -1
- package/dist/react/core/booking/Booking.d.ts +3 -2
- package/dist/react/core/booking/Booking.js +5 -2
- package/dist/react/core/time-slot-list/TimeSlot.d.ts +4 -4
- package/dist/react/core/time-slot-list/TimeSlot.js +17 -7
- package/dist/react/core/time-slot-list/TimeSlotList.js +3 -2
- package/dist/react/time-slot-list/TimeSlot.d.ts +6 -6
- package/dist/react/time-slot-list/TimeSlot.js +6 -6
- package/dist/react/time-slot-list/TimeSlotList.d.ts +4 -4
- package/dist/services/booking/booking.d.ts +6 -0
- package/dist/services/booking/booking.js +21 -1
- package/dist/services/time-slot-list/time-slot-list.def.d.ts +12 -4
- package/dist/services/time-slot-list/time-slot-list.js +37 -34
- package/package.json +2 -2
|
@@ -6,7 +6,11 @@
|
|
|
6
6
|
import { defineService, implementService } from '@wix/services-definitions';
|
|
7
7
|
import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
|
|
8
8
|
// ============================================================================
|
|
9
|
-
//
|
|
9
|
+
// Constants
|
|
10
|
+
// ============================================================================
|
|
11
|
+
export const ANY_STAFF_MEMBER_ID = '__any_staff_member__';
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Helpers
|
|
10
14
|
// ============================================================================
|
|
11
15
|
/**
|
|
12
16
|
* Generates a unique instance ID for service selections
|
|
@@ -14,6 +18,14 @@ import { SignalsServiceDefinition, } from '@wix/services-definitions/core-servic
|
|
|
14
18
|
function generateInstanceId() {
|
|
15
19
|
return crypto.randomUUID();
|
|
16
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Gets the client's timezone from Intl API
|
|
23
|
+
*/
|
|
24
|
+
function getClientTimezone() {
|
|
25
|
+
return typeof Intl !== 'undefined'
|
|
26
|
+
? Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
27
|
+
: undefined;
|
|
28
|
+
}
|
|
17
29
|
/**
|
|
18
30
|
* Service definition for Booking
|
|
19
31
|
*/
|
|
@@ -55,6 +67,7 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
|
|
|
55
67
|
}));
|
|
56
68
|
const serviceSelectionsSignal = signalsService.signal(initialItemsWithIds);
|
|
57
69
|
const locationSignal = signalsService.signal(config.location || null);
|
|
70
|
+
const timezoneSignal = signalsService.signal(config.timezone ?? getClientTimezone());
|
|
58
71
|
const formSubmissionSignal = signalsService.signal(config.formSubmission || null);
|
|
59
72
|
// ========================================================================
|
|
60
73
|
// Actions Implementation
|
|
@@ -142,6 +155,12 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
|
|
|
142
155
|
clearLocation() {
|
|
143
156
|
locationSignal.set(null);
|
|
144
157
|
},
|
|
158
|
+
// Timezone actions
|
|
159
|
+
setTimezone(timezone) {
|
|
160
|
+
if (timezoneSignal.get() !== timezone) {
|
|
161
|
+
timezoneSignal.set(timezone);
|
|
162
|
+
}
|
|
163
|
+
},
|
|
145
164
|
// Form Submission actions
|
|
146
165
|
setFormSubmission(values) {
|
|
147
166
|
formSubmissionSignal.set(values);
|
|
@@ -159,6 +178,7 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
|
|
|
159
178
|
return {
|
|
160
179
|
serviceSelections: serviceSelectionsSignal,
|
|
161
180
|
location: locationSignal,
|
|
181
|
+
timezone: timezoneSignal,
|
|
162
182
|
formSubmission: formSubmissionSignal,
|
|
163
183
|
actions,
|
|
164
184
|
};
|
|
@@ -65,11 +65,21 @@ export interface TimeSlotsFilters {
|
|
|
65
65
|
* Default: 1000. Max: 1000.
|
|
66
66
|
* @example
|
|
67
67
|
* ```ts
|
|
68
|
-
* // Load
|
|
69
|
-
* filters: { slotsPerPage:
|
|
68
|
+
* // Load 10 slots at a time
|
|
69
|
+
* filters: { slotsPerPage: 10 }
|
|
70
70
|
* ```
|
|
71
71
|
*/
|
|
72
72
|
slotsPerPage?: number;
|
|
73
|
+
/**
|
|
74
|
+
* Maximum number of time slots to return per day.
|
|
75
|
+
* Useful for fetching availability indicators (set to 1 to get one slot per day).
|
|
76
|
+
* @example
|
|
77
|
+
* ```ts
|
|
78
|
+
* // Get one slot per day for calendar indicators
|
|
79
|
+
* filters: { timeSlotsPerDay: 1 }
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
timeSlotsPerDay?: number;
|
|
73
83
|
}
|
|
74
84
|
export interface TimeSlotListServiceConfig {
|
|
75
85
|
/** Services to fetch time slots for */
|
|
@@ -92,7 +102,6 @@ export interface TimeSlotListServiceActions {
|
|
|
92
102
|
clearPreferences: () => void;
|
|
93
103
|
loadMore: () => Promise<void>;
|
|
94
104
|
setDateRange: (start: Date, end: Date) => void;
|
|
95
|
-
setTimezone: (tz: string) => void;
|
|
96
105
|
}
|
|
97
106
|
export interface TimeSlotListServiceAPI {
|
|
98
107
|
timeSlots: Signal<TimeSlot[]>;
|
|
@@ -102,7 +111,6 @@ export interface TimeSlotListServiceAPI {
|
|
|
102
111
|
hasMore: Signal<boolean>;
|
|
103
112
|
startDate: Signal<Date>;
|
|
104
113
|
endDate: Signal<Date>;
|
|
105
|
-
timezone: Signal<string | undefined>;
|
|
106
114
|
actions: TimeSlotListServiceActions;
|
|
107
115
|
}
|
|
108
116
|
export declare const TimeSlotListServiceDefinition: string & {
|
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { implementService } from '@wix/services-definitions';
|
|
6
6
|
import { SignalsServiceDefinition } from '@wix/services-definitions/core-services/signals';
|
|
7
|
-
import { format } from 'date-fns';
|
|
8
7
|
import { TimeSlotListServiceDefinition, ViewMode, } from './time-slot-list.def.js';
|
|
9
|
-
import { fetchAvailability } from '../../api/
|
|
10
|
-
import { BookingServiceDefinition, } from '../booking/booking.js';
|
|
8
|
+
import { fetchAvailability } from '../../api/fetch-availability/index.js';
|
|
9
|
+
import { BookingServiceDefinition, ANY_STAFF_MEMBER_ID, } from '../booking/booking.js';
|
|
11
10
|
// ============================================================================
|
|
12
11
|
// Helpers
|
|
13
12
|
// ============================================================================
|
|
@@ -19,13 +18,6 @@ function getClientTimezone() {
|
|
|
19
18
|
? Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
20
19
|
: undefined;
|
|
21
20
|
}
|
|
22
|
-
/**
|
|
23
|
-
* Formats a Date to local ISO string (YYYY-MM-DDThh:mm:ss)
|
|
24
|
-
*/
|
|
25
|
-
function toLocalDateString(date) {
|
|
26
|
-
const pattern = "yyyy-MM-dd'T'HH:mm:ss";
|
|
27
|
-
return format(date, pattern);
|
|
28
|
-
}
|
|
29
21
|
/**
|
|
30
22
|
* Merges new grouped slots with existing ones
|
|
31
23
|
* Slots with the same start time are merged
|
|
@@ -68,7 +60,6 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
|
|
|
68
60
|
const viewModeSignal = signalsService.signal(ViewMode.CLASSIC);
|
|
69
61
|
const startDateSignal = signalsService.signal(config.startDate || currentDate);
|
|
70
62
|
const endDateSignal = signalsService.signal(config.endDate || getDefaultEndDate());
|
|
71
|
-
const timezoneSignal = signalsService.signal(config.timezone ?? getClientTimezone());
|
|
72
63
|
const cursorSignal = signalsService.signal(undefined);
|
|
73
64
|
/**
|
|
74
65
|
* Helper: Get services from config or BookingService
|
|
@@ -84,9 +75,9 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
|
|
|
84
75
|
const getFilters = () => {
|
|
85
76
|
// Get BookingService selections (these take priority)
|
|
86
77
|
const location = bookingService.location.get();
|
|
87
|
-
const
|
|
88
|
-
const selectedStaffMemberIds =
|
|
89
|
-
.map((
|
|
78
|
+
const serviceSelections = bookingService.serviceSelections.get();
|
|
79
|
+
const selectedStaffMemberIds = serviceSelections
|
|
80
|
+
.map((serviceSelection) => serviceSelection.resources.map((r) => r._id))
|
|
90
81
|
.flat();
|
|
91
82
|
const selectedLocation = location ? { _id: location.id } : null;
|
|
92
83
|
// Merge config filters with BookingService selections (selections win)
|
|
@@ -114,9 +105,9 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
|
|
|
114
105
|
try {
|
|
115
106
|
const response = await fetchAvailability({
|
|
116
107
|
services: selectedServices,
|
|
117
|
-
fromLocalDate:
|
|
118
|
-
toLocalDate:
|
|
119
|
-
timeZone:
|
|
108
|
+
fromLocalDate: startDateSignal.get(),
|
|
109
|
+
toLocalDate: endDateSignal.get(),
|
|
110
|
+
timeZone: bookingService.timezone.get(),
|
|
120
111
|
viewMode: viewModeSignal.get(),
|
|
121
112
|
cursor: cursorSignal.get(),
|
|
122
113
|
...filters,
|
|
@@ -243,6 +234,18 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
|
|
|
243
234
|
const currentSelections = selectionSignal.get();
|
|
244
235
|
if (!currentSelections?.slot)
|
|
245
236
|
return;
|
|
237
|
+
if (staffMemberId === ANY_STAFF_MEMBER_ID) {
|
|
238
|
+
bookingService.actions.updateItem({
|
|
239
|
+
resources: [
|
|
240
|
+
{
|
|
241
|
+
_id: ANY_STAFF_MEMBER_ID,
|
|
242
|
+
name: 'Any staff member',
|
|
243
|
+
},
|
|
244
|
+
],
|
|
245
|
+
});
|
|
246
|
+
selectionSignal.set({ ...currentSelections, staffMemberId });
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
246
249
|
const slot = currentSelections.slot;
|
|
247
250
|
// Find all locations that have this staff member
|
|
248
251
|
const locationsWithThisStaff = slot.staffByLocation.filter((loc) => loc.staffMembers.some((s) => s.id === staffMemberId));
|
|
@@ -300,16 +303,14 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
|
|
|
300
303
|
if (!cursor || isLoadingSignal.get())
|
|
301
304
|
return;
|
|
302
305
|
const selectedServices = getServices();
|
|
303
|
-
if (selectedServices.length === 0)
|
|
304
|
-
return;
|
|
305
306
|
const filters = getFilters();
|
|
306
307
|
isLoadingSignal.set(true);
|
|
307
308
|
try {
|
|
308
309
|
const response = await fetchAvailability({
|
|
309
310
|
services: selectedServices,
|
|
310
|
-
fromLocalDate:
|
|
311
|
-
toLocalDate:
|
|
312
|
-
timeZone:
|
|
311
|
+
fromLocalDate: startDateSignal.get(),
|
|
312
|
+
toLocalDate: endDateSignal.get(),
|
|
313
|
+
timeZone: bookingService.timezone.get(),
|
|
313
314
|
cursor,
|
|
314
315
|
viewMode: viewModeSignal.get(),
|
|
315
316
|
...filters,
|
|
@@ -345,17 +346,21 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
|
|
|
345
346
|
endDateSignal.set(newEndDate);
|
|
346
347
|
fetchTimeSlots();
|
|
347
348
|
};
|
|
348
|
-
/**
|
|
349
|
-
* Action: Update timezone and refetch slots
|
|
350
|
-
*/
|
|
351
|
-
const setTimezone = (newTimezone) => {
|
|
352
|
-
timezoneSignal.set(newTimezone);
|
|
353
|
-
fetchTimeSlots();
|
|
354
|
-
};
|
|
355
349
|
// Auto-fetch on initialization if no pre-loaded data provided
|
|
356
|
-
if (!config.timeSlots
|
|
350
|
+
if (!config.timeSlots) {
|
|
357
351
|
fetchTimeSlots();
|
|
358
352
|
}
|
|
353
|
+
// Subscribe to timezone changes from BookingService to auto-refetch
|
|
354
|
+
// NOTE: This should depend ONLY on bookingService.timezone.
|
|
355
|
+
let firstTimezoneEffectRun = true;
|
|
356
|
+
signalsService.effect(() => {
|
|
357
|
+
bookingService.timezone.get();
|
|
358
|
+
if (firstTimezoneEffectRun) {
|
|
359
|
+
firstTimezoneEffectRun = false;
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
fetchTimeSlots();
|
|
363
|
+
});
|
|
359
364
|
// Return service API
|
|
360
365
|
return {
|
|
361
366
|
// State Signals
|
|
@@ -367,7 +372,6 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
|
|
|
367
372
|
// Configuration Signals (viewMode is internal only)
|
|
368
373
|
startDate: startDateSignal,
|
|
369
374
|
endDate: endDateSignal,
|
|
370
|
-
timezone: timezoneSignal,
|
|
371
375
|
// Actions
|
|
372
376
|
actions: {
|
|
373
377
|
selectSlot,
|
|
@@ -376,7 +380,6 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
|
|
|
376
380
|
clearPreferences,
|
|
377
381
|
loadMore,
|
|
378
382
|
setDateRange,
|
|
379
|
-
setTimezone,
|
|
380
383
|
},
|
|
381
384
|
};
|
|
382
385
|
});
|
|
@@ -408,8 +411,8 @@ export async function loadTimeSlotListConfig(options) {
|
|
|
408
411
|
try {
|
|
409
412
|
const response = await fetchAvailability({
|
|
410
413
|
services: options.services || [],
|
|
411
|
-
fromLocalDate:
|
|
412
|
-
toLocalDate:
|
|
414
|
+
fromLocalDate: startDate,
|
|
415
|
+
toLocalDate: endDate,
|
|
413
416
|
timeZone: options.timezone ?? getClientTimezone(),
|
|
414
417
|
...options.filters,
|
|
415
418
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/headless-bookings",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.22",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
"groupId": "com.wixpress.headless-components"
|
|
71
71
|
}
|
|
72
72
|
},
|
|
73
|
-
"falconPackageHash": "
|
|
73
|
+
"falconPackageHash": "0404aa644e83255c1641503e68142fb002318cef90f00e879d419ac9"
|
|
74
74
|
}
|