@wix/headless-bookings 0.0.51 → 0.0.53

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.
@@ -227,9 +227,9 @@ export interface BookingLocationProps {
227
227
  children: React.ReactNode;
228
228
  }
229
229
  /**
230
- * Wraps Location.Root with the location from the booking context.
230
+ * Wraps Location context with the location from the booking context.
231
231
  * Children can use all Location.* components (Location.Name, Location.Address, etc.).
232
- * Always renders with data-has-location attribute for CSS targeting.
232
+ * Returns null if no location is set.
233
233
  *
234
234
  * @component
235
235
  * @example
@@ -254,7 +254,7 @@ export interface StaffNameProps {
254
254
  }
255
255
  /**
256
256
  * Displays the first staff member's name from the current booking item.
257
- * Always renders with data-has-staff-name attribute for CSS targeting.
257
+ * Returns null when staff name is empty.
258
258
  *
259
259
  * @component
260
260
  * @example
@@ -10,7 +10,7 @@ import { AsChildSlot } from '@wix/headless-utils/react';
10
10
  import * as ServiceComponent from '../service/Service.js';
11
11
  import * as TimeSlotComponent from '../time-slot-list/TimeSlot.js';
12
12
  import * as PaymentComponent from '../payment/Payment.js';
13
- import * as LocationComponent from '../location/Location.js';
13
+ import * as CoreLocation from '../core/location/Location.js';
14
14
  import { GenericList } from '@wix/headless-components/react';
15
15
  // ============================================================================
16
16
  // TestIds
@@ -230,9 +230,9 @@ export function Payment(props) {
230
230
  return (_jsx(CoreBooking.PaymentData, { children: ({ slotServices }) => (_jsx(PaymentComponent.Root, { slotServices: slotServices, children: children })) }));
231
231
  }
232
232
  /**
233
- * Wraps Location.Root with the location from the booking context.
233
+ * Wraps Location context with the location from the booking context.
234
234
  * Children can use all Location.* components (Location.Name, Location.Address, etc.).
235
- * Always renders with data-has-location attribute for CSS targeting.
235
+ * Returns null if no location is set.
236
236
  *
237
237
  * @component
238
238
  * @example
@@ -246,11 +246,11 @@ export function Payment(props) {
246
246
  */
247
247
  export function Location(props) {
248
248
  const { children } = props;
249
- return (_jsx(CoreBooking.Data, { children: ({ location }) => location ? (_jsx(LocationComponent.Root, { location: location, children: children })) : null }));
249
+ return (_jsx(CoreBooking.Data, { children: ({ location }) => location ? (_jsx(CoreLocation.Root, { location: location, children: children })) : null }));
250
250
  }
251
251
  /**
252
252
  * Displays the first staff member's name from the current booking item.
253
- * Always renders with data-has-staff-name attribute for CSS targeting.
253
+ * Returns null when staff name is empty.
254
254
  *
255
255
  * @component
256
256
  * @example
@@ -260,6 +260,11 @@ export function Location(props) {
260
260
  */
261
261
  export const StaffName = React.forwardRef((props, ref) => {
262
262
  const { asChild, children, className } = props;
263
- return (_jsx(CoreBooking.BookingItemInfo, { children: ({ staffName }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.bookingStaffName, "data-has-staff-name": Boolean(staffName), customElement: children, customElementProps: { name: staffName }, children: _jsx("span", { children: staffName }) })) }));
263
+ return (_jsx(CoreBooking.BookingItemInfo, { children: ({ staffName }) => {
264
+ if (!staffName) {
265
+ return null;
266
+ }
267
+ return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.bookingStaffName, customElement: children, customElementProps: { name: staffName }, children: _jsx("span", { children: staffName }) }));
268
+ } }));
264
269
  });
265
270
  StaffName.displayName = 'Booking.StaffName';
@@ -46,13 +46,24 @@ export function Root(props) {
46
46
  */
47
47
  /**
48
48
  * Maps a TimeSlotLocationType to ServiceLocationType.
49
- * These types are structurally similar but have subtle differences
50
- * (e.g., _id being string | null | undefined vs string | undefined).
49
+ * TimeSlot location has flat structure: { name, formattedAddress, locationType }
50
+ * Service location has nested structure: { business: { name, address }, type }
51
51
  */
52
52
  function mapTimeSlotLocationToServiceLocation(timeSlotLocation) {
53
+ // TimeSlot location has flat name/formattedAddress at top level
54
+ // Convert to nested business structure that CoreLocation expects
53
55
  return {
54
- ...timeSlotLocation,
55
56
  _id: timeSlotLocation._id ?? undefined,
57
+ type: timeSlotLocation.locationType,
58
+ business: {
59
+ _id: timeSlotLocation._id ?? undefined,
60
+ name: timeSlotLocation.name ?? undefined,
61
+ address: timeSlotLocation.formattedAddress
62
+ ? {
63
+ addressLine: timeSlotLocation.formattedAddress,
64
+ }
65
+ : undefined,
66
+ },
56
67
  };
57
68
  }
58
69
  /**
@@ -3,6 +3,7 @@ export * as BookingForm from './booking-form/BookingForm.js';
3
3
  export * as Service from './service/Service.js';
4
4
  export * as ServiceMedia from './service/ServiceMedia.js';
5
5
  export * as TimeSlotList from './time-slot-list/TimeSlotList.js';
6
+ export * as TimeSlot from './time-slot-list/TimeSlot.js';
6
7
  export * as ServiceList from './service-list/ServiceList.js';
7
8
  export * as Location from './location/Location.js';
8
9
  export * as LocationList from './location/LocationList.js';
@@ -3,6 +3,7 @@ export * as BookingForm from './booking-form/BookingForm.js';
3
3
  export * as Service from './service/Service.js';
4
4
  export * as ServiceMedia from './service/ServiceMedia.js';
5
5
  export * as TimeSlotList from './time-slot-list/TimeSlotList.js';
6
+ export * as TimeSlot from './time-slot-list/TimeSlot.js';
6
7
  export * as ServiceList from './service-list/ServiceList.js';
7
8
  export * as Location from './location/Location.js';
8
9
  export * as LocationList from './location/LocationList.js';
@@ -89,7 +89,7 @@ Root.displayName = 'Location.Root';
89
89
  export const Name = React.forwardRef((props, ref) => {
90
90
  const { asChild, children, className, ...attrs } = props;
91
91
  const { name } = useLocationContext();
92
- return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.locationName, customElement: children, customElementProps: { name: name ?? '' }, ...attrs, children: _jsx("span", { children: name }) }));
92
+ return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.locationName, customElement: children, customElementProps: { name: name ?? '' }, ...attrs, children: name ? _jsx("span", { children: name }) : null }));
93
93
  });
94
94
  Name.displayName = 'Location.Name';
95
95
  /**
@@ -117,7 +117,7 @@ export const Type = React.forwardRef((props, ref) => {
117
117
  locationType,
118
118
  isCustomerLocation,
119
119
  isCustomLocation,
120
- }, ...attrs, children: _jsx("span", { children: locationType }) }));
120
+ }, ...attrs, children: locationType ? _jsx("span", { children: locationType }) : null }));
121
121
  });
122
122
  Type.displayName = 'Location.Type';
123
123
  /**
@@ -81,6 +81,7 @@ export function buildBookingRequest(params) {
81
81
  },
82
82
  },
83
83
  participantNotification: {
84
+ metadata: { channels: 'EMAIL,SMS' },
84
85
  notifyParticipants: true,
85
86
  },
86
87
  sendSmsReminder: true,
@@ -8,7 +8,7 @@ import type { Service } from '@wix/auto_sdk_bookings_services';
8
8
  /**
9
9
  * Payment option for line items
10
10
  */
11
- export type PaymentOption = 'FULL_PAYMENT_ONLINE' | 'FULL_PAYMENT_OFFLINE';
11
+ export type PaymentOption = 'FULL_PAYMENT_ONLINE' | 'FULL_PAYMENT_OFFLINE' | 'DEPOSIT_ONLINE';
12
12
  /**
13
13
  * Additional computed info for a line item (not in SDK response)
14
14
  */
@@ -25,11 +25,15 @@ function getAdditionalInfo(service, lineItemId) {
25
25
  : undefined;
26
26
  return { lineItemId, priceText };
27
27
  }
28
- function getPaymentOption(service) {
28
+ function getPaymentOption(service, hasDeposit) {
29
29
  const options = service.payment?.options;
30
30
  if (options?.inPerson) {
31
31
  return 'FULL_PAYMENT_OFFLINE';
32
32
  }
33
+ // If deposit is configured, use DEPOSIT_ONLINE to get correct payNow/payLater split
34
+ if (hasDeposit) {
35
+ return 'DEPOSIT_ONLINE';
36
+ }
33
37
  return 'FULL_PAYMENT_ONLINE';
34
38
  }
35
39
  function buildLineItem(service, numberOfParticipants, lineItemId) {
@@ -37,11 +41,13 @@ function buildLineItem(service, numberOfParticipants, lineItemId) {
37
41
  const servicePrice = service.payment?.fixed?.price?.value;
38
42
  const price = Number(servicePrice || 0) * numberOfParticipants;
39
43
  // Get deposit if configured
40
- const deposit = service.payment?.fixed?.deposit?.value
41
- ? Number(service.payment.fixed.deposit.value) * numberOfParticipants
44
+ const depositValue = service.payment?.fixed?.deposit?.value;
45
+ const hasDeposit = !!depositValue && Number(depositValue) > 0;
46
+ const deposit = hasDeposit
47
+ ? Number(depositValue) * numberOfParticipants
42
48
  : undefined;
43
- // Get payment option from service configuration
44
- const paymentOption = getPaymentOption(service);
49
+ // Get payment option from service configuration (pass hasDeposit for correct API behavior)
50
+ const paymentOption = getPaymentOption(service, hasDeposit);
45
51
  return {
46
52
  _id: lineItemId,
47
53
  catalogReference: {
@@ -227,9 +227,9 @@ export interface BookingLocationProps {
227
227
  children: React.ReactNode;
228
228
  }
229
229
  /**
230
- * Wraps Location.Root with the location from the booking context.
230
+ * Wraps Location context with the location from the booking context.
231
231
  * Children can use all Location.* components (Location.Name, Location.Address, etc.).
232
- * Always renders with data-has-location attribute for CSS targeting.
232
+ * Returns null if no location is set.
233
233
  *
234
234
  * @component
235
235
  * @example
@@ -254,7 +254,7 @@ export interface StaffNameProps {
254
254
  }
255
255
  /**
256
256
  * Displays the first staff member's name from the current booking item.
257
- * Always renders with data-has-staff-name attribute for CSS targeting.
257
+ * Returns null when staff name is empty.
258
258
  *
259
259
  * @component
260
260
  * @example
@@ -10,7 +10,7 @@ import { AsChildSlot } from '@wix/headless-utils/react';
10
10
  import * as ServiceComponent from '../service/Service.js';
11
11
  import * as TimeSlotComponent from '../time-slot-list/TimeSlot.js';
12
12
  import * as PaymentComponent from '../payment/Payment.js';
13
- import * as LocationComponent from '../location/Location.js';
13
+ import * as CoreLocation from '../core/location/Location.js';
14
14
  import { GenericList } from '@wix/headless-components/react';
15
15
  // ============================================================================
16
16
  // TestIds
@@ -230,9 +230,9 @@ export function Payment(props) {
230
230
  return (_jsx(CoreBooking.PaymentData, { children: ({ slotServices }) => (_jsx(PaymentComponent.Root, { slotServices: slotServices, children: children })) }));
231
231
  }
232
232
  /**
233
- * Wraps Location.Root with the location from the booking context.
233
+ * Wraps Location context with the location from the booking context.
234
234
  * Children can use all Location.* components (Location.Name, Location.Address, etc.).
235
- * Always renders with data-has-location attribute for CSS targeting.
235
+ * Returns null if no location is set.
236
236
  *
237
237
  * @component
238
238
  * @example
@@ -246,11 +246,11 @@ export function Payment(props) {
246
246
  */
247
247
  export function Location(props) {
248
248
  const { children } = props;
249
- return (_jsx(CoreBooking.Data, { children: ({ location }) => location ? (_jsx(LocationComponent.Root, { location: location, children: children })) : null }));
249
+ return (_jsx(CoreBooking.Data, { children: ({ location }) => location ? (_jsx(CoreLocation.Root, { location: location, children: children })) : null }));
250
250
  }
251
251
  /**
252
252
  * Displays the first staff member's name from the current booking item.
253
- * Always renders with data-has-staff-name attribute for CSS targeting.
253
+ * Returns null when staff name is empty.
254
254
  *
255
255
  * @component
256
256
  * @example
@@ -260,6 +260,11 @@ export function Location(props) {
260
260
  */
261
261
  export const StaffName = React.forwardRef((props, ref) => {
262
262
  const { asChild, children, className } = props;
263
- return (_jsx(CoreBooking.BookingItemInfo, { children: ({ staffName }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.bookingStaffName, "data-has-staff-name": Boolean(staffName), customElement: children, customElementProps: { name: staffName }, children: _jsx("span", { children: staffName }) })) }));
263
+ return (_jsx(CoreBooking.BookingItemInfo, { children: ({ staffName }) => {
264
+ if (!staffName) {
265
+ return null;
266
+ }
267
+ return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.bookingStaffName, customElement: children, customElementProps: { name: staffName }, children: _jsx("span", { children: staffName }) }));
268
+ } }));
264
269
  });
265
270
  StaffName.displayName = 'Booking.StaffName';
@@ -46,13 +46,24 @@ export function Root(props) {
46
46
  */
47
47
  /**
48
48
  * Maps a TimeSlotLocationType to ServiceLocationType.
49
- * These types are structurally similar but have subtle differences
50
- * (e.g., _id being string | null | undefined vs string | undefined).
49
+ * TimeSlot location has flat structure: { name, formattedAddress, locationType }
50
+ * Service location has nested structure: { business: { name, address }, type }
51
51
  */
52
52
  function mapTimeSlotLocationToServiceLocation(timeSlotLocation) {
53
+ // TimeSlot location has flat name/formattedAddress at top level
54
+ // Convert to nested business structure that CoreLocation expects
53
55
  return {
54
- ...timeSlotLocation,
55
56
  _id: timeSlotLocation._id ?? undefined,
57
+ type: timeSlotLocation.locationType,
58
+ business: {
59
+ _id: timeSlotLocation._id ?? undefined,
60
+ name: timeSlotLocation.name ?? undefined,
61
+ address: timeSlotLocation.formattedAddress
62
+ ? {
63
+ addressLine: timeSlotLocation.formattedAddress,
64
+ }
65
+ : undefined,
66
+ },
56
67
  };
57
68
  }
58
69
  /**
@@ -3,6 +3,7 @@ export * as BookingForm from './booking-form/BookingForm.js';
3
3
  export * as Service from './service/Service.js';
4
4
  export * as ServiceMedia from './service/ServiceMedia.js';
5
5
  export * as TimeSlotList from './time-slot-list/TimeSlotList.js';
6
+ export * as TimeSlot from './time-slot-list/TimeSlot.js';
6
7
  export * as ServiceList from './service-list/ServiceList.js';
7
8
  export * as Location from './location/Location.js';
8
9
  export * as LocationList from './location/LocationList.js';
@@ -3,6 +3,7 @@ export * as BookingForm from './booking-form/BookingForm.js';
3
3
  export * as Service from './service/Service.js';
4
4
  export * as ServiceMedia from './service/ServiceMedia.js';
5
5
  export * as TimeSlotList from './time-slot-list/TimeSlotList.js';
6
+ export * as TimeSlot from './time-slot-list/TimeSlot.js';
6
7
  export * as ServiceList from './service-list/ServiceList.js';
7
8
  export * as Location from './location/Location.js';
8
9
  export * as LocationList from './location/LocationList.js';
@@ -89,7 +89,7 @@ Root.displayName = 'Location.Root';
89
89
  export const Name = React.forwardRef((props, ref) => {
90
90
  const { asChild, children, className, ...attrs } = props;
91
91
  const { name } = useLocationContext();
92
- return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.locationName, customElement: children, customElementProps: { name: name ?? '' }, ...attrs, children: _jsx("span", { children: name }) }));
92
+ return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.locationName, customElement: children, customElementProps: { name: name ?? '' }, ...attrs, children: name ? _jsx("span", { children: name }) : null }));
93
93
  });
94
94
  Name.displayName = 'Location.Name';
95
95
  /**
@@ -117,7 +117,7 @@ export const Type = React.forwardRef((props, ref) => {
117
117
  locationType,
118
118
  isCustomerLocation,
119
119
  isCustomLocation,
120
- }, ...attrs, children: _jsx("span", { children: locationType }) }));
120
+ }, ...attrs, children: locationType ? _jsx("span", { children: locationType }) : null }));
121
121
  });
122
122
  Type.displayName = 'Location.Type';
123
123
  /**
@@ -81,6 +81,7 @@ export function buildBookingRequest(params) {
81
81
  },
82
82
  },
83
83
  participantNotification: {
84
+ metadata: { channels: 'EMAIL,SMS' },
84
85
  notifyParticipants: true,
85
86
  },
86
87
  sendSmsReminder: true,
@@ -8,7 +8,7 @@ import type { Service } from '@wix/auto_sdk_bookings_services';
8
8
  /**
9
9
  * Payment option for line items
10
10
  */
11
- export type PaymentOption = 'FULL_PAYMENT_ONLINE' | 'FULL_PAYMENT_OFFLINE';
11
+ export type PaymentOption = 'FULL_PAYMENT_ONLINE' | 'FULL_PAYMENT_OFFLINE' | 'DEPOSIT_ONLINE';
12
12
  /**
13
13
  * Additional computed info for a line item (not in SDK response)
14
14
  */
@@ -25,11 +25,15 @@ function getAdditionalInfo(service, lineItemId) {
25
25
  : undefined;
26
26
  return { lineItemId, priceText };
27
27
  }
28
- function getPaymentOption(service) {
28
+ function getPaymentOption(service, hasDeposit) {
29
29
  const options = service.payment?.options;
30
30
  if (options?.inPerson) {
31
31
  return 'FULL_PAYMENT_OFFLINE';
32
32
  }
33
+ // If deposit is configured, use DEPOSIT_ONLINE to get correct payNow/payLater split
34
+ if (hasDeposit) {
35
+ return 'DEPOSIT_ONLINE';
36
+ }
33
37
  return 'FULL_PAYMENT_ONLINE';
34
38
  }
35
39
  function buildLineItem(service, numberOfParticipants, lineItemId) {
@@ -37,11 +41,13 @@ function buildLineItem(service, numberOfParticipants, lineItemId) {
37
41
  const servicePrice = service.payment?.fixed?.price?.value;
38
42
  const price = Number(servicePrice || 0) * numberOfParticipants;
39
43
  // Get deposit if configured
40
- const deposit = service.payment?.fixed?.deposit?.value
41
- ? Number(service.payment.fixed.deposit.value) * numberOfParticipants
44
+ const depositValue = service.payment?.fixed?.deposit?.value;
45
+ const hasDeposit = !!depositValue && Number(depositValue) > 0;
46
+ const deposit = hasDeposit
47
+ ? Number(depositValue) * numberOfParticipants
42
48
  : undefined;
43
- // Get payment option from service configuration
44
- const paymentOption = getPaymentOption(service);
49
+ // Get payment option from service configuration (pass hasDeposit for correct API behavior)
50
+ const paymentOption = getPaymentOption(service, hasDeposit);
45
51
  return {
46
52
  _id: lineItemId,
47
53
  catalogReference: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/headless-bookings",
3
- "version": "0.0.51",
3
+ "version": "0.0.53",
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": "ef1225253b65e6a7c3e1ea15bc390bb4afebcfad2ef8f5c0d7337bde"
75
+ "falconPackageHash": "e2a82b9d4a1150c6bc5f6996ccc4f53eebcda6e1aa624a3eab20fbe7"
76
76
  }