@wix/headless-bookings 1.0.17 → 1.0.18
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 +4 -1
- package/cjs/dist/__mocks__/services/services-mocks.d.ts +13 -0
- package/cjs/dist/__mocks__/services/services-mocks.js +92 -1
- package/cjs/dist/react/core/booking/Booking.d.ts +6 -0
- package/cjs/dist/react/core/booking/Booking.js +2 -0
- package/cjs/dist/react/core/payment/Payment.d.ts +2 -1
- package/cjs/dist/react/core/payment/Payment.js +11 -8
- package/cjs/dist/react/payment/Payment.d.ts +3 -2
- package/cjs/dist/react/payment/Payment.js +11 -5
- package/cjs/dist/services/booking/book-action/buildBookingRequest.js +13 -4
- package/cjs/dist/services/booking/book-action/types.d.ts +6 -0
- package/cjs/dist/services/booking/booking.d.ts +17 -0
- package/cjs/dist/services/booking/booking.js +8 -0
- package/cjs/dist/services/payment/payment.d.ts +3 -0
- package/cjs/dist/services/payment/payment.def.d.ts +15 -1
- package/cjs/dist/services/payment/payment.js +89 -58
- package/cjs/dist/services/servicePayment.d.ts +26 -0
- package/cjs/dist/services/servicePayment.js +46 -0
- package/cjs/dist/utils/money.d.ts +12 -2
- package/cjs/dist/utils/money.js +30 -18
- package/dist/__mocks__/booking/booking-client-service.js +4 -1
- package/dist/__mocks__/services/services-mocks.d.ts +13 -0
- package/dist/__mocks__/services/services-mocks.js +91 -0
- package/dist/react/core/booking/Booking.d.ts +6 -0
- package/dist/react/core/booking/Booking.js +2 -0
- package/dist/react/core/payment/Payment.d.ts +2 -1
- package/dist/react/core/payment/Payment.js +11 -8
- package/dist/react/payment/Payment.d.ts +3 -2
- package/dist/react/payment/Payment.js +11 -5
- package/dist/services/booking/book-action/buildBookingRequest.js +13 -4
- package/dist/services/booking/book-action/types.d.ts +6 -0
- package/dist/services/booking/booking.d.ts +17 -0
- package/dist/services/booking/booking.js +8 -0
- package/dist/services/payment/payment.d.ts +3 -0
- package/dist/services/payment/payment.def.d.ts +15 -1
- package/dist/services/payment/payment.js +89 -58
- package/dist/services/servicePayment.d.ts +26 -0
- package/dist/services/servicePayment.js +40 -0
- package/dist/utils/money.d.ts +12 -2
- package/dist/utils/money.js +30 -18
- package/package.json +3 -3
|
@@ -29,18 +29,20 @@ function createMockSignalsService() {
|
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
31
|
function createMockBookingService(config = {}) {
|
|
32
|
-
const { serviceSelections = [], location = null, timezone = 'UTC', formSubmission = null, selectedPaymentOption, } = config;
|
|
32
|
+
const { serviceSelections = [], location = null, timezone = 'UTC', formSubmission = null, selectedPaymentOption, depositSelected, } = config;
|
|
33
33
|
const serviceSelectionsSignal = mockSignal(serviceSelections);
|
|
34
34
|
const locationSignal = mockSignal(location);
|
|
35
35
|
const timezoneSignal = mockSignal(timezone);
|
|
36
36
|
const formSubmissionSignal = mockSignal(formSubmission);
|
|
37
37
|
const selectedPaymentOptionSignal = mockSignal(selectedPaymentOption);
|
|
38
|
+
const depositSelectedSignal = mockSignal(depositSelected);
|
|
38
39
|
return {
|
|
39
40
|
serviceSelections: serviceSelectionsSignal,
|
|
40
41
|
location: locationSignal,
|
|
41
42
|
timezone: timezoneSignal,
|
|
42
43
|
formSubmission: formSubmissionSignal,
|
|
43
44
|
selectedPaymentOption: selectedPaymentOptionSignal,
|
|
45
|
+
depositSelected: depositSelectedSignal,
|
|
44
46
|
actions: {
|
|
45
47
|
updateItem: vitest_1.vi.fn(),
|
|
46
48
|
setItem: vitest_1.vi.fn(),
|
|
@@ -56,6 +58,7 @@ function createMockBookingService(config = {}) {
|
|
|
56
58
|
setFormSubmission: vitest_1.vi.fn(),
|
|
57
59
|
clearFormSubmission: vitest_1.vi.fn(),
|
|
58
60
|
setSelectedPaymentOption: vitest_1.vi.fn(),
|
|
61
|
+
setDepositSelected: vitest_1.vi.fn(),
|
|
59
62
|
setAllDay: vitest_1.vi.fn(),
|
|
60
63
|
clearAll: vitest_1.vi.fn(),
|
|
61
64
|
book: vitest_1.vi.fn(),
|
|
@@ -158,6 +158,19 @@ export declare function createLargeStaffMemberList(count: number): StaffMember[]
|
|
|
158
158
|
* Mock service with deposit configured
|
|
159
159
|
*/
|
|
160
160
|
export declare const mockServiceWithDeposit: Service;
|
|
161
|
+
/** Deposit set as a fixed amount under `depositDetails`, the newer field. */
|
|
162
|
+
export declare const mockServiceDepositDetailsAmount: Service;
|
|
163
|
+
/** Percentage deposit: `options.deposit` set, no amount anywhere on the entity. */
|
|
164
|
+
export declare const mockServicePercentageDeposit: Service;
|
|
165
|
+
/**
|
|
166
|
+
* Mock service with a deposit that may also be paid in full upfront — the only
|
|
167
|
+
* configuration where `booking.depositSelected` may be `false`.
|
|
168
|
+
*/
|
|
169
|
+
export declare const mockServiceWithDepositFullUpfront: Service;
|
|
170
|
+
/**
|
|
171
|
+
* Mock VARIED-rate service with a deposit (both under `payment.varied`).
|
|
172
|
+
*/
|
|
173
|
+
export declare const mockServiceVariedWithDeposit: Service;
|
|
161
174
|
/**
|
|
162
175
|
* Mock service with in-person payment option
|
|
163
176
|
*/
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Shared mock data for booking service tests
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.mockServiceInPerson = exports.mockServiceWithDeposit = exports.mockSingleStaffMemberListConfig = exports.mockEmptyStaffMemberListConfig = exports.mockStaffMemberListConfig = exports.mockStaffMembers = exports.mockStaffMemberNoName = exports.mockStaffMemberMinimal = exports.mockStaffMember2 = exports.mockStaffMember = exports.mockAvailabilityFilter = exports.mockAvailabilityPagingMetadataLast = exports.mockAvailabilityPagingMetadata = exports.mockServicesWithAvailability = exports.mockServiceListConfigWithCategories = exports.mockCategories = exports.mockServiceConfig = exports.mockEmptyServiceListConfig = exports.mockServiceListConfigWithMore = exports.mockServiceListConfig = exports.mockPagingMetadataEmpty = exports.mockPagingMetadataWithMore = exports.mockPagingMetadata = exports.mockServices = exports.mockServiceDayRange = exports.mockServiceHourRange = exports.mockServiceFixedDuration = exports.mockServiceMinimal = exports.mockServiceCourse = exports.mockServiceClass = exports.mockServiceNoFee = exports.mockServiceCustomPrice = exports.mockServiceVariedPrice = exports.mockService = void 0;
|
|
6
|
+
exports.mockServiceInPerson = exports.mockServiceVariedWithDeposit = exports.mockServiceWithDepositFullUpfront = exports.mockServicePercentageDeposit = exports.mockServiceDepositDetailsAmount = exports.mockServiceWithDeposit = exports.mockSingleStaffMemberListConfig = exports.mockEmptyStaffMemberListConfig = exports.mockStaffMemberListConfig = exports.mockStaffMembers = exports.mockStaffMemberNoName = exports.mockStaffMemberMinimal = exports.mockStaffMember2 = exports.mockStaffMember = exports.mockAvailabilityFilter = exports.mockAvailabilityPagingMetadataLast = exports.mockAvailabilityPagingMetadata = exports.mockServicesWithAvailability = exports.mockServiceListConfigWithCategories = exports.mockCategories = exports.mockServiceConfig = exports.mockEmptyServiceListConfig = exports.mockServiceListConfigWithMore = exports.mockServiceListConfig = exports.mockPagingMetadataEmpty = exports.mockPagingMetadataWithMore = exports.mockPagingMetadata = exports.mockServices = exports.mockServiceDayRange = exports.mockServiceHourRange = exports.mockServiceFixedDuration = exports.mockServiceMinimal = exports.mockServiceCourse = exports.mockServiceClass = exports.mockServiceNoFee = exports.mockServiceCustomPrice = exports.mockServiceVariedPrice = exports.mockService = void 0;
|
|
7
7
|
exports.createLargeServiceList = createLargeServiceList;
|
|
8
8
|
exports.createLargeStaffMemberList = createLargeStaffMemberList;
|
|
9
9
|
const auto_sdk_bookings_services_1 = require("@wix/auto_sdk_bookings_services");
|
|
@@ -540,6 +540,97 @@ exports.mockServiceWithDeposit = {
|
|
|
540
540
|
},
|
|
541
541
|
},
|
|
542
542
|
};
|
|
543
|
+
/** Deposit set as a fixed amount under `depositDetails`, the newer field. */
|
|
544
|
+
exports.mockServiceDepositDetailsAmount = {
|
|
545
|
+
...exports.mockService,
|
|
546
|
+
_id: 'test-service-deposit-details-amount',
|
|
547
|
+
name: 'Deposit Details Amount Service',
|
|
548
|
+
payment: {
|
|
549
|
+
rateType: auto_sdk_bookings_services_1.RateType.FIXED,
|
|
550
|
+
fixed: {
|
|
551
|
+
price: {
|
|
552
|
+
value: '100.00',
|
|
553
|
+
currency: 'USD',
|
|
554
|
+
},
|
|
555
|
+
depositDetails: {
|
|
556
|
+
amount: {
|
|
557
|
+
value: '25.00',
|
|
558
|
+
currency: 'USD',
|
|
559
|
+
},
|
|
560
|
+
},
|
|
561
|
+
},
|
|
562
|
+
options: {
|
|
563
|
+
online: true,
|
|
564
|
+
deposit: true,
|
|
565
|
+
},
|
|
566
|
+
},
|
|
567
|
+
};
|
|
568
|
+
/** Percentage deposit: `options.deposit` set, no amount anywhere on the entity. */
|
|
569
|
+
exports.mockServicePercentageDeposit = {
|
|
570
|
+
...exports.mockService,
|
|
571
|
+
_id: 'test-service-percentage-deposit',
|
|
572
|
+
name: 'Percentage Deposit Service',
|
|
573
|
+
payment: {
|
|
574
|
+
rateType: auto_sdk_bookings_services_1.RateType.FIXED,
|
|
575
|
+
fixed: {
|
|
576
|
+
price: {
|
|
577
|
+
value: '10',
|
|
578
|
+
currency: 'USD',
|
|
579
|
+
},
|
|
580
|
+
fullUpfrontPaymentAllowed: true,
|
|
581
|
+
},
|
|
582
|
+
options: {
|
|
583
|
+
online: true,
|
|
584
|
+
inPerson: false,
|
|
585
|
+
deposit: true,
|
|
586
|
+
},
|
|
587
|
+
},
|
|
588
|
+
};
|
|
589
|
+
/**
|
|
590
|
+
* Mock service with a deposit that may also be paid in full upfront — the only
|
|
591
|
+
* configuration where `booking.depositSelected` may be `false`.
|
|
592
|
+
*/
|
|
593
|
+
exports.mockServiceWithDepositFullUpfront = {
|
|
594
|
+
...exports.mockService,
|
|
595
|
+
_id: 'test-service-deposit-full-upfront',
|
|
596
|
+
name: 'Service with Deposit and Full Upfront Allowed',
|
|
597
|
+
payment: {
|
|
598
|
+
rateType: auto_sdk_bookings_services_1.RateType.FIXED,
|
|
599
|
+
fixed: {
|
|
600
|
+
price: {
|
|
601
|
+
value: '100.00',
|
|
602
|
+
currency: 'USD',
|
|
603
|
+
},
|
|
604
|
+
deposit: {
|
|
605
|
+
value: '30.00',
|
|
606
|
+
currency: 'USD',
|
|
607
|
+
},
|
|
608
|
+
fullUpfrontPaymentAllowed: true,
|
|
609
|
+
},
|
|
610
|
+
},
|
|
611
|
+
};
|
|
612
|
+
/**
|
|
613
|
+
* Mock VARIED-rate service with a deposit (both under `payment.varied`).
|
|
614
|
+
*/
|
|
615
|
+
exports.mockServiceVariedWithDeposit = {
|
|
616
|
+
...exports.mockService,
|
|
617
|
+
_id: 'test-service-varied-deposit',
|
|
618
|
+
name: 'Varied Service with Deposit',
|
|
619
|
+
payment: {
|
|
620
|
+
rateType: auto_sdk_bookings_services_1.RateType.VARIED,
|
|
621
|
+
varied: {
|
|
622
|
+
defaultPrice: {
|
|
623
|
+
value: '80.00',
|
|
624
|
+
currency: 'USD',
|
|
625
|
+
},
|
|
626
|
+
deposit: {
|
|
627
|
+
value: '20.00',
|
|
628
|
+
currency: 'USD',
|
|
629
|
+
},
|
|
630
|
+
fullUpfrontPaymentAllowed: true,
|
|
631
|
+
},
|
|
632
|
+
},
|
|
633
|
+
};
|
|
543
634
|
/**
|
|
544
635
|
* Mock service with in-person payment option
|
|
545
636
|
*/
|
|
@@ -45,6 +45,12 @@ export interface BookingData {
|
|
|
45
45
|
* heuristic applies. Set via `actions.setSelectedPaymentOption`.
|
|
46
46
|
*/
|
|
47
47
|
selectedPaymentOption: SelectedPaymentOption | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Deposit-vs-full-upfront choice. `true` pays only the deposit now, `false`
|
|
50
|
+
* pays the full price now, `undefined` means not chosen. Set via
|
|
51
|
+
* `actions.setDepositSelected`.
|
|
52
|
+
*/
|
|
53
|
+
depositSelected: boolean | undefined;
|
|
48
54
|
actions: BookingServiceActions;
|
|
49
55
|
}
|
|
50
56
|
/**
|
|
@@ -118,6 +118,7 @@ function Data(props) {
|
|
|
118
118
|
const timezone = bookingService.timezone.get();
|
|
119
119
|
const formSubmission = bookingService.formSubmission.get();
|
|
120
120
|
const selectedPaymentOption = bookingService.selectedPaymentOption.get();
|
|
121
|
+
const depositSelected = bookingService.depositSelected.get();
|
|
121
122
|
const { actions } = bookingService;
|
|
122
123
|
const location = resolveLocation(bookingLocation, serviceSelections);
|
|
123
124
|
return children({
|
|
@@ -126,6 +127,7 @@ function Data(props) {
|
|
|
126
127
|
timezone,
|
|
127
128
|
formSubmission,
|
|
128
129
|
selectedPaymentOption,
|
|
130
|
+
depositSelected,
|
|
129
131
|
actions,
|
|
130
132
|
});
|
|
131
133
|
}
|
|
@@ -172,7 +172,8 @@ export interface ServiceOptionsProps {
|
|
|
172
172
|
}
|
|
173
173
|
/**
|
|
174
174
|
* Core component that exposes service payment options via render props.
|
|
175
|
-
* Reads isOnline, isInPerson, isDeposit from the payment
|
|
175
|
+
* Reads isOnline, isInPerson, isDeposit, canPayFullUpfront from the payment
|
|
176
|
+
* service signal.
|
|
176
177
|
*
|
|
177
178
|
* @component
|
|
178
179
|
*/
|
|
@@ -93,10 +93,12 @@ function Data(props) {
|
|
|
93
93
|
const additionalInfoList = paymentDetails?.additionalInfo?.lineItems || [];
|
|
94
94
|
const firstLineItemInfo = additionalInfoList[0];
|
|
95
95
|
const customPrice = firstLineItemInfo?.customPrice || null;
|
|
96
|
-
// Computed flags
|
|
97
|
-
const hasTax = tax !== null && tax.amount > 0;
|
|
98
|
-
const hasDiscount = discount !== null && discount.amount > 0;
|
|
99
|
-
const isDeposit = payNow !== null &&
|
|
96
|
+
// Computed flags (amounts may be strings — compare numerically)
|
|
97
|
+
const hasTax = tax !== null && Number(tax.amount) > 0;
|
|
98
|
+
const hasDiscount = discount !== null && Number(discount.amount) > 0;
|
|
99
|
+
const isDeposit = payNow !== null &&
|
|
100
|
+
total !== null &&
|
|
101
|
+
Number(payNow.amount) < Number(total.amount);
|
|
100
102
|
return props.children({
|
|
101
103
|
subtotal,
|
|
102
104
|
total,
|
|
@@ -202,7 +204,8 @@ function LineItemProvider(props) {
|
|
|
202
204
|
}
|
|
203
205
|
/**
|
|
204
206
|
* Core component that exposes service payment options via render props.
|
|
205
|
-
* Reads isOnline, isInPerson, isDeposit from the payment
|
|
207
|
+
* Reads isOnline, isInPerson, isDeposit, canPayFullUpfront from the payment
|
|
208
|
+
* service signal.
|
|
206
209
|
*
|
|
207
210
|
* @component
|
|
208
211
|
*/
|
|
@@ -229,9 +232,9 @@ function ServiceOptions(props) {
|
|
|
229
232
|
*/
|
|
230
233
|
function LineItemInfo(props) {
|
|
231
234
|
const { lineItem, currency } = useLineItemContext();
|
|
232
|
-
// Computed flags
|
|
233
|
-
const hasDiscount = lineItem.discount !== null && lineItem.discount.amount > 0;
|
|
234
|
-
const hasDeposit = lineItem.deposit !== null && lineItem.deposit.amount > 0;
|
|
235
|
+
// Computed flags (amounts may be strings — compare numerically)
|
|
236
|
+
const hasDiscount = lineItem.discount !== null && Number(lineItem.discount.amount) > 0;
|
|
237
|
+
const hasDeposit = lineItem.deposit !== null && Number(lineItem.deposit.amount) > 0;
|
|
235
238
|
return props.children({
|
|
236
239
|
lineItem,
|
|
237
240
|
currency,
|
|
@@ -210,7 +210,8 @@ export interface ServiceOptionsProps {
|
|
|
210
210
|
*
|
|
211
211
|
* Payment scenarios:
|
|
212
212
|
* - `isOnline=true, isInPerson=false, isDeposit=false` → Pay now only (Due now = total)
|
|
213
|
-
* - `isOnline=true, isInPerson=false, isDeposit=true` → Pay now + security deposit
|
|
213
|
+
* - `isOnline=true, isInPerson=false, isDeposit=true, canPayFullUpfront=false` → Pay now + security deposit
|
|
214
|
+
* - `isOnline=true, isInPerson=false, isDeposit=true, canPayFullUpfront=true` → Radio: Pay deposit now / Pay in full now
|
|
214
215
|
* - `isOnline=true, isInPerson=true` → Radio: Pay Online / Pay on Arrival
|
|
215
216
|
* - `isOnline=false, isInPerson=true` → Pay on arrival only
|
|
216
217
|
*
|
|
@@ -223,7 +224,7 @@ export interface ServiceOptionsProps {
|
|
|
223
224
|
* @example
|
|
224
225
|
* ```tsx
|
|
225
226
|
* <Payment.ServiceOptions asChild>
|
|
226
|
-
* {({ isOnline, isInPerson, isDeposit }) => (
|
|
227
|
+
* {({ isOnline, isInPerson, isDeposit, canPayFullUpfront }) => (
|
|
227
228
|
* // render the correct payment scenario
|
|
228
229
|
* )}
|
|
229
230
|
* </Payment.ServiceOptions>
|
|
@@ -183,7 +183,7 @@ exports.Total.displayName = 'Payment.Total';
|
|
|
183
183
|
*/
|
|
184
184
|
exports.PayNow = react_1.default.forwardRef((props, ref) => {
|
|
185
185
|
const { asChild, children, className } = props;
|
|
186
|
-
return ((0, jsx_runtime_1.jsx)(CorePayment.Data, { children: ({ payNow, isDeposit }) => ((0, jsx_runtime_1.jsx)(react_2.AsChildSlot, { ref: ref, asChild: asChild, className: className, customElement: children, customElementProps: { payNow, isDeposit }, "data-testid": exports.TestIds.paymentPayNow, "data-has-deposit": isDeposit, children: isDeposit && payNow && payNow.amount > 0 && ((0, jsx_runtime_1.jsx)(react_3.Money, { money: payNow })) })) }));
|
|
186
|
+
return ((0, jsx_runtime_1.jsx)(CorePayment.Data, { children: ({ payNow, isDeposit }) => ((0, jsx_runtime_1.jsx)(react_2.AsChildSlot, { ref: ref, asChild: asChild, className: className, customElement: children, customElementProps: { payNow, isDeposit }, "data-testid": exports.TestIds.paymentPayNow, "data-has-deposit": isDeposit, children: isDeposit && payNow && Number(payNow.amount) > 0 && ((0, jsx_runtime_1.jsx)(react_3.Money, { money: payNow })) })) }));
|
|
187
187
|
});
|
|
188
188
|
exports.PayNow.displayName = 'Payment.PayNow';
|
|
189
189
|
/**
|
|
@@ -198,7 +198,7 @@ exports.PayNow.displayName = 'Payment.PayNow';
|
|
|
198
198
|
*/
|
|
199
199
|
exports.PayLater = react_1.default.forwardRef((props, ref) => {
|
|
200
200
|
const { asChild, children, className } = props;
|
|
201
|
-
return ((0, jsx_runtime_1.jsx)(CorePayment.Data, { children: ({ payLater, isDeposit }) => ((0, jsx_runtime_1.jsx)(react_2.AsChildSlot, { ref: ref, asChild: asChild, className: className, customElement: children, customElementProps: { payLater, isDeposit }, "data-testid": exports.TestIds.paymentPayLater, "data-has-deposit": isDeposit, children: isDeposit && payLater && payLater.amount > 0 && ((0, jsx_runtime_1.jsx)(react_3.Money, { money: payLater })) })) }));
|
|
201
|
+
return ((0, jsx_runtime_1.jsx)(CorePayment.Data, { children: ({ payLater, isDeposit }) => ((0, jsx_runtime_1.jsx)(react_2.AsChildSlot, { ref: ref, asChild: asChild, className: className, customElement: children, customElementProps: { payLater, isDeposit }, "data-testid": exports.TestIds.paymentPayLater, "data-has-deposit": isDeposit, children: isDeposit && payLater && Number(payLater.amount) > 0 && ((0, jsx_runtime_1.jsx)(react_3.Money, { money: payLater })) })) }));
|
|
202
202
|
});
|
|
203
203
|
exports.PayLater.displayName = 'Payment.PayLater';
|
|
204
204
|
/**
|
|
@@ -207,7 +207,8 @@ exports.PayLater.displayName = 'Payment.PayLater';
|
|
|
207
207
|
*
|
|
208
208
|
* Payment scenarios:
|
|
209
209
|
* - `isOnline=true, isInPerson=false, isDeposit=false` → Pay now only (Due now = total)
|
|
210
|
-
* - `isOnline=true, isInPerson=false, isDeposit=true` → Pay now + security deposit
|
|
210
|
+
* - `isOnline=true, isInPerson=false, isDeposit=true, canPayFullUpfront=false` → Pay now + security deposit
|
|
211
|
+
* - `isOnline=true, isInPerson=false, isDeposit=true, canPayFullUpfront=true` → Radio: Pay deposit now / Pay in full now
|
|
211
212
|
* - `isOnline=true, isInPerson=true` → Radio: Pay Online / Pay on Arrival
|
|
212
213
|
* - `isOnline=false, isInPerson=true` → Pay on arrival only
|
|
213
214
|
*
|
|
@@ -220,7 +221,7 @@ exports.PayLater.displayName = 'Payment.PayLater';
|
|
|
220
221
|
* @example
|
|
221
222
|
* ```tsx
|
|
222
223
|
* <Payment.ServiceOptions asChild>
|
|
223
|
-
* {({ isOnline, isInPerson, isDeposit }) => (
|
|
224
|
+
* {({ isOnline, isInPerson, isDeposit, canPayFullUpfront }) => (
|
|
224
225
|
* // render the correct payment scenario
|
|
225
226
|
* )}
|
|
226
227
|
* </Payment.ServiceOptions>
|
|
@@ -228,7 +229,12 @@ exports.PayLater.displayName = 'Payment.PayLater';
|
|
|
228
229
|
*/
|
|
229
230
|
exports.ServiceOptions = react_1.default.forwardRef((props, ref) => {
|
|
230
231
|
const { asChild, children } = props;
|
|
231
|
-
return ((0, jsx_runtime_1.jsx)(CorePayment.ServiceOptions, { children: ({ isOnline, isInPerson, isDeposit }) => ((0, jsx_runtime_1.jsx)(react_2.AsChildSlot, { ref: ref, asChild: asChild, customElement: children, customElementProps: {
|
|
232
|
+
return ((0, jsx_runtime_1.jsx)(CorePayment.ServiceOptions, { children: ({ isOnline, isInPerson, isDeposit, canPayFullUpfront }) => ((0, jsx_runtime_1.jsx)(react_2.AsChildSlot, { ref: ref, asChild: asChild, customElement: children, customElementProps: {
|
|
233
|
+
isOnline,
|
|
234
|
+
isInPerson,
|
|
235
|
+
isDeposit,
|
|
236
|
+
canPayFullUpfront,
|
|
237
|
+
}, "data-testid": exports.TestIds.paymentServiceOptions, "data-is-online": isOnline, "data-is-in-person": isInPerson, "data-is-deposit": isDeposit, "data-can-pay-full-upfront": canPayFullUpfront, children: null })) }));
|
|
232
238
|
});
|
|
233
239
|
exports.ServiceOptions.displayName = 'Payment.ServiceOptions';
|
|
234
240
|
/**
|
|
@@ -7,6 +7,7 @@ exports.buildBookingRequest = buildBookingRequest;
|
|
|
7
7
|
const auto_sdk_bookings_availability_time_slots_1 = require("@wix/auto_sdk_bookings_availability-time-slots");
|
|
8
8
|
const auto_sdk_bookings_bookings_1 = require("@wix/auto_sdk_bookings_bookings");
|
|
9
9
|
const constants_js_1 = require("../../constants.js");
|
|
10
|
+
const servicePayment_js_1 = require("../../servicePayment.js");
|
|
10
11
|
/**
|
|
11
12
|
* Derives the selected payment option from service payment settings.
|
|
12
13
|
* Maps service.payment.options to booking API's selectedPaymentOption.
|
|
@@ -56,12 +57,20 @@ function buildBookingRequest(params) {
|
|
|
56
57
|
const resource = item.timeSlot.resources?.[0] ?? item.resources?.[0];
|
|
57
58
|
// Get location: prefer timeSlot.location, fallback to params.location
|
|
58
59
|
const slotLocation = item.timeSlot.location ?? location;
|
|
60
|
+
// Consumer override (if set) wins over the service-config heuristic.
|
|
61
|
+
const selectedPaymentOption = params.selectedPaymentOption ?? deriveSelectedPaymentOption(item.service);
|
|
62
|
+
// The only state where the schema allows `false`. Outside it, omitting the key
|
|
63
|
+
// leaves the server default in place.
|
|
64
|
+
const depositSelectedApplies = params.depositSelected !== undefined &&
|
|
65
|
+
selectedPaymentOption === 'ONLINE' &&
|
|
66
|
+
(0, servicePayment_js_1.requiresDeposit)(item.service) &&
|
|
67
|
+
(0, servicePayment_js_1.isFullUpfrontPaymentAllowed)(item.service);
|
|
59
68
|
return {
|
|
60
69
|
booking: {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
70
|
+
selectedPaymentOption,
|
|
71
|
+
...(depositSelectedApplies && {
|
|
72
|
+
depositSelected: params.depositSelected,
|
|
73
|
+
}),
|
|
65
74
|
// Participants
|
|
66
75
|
totalParticipants: item.totalParticipants || 1,
|
|
67
76
|
// App that created the booking (used to filter bookings by source app).
|
|
@@ -59,6 +59,12 @@ export interface BookActionParams {
|
|
|
59
59
|
* service. When omitted, the existing service-config heuristic applies.
|
|
60
60
|
*/
|
|
61
61
|
selectedPaymentOption?: SelectedPaymentOption;
|
|
62
|
+
/**
|
|
63
|
+
* Optional consumer choice: `true` pays only the deposit now, `false` pays the
|
|
64
|
+
* full price now. Dropped unless the booking is ONLINE and the service has a
|
|
65
|
+
* deposit with `fullUpfrontPaymentAllowed`. Omit to keep the server default.
|
|
66
|
+
*/
|
|
67
|
+
depositSelected?: boolean;
|
|
62
68
|
/**
|
|
63
69
|
* DAY-range only. When `true`, the picked per-day slots are collapsed into a
|
|
64
70
|
* single Booking spanning the whole range (`firstSlot.startDate ->
|
|
@@ -89,6 +89,12 @@ export interface BookingServiceActions {
|
|
|
89
89
|
* is cleared and the heuristic applies again.
|
|
90
90
|
*/
|
|
91
91
|
setSelectedPaymentOption(value: SelectedPaymentOption | null): void;
|
|
92
|
+
/**
|
|
93
|
+
* Set (or clear with `undefined`) the deposit-vs-full-upfront choice. `true`
|
|
94
|
+
* charges only the deposit now, `false` charges the full price now. Gate the UI
|
|
95
|
+
* on `Payment.ServiceOptions`' `isDeposit && canPayFullUpfront`.
|
|
96
|
+
*/
|
|
97
|
+
setDepositSelected(value: boolean | undefined): void;
|
|
92
98
|
/**
|
|
93
99
|
* Toggle the DAY-range `allDay` flag. When `true`, `book()` collapses the
|
|
94
100
|
* picked per-day slots into one range-spanning Booking created via
|
|
@@ -117,6 +123,12 @@ export interface BookingService {
|
|
|
117
123
|
* service-config heuristic. Set to `'ONLINE'` or `'OFFLINE'` to override.
|
|
118
124
|
*/
|
|
119
125
|
selectedPaymentOption: Signal<SelectedPaymentOption | undefined>;
|
|
126
|
+
/**
|
|
127
|
+
* Signal containing the deposit-vs-full-upfront choice. `true` pays only the
|
|
128
|
+
* deposit now, `false` pays the full price now. `undefined` means "not chosen"
|
|
129
|
+
* — `book()` omits the field and the preview keeps its deposit default.
|
|
130
|
+
*/
|
|
131
|
+
depositSelected: Signal<boolean | undefined>;
|
|
120
132
|
/** Actions for modifying booking state */
|
|
121
133
|
actions: BookingServiceActions;
|
|
122
134
|
}
|
|
@@ -146,6 +158,11 @@ export interface BookingServiceConfig {
|
|
|
146
158
|
* service-config heuristic; set to `'ONLINE'` or `'OFFLINE'` to override.
|
|
147
159
|
*/
|
|
148
160
|
selectedPaymentOption?: SelectedPaymentOption;
|
|
161
|
+
/**
|
|
162
|
+
* Optional initial deposit-vs-full-upfront choice. Omit to keep the server's
|
|
163
|
+
* default.
|
|
164
|
+
*/
|
|
165
|
+
depositSelected?: boolean;
|
|
149
166
|
/** Optional app ID override for the catalog reference. Defaults to the bookings app ID. */
|
|
150
167
|
appId?: string;
|
|
151
168
|
/**
|
|
@@ -74,6 +74,7 @@ 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
|
+
const depositSelectedSignal = signalsService.signal(config.depositSelected);
|
|
77
78
|
// Internal-only signal: set via `setAllDay`, read by `book()`. Not
|
|
78
79
|
// exposed on the service surface — consumers derive and push the value
|
|
79
80
|
// (e.g. from the picker's selection mode), so there's no read-back.
|
|
@@ -176,6 +177,10 @@ exports.BookingService = services_definitions_1.implementService.withConfig()(ex
|
|
|
176
177
|
setSelectedPaymentOption(value) {
|
|
177
178
|
selectedPaymentOptionSignal.set(value ?? undefined);
|
|
178
179
|
},
|
|
180
|
+
// Deposit vs full upfront action
|
|
181
|
+
setDepositSelected(value) {
|
|
182
|
+
depositSelectedSignal.set(value);
|
|
183
|
+
},
|
|
179
184
|
// All-day (DAY-range) action
|
|
180
185
|
setAllDay(value) {
|
|
181
186
|
allDaySignal.set(value);
|
|
@@ -195,6 +200,7 @@ exports.BookingService = services_definitions_1.implementService.withConfig()(ex
|
|
|
195
200
|
const location = locationSignal.get();
|
|
196
201
|
const timezone = timezoneSignal.get();
|
|
197
202
|
const selectedPaymentOption = selectedPaymentOptionSignal.get();
|
|
203
|
+
const depositSelected = depositSelectedSignal.get();
|
|
198
204
|
const allDay = allDaySignal.get();
|
|
199
205
|
// Validation happens inside executeBookAction
|
|
200
206
|
return (0, bookAction_js_1.executeBookAction)({
|
|
@@ -205,6 +211,7 @@ exports.BookingService = services_definitions_1.implementService.withConfig()(ex
|
|
|
205
211
|
appId: config.appId,
|
|
206
212
|
sourceAppId: config.sourceAppId,
|
|
207
213
|
selectedPaymentOption,
|
|
214
|
+
depositSelected,
|
|
208
215
|
allDay,
|
|
209
216
|
});
|
|
210
217
|
},
|
|
@@ -215,6 +222,7 @@ exports.BookingService = services_definitions_1.implementService.withConfig()(ex
|
|
|
215
222
|
timezone: timezoneSignal,
|
|
216
223
|
formSubmission: formSubmissionSignal,
|
|
217
224
|
selectedPaymentOption: selectedPaymentOptionSignal,
|
|
225
|
+
depositSelected: depositSelectedSignal,
|
|
218
226
|
actions,
|
|
219
227
|
};
|
|
220
228
|
});
|
|
@@ -28,9 +28,12 @@ export type ErrorPaymentConfigResult = {
|
|
|
28
28
|
* @param params.totalParticipants - Number of participants (default: 1)
|
|
29
29
|
* @param params.selectedPaymentOption - Optional consumer-selected payment option;
|
|
30
30
|
* overrides the service-config heuristic on each line item's `paymentOption`.
|
|
31
|
+
* @param params.depositSelected - Optional deposit-vs-full-upfront choice; `false`
|
|
32
|
+
* resolves a deposit service to full payment. Omit to keep the deposit default.
|
|
31
33
|
*/
|
|
32
34
|
export declare function loadPaymentConfig(params: {
|
|
33
35
|
pricingServiceSelections: PricingServiceSelection[];
|
|
34
36
|
totalParticipants?: number;
|
|
35
37
|
selectedPaymentOption?: SelectedPaymentOption;
|
|
38
|
+
depositSelected?: boolean;
|
|
36
39
|
}): Promise<SuccessPaymentConfigResult | ErrorPaymentConfigResult>;
|
|
@@ -16,8 +16,17 @@ export interface ServicePaymentOptions {
|
|
|
16
16
|
isOnline: boolean;
|
|
17
17
|
/** Customer can pay in person (on arrival) */
|
|
18
18
|
isInPerson: boolean;
|
|
19
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* A deposit is required at booking time — including percentage deposits, which
|
|
21
|
+
* set no amount. For the amount use `Payment.PayNow` / `Payment.PayLater`.
|
|
22
|
+
*/
|
|
20
23
|
isDeposit: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Customers may pay the full price upfront instead of only the deposit.
|
|
26
|
+
* Meaningful only with `isDeposit`; together they gate the
|
|
27
|
+
* deposit-vs-pay-in-full toggle.
|
|
28
|
+
*/
|
|
29
|
+
canPayFullUpfront: boolean;
|
|
21
30
|
}
|
|
22
31
|
/**
|
|
23
32
|
* Payment option for line items
|
|
@@ -83,6 +92,11 @@ export interface PaymentServiceInternalConfig extends PaymentServiceConfig {
|
|
|
83
92
|
* set, overrides the service-config heuristic in line item `paymentOption`.
|
|
84
93
|
*/
|
|
85
94
|
selectedPaymentOption?: SelectedPaymentOption;
|
|
95
|
+
/**
|
|
96
|
+
* Deposit-vs-full-upfront choice for lazy loading. `false` resolves a deposit
|
|
97
|
+
* service to full payment instead of `DEPOSIT_ONLINE`.
|
|
98
|
+
*/
|
|
99
|
+
depositSelected?: boolean;
|
|
86
100
|
}
|
|
87
101
|
export interface PaymentServiceAPI {
|
|
88
102
|
paymentDetailsSignal: Signal<PaymentDetails | null>;
|