@wix/headless-bookings 1.0.6 → 1.0.8
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/__mocks__/booking/booking-client-service.js +1 -0
- package/cjs/dist/api/create-bulk-booking/index.d.ts +9 -6
- package/cjs/dist/api/create-bulk-booking/index.js +2 -0
- package/cjs/dist/api/create-multi-service-booking/index.d.ts +7 -6
- package/cjs/dist/api/create-multi-service-booking/index.js +2 -0
- package/cjs/dist/services/booking/book-action/bookAction.js +5 -1
- package/cjs/dist/services/booking/book-action/buildBookingRequest.js +0 -2
- package/cjs/dist/services/booking/book-action/buildDayRangeBookingRequest.d.ts +6 -1
- package/cjs/dist/services/booking/book-action/buildDayRangeBookingRequest.js +13 -8
- package/cjs/dist/services/booking/book-action/createBookingsForCart.d.ts +3 -2
- package/cjs/dist/services/booking/book-action/createBookingsForCart.js +19 -6
- package/cjs/dist/services/booking/book-action/types.d.ts +8 -0
- package/cjs/dist/services/booking/booking.d.ts +7 -0
- package/cjs/dist/services/booking/booking.js +11 -0
- package/cjs/dist/services/time-slot-list/time-slot-list.d.ts +1 -1
- package/cjs/dist/services/time-slot-list/time-slot-list.js +3 -3
- package/dist/__mocks__/booking/booking-client-service.js +1 -0
- package/dist/api/create-bulk-booking/index.d.ts +9 -6
- package/dist/api/create-bulk-booking/index.js +2 -0
- package/dist/api/create-multi-service-booking/index.d.ts +7 -6
- package/dist/api/create-multi-service-booking/index.js +2 -0
- package/dist/services/booking/book-action/bookAction.js +5 -1
- package/dist/services/booking/book-action/buildBookingRequest.js +0 -2
- package/dist/services/booking/book-action/buildDayRangeBookingRequest.d.ts +6 -1
- package/dist/services/booking/book-action/buildDayRangeBookingRequest.js +13 -8
- package/dist/services/booking/book-action/createBookingsForCart.d.ts +3 -2
- package/dist/services/booking/book-action/createBookingsForCart.js +19 -6
- package/dist/services/booking/book-action/types.d.ts +8 -0
- package/dist/services/booking/booking.d.ts +7 -0
- package/dist/services/booking/booking.js +11 -0
- package/dist/services/time-slot-list/time-slot-list.d.ts +1 -1
- package/dist/services/time-slot-list/time-slot-list.js +1 -1
- package/package.json +5 -4
|
@@ -56,6 +56,7 @@ function createMockBookingService(config = {}) {
|
|
|
56
56
|
setFormSubmission: vitest_1.vi.fn(),
|
|
57
57
|
clearFormSubmission: vitest_1.vi.fn(),
|
|
58
58
|
setSelectedPaymentOption: vitest_1.vi.fn(),
|
|
59
|
+
setAllDay: vitest_1.vi.fn(),
|
|
59
60
|
clearAll: vitest_1.vi.fn(),
|
|
60
61
|
book: vitest_1.vi.fn(),
|
|
61
62
|
},
|
|
@@ -8,20 +8,22 @@
|
|
|
8
8
|
* createMultiServiceBooking.
|
|
9
9
|
*/
|
|
10
10
|
import { type CreateBookingInfo, type BulkCreateBookingResponse, type ParticipantNotification } from '@wix/auto_sdk_bookings_bookings';
|
|
11
|
+
import type { FormValues } from '@wix/forms/components';
|
|
11
12
|
/**
|
|
12
13
|
* Options for creating bookings in bulk.
|
|
13
14
|
*
|
|
14
|
-
* `formSubmission`
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* cart wiring.
|
|
15
|
+
* The SDK accepts `formSubmission` on each `CreateBookingInfo` entry, while
|
|
16
|
+
* this wrapper accepts one shared payload and applies it to every entry.
|
|
17
|
+
* We always set `returnFullEntity: true` so the response includes per-booking
|
|
18
|
+
* entities (with `contactDetails`) for cart wiring.
|
|
19
19
|
*/
|
|
20
20
|
export interface BulkCreateBookingOptions {
|
|
21
21
|
/** Notification settings for participants. Applied to every entry. */
|
|
22
22
|
participantNotification?: ParticipantNotification;
|
|
23
23
|
/** Whether to send SMS reminder. Applied to every entry. */
|
|
24
|
-
sendSmsReminder?: boolean;
|
|
24
|
+
sendSmsReminder?: boolean | null;
|
|
25
|
+
/** Form submission data. Applied to every entry. */
|
|
26
|
+
formSubmission?: FormValues | null;
|
|
25
27
|
}
|
|
26
28
|
/**
|
|
27
29
|
* Creates 1-8 bookings in a single bulk call.
|
|
@@ -44,6 +46,7 @@ export interface BulkCreateBookingOptions {
|
|
|
44
46
|
* {
|
|
45
47
|
* participantNotification: { notifyParticipants: true },
|
|
46
48
|
* sendSmsReminder: true,
|
|
49
|
+
* formSubmission: formValues,
|
|
47
50
|
* }
|
|
48
51
|
* );
|
|
49
52
|
* const ids = response.results
|
|
@@ -32,6 +32,7 @@ const auto_sdk_bookings_bookings_1 = require("@wix/auto_sdk_bookings_bookings");
|
|
|
32
32
|
* {
|
|
33
33
|
* participantNotification: { notifyParticipants: true },
|
|
34
34
|
* sendSmsReminder: true,
|
|
35
|
+
* formSubmission: formValues,
|
|
35
36
|
* }
|
|
36
37
|
* );
|
|
37
38
|
* const ids = response.results
|
|
@@ -47,6 +48,7 @@ function bulkCreateBooking(createBookingsInfo, options) {
|
|
|
47
48
|
...info,
|
|
48
49
|
participantNotification: info.participantNotification ?? options?.participantNotification,
|
|
49
50
|
sendSmsReminder: info.sendSmsReminder ?? options?.sendSmsReminder,
|
|
51
|
+
formSubmission: info.formSubmission ?? options?.formSubmission,
|
|
50
52
|
}));
|
|
51
53
|
return (0, auto_sdk_bookings_bookings_1.bulkCreateBooking)(enriched, {
|
|
52
54
|
returnFullEntity: true,
|
|
@@ -8,20 +8,20 @@
|
|
|
8
8
|
* picked slot.
|
|
9
9
|
*/
|
|
10
10
|
import { type Booking, type CreateMultiServiceBookingResponse, type ParticipantNotification } from '@wix/auto_sdk_bookings_bookings';
|
|
11
|
+
import type { FormValues } from '@wix/forms/components';
|
|
11
12
|
/**
|
|
12
13
|
* Options for creating a multi-service booking.
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
-
* `
|
|
16
|
-
* flow through the cart layer instead. We always set `returnFullEntity: true`
|
|
17
|
-
* so the response includes per-booking entities (with `contactDetails`) for
|
|
18
|
-
* cart wiring.
|
|
15
|
+
* We always set `returnFullEntity: true` so the response includes per-booking
|
|
16
|
+
* entities (with `contactDetails`) for cart wiring.
|
|
19
17
|
*/
|
|
20
18
|
export interface CreateMultiServiceBookingOptions {
|
|
21
19
|
/** Notification settings for participants */
|
|
22
20
|
participantNotification?: ParticipantNotification;
|
|
23
21
|
/** Whether to send SMS reminder */
|
|
24
|
-
sendSmsReminder?: boolean;
|
|
22
|
+
sendSmsReminder?: boolean | null;
|
|
23
|
+
/** Form submission data */
|
|
24
|
+
formSubmission?: FormValues | null;
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
27
|
* Creates a multi-service booking from 2-8 single-service booking specs.
|
|
@@ -43,6 +43,7 @@ export interface CreateMultiServiceBookingOptions {
|
|
|
43
43
|
* {
|
|
44
44
|
* participantNotification: { notifyParticipants: true },
|
|
45
45
|
* sendSmsReminder: true,
|
|
46
|
+
* formSubmission: formValues,
|
|
46
47
|
* }
|
|
47
48
|
* );
|
|
48
49
|
* const ids = response.multiServiceBooking?.bookings
|
|
@@ -31,6 +31,7 @@ const auto_sdk_bookings_bookings_1 = require("@wix/auto_sdk_bookings_bookings");
|
|
|
31
31
|
* {
|
|
32
32
|
* participantNotification: { notifyParticipants: true },
|
|
33
33
|
* sendSmsReminder: true,
|
|
34
|
+
* formSubmission: formValues,
|
|
34
35
|
* }
|
|
35
36
|
* );
|
|
36
37
|
* const ids = response.multiServiceBooking?.bookings
|
|
@@ -42,6 +43,7 @@ function createMultiServiceBooking(bookings, options) {
|
|
|
42
43
|
return (0, auto_sdk_bookings_bookings_1.createMultiServiceBooking)(bookings, {
|
|
43
44
|
participantNotification: options?.participantNotification,
|
|
44
45
|
sendSmsReminder: options?.sendSmsReminder,
|
|
46
|
+
formSubmission: options?.formSubmission,
|
|
45
47
|
returnFullEntity: true,
|
|
46
48
|
});
|
|
47
49
|
}
|
|
@@ -38,7 +38,11 @@ async function executeBookAction(params) {
|
|
|
38
38
|
// it from the service's first configured location.
|
|
39
39
|
firstSelection.service.locations?.[0]?._id
|
|
40
40
|
: firstSelection.timeSlot?.location?._id;
|
|
41
|
-
|
|
41
|
+
// `allDay` DAY-range bookings collapse to a single booking ID, so they use
|
|
42
|
+
// the single-booking cart shape (like the default path). Only the per-slot
|
|
43
|
+
// DAY-range expansion produces N>1 ids needing the multi-item cart.
|
|
44
|
+
const isMultiBookingCart = isDayRange && !params.allDay;
|
|
45
|
+
const cartRequest = isMultiBookingCart
|
|
42
46
|
? (0, buildCartRequest_js_1.buildDayRangeCartRequest)({
|
|
43
47
|
bookingIds,
|
|
44
48
|
contactDetails,
|
|
@@ -110,8 +110,6 @@ function mapTimeSlotLocationTypeToBookingLocationType(slotLocationType) {
|
|
|
110
110
|
return auto_sdk_bookings_bookings_1.LocationType.CUSTOM;
|
|
111
111
|
case auto_sdk_bookings_availability_time_slots_1.LocationType.CUSTOM:
|
|
112
112
|
return auto_sdk_bookings_bookings_1.LocationType.OWNER_CUSTOM;
|
|
113
|
-
case auto_sdk_bookings_availability_time_slots_1.LocationType.UNKNOWN_LOCATION_TYPE:
|
|
114
|
-
return auto_sdk_bookings_bookings_1.LocationType.UNDEFINED;
|
|
115
113
|
default:
|
|
116
114
|
return auto_sdk_bookings_bookings_1.LocationType.OWNER_BUSINESS;
|
|
117
115
|
}
|
|
@@ -12,10 +12,13 @@
|
|
|
12
12
|
* The 8-day cap is enforced server-side; the builder does not gate on it.
|
|
13
13
|
*/
|
|
14
14
|
import type { Booking, ParticipantNotification } from '@wix/auto_sdk_bookings_bookings';
|
|
15
|
+
import type { FormValues } from '@wix/forms/components';
|
|
15
16
|
import type { BookActionParams } from './types.js';
|
|
16
17
|
export interface BuildDayRangeBookingRequest {
|
|
17
18
|
/**
|
|
18
|
-
*
|
|
19
|
+
* The Bookings to create. With `allDay`, this is a single Booking spanning
|
|
20
|
+
* the whole range, routed to plain `createBooking`. Otherwise it is one
|
|
21
|
+
* Booking per picked per-day slot: length 1 routes to bulkCreateBooking,
|
|
19
22
|
* length >=2 routes to createMultiServiceBooking.
|
|
20
23
|
*/
|
|
21
24
|
bookings: Booking[];
|
|
@@ -23,6 +26,8 @@ export interface BuildDayRangeBookingRequest {
|
|
|
23
26
|
participantNotification?: ParticipantNotification;
|
|
24
27
|
/** Whether to send SMS reminder. */
|
|
25
28
|
sendSmsReminder: boolean;
|
|
29
|
+
/** Form submission data forwarded to booking creation. */
|
|
30
|
+
formSubmission?: FormValues | null;
|
|
26
31
|
}
|
|
27
32
|
/**
|
|
28
33
|
* Builds N Bookings from a DAY-range selection.
|
|
@@ -47,24 +47,29 @@ function buildDayRangeBookingRequest(params) {
|
|
|
47
47
|
...params,
|
|
48
48
|
serviceSelections: [baseSelection, ...params.serviceSelections.slice(1)],
|
|
49
49
|
});
|
|
50
|
-
|
|
50
|
+
// Clone the base Booking, overriding only the slot start/end.
|
|
51
|
+
const buildBooking = (startDate, endDate) => ({
|
|
51
52
|
...baseRequest.booking,
|
|
52
53
|
bookedEntity: {
|
|
53
54
|
...baseRequest.booking.bookedEntity,
|
|
54
55
|
slot: {
|
|
55
56
|
...baseRequest.booking.bookedEntity?.slot,
|
|
56
|
-
startDate
|
|
57
|
-
endDate
|
|
57
|
+
startDate,
|
|
58
|
+
endDate,
|
|
58
59
|
},
|
|
59
60
|
},
|
|
60
|
-
})
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
61
|
+
});
|
|
62
|
+
// `allDay`: collapse every picked slot into one Booking spanning the whole
|
|
63
|
+
// range (`slots[0].startDate -> slots[N-1].endDate`). `createBookingsForCart`
|
|
64
|
+
// then routes this single Booking through plain `createBooking` instead of
|
|
65
|
+
// bulk / multi-service. Otherwise, emit one Booking per picked slot.
|
|
66
|
+
const bookings = params.allDay
|
|
67
|
+
? [buildBooking(slots[0].startDate, slots[slots.length - 1].endDate)]
|
|
68
|
+
: slots.map((slot) => buildBooking(slot.startDate, slot.endDate));
|
|
65
69
|
return {
|
|
66
70
|
bookings,
|
|
67
71
|
participantNotification: baseRequest.participantNotification,
|
|
68
72
|
sendSmsReminder: baseRequest.sendSmsReminder ?? true,
|
|
73
|
+
formSubmission: baseRequest.formSubmission,
|
|
69
74
|
};
|
|
70
75
|
}
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* Creates the booking(s) needed for cart construction.
|
|
3
3
|
*
|
|
4
4
|
* Branches on the service selection:
|
|
5
|
-
* - DAY-range path with
|
|
5
|
+
* - DAY-range path with `allDay` -> `createBooking` (one combined Booking)
|
|
6
|
+
* - DAY-range path with 1 picked slot -> `bulkCreateBooking`
|
|
6
7
|
* - DAY-range path with 2..8 picked slots -> `createMultiServiceBooking`
|
|
7
|
-
* - default path
|
|
8
|
+
* - default path -> `createBooking`
|
|
8
9
|
*
|
|
9
10
|
* All branches return the same shape so `executeBookAction` can stay
|
|
10
11
|
* branchless from cart-creation onwards. Cart construction reads each
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
* Creates the booking(s) needed for cart construction.
|
|
4
4
|
*
|
|
5
5
|
* Branches on the service selection:
|
|
6
|
-
* - DAY-range path with
|
|
6
|
+
* - DAY-range path with `allDay` -> `createBooking` (one combined Booking)
|
|
7
|
+
* - DAY-range path with 1 picked slot -> `bulkCreateBooking`
|
|
7
8
|
* - DAY-range path with 2..8 picked slots -> `createMultiServiceBooking`
|
|
8
|
-
* - default path
|
|
9
|
+
* - default path -> `createBooking`
|
|
9
10
|
*
|
|
10
11
|
* All branches return the same shape so `executeBookAction` can stay
|
|
11
12
|
* branchless from cart-creation onwards. Cart construction reads each
|
|
@@ -27,14 +28,25 @@ async function createBookingsForCart(params) {
|
|
|
27
28
|
}
|
|
28
29
|
if ((0, dayRange_js_1.isDayRangeService)(firstSelection.service)) {
|
|
29
30
|
const req = (0, buildDayRangeBookingRequest_js_1.buildDayRangeBookingRequest)(params);
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
// `allDay`: the builder has already collapsed the range into a single
|
|
32
|
+
// Booking. Create it with plain `createBooking` (not bulk / multi-service).
|
|
33
|
+
if (params.allDay) {
|
|
34
|
+
const bookingResponse = await (0, index_js_1.createBooking)(req.bookings[0], {
|
|
35
|
+
participantNotification: req.participantNotification,
|
|
36
|
+
sendSmsReminder: req.sendSmsReminder,
|
|
37
|
+
formSubmission: req.formSubmission,
|
|
38
|
+
});
|
|
39
|
+
const bookingId = bookingResponse.booking?._id;
|
|
40
|
+
return {
|
|
41
|
+
bookingIds: bookingId ? [bookingId] : [],
|
|
42
|
+
contactDetails: bookingResponse.booking?.contactDetails,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
34
45
|
if (req.bookings.length === 1) {
|
|
35
46
|
const response = await (0, index_js_2.bulkCreateBooking)([{ booking: req.bookings[0] }], {
|
|
36
47
|
participantNotification: req.participantNotification,
|
|
37
48
|
sendSmsReminder: req.sendSmsReminder,
|
|
49
|
+
formSubmission: req.formSubmission,
|
|
38
50
|
});
|
|
39
51
|
const results = response.results ?? [];
|
|
40
52
|
return {
|
|
@@ -46,6 +58,7 @@ async function createBookingsForCart(params) {
|
|
|
46
58
|
const response = await (0, index_js_3.createMultiServiceBooking)(req.bookings, {
|
|
47
59
|
participantNotification: req.participantNotification,
|
|
48
60
|
sendSmsReminder: req.sendSmsReminder,
|
|
61
|
+
formSubmission: req.formSubmission,
|
|
49
62
|
});
|
|
50
63
|
const bookings = response.multiServiceBooking?.bookings ?? [];
|
|
51
64
|
return {
|
|
@@ -53,6 +53,14 @@ export interface BookActionParams {
|
|
|
53
53
|
* service. When omitted, the existing service-config heuristic applies.
|
|
54
54
|
*/
|
|
55
55
|
selectedPaymentOption?: SelectedPaymentOption;
|
|
56
|
+
/**
|
|
57
|
+
* DAY-range only. When `true`, the picked per-day slots are collapsed into a
|
|
58
|
+
* single Booking spanning the whole range (`firstSlot.startDate ->
|
|
59
|
+
* lastSlot.endDate`) and created via plain `createBooking` — instead of the
|
|
60
|
+
* default per-slot expansion that routes to `bulkCreateBooking` (1 slot) or
|
|
61
|
+
* `createMultiServiceBooking` (2-8 slots). Ignored for non-DAY-range services.
|
|
62
|
+
*/
|
|
63
|
+
allDay?: boolean;
|
|
56
64
|
}
|
|
57
65
|
/**
|
|
58
66
|
* Props passed to children of Book component
|
|
@@ -88,6 +88,13 @@ export interface BookingServiceActions {
|
|
|
88
88
|
* is cleared and the heuristic applies again.
|
|
89
89
|
*/
|
|
90
90
|
setSelectedPaymentOption(value: SelectedPaymentOption | null): void;
|
|
91
|
+
/**
|
|
92
|
+
* Toggle the DAY-range `allDay` flag. When `true`, `book()` collapses the
|
|
93
|
+
* picked per-day slots of a DAY-range service into a single Booking created
|
|
94
|
+
* via `createBooking` (instead of the per-slot bulk / multi-service path).
|
|
95
|
+
* Ignored for non-DAY-range services.
|
|
96
|
+
*/
|
|
97
|
+
setAllDay(value: boolean): void;
|
|
91
98
|
clearAll(): void;
|
|
92
99
|
book(): Promise<BookResult>;
|
|
93
100
|
}
|
|
@@ -74,6 +74,10 @@ exports.BookingService = services_definitions_1.implementService.withConfig()(ex
|
|
|
74
74
|
const timezoneSignal = signalsService.signal(config.timezone ?? getClientTimezone());
|
|
75
75
|
const formSubmissionSignal = signalsService.signal(config.formSubmission || null);
|
|
76
76
|
const selectedPaymentOptionSignal = signalsService.signal(config.selectedPaymentOption);
|
|
77
|
+
// Internal-only signal: set via `setAllDay`, read by `book()`. Not
|
|
78
|
+
// exposed on the service surface — consumers derive and push the value
|
|
79
|
+
// (e.g. from the picker's selection mode), so there's no read-back.
|
|
80
|
+
const allDaySignal = signalsService.signal(false);
|
|
77
81
|
// ========================================================================
|
|
78
82
|
// Helpers
|
|
79
83
|
// ========================================================================
|
|
@@ -172,11 +176,16 @@ exports.BookingService = services_definitions_1.implementService.withConfig()(ex
|
|
|
172
176
|
setSelectedPaymentOption(value) {
|
|
173
177
|
selectedPaymentOptionSignal.set(value ?? undefined);
|
|
174
178
|
},
|
|
179
|
+
// All-day (DAY-range) action
|
|
180
|
+
setAllDay(value) {
|
|
181
|
+
allDaySignal.set(value);
|
|
182
|
+
},
|
|
175
183
|
// Clear all
|
|
176
184
|
clearAll() {
|
|
177
185
|
this.clearItems();
|
|
178
186
|
this.clearLocation();
|
|
179
187
|
this.clearFormSubmission();
|
|
188
|
+
this.setAllDay(false);
|
|
180
189
|
},
|
|
181
190
|
// Book action - collects data from signals and delegates to executeBookAction
|
|
182
191
|
// Loading/error state management is handled in Book.tsx component
|
|
@@ -186,6 +195,7 @@ exports.BookingService = services_definitions_1.implementService.withConfig()(ex
|
|
|
186
195
|
const location = locationSignal.get();
|
|
187
196
|
const timezone = timezoneSignal.get();
|
|
188
197
|
const selectedPaymentOption = selectedPaymentOptionSignal.get();
|
|
198
|
+
const allDay = allDaySignal.get();
|
|
189
199
|
// Validation happens inside executeBookAction
|
|
190
200
|
return (0, bookAction_js_1.executeBookAction)({
|
|
191
201
|
serviceSelections,
|
|
@@ -194,6 +204,7 @@ exports.BookingService = services_definitions_1.implementService.withConfig()(ex
|
|
|
194
204
|
timezone,
|
|
195
205
|
appId: config.appId,
|
|
196
206
|
selectedPaymentOption,
|
|
207
|
+
allDay,
|
|
197
208
|
});
|
|
198
209
|
},
|
|
199
210
|
};
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { Service } from '@wix/auto_sdk_bookings_services';
|
|
6
6
|
import { type TimeSlotListServiceConfig, type TimeSlotsFilters } from './time-slot-list.def.js';
|
|
7
|
-
import { TimeSlot } from '@wix/
|
|
7
|
+
import { TimeSlot } from '@wix/auto_sdk_bookings_availability-time-slots';
|
|
8
8
|
/**
|
|
9
9
|
* Helper to get staff member name from time slots by ID
|
|
10
10
|
* @internal - exported for testing
|
|
@@ -9,7 +9,7 @@ exports.loadTimeSlotListConfig = loadTimeSlotListConfig;
|
|
|
9
9
|
const services_definitions_1 = require("@wix/services-definitions");
|
|
10
10
|
const signals_1 = require("@wix/services-definitions/core-services/signals");
|
|
11
11
|
const time_slot_list_def_js_1 = require("./time-slot-list.def.js");
|
|
12
|
-
const
|
|
12
|
+
const auto_sdk_bookings_availability_time_slots_1 = require("@wix/auto_sdk_bookings_availability-time-slots");
|
|
13
13
|
const index_js_1 = require("../../api/fetch-availability/index.js");
|
|
14
14
|
const booking_js_1 = require("../booking/booking.js");
|
|
15
15
|
// ============================================================================
|
|
@@ -61,8 +61,8 @@ exports.TimeSlotListService = services_definitions_1.implementService.withConfig
|
|
|
61
61
|
const getFilters = () => {
|
|
62
62
|
const baseFilters = config.filters ?? {};
|
|
63
63
|
const selectedLocation = bookingService.location.peek();
|
|
64
|
-
const isCustomOrCustomerLocation = selectedLocation?.type ===
|
|
65
|
-
selectedLocation?.type ===
|
|
64
|
+
const isCustomOrCustomerLocation = selectedLocation?.type === auto_sdk_bookings_availability_time_slots_1.LocationType.CUSTOM ||
|
|
65
|
+
selectedLocation?.type === auto_sdk_bookings_availability_time_slots_1.LocationType.CUSTOMER;
|
|
66
66
|
const location = selectedLocation
|
|
67
67
|
? {
|
|
68
68
|
id: isCustomOrCustomerLocation ? undefined : selectedLocation._id,
|
|
@@ -8,20 +8,22 @@
|
|
|
8
8
|
* createMultiServiceBooking.
|
|
9
9
|
*/
|
|
10
10
|
import { type CreateBookingInfo, type BulkCreateBookingResponse, type ParticipantNotification } from '@wix/auto_sdk_bookings_bookings';
|
|
11
|
+
import type { FormValues } from '@wix/forms/components';
|
|
11
12
|
/**
|
|
12
13
|
* Options for creating bookings in bulk.
|
|
13
14
|
*
|
|
14
|
-
* `formSubmission`
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* cart wiring.
|
|
15
|
+
* The SDK accepts `formSubmission` on each `CreateBookingInfo` entry, while
|
|
16
|
+
* this wrapper accepts one shared payload and applies it to every entry.
|
|
17
|
+
* We always set `returnFullEntity: true` so the response includes per-booking
|
|
18
|
+
* entities (with `contactDetails`) for cart wiring.
|
|
19
19
|
*/
|
|
20
20
|
export interface BulkCreateBookingOptions {
|
|
21
21
|
/** Notification settings for participants. Applied to every entry. */
|
|
22
22
|
participantNotification?: ParticipantNotification;
|
|
23
23
|
/** Whether to send SMS reminder. Applied to every entry. */
|
|
24
|
-
sendSmsReminder?: boolean;
|
|
24
|
+
sendSmsReminder?: boolean | null;
|
|
25
|
+
/** Form submission data. Applied to every entry. */
|
|
26
|
+
formSubmission?: FormValues | null;
|
|
25
27
|
}
|
|
26
28
|
/**
|
|
27
29
|
* Creates 1-8 bookings in a single bulk call.
|
|
@@ -44,6 +46,7 @@ export interface BulkCreateBookingOptions {
|
|
|
44
46
|
* {
|
|
45
47
|
* participantNotification: { notifyParticipants: true },
|
|
46
48
|
* sendSmsReminder: true,
|
|
49
|
+
* formSubmission: formValues,
|
|
47
50
|
* }
|
|
48
51
|
* );
|
|
49
52
|
* const ids = response.results
|
|
@@ -29,6 +29,7 @@ import { bulkCreateBooking as bulkCreateBookingSdk, } from '@wix/auto_sdk_bookin
|
|
|
29
29
|
* {
|
|
30
30
|
* participantNotification: { notifyParticipants: true },
|
|
31
31
|
* sendSmsReminder: true,
|
|
32
|
+
* formSubmission: formValues,
|
|
32
33
|
* }
|
|
33
34
|
* );
|
|
34
35
|
* const ids = response.results
|
|
@@ -44,6 +45,7 @@ export function bulkCreateBooking(createBookingsInfo, options) {
|
|
|
44
45
|
...info,
|
|
45
46
|
participantNotification: info.participantNotification ?? options?.participantNotification,
|
|
46
47
|
sendSmsReminder: info.sendSmsReminder ?? options?.sendSmsReminder,
|
|
48
|
+
formSubmission: info.formSubmission ?? options?.formSubmission,
|
|
47
49
|
}));
|
|
48
50
|
return bulkCreateBookingSdk(enriched, {
|
|
49
51
|
returnFullEntity: true,
|
|
@@ -8,20 +8,20 @@
|
|
|
8
8
|
* picked slot.
|
|
9
9
|
*/
|
|
10
10
|
import { type Booking, type CreateMultiServiceBookingResponse, type ParticipantNotification } from '@wix/auto_sdk_bookings_bookings';
|
|
11
|
+
import type { FormValues } from '@wix/forms/components';
|
|
11
12
|
/**
|
|
12
13
|
* Options for creating a multi-service booking.
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
-
* `
|
|
16
|
-
* flow through the cart layer instead. We always set `returnFullEntity: true`
|
|
17
|
-
* so the response includes per-booking entities (with `contactDetails`) for
|
|
18
|
-
* cart wiring.
|
|
15
|
+
* We always set `returnFullEntity: true` so the response includes per-booking
|
|
16
|
+
* entities (with `contactDetails`) for cart wiring.
|
|
19
17
|
*/
|
|
20
18
|
export interface CreateMultiServiceBookingOptions {
|
|
21
19
|
/** Notification settings for participants */
|
|
22
20
|
participantNotification?: ParticipantNotification;
|
|
23
21
|
/** Whether to send SMS reminder */
|
|
24
|
-
sendSmsReminder?: boolean;
|
|
22
|
+
sendSmsReminder?: boolean | null;
|
|
23
|
+
/** Form submission data */
|
|
24
|
+
formSubmission?: FormValues | null;
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
27
|
* Creates a multi-service booking from 2-8 single-service booking specs.
|
|
@@ -43,6 +43,7 @@ export interface CreateMultiServiceBookingOptions {
|
|
|
43
43
|
* {
|
|
44
44
|
* participantNotification: { notifyParticipants: true },
|
|
45
45
|
* sendSmsReminder: true,
|
|
46
|
+
* formSubmission: formValues,
|
|
46
47
|
* }
|
|
47
48
|
* );
|
|
48
49
|
* const ids = response.multiServiceBooking?.bookings
|
|
@@ -28,6 +28,7 @@ import { createMultiServiceBooking as createMultiServiceBookingSdk, } from '@wix
|
|
|
28
28
|
* {
|
|
29
29
|
* participantNotification: { notifyParticipants: true },
|
|
30
30
|
* sendSmsReminder: true,
|
|
31
|
+
* formSubmission: formValues,
|
|
31
32
|
* }
|
|
32
33
|
* );
|
|
33
34
|
* const ids = response.multiServiceBooking?.bookings
|
|
@@ -39,6 +40,7 @@ export function createMultiServiceBooking(bookings, options) {
|
|
|
39
40
|
return createMultiServiceBookingSdk(bookings, {
|
|
40
41
|
participantNotification: options?.participantNotification,
|
|
41
42
|
sendSmsReminder: options?.sendSmsReminder,
|
|
43
|
+
formSubmission: options?.formSubmission,
|
|
42
44
|
returnFullEntity: true,
|
|
43
45
|
});
|
|
44
46
|
}
|
|
@@ -35,7 +35,11 @@ export async function executeBookAction(params) {
|
|
|
35
35
|
// it from the service's first configured location.
|
|
36
36
|
firstSelection.service.locations?.[0]?._id
|
|
37
37
|
: firstSelection.timeSlot?.location?._id;
|
|
38
|
-
|
|
38
|
+
// `allDay` DAY-range bookings collapse to a single booking ID, so they use
|
|
39
|
+
// the single-booking cart shape (like the default path). Only the per-slot
|
|
40
|
+
// DAY-range expansion produces N>1 ids needing the multi-item cart.
|
|
41
|
+
const isMultiBookingCart = isDayRange && !params.allDay;
|
|
42
|
+
const cartRequest = isMultiBookingCart
|
|
39
43
|
? buildDayRangeCartRequest({
|
|
40
44
|
bookingIds,
|
|
41
45
|
contactDetails,
|
|
@@ -107,8 +107,6 @@ function mapTimeSlotLocationTypeToBookingLocationType(slotLocationType) {
|
|
|
107
107
|
return BookingLocationType.CUSTOM;
|
|
108
108
|
case TimeSlotLocationType.CUSTOM:
|
|
109
109
|
return BookingLocationType.OWNER_CUSTOM;
|
|
110
|
-
case TimeSlotLocationType.UNKNOWN_LOCATION_TYPE:
|
|
111
|
-
return BookingLocationType.UNDEFINED;
|
|
112
110
|
default:
|
|
113
111
|
return BookingLocationType.OWNER_BUSINESS;
|
|
114
112
|
}
|
|
@@ -12,10 +12,13 @@
|
|
|
12
12
|
* The 8-day cap is enforced server-side; the builder does not gate on it.
|
|
13
13
|
*/
|
|
14
14
|
import type { Booking, ParticipantNotification } from '@wix/auto_sdk_bookings_bookings';
|
|
15
|
+
import type { FormValues } from '@wix/forms/components';
|
|
15
16
|
import type { BookActionParams } from './types.js';
|
|
16
17
|
export interface BuildDayRangeBookingRequest {
|
|
17
18
|
/**
|
|
18
|
-
*
|
|
19
|
+
* The Bookings to create. With `allDay`, this is a single Booking spanning
|
|
20
|
+
* the whole range, routed to plain `createBooking`. Otherwise it is one
|
|
21
|
+
* Booking per picked per-day slot: length 1 routes to bulkCreateBooking,
|
|
19
22
|
* length >=2 routes to createMultiServiceBooking.
|
|
20
23
|
*/
|
|
21
24
|
bookings: Booking[];
|
|
@@ -23,6 +26,8 @@ export interface BuildDayRangeBookingRequest {
|
|
|
23
26
|
participantNotification?: ParticipantNotification;
|
|
24
27
|
/** Whether to send SMS reminder. */
|
|
25
28
|
sendSmsReminder: boolean;
|
|
29
|
+
/** Form submission data forwarded to booking creation. */
|
|
30
|
+
formSubmission?: FormValues | null;
|
|
26
31
|
}
|
|
27
32
|
/**
|
|
28
33
|
* Builds N Bookings from a DAY-range selection.
|
|
@@ -44,24 +44,29 @@ export function buildDayRangeBookingRequest(params) {
|
|
|
44
44
|
...params,
|
|
45
45
|
serviceSelections: [baseSelection, ...params.serviceSelections.slice(1)],
|
|
46
46
|
});
|
|
47
|
-
|
|
47
|
+
// Clone the base Booking, overriding only the slot start/end.
|
|
48
|
+
const buildBooking = (startDate, endDate) => ({
|
|
48
49
|
...baseRequest.booking,
|
|
49
50
|
bookedEntity: {
|
|
50
51
|
...baseRequest.booking.bookedEntity,
|
|
51
52
|
slot: {
|
|
52
53
|
...baseRequest.booking.bookedEntity?.slot,
|
|
53
|
-
startDate
|
|
54
|
-
endDate
|
|
54
|
+
startDate,
|
|
55
|
+
endDate,
|
|
55
56
|
},
|
|
56
57
|
},
|
|
57
|
-
})
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
//
|
|
58
|
+
});
|
|
59
|
+
// `allDay`: collapse every picked slot into one Booking spanning the whole
|
|
60
|
+
// range (`slots[0].startDate -> slots[N-1].endDate`). `createBookingsForCart`
|
|
61
|
+
// then routes this single Booking through plain `createBooking` instead of
|
|
62
|
+
// bulk / multi-service. Otherwise, emit one Booking per picked slot.
|
|
63
|
+
const bookings = params.allDay
|
|
64
|
+
? [buildBooking(slots[0].startDate, slots[slots.length - 1].endDate)]
|
|
65
|
+
: slots.map((slot) => buildBooking(slot.startDate, slot.endDate));
|
|
62
66
|
return {
|
|
63
67
|
bookings,
|
|
64
68
|
participantNotification: baseRequest.participantNotification,
|
|
65
69
|
sendSmsReminder: baseRequest.sendSmsReminder ?? true,
|
|
70
|
+
formSubmission: baseRequest.formSubmission,
|
|
66
71
|
};
|
|
67
72
|
}
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* Creates the booking(s) needed for cart construction.
|
|
3
3
|
*
|
|
4
4
|
* Branches on the service selection:
|
|
5
|
-
* - DAY-range path with
|
|
5
|
+
* - DAY-range path with `allDay` -> `createBooking` (one combined Booking)
|
|
6
|
+
* - DAY-range path with 1 picked slot -> `bulkCreateBooking`
|
|
6
7
|
* - DAY-range path with 2..8 picked slots -> `createMultiServiceBooking`
|
|
7
|
-
* - default path
|
|
8
|
+
* - default path -> `createBooking`
|
|
8
9
|
*
|
|
9
10
|
* All branches return the same shape so `executeBookAction` can stay
|
|
10
11
|
* branchless from cart-creation onwards. Cart construction reads each
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* Creates the booking(s) needed for cart construction.
|
|
3
3
|
*
|
|
4
4
|
* Branches on the service selection:
|
|
5
|
-
* - DAY-range path with
|
|
5
|
+
* - DAY-range path with `allDay` -> `createBooking` (one combined Booking)
|
|
6
|
+
* - DAY-range path with 1 picked slot -> `bulkCreateBooking`
|
|
6
7
|
* - DAY-range path with 2..8 picked slots -> `createMultiServiceBooking`
|
|
7
|
-
* - default path
|
|
8
|
+
* - default path -> `createBooking`
|
|
8
9
|
*
|
|
9
10
|
* All branches return the same shape so `executeBookAction` can stay
|
|
10
11
|
* branchless from cart-creation onwards. Cart construction reads each
|
|
@@ -24,14 +25,25 @@ export async function createBookingsForCart(params) {
|
|
|
24
25
|
}
|
|
25
26
|
if (isDayRangeService(firstSelection.service)) {
|
|
26
27
|
const req = buildDayRangeBookingRequest(params);
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
// `allDay`: the builder has already collapsed the range into a single
|
|
29
|
+
// Booking. Create it with plain `createBooking` (not bulk / multi-service).
|
|
30
|
+
if (params.allDay) {
|
|
31
|
+
const bookingResponse = await createBooking(req.bookings[0], {
|
|
32
|
+
participantNotification: req.participantNotification,
|
|
33
|
+
sendSmsReminder: req.sendSmsReminder,
|
|
34
|
+
formSubmission: req.formSubmission,
|
|
35
|
+
});
|
|
36
|
+
const bookingId = bookingResponse.booking?._id;
|
|
37
|
+
return {
|
|
38
|
+
bookingIds: bookingId ? [bookingId] : [],
|
|
39
|
+
contactDetails: bookingResponse.booking?.contactDetails,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
31
42
|
if (req.bookings.length === 1) {
|
|
32
43
|
const response = await bulkCreateBooking([{ booking: req.bookings[0] }], {
|
|
33
44
|
participantNotification: req.participantNotification,
|
|
34
45
|
sendSmsReminder: req.sendSmsReminder,
|
|
46
|
+
formSubmission: req.formSubmission,
|
|
35
47
|
});
|
|
36
48
|
const results = response.results ?? [];
|
|
37
49
|
return {
|
|
@@ -43,6 +55,7 @@ export async function createBookingsForCart(params) {
|
|
|
43
55
|
const response = await createMultiServiceBooking(req.bookings, {
|
|
44
56
|
participantNotification: req.participantNotification,
|
|
45
57
|
sendSmsReminder: req.sendSmsReminder,
|
|
58
|
+
formSubmission: req.formSubmission,
|
|
46
59
|
});
|
|
47
60
|
const bookings = response.multiServiceBooking?.bookings ?? [];
|
|
48
61
|
return {
|
|
@@ -53,6 +53,14 @@ export interface BookActionParams {
|
|
|
53
53
|
* service. When omitted, the existing service-config heuristic applies.
|
|
54
54
|
*/
|
|
55
55
|
selectedPaymentOption?: SelectedPaymentOption;
|
|
56
|
+
/**
|
|
57
|
+
* DAY-range only. When `true`, the picked per-day slots are collapsed into a
|
|
58
|
+
* single Booking spanning the whole range (`firstSlot.startDate ->
|
|
59
|
+
* lastSlot.endDate`) and created via plain `createBooking` — instead of the
|
|
60
|
+
* default per-slot expansion that routes to `bulkCreateBooking` (1 slot) or
|
|
61
|
+
* `createMultiServiceBooking` (2-8 slots). Ignored for non-DAY-range services.
|
|
62
|
+
*/
|
|
63
|
+
allDay?: boolean;
|
|
56
64
|
}
|
|
57
65
|
/**
|
|
58
66
|
* Props passed to children of Book component
|
|
@@ -88,6 +88,13 @@ export interface BookingServiceActions {
|
|
|
88
88
|
* is cleared and the heuristic applies again.
|
|
89
89
|
*/
|
|
90
90
|
setSelectedPaymentOption(value: SelectedPaymentOption | null): void;
|
|
91
|
+
/**
|
|
92
|
+
* Toggle the DAY-range `allDay` flag. When `true`, `book()` collapses the
|
|
93
|
+
* picked per-day slots of a DAY-range service into a single Booking created
|
|
94
|
+
* via `createBooking` (instead of the per-slot bulk / multi-service path).
|
|
95
|
+
* Ignored for non-DAY-range services.
|
|
96
|
+
*/
|
|
97
|
+
setAllDay(value: boolean): void;
|
|
91
98
|
clearAll(): void;
|
|
92
99
|
book(): Promise<BookResult>;
|
|
93
100
|
}
|
|
@@ -71,6 +71,10 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
|
|
|
71
71
|
const timezoneSignal = signalsService.signal(config.timezone ?? getClientTimezone());
|
|
72
72
|
const formSubmissionSignal = signalsService.signal(config.formSubmission || null);
|
|
73
73
|
const selectedPaymentOptionSignal = signalsService.signal(config.selectedPaymentOption);
|
|
74
|
+
// Internal-only signal: set via `setAllDay`, read by `book()`. Not
|
|
75
|
+
// exposed on the service surface — consumers derive and push the value
|
|
76
|
+
// (e.g. from the picker's selection mode), so there's no read-back.
|
|
77
|
+
const allDaySignal = signalsService.signal(false);
|
|
74
78
|
// ========================================================================
|
|
75
79
|
// Helpers
|
|
76
80
|
// ========================================================================
|
|
@@ -169,11 +173,16 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
|
|
|
169
173
|
setSelectedPaymentOption(value) {
|
|
170
174
|
selectedPaymentOptionSignal.set(value ?? undefined);
|
|
171
175
|
},
|
|
176
|
+
// All-day (DAY-range) action
|
|
177
|
+
setAllDay(value) {
|
|
178
|
+
allDaySignal.set(value);
|
|
179
|
+
},
|
|
172
180
|
// Clear all
|
|
173
181
|
clearAll() {
|
|
174
182
|
this.clearItems();
|
|
175
183
|
this.clearLocation();
|
|
176
184
|
this.clearFormSubmission();
|
|
185
|
+
this.setAllDay(false);
|
|
177
186
|
},
|
|
178
187
|
// Book action - collects data from signals and delegates to executeBookAction
|
|
179
188
|
// Loading/error state management is handled in Book.tsx component
|
|
@@ -183,6 +192,7 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
|
|
|
183
192
|
const location = locationSignal.get();
|
|
184
193
|
const timezone = timezoneSignal.get();
|
|
185
194
|
const selectedPaymentOption = selectedPaymentOptionSignal.get();
|
|
195
|
+
const allDay = allDaySignal.get();
|
|
186
196
|
// Validation happens inside executeBookAction
|
|
187
197
|
return executeBookAction({
|
|
188
198
|
serviceSelections,
|
|
@@ -191,6 +201,7 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
|
|
|
191
201
|
timezone,
|
|
192
202
|
appId: config.appId,
|
|
193
203
|
selectedPaymentOption,
|
|
204
|
+
allDay,
|
|
194
205
|
});
|
|
195
206
|
},
|
|
196
207
|
};
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { Service } from '@wix/auto_sdk_bookings_services';
|
|
6
6
|
import { type TimeSlotListServiceConfig, type TimeSlotsFilters } from './time-slot-list.def.js';
|
|
7
|
-
import { TimeSlot } from '@wix/
|
|
7
|
+
import { TimeSlot } from '@wix/auto_sdk_bookings_availability-time-slots';
|
|
8
8
|
/**
|
|
9
9
|
* Helper to get staff member name from time slots by ID
|
|
10
10
|
* @internal - exported for testing
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { implementService } from '@wix/services-definitions';
|
|
6
6
|
import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
|
|
7
7
|
import { TimeSlotListServiceDefinition, ViewMode, } from './time-slot-list.def.js';
|
|
8
|
-
import { LocationType, } from '@wix/
|
|
8
|
+
import { LocationType, } from '@wix/auto_sdk_bookings_availability-time-slots';
|
|
9
9
|
import { fetchAvailability } from '../../api/fetch-availability/index.js';
|
|
10
10
|
import { BookingServiceDefinition, } from '../booking/booking.js';
|
|
11
11
|
// ============================================================================
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/headless-bookings",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"scripts": {
|
|
@@ -34,8 +34,9 @@
|
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@wix/
|
|
38
|
-
"@wix/
|
|
37
|
+
"@wix/auto_sdk_bookings_availability-time-slots": "^1.0.244",
|
|
38
|
+
"@wix/auto_sdk_bookings_bookings": "^1.0.192",
|
|
39
|
+
"@wix/auto_sdk_bookings_event-time-slots": "^1.0.112",
|
|
39
40
|
"@wix/auto_sdk_bookings_pricing": "^1.0.87",
|
|
40
41
|
"@wix/auto_sdk_bookings_services": "^1.0.226",
|
|
41
42
|
"@wix/auto_sdk_ecom_cart-v-2": "^1.0.86",
|
|
@@ -75,5 +76,5 @@
|
|
|
75
76
|
"groupId": "com.wixpress.headless-components"
|
|
76
77
|
}
|
|
77
78
|
},
|
|
78
|
-
"falconPackageHash": "
|
|
79
|
+
"falconPackageHash": "fd8f02351f0165bcc83688ccbf4bafc628fde453ffb4fc6e0ead24dc"
|
|
79
80
|
}
|