@wix/headless-bookings 1.0.18 → 1.0.20
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/services/booking/book-action/buildBookingRequest.js +12 -2
- package/cjs/dist/services/booking/book-action/buildDayRangeBookingRequest.js +6 -1
- package/cjs/dist/services/booking/booking.d.ts +5 -0
- package/cjs/dist/services/booking/booking.js +15 -1
- package/cjs/dist/services/index.d.ts +1 -1
- package/cjs/dist/services/payment/payment.d.ts +1 -1
- package/cjs/dist/services/payment/payment.def.d.ts +34 -0
- package/cjs/dist/services/payment/payment.js +30 -23
- package/dist/services/booking/book-action/buildBookingRequest.js +12 -2
- package/dist/services/booking/book-action/buildDayRangeBookingRequest.js +6 -1
- package/dist/services/booking/booking.d.ts +5 -0
- package/dist/services/booking/booking.js +14 -1
- package/dist/services/index.d.ts +1 -1
- package/dist/services/payment/payment.d.ts +1 -1
- package/dist/services/payment/payment.def.d.ts +34 -0
- package/dist/services/payment/payment.js +30 -23
- package/package.json +5 -5
|
@@ -71,8 +71,18 @@ function buildBookingRequest(params) {
|
|
|
71
71
|
...(depositSelectedApplies && {
|
|
72
72
|
depositSelected: params.depositSelected,
|
|
73
73
|
}),
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
...(item.priceChoices?.length
|
|
75
|
+
? {
|
|
76
|
+
participantsChoices: {
|
|
77
|
+
serviceChoices: [
|
|
78
|
+
{
|
|
79
|
+
numberOfParticipants: item.totalParticipants || 1,
|
|
80
|
+
choices: item.priceChoices,
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
: { totalParticipants: item.totalParticipants || 1 }),
|
|
76
86
|
// App that created the booking (used to filter bookings by source app).
|
|
77
87
|
...(params.sourceAppId && {
|
|
78
88
|
bookingSource: { appDefId: params.sourceAppId },
|
|
@@ -45,7 +45,12 @@ function buildDayRangeBookingRequest(params) {
|
|
|
45
45
|
// fields (service, resource, location, payment, participants) are derived
|
|
46
46
|
// exactly once and consistently. Each per-day Booking is then a shallow
|
|
47
47
|
// clone with only the slot start/end overridden from `slots[i]`.
|
|
48
|
-
const
|
|
48
|
+
const isOneBooking = params.allDay || slots.length === 1;
|
|
49
|
+
const withSlot = item.timeSlot ? item : { ...item, timeSlot: slots[0] };
|
|
50
|
+
// A Booking per day may not carry another day's rules.
|
|
51
|
+
const baseSelection = isOneBooking
|
|
52
|
+
? withSlot
|
|
53
|
+
: { ...withSlot, priceChoices: undefined };
|
|
49
54
|
const baseRequest = (0, buildBookingRequest_js_1.buildBookingRequest)({
|
|
50
55
|
...params,
|
|
51
56
|
serviceSelections: [baseSelection, ...params.serviceSelections.slice(1)],
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { type Signal } from '@wix/services-definitions/core-services/signals';
|
|
7
7
|
import type { Service, V2Location as ServiceLocationType } from '@wix/auto_sdk_bookings_services';
|
|
8
8
|
import type { Resource, EventInfo, Location as TimeSlotLocationType } from '@wix/auto_sdk_bookings_availability-time-slots';
|
|
9
|
+
import type { ServiceChoice } from '@wix/auto_sdk_bookings_bookings';
|
|
9
10
|
import type { FormValues } from '@wix/forms/components';
|
|
10
11
|
import type { BookResult, SelectedPaymentOption } from './book-action/types.js';
|
|
11
12
|
export type { SelectedPaymentOption } from './book-action/types.js';
|
|
@@ -56,7 +57,11 @@ export interface ServiceSelection {
|
|
|
56
57
|
rangeTimeSlots?: ServiceSelectionTimeSlot[];
|
|
57
58
|
/** Number of participants for this service selection */
|
|
58
59
|
totalParticipants?: number;
|
|
60
|
+
/** Date & time pricing rules to record on the booking (at most five). */
|
|
61
|
+
priceChoices?: ServiceChoice[];
|
|
59
62
|
}
|
|
63
|
+
/** Rules priced for the old dates don't follow the slot to new ones. */
|
|
64
|
+
export declare function applySelectionUpdates(item: ServiceSelection, updates: Partial<Omit<ServiceSelection, 'instanceId'>>): ServiceSelection;
|
|
60
65
|
/**
|
|
61
66
|
* BookingService actions - setters only, no API calls
|
|
62
67
|
*/
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.BookingService = exports.BookingServiceDefinition = void 0;
|
|
9
|
+
exports.applySelectionUpdates = applySelectionUpdates;
|
|
9
10
|
const services_definitions_1 = require("@wix/services-definitions");
|
|
10
11
|
const signals_1 = require("@wix/services-definitions/core-services/signals");
|
|
11
12
|
const bookAction_js_1 = require("./book-action/bookAction.js");
|
|
@@ -30,6 +31,17 @@ function getClientTimezone() {
|
|
|
30
31
|
? Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
31
32
|
: undefined;
|
|
32
33
|
}
|
|
34
|
+
const datesOf = (selection) => JSON.stringify([selection.timeSlot, ...(selection.rangeTimeSlots ?? [])].map((slot) => [
|
|
35
|
+
slot?.startDate,
|
|
36
|
+
slot?.endDate,
|
|
37
|
+
]));
|
|
38
|
+
/** Rules priced for the old dates don't follow the slot to new ones. */
|
|
39
|
+
function applySelectionUpdates(item, updates) {
|
|
40
|
+
const updated = { ...item, ...updates };
|
|
41
|
+
return datesOf(updated) !== datesOf(item) && !('priceChoices' in updates)
|
|
42
|
+
? { ...updated, priceChoices: undefined }
|
|
43
|
+
: updated;
|
|
44
|
+
}
|
|
33
45
|
/**
|
|
34
46
|
* Service definition for Booking
|
|
35
47
|
*/
|
|
@@ -117,7 +129,9 @@ exports.BookingService = services_definitions_1.implementService.withConfig()(ex
|
|
|
117
129
|
const current = serviceSelectionsSignal.get();
|
|
118
130
|
// If no instanceId provided, update the first item (index 0)
|
|
119
131
|
const targetId = instanceId ?? current[0]?.instanceId;
|
|
120
|
-
const updated = current.map((item) => item.instanceId === targetId
|
|
132
|
+
const updated = current.map((item) => item.instanceId === targetId
|
|
133
|
+
? applySelectionUpdates(item, updates)
|
|
134
|
+
: item);
|
|
121
135
|
serviceSelectionsSignal.set(updated);
|
|
122
136
|
},
|
|
123
137
|
removeItem(instanceId) {
|
|
@@ -9,6 +9,6 @@ export { ServiceListService, ServiceListServiceDefinition, type ServiceListServi
|
|
|
9
9
|
export { SYNTHETIC_CUSTOM_ID, SYNTHETIC_CUSTOMER_ID, AvailabilityLocationType, type ServiceWithAvailabilityItem, type AvailabilityFilter, type Attribute, type AvailabilityLocation, } from '../api/query-services/index.js';
|
|
10
10
|
export { executeBookAction, canBook, buildBookingRequest, buildCartRequest, buildDayRangeBookingRequest, createBookingsForCart, isDayRangeService, getDayRangeBounds, type CanBookParams, type BookResult, type BookingError, type BookActionParams, type BookChildProps, type BookProps, type BuildCartParams, type BuildDayRangeBookingRequest, type CreatedBookings, type DayRangeBounds, } from './booking/book-action/index.js';
|
|
11
11
|
export { BookingFormService, BookingFormServiceDefinition, type BookingFormServiceAPI, type BookingFormServiceConfig, } from './booking-form/booking-form.js';
|
|
12
|
-
export { PaymentService, PaymentServiceDefinition, type PaymentServiceAPI, type PaymentServiceConfig, type PaymentDetails, type PricingServiceSelection, type LineItemAdditionalInfo, type ServicePaymentOptions, loadPaymentConfig, type SuccessPaymentConfigResult, type ErrorPaymentConfigResult, } from './payment/payment.js';
|
|
12
|
+
export { PaymentService, PaymentServiceDefinition, type PaymentServiceAPI, type PaymentServiceConfig, type PaymentDetails, type PricingServiceSelection, type LineItemAdditionalInfo, type AppliedAdditionalFee, type PreviewPriceInfo, type ServicePaymentOptions, loadPaymentConfig, type SuccessPaymentConfigResult, type ErrorPaymentConfigResult, } from './payment/payment.js';
|
|
13
13
|
export { LocationListService, LocationListServiceDefinition, LocationType, loadLocationListServiceInitialData, locationListServiceBinding, type LocationListServiceAPI, type LocationListServiceConfig, type LocationListActions, type Location, type LoadLocationListServiceResult, getLocationById, } from './location-list/location-list.js';
|
|
14
14
|
export { StaffMemberListService, StaffMemberListServiceDefinition, loadStaffMemberListServiceInitialData, staffMemberListServiceBinding, type StaffMemberListServiceAPI, type StaffMemberListServiceConfig, type StaffMemberListActions, type StaffMemberData, type LoadStaffMemberListServiceResult, } from './staff-member-list/staff-member-list.js';
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { type PaymentServiceConfig, type PaymentServiceInternalConfig, type PricingServiceSelection } from './payment.def.js';
|
|
7
7
|
import type { SelectedPaymentOption } from '../booking/book-action/types.js';
|
|
8
|
-
export { PaymentServiceDefinition, type PaymentServiceConfig, type PaymentDetails, type LineItemAdditionalInfo, type PricingServiceSelection, type ServicePaymentOptions, } from './payment.def.js';
|
|
8
|
+
export { PaymentServiceDefinition, type PaymentServiceConfig, type PaymentDetails, type LineItemAdditionalInfo, type AppliedAdditionalFee, type PreviewPriceInfo, type PricingServiceSelection, type ServicePaymentOptions, } from './payment.def.js';
|
|
9
9
|
export type { PaymentServiceAPI, PaymentServiceInternalConfig, } from './payment.def.js';
|
|
10
10
|
export declare const PaymentService: import("@wix/services-definitions").ServiceFactory<string & {
|
|
11
11
|
__api: import("./payment.def.js").PaymentServiceAPI;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import type { Signal } from '@wix/services-definitions/core-services/signals';
|
|
6
6
|
import type { CalculateTotalsResponse } from '@wix/auto_sdk_ecom_totals-calculator';
|
|
7
7
|
import type { Service } from '@wix/auto_sdk_bookings_services';
|
|
8
|
+
import type { BookingLineItem, PriceInfo } from '@wix/auto_sdk_bookings_pricing';
|
|
8
9
|
import type { SelectedPaymentOption } from '../booking/book-action/types.js';
|
|
9
10
|
import type { ServiceSelectionTimeSlot } from '../booking/booking.js';
|
|
10
11
|
/**
|
|
@@ -32,6 +33,31 @@ export interface ServicePaymentOptions {
|
|
|
32
33
|
* Payment option for line items
|
|
33
34
|
*/
|
|
34
35
|
export type PaymentOption = 'FULL_PAYMENT_ONLINE' | 'FULL_PAYMENT_OFFLINE' | 'DEPOSIT_ONLINE';
|
|
36
|
+
/**
|
|
37
|
+
* An additional fee pricing applied to a booking line, as served.
|
|
38
|
+
*/
|
|
39
|
+
export interface AppliedAdditionalFee {
|
|
40
|
+
/** The service's additional fee ID. */
|
|
41
|
+
feeId?: string;
|
|
42
|
+
/** Units the fee was charged for (1 for a per-reservation fee). */
|
|
43
|
+
units?: number | null;
|
|
44
|
+
/** The fee amount for this line. */
|
|
45
|
+
amount?: number | null;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* `PriceInfo` with the additional-fee fields `previewPrice` serves, which the
|
|
49
|
+
* public pricing SDK types don't declare (they are `@internal` there). Types
|
|
50
|
+
* only: the values are the response as served.
|
|
51
|
+
*/
|
|
52
|
+
export interface PreviewPriceInfo extends PriceInfo {
|
|
53
|
+
bookingLineItems?: (BookingLineItem & {
|
|
54
|
+
additionalFees?: AppliedAdditionalFee[];
|
|
55
|
+
})[];
|
|
56
|
+
/** Sum of all lines' additional fees. */
|
|
57
|
+
totalAdditionalFees?: number | null;
|
|
58
|
+
/** `calculatedPrice` plus `totalAdditionalFees`. */
|
|
59
|
+
calculatedPriceWithFees?: number | null;
|
|
60
|
+
}
|
|
35
61
|
/**
|
|
36
62
|
* Additional computed info for a line item (not in SDK response)
|
|
37
63
|
*/
|
|
@@ -40,6 +66,14 @@ export interface LineItemAdditionalInfo {
|
|
|
40
66
|
lineItemId: string;
|
|
41
67
|
/** Custom price (for CUSTOM rate type services) */
|
|
42
68
|
customPrice?: string;
|
|
69
|
+
/**
|
|
70
|
+
* The raw `previewPrice` response for this line, as served — for fields the
|
|
71
|
+
* payment service does not read. Not the amounts charged: those (including
|
|
72
|
+
* a capped deposit) come from `response`. Set only when the line was priced
|
|
73
|
+
* by `previewPrice` (duration-range services, or a deposit the server
|
|
74
|
+
* resolves).
|
|
75
|
+
*/
|
|
76
|
+
priceInfo?: PreviewPriceInfo;
|
|
43
77
|
}
|
|
44
78
|
/**
|
|
45
79
|
* Payment calculation result with SDK response and additional computed info
|
|
@@ -139,14 +139,9 @@ function getDurationRange(service) {
|
|
|
139
139
|
async function getPreviewedPrice(bookingLineItems) {
|
|
140
140
|
if (!bookingLineItems.length)
|
|
141
141
|
return null;
|
|
142
|
-
const
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
return null;
|
|
146
|
-
return {
|
|
147
|
-
price,
|
|
148
|
-
deposit: result.priceInfo?.deposit ?? null,
|
|
149
|
-
};
|
|
142
|
+
const { priceInfo } = await (0, auto_sdk_bookings_pricing_1.previewPrice)(bookingLineItems);
|
|
143
|
+
const calculatedPrice = priceInfo?.calculatedPrice;
|
|
144
|
+
return calculatedPrice != null ? { ...priceInfo, calculatedPrice } : null;
|
|
150
145
|
}
|
|
151
146
|
async function buildLineItemWithPreview(item, totalParticipants, selectedPaymentOption, depositSelected) {
|
|
152
147
|
const slots = item.rangeTimeSlots && item.rangeTimeSlots.length > 0
|
|
@@ -172,13 +167,13 @@ async function buildLineItemWithPreview(item, totalParticipants, selectedPayment
|
|
|
172
167
|
serviceId: item.service._id,
|
|
173
168
|
localStartDate: slot.localStartDate,
|
|
174
169
|
localEndDate: slot.localEndDate,
|
|
175
|
-
numberOfParticipants: totalParticipants,
|
|
170
|
+
serviceChoices: [{ numberOfParticipants: totalParticipants }],
|
|
176
171
|
...(item.timeZone ? { timeZone: item.timeZone } : {}),
|
|
177
172
|
}));
|
|
178
|
-
const
|
|
179
|
-
if (
|
|
173
|
+
const priceInfo = await getPreviewedPrice(bookingLineItems).catch(() => null);
|
|
174
|
+
if (priceInfo != null) {
|
|
180
175
|
const depositValue = (0, servicePayment_js_1.getDepositValue)(item.service);
|
|
181
|
-
const previewedDeposit =
|
|
176
|
+
const previewedDeposit = priceInfo.deposit ?? null;
|
|
182
177
|
const hasDeposit = (0, servicePayment_js_1.requiresDeposit)(item.service) &&
|
|
183
178
|
(previewedDeposit != null
|
|
184
179
|
? previewedDeposit > 0
|
|
@@ -188,27 +183,39 @@ async function buildLineItemWithPreview(item, totalParticipants, selectedPayment
|
|
|
188
183
|
? previewedDeposit
|
|
189
184
|
: Number(depositValue) * totalParticipants
|
|
190
185
|
: undefined;
|
|
191
|
-
return
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
186
|
+
return {
|
|
187
|
+
lineItem: toLineItem({
|
|
188
|
+
lineItemId: item.lineItemId,
|
|
189
|
+
serviceId: item.service._id,
|
|
190
|
+
price: priceInfo.calculatedPrice,
|
|
191
|
+
deposit,
|
|
192
|
+
paymentOption: getPaymentOption(item.service, hasDeposit, selectedPaymentOption, depositSelected),
|
|
193
|
+
}),
|
|
194
|
+
priceInfo,
|
|
195
|
+
};
|
|
198
196
|
}
|
|
199
197
|
}
|
|
200
|
-
return
|
|
198
|
+
return {
|
|
199
|
+
lineItem: buildLineItem(item.service, totalParticipants, item.lineItemId, selectedPaymentOption, depositSelected),
|
|
200
|
+
};
|
|
201
201
|
}
|
|
202
202
|
async function calculatePaymentDetails(pricingServiceSelections, totalParticipants, selectedPaymentOption, depositSelected) {
|
|
203
203
|
const data = pricingServiceSelections.map((selection) => ({
|
|
204
204
|
...selection,
|
|
205
205
|
lineItemId: selection.lineItemId || (0, guid_js_1.generateLineItemId)(),
|
|
206
206
|
}));
|
|
207
|
-
const
|
|
207
|
+
const builtLineItems = await Promise.all(data.map(async (item) => {
|
|
208
|
+
const { lineItem, priceInfo } = await buildLineItemWithPreview(item, totalParticipants, selectedPaymentOption, depositSelected);
|
|
209
|
+
const additionalInfo = {
|
|
210
|
+
...getAdditionalInfo(item.service, item.lineItemId),
|
|
211
|
+
...(priceInfo ? { priceInfo } : {}),
|
|
212
|
+
};
|
|
213
|
+
return { lineItem, additionalInfo };
|
|
214
|
+
}));
|
|
208
215
|
const response = await (0, auto_sdk_ecom_totals_calculator_1.calculateTotals)({
|
|
209
|
-
lineItems,
|
|
216
|
+
lineItems: builtLineItems.map(({ lineItem }) => lineItem),
|
|
210
217
|
});
|
|
211
|
-
const additionalInfoList =
|
|
218
|
+
const additionalInfoList = builtLineItems.map(({ additionalInfo }) => additionalInfo);
|
|
212
219
|
return {
|
|
213
220
|
response,
|
|
214
221
|
additionalInfo: {
|
|
@@ -68,8 +68,18 @@ export function buildBookingRequest(params) {
|
|
|
68
68
|
...(depositSelectedApplies && {
|
|
69
69
|
depositSelected: params.depositSelected,
|
|
70
70
|
}),
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
...(item.priceChoices?.length
|
|
72
|
+
? {
|
|
73
|
+
participantsChoices: {
|
|
74
|
+
serviceChoices: [
|
|
75
|
+
{
|
|
76
|
+
numberOfParticipants: item.totalParticipants || 1,
|
|
77
|
+
choices: item.priceChoices,
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
}
|
|
82
|
+
: { totalParticipants: item.totalParticipants || 1 }),
|
|
73
83
|
// App that created the booking (used to filter bookings by source app).
|
|
74
84
|
...(params.sourceAppId && {
|
|
75
85
|
bookingSource: { appDefId: params.sourceAppId },
|
|
@@ -42,7 +42,12 @@ export function buildDayRangeBookingRequest(params) {
|
|
|
42
42
|
// fields (service, resource, location, payment, participants) are derived
|
|
43
43
|
// exactly once and consistently. Each per-day Booking is then a shallow
|
|
44
44
|
// clone with only the slot start/end overridden from `slots[i]`.
|
|
45
|
-
const
|
|
45
|
+
const isOneBooking = params.allDay || slots.length === 1;
|
|
46
|
+
const withSlot = item.timeSlot ? item : { ...item, timeSlot: slots[0] };
|
|
47
|
+
// A Booking per day may not carry another day's rules.
|
|
48
|
+
const baseSelection = isOneBooking
|
|
49
|
+
? withSlot
|
|
50
|
+
: { ...withSlot, priceChoices: undefined };
|
|
46
51
|
const baseRequest = buildBookingRequest({
|
|
47
52
|
...params,
|
|
48
53
|
serviceSelections: [baseSelection, ...params.serviceSelections.slice(1)],
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { type Signal } from '@wix/services-definitions/core-services/signals';
|
|
7
7
|
import type { Service, V2Location as ServiceLocationType } from '@wix/auto_sdk_bookings_services';
|
|
8
8
|
import type { Resource, EventInfo, Location as TimeSlotLocationType } from '@wix/auto_sdk_bookings_availability-time-slots';
|
|
9
|
+
import type { ServiceChoice } from '@wix/auto_sdk_bookings_bookings';
|
|
9
10
|
import type { FormValues } from '@wix/forms/components';
|
|
10
11
|
import type { BookResult, SelectedPaymentOption } from './book-action/types.js';
|
|
11
12
|
export type { SelectedPaymentOption } from './book-action/types.js';
|
|
@@ -56,7 +57,11 @@ export interface ServiceSelection {
|
|
|
56
57
|
rangeTimeSlots?: ServiceSelectionTimeSlot[];
|
|
57
58
|
/** Number of participants for this service selection */
|
|
58
59
|
totalParticipants?: number;
|
|
60
|
+
/** Date & time pricing rules to record on the booking (at most five). */
|
|
61
|
+
priceChoices?: ServiceChoice[];
|
|
59
62
|
}
|
|
63
|
+
/** Rules priced for the old dates don't follow the slot to new ones. */
|
|
64
|
+
export declare function applySelectionUpdates(item: ServiceSelection, updates: Partial<Omit<ServiceSelection, 'instanceId'>>): ServiceSelection;
|
|
60
65
|
/**
|
|
61
66
|
* BookingService actions - setters only, no API calls
|
|
62
67
|
*/
|
|
@@ -27,6 +27,17 @@ function getClientTimezone() {
|
|
|
27
27
|
? Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
28
28
|
: undefined;
|
|
29
29
|
}
|
|
30
|
+
const datesOf = (selection) => JSON.stringify([selection.timeSlot, ...(selection.rangeTimeSlots ?? [])].map((slot) => [
|
|
31
|
+
slot?.startDate,
|
|
32
|
+
slot?.endDate,
|
|
33
|
+
]));
|
|
34
|
+
/** Rules priced for the old dates don't follow the slot to new ones. */
|
|
35
|
+
export function applySelectionUpdates(item, updates) {
|
|
36
|
+
const updated = { ...item, ...updates };
|
|
37
|
+
return datesOf(updated) !== datesOf(item) && !('priceChoices' in updates)
|
|
38
|
+
? { ...updated, priceChoices: undefined }
|
|
39
|
+
: updated;
|
|
40
|
+
}
|
|
30
41
|
/**
|
|
31
42
|
* Service definition for Booking
|
|
32
43
|
*/
|
|
@@ -114,7 +125,9 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
|
|
|
114
125
|
const current = serviceSelectionsSignal.get();
|
|
115
126
|
// If no instanceId provided, update the first item (index 0)
|
|
116
127
|
const targetId = instanceId ?? current[0]?.instanceId;
|
|
117
|
-
const updated = current.map((item) => item.instanceId === targetId
|
|
128
|
+
const updated = current.map((item) => item.instanceId === targetId
|
|
129
|
+
? applySelectionUpdates(item, updates)
|
|
130
|
+
: item);
|
|
118
131
|
serviceSelectionsSignal.set(updated);
|
|
119
132
|
},
|
|
120
133
|
removeItem(instanceId) {
|
package/dist/services/index.d.ts
CHANGED
|
@@ -9,6 +9,6 @@ export { ServiceListService, ServiceListServiceDefinition, type ServiceListServi
|
|
|
9
9
|
export { SYNTHETIC_CUSTOM_ID, SYNTHETIC_CUSTOMER_ID, AvailabilityLocationType, type ServiceWithAvailabilityItem, type AvailabilityFilter, type Attribute, type AvailabilityLocation, } from '../api/query-services/index.js';
|
|
10
10
|
export { executeBookAction, canBook, buildBookingRequest, buildCartRequest, buildDayRangeBookingRequest, createBookingsForCart, isDayRangeService, getDayRangeBounds, type CanBookParams, type BookResult, type BookingError, type BookActionParams, type BookChildProps, type BookProps, type BuildCartParams, type BuildDayRangeBookingRequest, type CreatedBookings, type DayRangeBounds, } from './booking/book-action/index.js';
|
|
11
11
|
export { BookingFormService, BookingFormServiceDefinition, type BookingFormServiceAPI, type BookingFormServiceConfig, } from './booking-form/booking-form.js';
|
|
12
|
-
export { PaymentService, PaymentServiceDefinition, type PaymentServiceAPI, type PaymentServiceConfig, type PaymentDetails, type PricingServiceSelection, type LineItemAdditionalInfo, type ServicePaymentOptions, loadPaymentConfig, type SuccessPaymentConfigResult, type ErrorPaymentConfigResult, } from './payment/payment.js';
|
|
12
|
+
export { PaymentService, PaymentServiceDefinition, type PaymentServiceAPI, type PaymentServiceConfig, type PaymentDetails, type PricingServiceSelection, type LineItemAdditionalInfo, type AppliedAdditionalFee, type PreviewPriceInfo, type ServicePaymentOptions, loadPaymentConfig, type SuccessPaymentConfigResult, type ErrorPaymentConfigResult, } from './payment/payment.js';
|
|
13
13
|
export { LocationListService, LocationListServiceDefinition, LocationType, loadLocationListServiceInitialData, locationListServiceBinding, type LocationListServiceAPI, type LocationListServiceConfig, type LocationListActions, type Location, type LoadLocationListServiceResult, getLocationById, } from './location-list/location-list.js';
|
|
14
14
|
export { StaffMemberListService, StaffMemberListServiceDefinition, loadStaffMemberListServiceInitialData, staffMemberListServiceBinding, type StaffMemberListServiceAPI, type StaffMemberListServiceConfig, type StaffMemberListActions, type StaffMemberData, type LoadStaffMemberListServiceResult, } from './staff-member-list/staff-member-list.js';
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { type PaymentServiceConfig, type PaymentServiceInternalConfig, type PricingServiceSelection } from './payment.def.js';
|
|
7
7
|
import type { SelectedPaymentOption } from '../booking/book-action/types.js';
|
|
8
|
-
export { PaymentServiceDefinition, type PaymentServiceConfig, type PaymentDetails, type LineItemAdditionalInfo, type PricingServiceSelection, type ServicePaymentOptions, } from './payment.def.js';
|
|
8
|
+
export { PaymentServiceDefinition, type PaymentServiceConfig, type PaymentDetails, type LineItemAdditionalInfo, type AppliedAdditionalFee, type PreviewPriceInfo, type PricingServiceSelection, type ServicePaymentOptions, } from './payment.def.js';
|
|
9
9
|
export type { PaymentServiceAPI, PaymentServiceInternalConfig, } from './payment.def.js';
|
|
10
10
|
export declare const PaymentService: import("@wix/services-definitions").ServiceFactory<string & {
|
|
11
11
|
__api: import("./payment.def.js").PaymentServiceAPI;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import type { Signal } from '@wix/services-definitions/core-services/signals';
|
|
6
6
|
import type { CalculateTotalsResponse } from '@wix/auto_sdk_ecom_totals-calculator';
|
|
7
7
|
import type { Service } from '@wix/auto_sdk_bookings_services';
|
|
8
|
+
import type { BookingLineItem, PriceInfo } from '@wix/auto_sdk_bookings_pricing';
|
|
8
9
|
import type { SelectedPaymentOption } from '../booking/book-action/types.js';
|
|
9
10
|
import type { ServiceSelectionTimeSlot } from '../booking/booking.js';
|
|
10
11
|
/**
|
|
@@ -32,6 +33,31 @@ export interface ServicePaymentOptions {
|
|
|
32
33
|
* Payment option for line items
|
|
33
34
|
*/
|
|
34
35
|
export type PaymentOption = 'FULL_PAYMENT_ONLINE' | 'FULL_PAYMENT_OFFLINE' | 'DEPOSIT_ONLINE';
|
|
36
|
+
/**
|
|
37
|
+
* An additional fee pricing applied to a booking line, as served.
|
|
38
|
+
*/
|
|
39
|
+
export interface AppliedAdditionalFee {
|
|
40
|
+
/** The service's additional fee ID. */
|
|
41
|
+
feeId?: string;
|
|
42
|
+
/** Units the fee was charged for (1 for a per-reservation fee). */
|
|
43
|
+
units?: number | null;
|
|
44
|
+
/** The fee amount for this line. */
|
|
45
|
+
amount?: number | null;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* `PriceInfo` with the additional-fee fields `previewPrice` serves, which the
|
|
49
|
+
* public pricing SDK types don't declare (they are `@internal` there). Types
|
|
50
|
+
* only: the values are the response as served.
|
|
51
|
+
*/
|
|
52
|
+
export interface PreviewPriceInfo extends PriceInfo {
|
|
53
|
+
bookingLineItems?: (BookingLineItem & {
|
|
54
|
+
additionalFees?: AppliedAdditionalFee[];
|
|
55
|
+
})[];
|
|
56
|
+
/** Sum of all lines' additional fees. */
|
|
57
|
+
totalAdditionalFees?: number | null;
|
|
58
|
+
/** `calculatedPrice` plus `totalAdditionalFees`. */
|
|
59
|
+
calculatedPriceWithFees?: number | null;
|
|
60
|
+
}
|
|
35
61
|
/**
|
|
36
62
|
* Additional computed info for a line item (not in SDK response)
|
|
37
63
|
*/
|
|
@@ -40,6 +66,14 @@ export interface LineItemAdditionalInfo {
|
|
|
40
66
|
lineItemId: string;
|
|
41
67
|
/** Custom price (for CUSTOM rate type services) */
|
|
42
68
|
customPrice?: string;
|
|
69
|
+
/**
|
|
70
|
+
* The raw `previewPrice` response for this line, as served — for fields the
|
|
71
|
+
* payment service does not read. Not the amounts charged: those (including
|
|
72
|
+
* a capped deposit) come from `response`. Set only when the line was priced
|
|
73
|
+
* by `previewPrice` (duration-range services, or a deposit the server
|
|
74
|
+
* resolves).
|
|
75
|
+
*/
|
|
76
|
+
priceInfo?: PreviewPriceInfo;
|
|
43
77
|
}
|
|
44
78
|
/**
|
|
45
79
|
* Payment calculation result with SDK response and additional computed info
|
|
@@ -134,14 +134,9 @@ function getDurationRange(service) {
|
|
|
134
134
|
async function getPreviewedPrice(bookingLineItems) {
|
|
135
135
|
if (!bookingLineItems.length)
|
|
136
136
|
return null;
|
|
137
|
-
const
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
return null;
|
|
141
|
-
return {
|
|
142
|
-
price,
|
|
143
|
-
deposit: result.priceInfo?.deposit ?? null,
|
|
144
|
-
};
|
|
137
|
+
const { priceInfo } = await previewPrice(bookingLineItems);
|
|
138
|
+
const calculatedPrice = priceInfo?.calculatedPrice;
|
|
139
|
+
return calculatedPrice != null ? { ...priceInfo, calculatedPrice } : null;
|
|
145
140
|
}
|
|
146
141
|
async function buildLineItemWithPreview(item, totalParticipants, selectedPaymentOption, depositSelected) {
|
|
147
142
|
const slots = item.rangeTimeSlots && item.rangeTimeSlots.length > 0
|
|
@@ -167,13 +162,13 @@ async function buildLineItemWithPreview(item, totalParticipants, selectedPayment
|
|
|
167
162
|
serviceId: item.service._id,
|
|
168
163
|
localStartDate: slot.localStartDate,
|
|
169
164
|
localEndDate: slot.localEndDate,
|
|
170
|
-
numberOfParticipants: totalParticipants,
|
|
165
|
+
serviceChoices: [{ numberOfParticipants: totalParticipants }],
|
|
171
166
|
...(item.timeZone ? { timeZone: item.timeZone } : {}),
|
|
172
167
|
}));
|
|
173
|
-
const
|
|
174
|
-
if (
|
|
168
|
+
const priceInfo = await getPreviewedPrice(bookingLineItems).catch(() => null);
|
|
169
|
+
if (priceInfo != null) {
|
|
175
170
|
const depositValue = getDepositValue(item.service);
|
|
176
|
-
const previewedDeposit =
|
|
171
|
+
const previewedDeposit = priceInfo.deposit ?? null;
|
|
177
172
|
const hasDeposit = requiresDeposit(item.service) &&
|
|
178
173
|
(previewedDeposit != null
|
|
179
174
|
? previewedDeposit > 0
|
|
@@ -183,27 +178,39 @@ async function buildLineItemWithPreview(item, totalParticipants, selectedPayment
|
|
|
183
178
|
? previewedDeposit
|
|
184
179
|
: Number(depositValue) * totalParticipants
|
|
185
180
|
: undefined;
|
|
186
|
-
return
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
181
|
+
return {
|
|
182
|
+
lineItem: toLineItem({
|
|
183
|
+
lineItemId: item.lineItemId,
|
|
184
|
+
serviceId: item.service._id,
|
|
185
|
+
price: priceInfo.calculatedPrice,
|
|
186
|
+
deposit,
|
|
187
|
+
paymentOption: getPaymentOption(item.service, hasDeposit, selectedPaymentOption, depositSelected),
|
|
188
|
+
}),
|
|
189
|
+
priceInfo,
|
|
190
|
+
};
|
|
193
191
|
}
|
|
194
192
|
}
|
|
195
|
-
return
|
|
193
|
+
return {
|
|
194
|
+
lineItem: buildLineItem(item.service, totalParticipants, item.lineItemId, selectedPaymentOption, depositSelected),
|
|
195
|
+
};
|
|
196
196
|
}
|
|
197
197
|
async function calculatePaymentDetails(pricingServiceSelections, totalParticipants, selectedPaymentOption, depositSelected) {
|
|
198
198
|
const data = pricingServiceSelections.map((selection) => ({
|
|
199
199
|
...selection,
|
|
200
200
|
lineItemId: selection.lineItemId || generateLineItemId(),
|
|
201
201
|
}));
|
|
202
|
-
const
|
|
202
|
+
const builtLineItems = await Promise.all(data.map(async (item) => {
|
|
203
|
+
const { lineItem, priceInfo } = await buildLineItemWithPreview(item, totalParticipants, selectedPaymentOption, depositSelected);
|
|
204
|
+
const additionalInfo = {
|
|
205
|
+
...getAdditionalInfo(item.service, item.lineItemId),
|
|
206
|
+
...(priceInfo ? { priceInfo } : {}),
|
|
207
|
+
};
|
|
208
|
+
return { lineItem, additionalInfo };
|
|
209
|
+
}));
|
|
203
210
|
const response = await calculateTotals({
|
|
204
|
-
lineItems,
|
|
211
|
+
lineItems: builtLineItems.map(({ lineItem }) => lineItem),
|
|
205
212
|
});
|
|
206
|
-
const additionalInfoList =
|
|
213
|
+
const additionalInfoList = builtLineItems.map(({ additionalInfo }) => additionalInfo);
|
|
207
214
|
return {
|
|
208
215
|
response,
|
|
209
216
|
additionalInfo: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/headless-bookings",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.20",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"scripts": {
|
|
@@ -37,10 +37,10 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@wix/auto_sdk_bookings_availability-time-slots": "^1.0.244",
|
|
40
|
-
"@wix/auto_sdk_bookings_bookings": "^1.0.
|
|
40
|
+
"@wix/auto_sdk_bookings_bookings": "^1.0.262",
|
|
41
41
|
"@wix/auto_sdk_bookings_catalog-search": "^1.0.2",
|
|
42
42
|
"@wix/auto_sdk_bookings_event-time-slots": "^1.0.112",
|
|
43
|
-
"@wix/auto_sdk_bookings_pricing": "^1.0.
|
|
43
|
+
"@wix/auto_sdk_bookings_pricing": "^1.0.117",
|
|
44
44
|
"@wix/auto_sdk_bookings_services": "^1.0.265",
|
|
45
45
|
"@wix/auto_sdk_ecom_cart-v-2": "^1.0.86",
|
|
46
46
|
"@wix/forms": "^1.0.384",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"vitest": "^3.1.4"
|
|
79
79
|
},
|
|
80
80
|
"peerDependencies": {
|
|
81
|
-
"@wix/headless-components": "
|
|
81
|
+
"@wix/headless-components": "~0.0.47",
|
|
82
82
|
"react": ">=16.3.0"
|
|
83
83
|
},
|
|
84
84
|
"publishConfig": {
|
|
@@ -91,5 +91,5 @@
|
|
|
91
91
|
"groupId": "com.wixpress.headless-components"
|
|
92
92
|
}
|
|
93
93
|
},
|
|
94
|
-
"falconPackageHash": "
|
|
94
|
+
"falconPackageHash": "4cfe5a2f1743c1743eb4892fd20c8ed27a7e6b69813c2727bb0f1100"
|
|
95
95
|
}
|