@wix/headless-bookings 0.0.57 → 0.0.59
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.d.ts +4 -5
- package/cjs/dist/__mocks__/booking.js +6 -3
- package/cjs/dist/react/booking/Booking.js +1 -1
- package/cjs/dist/react/core/booking/Booking.d.ts +3 -3
- package/cjs/dist/react/core/booking/Booking.js +2 -2
- package/cjs/dist/react/core/payment/Payment.d.ts +84 -5
- package/cjs/dist/react/core/payment/Payment.js +102 -4
- package/cjs/dist/react/core/staff-member/StaffMember.js +2 -1
- package/cjs/dist/react/payment/Payment.d.ts +64 -58
- package/cjs/dist/react/payment/Payment.js +66 -80
- package/cjs/dist/react/staff-member/StaffMemberList.js +1 -1
- package/cjs/dist/services/booking/booking.d.ts +15 -8
- package/cjs/dist/services/booking/booking.js +8 -16
- package/cjs/dist/services/index.d.ts +1 -1
- package/cjs/dist/services/payment/payment.d.ts +4 -4
- package/cjs/dist/services/payment/payment.def.d.ts +4 -4
- package/cjs/dist/services/payment/payment.js +26 -18
- package/cjs/dist/services/time-slot-list/time-slot-list.js +1 -1
- package/dist/__mocks__/booking.d.ts +4 -5
- package/dist/__mocks__/booking.js +6 -3
- package/dist/react/booking/Booking.js +1 -1
- package/dist/react/core/booking/Booking.d.ts +3 -3
- package/dist/react/core/booking/Booking.js +2 -2
- package/dist/react/core/payment/Payment.d.ts +84 -5
- package/dist/react/core/payment/Payment.js +102 -4
- package/dist/react/core/staff-member/StaffMember.js +2 -1
- package/dist/react/payment/Payment.d.ts +64 -58
- package/dist/react/payment/Payment.js +66 -80
- package/dist/react/staff-member/StaffMemberList.js +1 -1
- package/dist/services/booking/booking.d.ts +15 -8
- package/dist/services/booking/booking.js +8 -16
- package/dist/services/index.d.ts +1 -1
- package/dist/services/payment/payment.d.ts +4 -4
- package/dist/services/payment/payment.def.d.ts +4 -4
- package/dist/services/payment/payment.js +26 -18
- package/dist/services/time-slot-list/time-slot-list.js +1 -1
- package/package.json +2 -2
|
@@ -19,8 +19,8 @@ var TestIds;
|
|
|
19
19
|
TestIds["paymentLineItems"] = "payment-line-items";
|
|
20
20
|
TestIds["paymentLineItemsList"] = "payment-line-items-list";
|
|
21
21
|
TestIds["paymentLineItemRepeater"] = "payment-line-item-repeater";
|
|
22
|
-
TestIds["
|
|
23
|
-
TestIds["
|
|
22
|
+
TestIds["paymentLineItemTotal"] = "payment-line-item-total";
|
|
23
|
+
TestIds["paymentLineItemSubtotal"] = "payment-line-item-subtotal";
|
|
24
24
|
TestIds["paymentLineItemDiscount"] = "payment-line-item-discount";
|
|
25
25
|
TestIds["paymentLineItemDeposit"] = "payment-line-item-deposit";
|
|
26
26
|
})(TestIds || (TestIds = {}));
|
|
@@ -28,7 +28,7 @@ var TestIds;
|
|
|
28
28
|
* Root component that provides payment context to the entire app.
|
|
29
29
|
* Supports 3 modes:
|
|
30
30
|
* 1. SSR: paymentServiceConfig.paymentDetails - pre-fetched data
|
|
31
|
-
* 2. Lazy loading:
|
|
31
|
+
* 2. Lazy loading: pricingServiceSelections + numberOfParticipants props - calls API via useEffect
|
|
32
32
|
* 3. Reactive: no config/props - reads from BookingService signals
|
|
33
33
|
*
|
|
34
34
|
* @order 1
|
|
@@ -57,24 +57,36 @@ var TestIds;
|
|
|
57
57
|
* ```
|
|
58
58
|
*/
|
|
59
59
|
export const Root = React.forwardRef((props, ref) => {
|
|
60
|
-
const { children, paymentServiceConfig,
|
|
61
|
-
return (_jsx(CorePayment.Root, { paymentServiceConfig: paymentServiceConfig,
|
|
60
|
+
const { children, paymentServiceConfig, pricingServiceSelections, numberOfParticipants, asChild, className, ...attrs } = props;
|
|
61
|
+
return (_jsx(CorePayment.Root, { paymentServiceConfig: paymentServiceConfig, pricingServiceSelections: pricingServiceSelections, numberOfParticipants: numberOfParticipants, children: ({ isLoading, hasError }) => {
|
|
62
62
|
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentRoot, "data-loading": isLoading, "data-has-error": hasError, customElement: children, customElementProps: { isLoading, hasError }, ...attrs, children: children }));
|
|
63
63
|
} }));
|
|
64
64
|
});
|
|
65
65
|
Root.displayName = 'Payment.Root';
|
|
66
66
|
/**
|
|
67
67
|
* Displays the payment subtotal.
|
|
68
|
+
* Always displays the monetary value but exposes priceText, hasPriceText, and isFree for custom rendering.
|
|
68
69
|
*
|
|
69
70
|
* @component
|
|
70
71
|
* @example
|
|
71
72
|
* ```tsx
|
|
72
73
|
* <Payment.Subtotal className="text-lg" />
|
|
73
74
|
* ```
|
|
75
|
+
* @example
|
|
76
|
+
* ```tsx
|
|
77
|
+
* <Payment.Subtotal asChild>
|
|
78
|
+
* {({ subtotal, priceText, hasPriceText, isFree }) => (
|
|
79
|
+
* <div>
|
|
80
|
+
* <Money money={subtotal} />
|
|
81
|
+
* {hasPriceText && <span className="text-sm">({priceText})</span>}
|
|
82
|
+
* </div>
|
|
83
|
+
* )}
|
|
84
|
+
* </Payment.Subtotal>
|
|
85
|
+
* ```
|
|
74
86
|
*/
|
|
75
87
|
export const Subtotal = React.forwardRef((props, ref) => {
|
|
76
88
|
const { asChild, children, className } = props;
|
|
77
|
-
return (_jsx(CorePayment.Data, { children: ({ subtotal }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentSubtotal, customElement: children, customElementProps: { subtotal }, children: subtotal
|
|
89
|
+
return (_jsx(CorePayment.Data, { children: ({ subtotal, priceText, hasPriceText, isFree }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentSubtotal, "data-has-price-text": hasPriceText, "data-is-free": isFree, customElement: children, customElementProps: { subtotal, priceText, hasPriceText, isFree }, children: subtotal && _jsx(Money, { money: subtotal }) })) }));
|
|
78
90
|
});
|
|
79
91
|
Subtotal.displayName = 'Payment.Subtotal';
|
|
80
92
|
/**
|
|
@@ -89,10 +101,7 @@ Subtotal.displayName = 'Payment.Subtotal';
|
|
|
89
101
|
*/
|
|
90
102
|
export const Tax = React.forwardRef((props, ref) => {
|
|
91
103
|
const { asChild, children, className } = props;
|
|
92
|
-
return (_jsx(CorePayment.Data, { children: ({ tax }) => {
|
|
93
|
-
const hasTax = tax !== null && tax.amount > 0;
|
|
94
|
-
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentTax, "data-has-tax": hasTax, customElement: children, customElementProps: { tax }, children: tax ? _jsx(Money, { money: tax }) : null }));
|
|
95
|
-
} }));
|
|
104
|
+
return (_jsx(CorePayment.Data, { children: ({ tax, hasTax }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentTax, "data-has-tax": hasTax, customElement: children, customElementProps: { tax }, children: hasTax && _jsx(Money, { money: tax }) })) }));
|
|
96
105
|
});
|
|
97
106
|
Tax.displayName = 'Payment.Tax';
|
|
98
107
|
/**
|
|
@@ -107,24 +116,37 @@ Tax.displayName = 'Payment.Tax';
|
|
|
107
116
|
*/
|
|
108
117
|
export const Discount = React.forwardRef((props, ref) => {
|
|
109
118
|
const { asChild, children, className } = props;
|
|
110
|
-
return (_jsx(CorePayment.Data, { children: ({ discount }) => {
|
|
111
|
-
const hasDiscount = discount !== null && discount.amount > 0;
|
|
112
|
-
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentDiscount, "data-has-discount": hasDiscount, customElement: children, customElementProps: { discount }, children: discount ? _jsx(Money, { money: discount }) : null }));
|
|
113
|
-
} }));
|
|
119
|
+
return (_jsx(CorePayment.Data, { children: ({ discount, hasDiscount }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentDiscount, "data-has-discount": hasDiscount, customElement: children, customElementProps: { discount }, children: hasDiscount && _jsx(Money, { money: discount }) })) }));
|
|
114
120
|
});
|
|
115
121
|
Discount.displayName = 'Payment.Discount';
|
|
116
122
|
/**
|
|
117
123
|
* Displays the payment total.
|
|
124
|
+
* Always displays the monetary value but exposes priceText, hasPriceText, and isFree for custom rendering.
|
|
118
125
|
*
|
|
119
126
|
* @component
|
|
120
127
|
* @example
|
|
121
128
|
* ```tsx
|
|
122
129
|
* <Payment.Total className="text-2xl font-bold" />
|
|
123
130
|
* ```
|
|
131
|
+
* @example
|
|
132
|
+
* ```tsx
|
|
133
|
+
* <Payment.Total asChild>
|
|
134
|
+
* {({ total, priceText, hasPriceText, isFree }) => (
|
|
135
|
+
* <div>
|
|
136
|
+
* {isFree ? (
|
|
137
|
+
* <span className="text-green-500">Free</span>
|
|
138
|
+
* ) : (
|
|
139
|
+
* <Money money={total} />
|
|
140
|
+
* )}
|
|
141
|
+
* {hasPriceText && <span className="text-sm">({priceText})</span>}
|
|
142
|
+
* </div>
|
|
143
|
+
* )}
|
|
144
|
+
* </Payment.Total>
|
|
145
|
+
* ```
|
|
124
146
|
*/
|
|
125
147
|
export const Total = React.forwardRef((props, ref) => {
|
|
126
148
|
const { asChild, children, className } = props;
|
|
127
|
-
return (_jsx(CorePayment.Data, { children: ({ total }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentTotal, customElement: children, customElementProps: { total }, children: total
|
|
149
|
+
return (_jsx(CorePayment.Data, { children: ({ total, priceText, hasPriceText, isFree }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentTotal, "data-has-price-text": hasPriceText, "data-is-free": isFree, customElement: children, customElementProps: { total, priceText, hasPriceText, isFree }, children: total && _jsx(Money, { money: total }) })) }));
|
|
128
150
|
});
|
|
129
151
|
Total.displayName = 'Payment.Total';
|
|
130
152
|
/**
|
|
@@ -139,10 +161,7 @@ Total.displayName = 'Payment.Total';
|
|
|
139
161
|
*/
|
|
140
162
|
export const PayNow = React.forwardRef((props, ref) => {
|
|
141
163
|
const { asChild, children, className } = props;
|
|
142
|
-
return (_jsx(CorePayment.Data, { children: ({ payNow,
|
|
143
|
-
const isDeposit = payNow !== null && total !== null && payNow.amount < total.amount;
|
|
144
|
-
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentPayNow, "data-has-deposit": isDeposit, customElement: children, customElementProps: { payNow }, children: payNow ? _jsx(Money, { money: payNow }) : null }));
|
|
145
|
-
} }));
|
|
164
|
+
return (_jsx(CorePayment.Data, { children: ({ payNow, isDeposit }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentPayNow, "data-has-deposit": isDeposit, customElement: children, customElementProps: { payNow }, children: payNow && payNow.amount > 0 && _jsx(Money, { money: payNow }) })) }));
|
|
146
165
|
});
|
|
147
166
|
PayNow.displayName = 'Payment.PayNow';
|
|
148
167
|
/**
|
|
@@ -157,10 +176,7 @@ PayNow.displayName = 'Payment.PayNow';
|
|
|
157
176
|
*/
|
|
158
177
|
export const PayLater = React.forwardRef((props, ref) => {
|
|
159
178
|
const { asChild, children, className } = props;
|
|
160
|
-
return (_jsx(CorePayment.Data, { children: ({ payLater,
|
|
161
|
-
const isDeposit = payNow !== null && total !== null && payNow.amount < total.amount;
|
|
162
|
-
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentPayLater, "data-has-deposit": isDeposit, customElement: children, customElementProps: { payLater }, children: payLater ? _jsx(Money, { money: payLater }) : null }));
|
|
163
|
-
} }));
|
|
179
|
+
return (_jsx(CorePayment.Data, { children: ({ payLater, isDeposit }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentPayLater, "data-has-deposit": isDeposit, customElement: children, customElementProps: { payLater }, children: payLater && payLater.amount > 0 && _jsx(Money, { money: payLater }) })) }));
|
|
164
180
|
});
|
|
165
181
|
PayLater.displayName = 'Payment.PayLater';
|
|
166
182
|
/**
|
|
@@ -219,84 +235,60 @@ export const LineItemsList = React.forwardRef((props, ref) => {
|
|
|
219
235
|
});
|
|
220
236
|
LineItemsList.displayName = 'Payment.LineItemsList';
|
|
221
237
|
/**
|
|
222
|
-
*
|
|
223
|
-
|
|
238
|
+
* Internal component that wraps each line item with context provider.
|
|
239
|
+
*/
|
|
240
|
+
const LineItemWrapper = ({ item, currency, children, }) => {
|
|
241
|
+
return (_jsx(CorePayment.LineItemProvider, { lineItem: item, currency: currency, children: children }));
|
|
242
|
+
};
|
|
243
|
+
/**
|
|
244
|
+
* Repeater component that maps over line items and provides context per item.
|
|
245
|
+
* Uses GenericList.Repeater internally with itemWrapper that provides LineItemContext.
|
|
224
246
|
*
|
|
225
247
|
* @component
|
|
226
248
|
* @example
|
|
227
249
|
* ```tsx
|
|
228
|
-
* // Standard usage
|
|
229
250
|
* <Payment.LineItemRepeater>
|
|
230
|
-
* <Payment.
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
* // AsChild usage with custom list
|
|
234
|
-
* <Payment.LineItemRepeater asChild>
|
|
235
|
-
* {({ items, itemWrapper }) => (
|
|
236
|
-
* <ol>
|
|
237
|
-
* {items.map((item, index) => (
|
|
238
|
-
* <li key={item.id}>
|
|
239
|
-
* {itemWrapper({ item, index, children: <Payment.LineItemPrice /> })}
|
|
240
|
-
* </li>
|
|
241
|
-
* ))}
|
|
242
|
-
* </ol>
|
|
243
|
-
* )}
|
|
251
|
+
* <Payment.LineItemTotal />
|
|
252
|
+
* <Payment.LineItemDiscount />
|
|
244
253
|
* </Payment.LineItemRepeater>
|
|
245
254
|
* ```
|
|
246
255
|
*/
|
|
247
256
|
export const LineItemRepeater = React.forwardRef((props, ref) => {
|
|
248
|
-
const { children
|
|
257
|
+
const { children } = props;
|
|
249
258
|
const { currency } = useLineItemsContext();
|
|
250
|
-
|
|
251
|
-
const lineItemWrapper = ({ item, children: itemChildren, }) => {
|
|
252
|
-
return (_jsx(LineItemRoot, { lineItem: item, currency: currency, "data-testid": TestIds.paymentLineItemRepeater, children: itemChildren || undefined }, item.id));
|
|
253
|
-
};
|
|
254
|
-
return (_jsx(GenericList.Repeater, { ref: ref, itemWrapper: lineItemWrapper, asChild: asChild, children: children }));
|
|
259
|
+
return (_jsx(GenericList.Repeater, { ref: ref, itemWrapper: ({ item }) => (_jsx(LineItemWrapper, { item: item, currency: currency, children: children }, item.id)), children: undefined }));
|
|
255
260
|
});
|
|
256
261
|
LineItemRepeater.displayName = 'Payment.LineItemRepeater';
|
|
257
|
-
const LineItemContext = React.createContext(null);
|
|
258
|
-
function useLineItemContext() {
|
|
259
|
-
const context = React.useContext(LineItemContext);
|
|
260
|
-
if (!context) {
|
|
261
|
-
throw new Error('useLineItemContext must be used within a Payment.LineItemRoot component');
|
|
262
|
-
}
|
|
263
|
-
return context;
|
|
264
|
-
}
|
|
265
262
|
/**
|
|
266
|
-
*
|
|
267
|
-
*
|
|
263
|
+
* Displays the line item total (total price after tax).
|
|
264
|
+
* Shows priceText for CUSTOM rate type services, otherwise shows totalPrice.
|
|
268
265
|
*
|
|
269
266
|
* @component
|
|
270
267
|
* @example
|
|
271
268
|
* ```tsx
|
|
272
|
-
* <Payment.
|
|
273
|
-
* <Payment.LineItemPrice />
|
|
274
|
-
* <Payment.LineItemDiscount />
|
|
275
|
-
* </Payment.LineItemRoot>
|
|
269
|
+
* <Payment.LineItemTotal className="text-2xl font-bold" />
|
|
276
270
|
* ```
|
|
277
271
|
*/
|
|
278
|
-
export const
|
|
279
|
-
const {
|
|
280
|
-
return (_jsx(
|
|
272
|
+
export const LineItemTotal = React.forwardRef((props, ref) => {
|
|
273
|
+
const { asChild, children, className } = props;
|
|
274
|
+
return (_jsx(CorePayment.LineItemInfo, { children: ({ totalPrice, priceText, hasPriceText, isFree }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentLineItemTotal, "data-has-price-text": hasPriceText, "data-is-free": isFree, customElement: children, customElementProps: { totalPrice, priceText, hasPriceText, isFree }, children: priceText ? (_jsx("span", { children: priceText })) : (totalPrice && _jsx(Money, { money: totalPrice })) })) }));
|
|
281
275
|
});
|
|
282
|
-
|
|
276
|
+
LineItemTotal.displayName = 'Payment.LineItemTotal';
|
|
283
277
|
/**
|
|
284
|
-
* Displays the line item price.
|
|
285
|
-
* Shows priceText for CUSTOM rate type services, otherwise shows
|
|
278
|
+
* Displays the line item subtotal (full price before discounts).
|
|
279
|
+
* Shows priceText for CUSTOM rate type services, otherwise shows subtotal.
|
|
286
280
|
*
|
|
287
281
|
* @component
|
|
288
282
|
* @example
|
|
289
283
|
* ```tsx
|
|
290
|
-
* <Payment.
|
|
284
|
+
* <Payment.LineItemSubtotal className="text-lg" />
|
|
291
285
|
* ```
|
|
292
286
|
*/
|
|
293
|
-
export const
|
|
287
|
+
export const LineItemSubtotal = React.forwardRef((props, ref) => {
|
|
294
288
|
const { asChild, children, className } = props;
|
|
295
|
-
|
|
296
|
-
const { totalPrice, priceText } = lineItem;
|
|
297
|
-
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentLineItemPrice, "data-has-price-text": !!priceText, customElement: children, customElementProps: { totalPrice, priceText }, children: priceText ? (_jsx("span", { children: priceText })) : totalPrice ? (_jsx(Money, { money: totalPrice })) : null }));
|
|
289
|
+
return (_jsx(CorePayment.LineItemInfo, { children: ({ subtotal, priceText, hasPriceText, isFree }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentLineItemSubtotal, "data-has-price-text": hasPriceText, "data-is-free": isFree, customElement: children, customElementProps: { subtotal, priceText, hasPriceText, isFree }, children: priceText ? (_jsx("span", { children: priceText })) : (subtotal && _jsx(Money, { money: subtotal })) })) }));
|
|
298
290
|
});
|
|
299
|
-
|
|
291
|
+
LineItemSubtotal.displayName = 'Payment.LineItemSubtotal';
|
|
300
292
|
/**
|
|
301
293
|
* Displays the line item discount.
|
|
302
294
|
* Uses data-has-discount attribute for conditional visibility.
|
|
@@ -309,10 +301,7 @@ LineItemPrice.displayName = 'Payment.LineItemPrice';
|
|
|
309
301
|
*/
|
|
310
302
|
export const LineItemDiscount = React.forwardRef((props, ref) => {
|
|
311
303
|
const { asChild, children, className } = props;
|
|
312
|
-
|
|
313
|
-
const { discount } = lineItem;
|
|
314
|
-
const hasDiscount = discount !== null && discount.amount > 0;
|
|
315
|
-
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentLineItemDiscount, "data-has-discount": hasDiscount, customElement: children, customElementProps: { discount }, children: discount ? _jsx(Money, { money: discount }) : null }));
|
|
304
|
+
return (_jsx(CorePayment.LineItemInfo, { children: ({ discount, hasDiscount }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentLineItemDiscount, "data-has-discount": hasDiscount, customElement: children, customElementProps: { discount }, children: hasDiscount && _jsx(Money, { money: discount }) })) }));
|
|
316
305
|
});
|
|
317
306
|
LineItemDiscount.displayName = 'Payment.LineItemDiscount';
|
|
318
307
|
/**
|
|
@@ -327,9 +316,6 @@ LineItemDiscount.displayName = 'Payment.LineItemDiscount';
|
|
|
327
316
|
*/
|
|
328
317
|
export const LineItemDeposit = React.forwardRef((props, ref) => {
|
|
329
318
|
const { asChild, children, className } = props;
|
|
330
|
-
|
|
331
|
-
const { deposit } = lineItem;
|
|
332
|
-
const hasDeposit = deposit !== null && deposit.amount > 0;
|
|
333
|
-
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentLineItemDeposit, "data-has-deposit": hasDeposit, customElement: children, customElementProps: { deposit }, children: deposit ? _jsx(Money, { money: deposit }) : null }));
|
|
319
|
+
return (_jsx(CorePayment.LineItemInfo, { children: ({ deposit, hasDeposit }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.paymentLineItemDeposit, "data-has-deposit": hasDeposit, customElement: children, customElementProps: { deposit }, children: hasDeposit && _jsx(Money, { money: deposit }) })) }));
|
|
334
320
|
});
|
|
335
321
|
LineItemDeposit.displayName = 'Payment.LineItemDeposit';
|
|
@@ -152,7 +152,7 @@ const Clear = React.forwardRef((props, ref) => {
|
|
|
152
152
|
// BookingService not available - likely no ServiceManagerProvider
|
|
153
153
|
}
|
|
154
154
|
const handleClick = () => {
|
|
155
|
-
bookingService?.actions.
|
|
155
|
+
bookingService?.actions.clearResourceByType(STAFF_MEMBER_RESOURCE_TYPE_ID);
|
|
156
156
|
onClicked?.();
|
|
157
157
|
};
|
|
158
158
|
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.staffMemberListActionClear, customElement: children, customElementProps: {
|
|
@@ -9,6 +9,13 @@ import type { Resource, EventInfo, Location as TimeSlotLocationType } from '@wix
|
|
|
9
9
|
import type { FormValues } from '@wix/form-public';
|
|
10
10
|
import type { BookResult } from './book-action/types.js';
|
|
11
11
|
export declare const ANY_STAFF_MEMBER_ID = "__any_staff_member__";
|
|
12
|
+
/**
|
|
13
|
+
* Extended Resource type with a type field for categorization
|
|
14
|
+
*/
|
|
15
|
+
export interface ExtendedResource extends Resource {
|
|
16
|
+
/** Resource type identifier (e.g., 'staff', 'room', 'equipment') */
|
|
17
|
+
type: string;
|
|
18
|
+
}
|
|
12
19
|
/**
|
|
13
20
|
* Minimal time slot data for service selections
|
|
14
21
|
*/
|
|
@@ -32,8 +39,8 @@ export interface ServiceSelection {
|
|
|
32
39
|
instanceId: string;
|
|
33
40
|
/** The selected service */
|
|
34
41
|
service: Service;
|
|
35
|
-
/** Selected resources (staff members, rooms, etc.) */
|
|
36
|
-
resources:
|
|
42
|
+
/** Selected resources (staff members, rooms, etc.) with type information */
|
|
43
|
+
resources: ExtendedResource[];
|
|
37
44
|
/** Per-item time slot data */
|
|
38
45
|
timeSlot?: ServiceSelectionTimeSlot;
|
|
39
46
|
/** Number of participants for this service selection */
|
|
@@ -53,12 +60,12 @@ export interface BookingServiceActions {
|
|
|
53
60
|
removeItem(instanceId?: string): void;
|
|
54
61
|
/** Clears all service selections */
|
|
55
62
|
clearItems(): void;
|
|
56
|
-
/** Sets a resource by
|
|
57
|
-
|
|
58
|
-
/** Gets a resource by
|
|
59
|
-
|
|
60
|
-
/** Clears a resource by
|
|
61
|
-
|
|
63
|
+
/** Sets a resource by type within a service selection. If no instanceId provided, uses the first item. Only one resource per type is allowed. The resourceType parameter specifies which type to set. */
|
|
64
|
+
setResource(resource: ExtendedResource, instanceId?: string): void;
|
|
65
|
+
/** Gets a resource by type from a service selection. If no instanceId provided, uses the first item. */
|
|
66
|
+
getResourceByType(resourceType: string, instanceId?: string): Resource | undefined;
|
|
67
|
+
/** Clears a resource by type from a service selection. If no instanceId provided, uses the first item. */
|
|
68
|
+
clearResourceByType(resourceType: string, instanceId?: string): void;
|
|
62
69
|
setLocation(location: ServiceLocationType | null): void;
|
|
63
70
|
clearLocation(): void;
|
|
64
71
|
setTimezone(timezone: string): void;
|
|
@@ -115,8 +115,7 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
|
|
|
115
115
|
clearItems() {
|
|
116
116
|
serviceSelectionsSignal.set([]);
|
|
117
117
|
},
|
|
118
|
-
|
|
119
|
-
setResourceById(resourceId, resource, instanceId) {
|
|
118
|
+
setResource(resource, instanceId) {
|
|
120
119
|
const current = serviceSelectionsSignal.get();
|
|
121
120
|
// If no instanceId provided, use the first item
|
|
122
121
|
const targetId = instanceId ?? current[0]?.instanceId;
|
|
@@ -125,20 +124,13 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
|
|
|
125
124
|
const updated = current.map((item) => {
|
|
126
125
|
if (item.instanceId !== targetId)
|
|
127
126
|
return item;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const newResources = [...item.resources];
|
|
131
|
-
if (existingIndex >= 0) {
|
|
132
|
-
newResources[existingIndex] = resource;
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
newResources.push(resource);
|
|
136
|
-
}
|
|
127
|
+
const newResources = item.resources.filter((r) => r.type !== resource.type);
|
|
128
|
+
newResources.push(resource);
|
|
137
129
|
return { ...item, resources: newResources };
|
|
138
130
|
});
|
|
139
131
|
serviceSelectionsSignal.set(updated);
|
|
140
132
|
},
|
|
141
|
-
|
|
133
|
+
getResourceByType(resourceType, instanceId) {
|
|
142
134
|
const current = serviceSelectionsSignal.get();
|
|
143
135
|
// If no instanceId provided, use the first item
|
|
144
136
|
const targetId = instanceId ?? current[0]?.instanceId;
|
|
@@ -147,9 +139,9 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
|
|
|
147
139
|
const targetItem = current.find((item) => item.instanceId === targetId);
|
|
148
140
|
if (!targetItem)
|
|
149
141
|
return undefined;
|
|
150
|
-
return targetItem.resources.find((r) => r.
|
|
142
|
+
return targetItem.resources.find((r) => r.type === resourceType);
|
|
151
143
|
},
|
|
152
|
-
|
|
144
|
+
clearResourceByType(resourceType, instanceId) {
|
|
153
145
|
const current = serviceSelectionsSignal.get();
|
|
154
146
|
// If no instanceId provided, use the first item
|
|
155
147
|
const targetId = instanceId ?? current[0]?.instanceId;
|
|
@@ -158,8 +150,8 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
|
|
|
158
150
|
const updated = current.map((item) => {
|
|
159
151
|
if (item.instanceId !== targetId)
|
|
160
152
|
return item;
|
|
161
|
-
// Filter out the resource with matching
|
|
162
|
-
const newResources = item.resources.filter((r) => r.
|
|
153
|
+
// Filter out the resource with matching type
|
|
154
|
+
const newResources = item.resources.filter((r) => r.type !== resourceType);
|
|
163
155
|
return { ...item, resources: newResources };
|
|
164
156
|
});
|
|
165
157
|
serviceSelectionsSignal.set(updated);
|
package/dist/services/index.d.ts
CHANGED
|
@@ -8,6 +8,6 @@ export { TimeSlotListService, TimeSlotListServiceDefinition, TimeSlotService, Ti
|
|
|
8
8
|
export { ServiceListService, ServiceListServiceDefinition, type ServiceListServiceAPI, type ServiceListServiceConfig, type ServiceListFilters, type ServiceListActions, type QueryOptions, loadServiceListServiceInitialData, type SuccessServiceListServiceConfigResult, type ErrorServiceListServiceConfigResult, } from './service-list/service-list.js';
|
|
9
9
|
export { executeBookAction, canBook, buildBookingRequest, buildCheckoutRequest, type CanBookParams, type BookResult, type BookingError, type BookActionParams, type BookChildProps, type BookProps, type BuildCheckoutParams, } from './booking/book-action/index.js';
|
|
10
10
|
export { BookingFormService, BookingFormServiceDefinition, type BookingFormServiceAPI, type BookingFormServiceConfig, type BookingFormServiceInternalAPI, type ValidationResult, } from './booking-form/booking-form.js';
|
|
11
|
-
export { PaymentService, PaymentServiceDefinition, type PaymentServiceAPI, type PaymentServiceConfig, type PaymentDetails, type
|
|
11
|
+
export { PaymentService, PaymentServiceDefinition, type PaymentServiceAPI, type PaymentServiceConfig, type PaymentDetails, type PricingServiceSelection, type LineItemAdditionalInfo, loadPaymentConfig, type SuccessPaymentConfigResult, type ErrorPaymentConfigResult, } from './payment/payment.js';
|
|
12
12
|
export { LocationListService, LocationListServiceDefinition, LocationType, loadLocationListServiceInitialData, locationListServiceBinding, type LocationListServiceAPI, type LocationListServiceConfig, type LocationListActions, type LocationData, type DisplayLocation, type LoadLocationListServiceResult, } from './location-list/location-list.js';
|
|
13
13
|
export { StaffMemberListService, StaffMemberListServiceDefinition, loadStaffMemberListServiceInitialData, staffMemberListServiceBinding, type StaffMemberListServiceAPI, type StaffMemberListServiceConfig, type StaffMemberListActions, type StaffMemberData, type LoadStaffMemberListServiceResult, } from './staff-member-list/staff-member-list.js';
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Handles calculating total prices, taxes, discounts, and deposit information
|
|
4
4
|
* Supports two modes: SSR (config with pre-fetched data) and lazy loading (reactive)
|
|
5
5
|
*/
|
|
6
|
-
import { type PaymentServiceConfig, type PaymentServiceInternalConfig, type
|
|
7
|
-
export { PaymentServiceDefinition, type PaymentServiceConfig, type PaymentDetails, type LineItemAdditionalInfo, type
|
|
6
|
+
import { type PaymentServiceConfig, type PaymentServiceInternalConfig, type PricingServiceSelection } from './payment.def.js';
|
|
7
|
+
export { PaymentServiceDefinition, type PaymentServiceConfig, type PaymentDetails, type LineItemAdditionalInfo, type PricingServiceSelection, } from './payment.def.js';
|
|
8
8
|
export type { PaymentServiceAPI, PaymentServiceInternalConfig, } from './payment.def.js';
|
|
9
9
|
export declare const PaymentService: import("@wix/services-definitions").ServiceFactory<string & {
|
|
10
10
|
__api: import("./payment.def.js").PaymentServiceAPI;
|
|
@@ -23,10 +23,10 @@ export type ErrorPaymentConfigResult = {
|
|
|
23
23
|
* Load payment configuration for Server-Side Rendering (SSR).
|
|
24
24
|
* Calls the pricing APIs and returns pre-calculated payment details.
|
|
25
25
|
*
|
|
26
|
-
* @param params.
|
|
26
|
+
* @param params.pricingServiceSelections - Pricing service selections for calculation
|
|
27
27
|
* @param params.numberOfParticipants - Number of participants (default: 1)
|
|
28
28
|
*/
|
|
29
29
|
export declare function loadPaymentConfig(params: {
|
|
30
|
-
|
|
30
|
+
pricingServiceSelections: PricingServiceSelection[];
|
|
31
31
|
numberOfParticipants?: number;
|
|
32
32
|
}): Promise<SuccessPaymentConfigResult | ErrorPaymentConfigResult>;
|
|
@@ -30,9 +30,9 @@ export interface PaymentDetails {
|
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
* Input for calculating payment for a
|
|
33
|
+
* Input for calculating payment for a booking service
|
|
34
34
|
*/
|
|
35
|
-
export interface
|
|
35
|
+
export interface PricingServiceSelection {
|
|
36
36
|
service: Service;
|
|
37
37
|
/** Optional line item ID. If not provided, one will be generated. */
|
|
38
38
|
lineItemId?: string;
|
|
@@ -50,8 +50,8 @@ export interface PaymentServiceConfig {
|
|
|
50
50
|
* Not exposed publicly - Core merges this with PaymentServiceConfig
|
|
51
51
|
*/
|
|
52
52
|
export interface PaymentServiceInternalConfig extends PaymentServiceConfig {
|
|
53
|
-
/**
|
|
54
|
-
|
|
53
|
+
/** Booking services for lazy loading (internal use) */
|
|
54
|
+
pricingServiceSelections?: PricingServiceSelection[];
|
|
55
55
|
/** Number of participants for lazy loading (internal use) */
|
|
56
56
|
numberOfParticipants?: number;
|
|
57
57
|
}
|
|
@@ -60,11 +60,11 @@ function buildLineItem(service, numberOfParticipants, lineItemId) {
|
|
|
60
60
|
paymentOption,
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
|
-
async function calculatePaymentDetails(
|
|
64
|
-
// Ensure all
|
|
65
|
-
const data =
|
|
66
|
-
...
|
|
67
|
-
lineItemId:
|
|
63
|
+
async function calculatePaymentDetails(pricingServiceSelections, numberOfParticipants) {
|
|
64
|
+
// Ensure all booking services have a lineItemId
|
|
65
|
+
const data = pricingServiceSelections.map((selection) => ({
|
|
66
|
+
...selection,
|
|
67
|
+
lineItemId: selection.lineItemId || generateLineItemId(),
|
|
68
68
|
}));
|
|
69
69
|
const lineItems = data.map((item) => buildLineItem(item.service, numberOfParticipants, item.lineItemId));
|
|
70
70
|
const response = await calculateTotals({
|
|
@@ -96,15 +96,15 @@ export const PaymentService = implementService.withConfig()(PaymentServiceDefini
|
|
|
96
96
|
const isLoadingSignal = signalsService.signal(false);
|
|
97
97
|
const errorSignal = signalsService.signal(null);
|
|
98
98
|
// Internal calculate function
|
|
99
|
-
const calculate = async (
|
|
100
|
-
if (!
|
|
99
|
+
const calculate = async (pricingServiceSelections, numberOfParticipants) => {
|
|
100
|
+
if (!pricingServiceSelections.length) {
|
|
101
101
|
paymentDetailsSignal.set(null);
|
|
102
102
|
return;
|
|
103
103
|
}
|
|
104
104
|
isLoadingSignal.set(true);
|
|
105
105
|
errorSignal.set(null);
|
|
106
106
|
try {
|
|
107
|
-
const paymentDetails = await calculatePaymentDetails(
|
|
107
|
+
const paymentDetails = await calculatePaymentDetails(pricingServiceSelections, numberOfParticipants);
|
|
108
108
|
paymentDetailsSignal.set(paymentDetails);
|
|
109
109
|
}
|
|
110
110
|
catch (error) {
|
|
@@ -122,22 +122,30 @@ export const PaymentService = implementService.withConfig()(PaymentServiceDefini
|
|
|
122
122
|
if (config.paymentDetails) {
|
|
123
123
|
// No-op - data is pre-fetched
|
|
124
124
|
}
|
|
125
|
-
// Mode 2: Lazy loading -
|
|
126
|
-
else if (config.
|
|
127
|
-
void calculate(config.
|
|
125
|
+
// Mode 2: Lazy loading - pricingServiceSelections provided via internal config
|
|
126
|
+
else if (config.pricingServiceSelections?.length) {
|
|
127
|
+
void calculate(config.pricingServiceSelections, config.numberOfParticipants ?? 1);
|
|
128
128
|
}
|
|
129
129
|
// Mode 3: Reactive - observe BookingService signals (client-side only)
|
|
130
130
|
else if (typeof window !== 'undefined' && bookingService) {
|
|
131
|
-
|
|
131
|
+
// Computed signal that only changes when services change (not participants)
|
|
132
|
+
const servicesKey = signalsService.computed(() => {
|
|
132
133
|
const selections = bookingService?.serviceSelections.get() || [];
|
|
134
|
+
return selections.map((s) => s.service._id).join(',');
|
|
135
|
+
});
|
|
136
|
+
signalsService.effect(() => {
|
|
137
|
+
// Subscribe to servicesKey to trigger effect only when services change
|
|
138
|
+
servicesKey.get();
|
|
139
|
+
// Read current selections without subscribing (peek)
|
|
140
|
+
const selections = bookingService?.serviceSelections.peek() || [];
|
|
133
141
|
// For single service mode, take the first selection
|
|
134
142
|
const firstSelection = selections[0];
|
|
135
143
|
const numParticipants = firstSelection?.totalParticipants || 1;
|
|
136
|
-
const
|
|
144
|
+
const pricingServiceSelections = selections.map((selection) => ({
|
|
137
145
|
service: selection.service,
|
|
138
146
|
lineItemId: selection.instanceId,
|
|
139
147
|
}));
|
|
140
|
-
void calculate(
|
|
148
|
+
void calculate(pricingServiceSelections, numParticipants);
|
|
141
149
|
});
|
|
142
150
|
}
|
|
143
151
|
return {
|
|
@@ -150,19 +158,19 @@ export const PaymentService = implementService.withConfig()(PaymentServiceDefini
|
|
|
150
158
|
* Load payment configuration for Server-Side Rendering (SSR).
|
|
151
159
|
* Calls the pricing APIs and returns pre-calculated payment details.
|
|
152
160
|
*
|
|
153
|
-
* @param params.
|
|
161
|
+
* @param params.pricingServiceSelections - Pricing service selections for calculation
|
|
154
162
|
* @param params.numberOfParticipants - Number of participants (default: 1)
|
|
155
163
|
*/
|
|
156
164
|
export async function loadPaymentConfig(params) {
|
|
157
165
|
try {
|
|
158
|
-
const {
|
|
159
|
-
if (!
|
|
166
|
+
const { pricingServiceSelections, numberOfParticipants = 1 } = params;
|
|
167
|
+
if (!pricingServiceSelections.length) {
|
|
160
168
|
return {
|
|
161
169
|
type: 'success',
|
|
162
170
|
config: { paymentDetails: undefined },
|
|
163
171
|
};
|
|
164
172
|
}
|
|
165
|
-
const paymentDetails = await calculatePaymentDetails(
|
|
173
|
+
const paymentDetails = await calculatePaymentDetails(pricingServiceSelections, numberOfParticipants);
|
|
166
174
|
return {
|
|
167
175
|
type: 'success',
|
|
168
176
|
config: { paymentDetails },
|
|
@@ -195,7 +195,7 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
|
|
|
195
195
|
dateRangeSignal.set({ start: newStartDate, end: newEndDate });
|
|
196
196
|
};
|
|
197
197
|
const preSelectedStaffMemberId = signalsService.computed(() => {
|
|
198
|
-
const serviceSelections = bookingService.serviceSelections.
|
|
198
|
+
const serviceSelections = bookingService.serviceSelections.get();
|
|
199
199
|
return serviceSelections.length
|
|
200
200
|
? (serviceSelections[0]?.resources?.[0]?._id ?? undefined)
|
|
201
201
|
: undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/headless-bookings",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.59",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -72,5 +72,5 @@
|
|
|
72
72
|
"groupId": "com.wixpress.headless-components"
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
|
-
"falconPackageHash": "
|
|
75
|
+
"falconPackageHash": "61ca8eb4d4959dd03911f50f6d490b55be609f85f03f0aff55af5948"
|
|
76
76
|
}
|