@wix/headless-bookings 0.0.118 → 1.0.1

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.
Files changed (93) hide show
  1. package/cjs/dist/__mocks__/booking/booking-mocks.d.ts +1 -1
  2. package/cjs/dist/__mocks__/services/services-mocks.d.ts +23 -0
  3. package/cjs/dist/__mocks__/services/services-mocks.js +65 -1
  4. package/cjs/dist/api/calculate-cart/index.d.ts +3 -0
  5. package/cjs/dist/api/calculate-cart/index.js +7 -0
  6. package/cjs/dist/api/create-cart/index.d.ts +3 -0
  7. package/cjs/dist/api/create-cart/index.js +10 -0
  8. package/cjs/dist/api/index.d.ts +3 -9
  9. package/cjs/dist/api/index.js +12 -17
  10. package/cjs/dist/api/place-order/index.d.ts +3 -0
  11. package/cjs/dist/api/place-order/index.js +7 -0
  12. package/cjs/dist/api/query-services/index.js +2 -2
  13. package/cjs/dist/react/booking/Book.js +1 -1
  14. package/cjs/dist/react/core/booking/Book.d.ts +1 -1
  15. package/cjs/dist/react/core/booking/Book.js +1 -1
  16. package/cjs/dist/react/core/booking/Booking.d.ts +1 -1
  17. package/cjs/dist/react/core/booking/Booking.js +14 -5
  18. package/cjs/dist/react/core/location/Location.d.ts +1 -1
  19. package/cjs/dist/react/core/location/Location.js +5 -5
  20. package/cjs/dist/react/core/service/Service.d.ts +10 -1
  21. package/cjs/dist/react/core/service/Service.js +5 -4
  22. package/cjs/dist/react/service/Service.d.ts +68 -1
  23. package/cjs/dist/react/service/Service.js +81 -1
  24. package/cjs/dist/services/booking/book-action/bookAction.d.ts +0 -22
  25. package/cjs/dist/services/booking/book-action/bookAction.js +20 -39
  26. package/cjs/dist/services/booking/book-action/buildCartRequest.d.ts +10 -0
  27. package/cjs/dist/services/booking/book-action/buildCartRequest.js +37 -0
  28. package/cjs/dist/services/booking/book-action/index.d.ts +1 -1
  29. package/cjs/dist/services/booking/book-action/index.js +3 -3
  30. package/cjs/dist/services/booking/book-action/isCheckoutRequired.d.ts +3 -19
  31. package/cjs/dist/services/booking/book-action/isCheckoutRequired.js +11 -29
  32. package/cjs/dist/services/booking/book-action/types.d.ts +1 -1
  33. package/cjs/dist/services/booking/booking.d.ts +1 -1
  34. package/cjs/dist/services/index.d.ts +1 -1
  35. package/cjs/dist/services/index.js +2 -2
  36. package/cjs/dist/services/location-list/location-list.def.d.ts +1 -1
  37. package/cjs/dist/services/location-list/location-list.def.js +1 -1
  38. package/cjs/dist/services/location-list/location-list.js +7 -7
  39. package/cjs/dist/utils/navigation.d.ts +2 -2
  40. package/cjs/dist/utils/navigation.js +2 -2
  41. package/dist/__mocks__/booking/booking-mocks.d.ts +1 -1
  42. package/dist/__mocks__/services/services-mocks.d.ts +23 -0
  43. package/dist/__mocks__/services/services-mocks.js +64 -0
  44. package/dist/api/calculate-cart/index.d.ts +3 -0
  45. package/dist/api/calculate-cart/index.js +4 -0
  46. package/dist/api/create-cart/index.d.ts +3 -0
  47. package/dist/api/create-cart/index.js +5 -0
  48. package/dist/api/index.d.ts +3 -9
  49. package/dist/api/index.js +3 -9
  50. package/dist/api/place-order/index.d.ts +3 -0
  51. package/dist/api/place-order/index.js +4 -0
  52. package/dist/api/query-services/index.js +1 -1
  53. package/dist/react/booking/Book.js +1 -1
  54. package/dist/react/core/booking/Book.d.ts +1 -1
  55. package/dist/react/core/booking/Book.js +1 -1
  56. package/dist/react/core/booking/Booking.d.ts +1 -1
  57. package/dist/react/core/booking/Booking.js +14 -5
  58. package/dist/react/core/location/Location.d.ts +1 -1
  59. package/dist/react/core/location/Location.js +1 -1
  60. package/dist/react/core/service/Service.d.ts +10 -1
  61. package/dist/react/core/service/Service.js +5 -4
  62. package/dist/react/service/Service.d.ts +68 -1
  63. package/dist/react/service/Service.js +81 -1
  64. package/dist/services/booking/book-action/bookAction.d.ts +0 -22
  65. package/dist/services/booking/book-action/bookAction.js +20 -39
  66. package/dist/services/booking/book-action/buildCartRequest.d.ts +10 -0
  67. package/dist/services/booking/book-action/buildCartRequest.js +34 -0
  68. package/dist/services/booking/book-action/index.d.ts +1 -1
  69. package/dist/services/booking/book-action/index.js +1 -1
  70. package/dist/services/booking/book-action/isCheckoutRequired.d.ts +3 -19
  71. package/dist/services/booking/book-action/isCheckoutRequired.js +11 -29
  72. package/dist/services/booking/book-action/types.d.ts +1 -1
  73. package/dist/services/booking/booking.d.ts +1 -1
  74. package/dist/services/index.d.ts +1 -1
  75. package/dist/services/index.js +1 -1
  76. package/dist/services/location-list/location-list.def.d.ts +1 -1
  77. package/dist/services/location-list/location-list.def.js +1 -1
  78. package/dist/services/location-list/location-list.js +1 -1
  79. package/dist/utils/navigation.d.ts +2 -2
  80. package/dist/utils/navigation.js +2 -2
  81. package/package.json +5 -4
  82. package/cjs/dist/api/create-checkout/index.d.ts +0 -40
  83. package/cjs/dist/api/create-checkout/index.js +0 -42
  84. package/cjs/dist/api/create-order/index.d.ts +0 -20
  85. package/cjs/dist/api/create-order/index.js +0 -24
  86. package/cjs/dist/services/booking/book-action/buildCheckoutRequest.d.ts +0 -28
  87. package/cjs/dist/services/booking/book-action/buildCheckoutRequest.js +0 -65
  88. package/dist/api/create-checkout/index.d.ts +0 -40
  89. package/dist/api/create-checkout/index.js +0 -37
  90. package/dist/api/create-order/index.d.ts +0 -20
  91. package/dist/api/create-order/index.js +0 -21
  92. package/dist/services/booking/book-action/buildCheckoutRequest.d.ts +0 -28
  93. package/dist/services/booking/book-action/buildCheckoutRequest.js +0 -62
@@ -7,7 +7,7 @@ import React from 'react';
7
7
  import { WixServices, useService } from '@wix/services-manager-react';
8
8
  import { createServicesMap } from '@wix/services-manager';
9
9
  import { BookingServiceDefinition, BookingService, } from '../../../services/booking/booking.js';
10
- import { LocationType, } from '@wix/auto_sdk_bookings_services';
10
+ import { LocationTypeEnumLocationType as LocationType, } from '@wix/auto_sdk_bookings_services';
11
11
  /**
12
12
  * Root component that provides booking context to the entire app.
13
13
  *
@@ -53,7 +53,16 @@ export function Root(props) {
53
53
  function mapTimeSlotLocationToServiceLocation(timeSlotLocation) {
54
54
  // TimeSlot location has flat name/formattedAddress at top level
55
55
  // Convert to nested business/custom structure that CoreLocation expects
56
- const locationType = timeSlotLocation.locationType;
56
+ const isCustomer = timeSlotLocation.locationType === LocationType.CUSTOMER;
57
+ const isCustom = timeSlotLocation.locationType === LocationType.CUSTOM;
58
+ // The two SDKs share BUSINESS/CUSTOM/CUSTOMER but the time-slots enum also
59
+ // exposes UNKNOWN_LOCATION_TYPE, which V2Location.type does not accept.
60
+ // Default to BUSINESS for any unrecognized value.
61
+ const type = isCustomer
62
+ ? LocationType.CUSTOMER
63
+ : isCustom
64
+ ? LocationType.CUSTOM
65
+ : LocationType.BUSINESS;
57
66
  const location = {
58
67
  _id: timeSlotLocation._id ?? undefined,
59
68
  name: timeSlotLocation.name ?? undefined,
@@ -65,10 +74,10 @@ function mapTimeSlotLocationToServiceLocation(timeSlotLocation) {
65
74
  };
66
75
  return {
67
76
  _id: timeSlotLocation._id ?? undefined,
68
- type: locationType,
69
- ...(locationType === LocationType.CUSTOMER
77
+ type,
78
+ ...(isCustomer
70
79
  ? null
71
- : locationType === LocationType.CUSTOM
80
+ : isCustom
72
81
  ? { custom: location }
73
82
  : { business: location }),
74
83
  };
@@ -6,7 +6,7 @@
6
6
  * @module Core/Location
7
7
  */
8
8
  import React from 'react';
9
- import { LocationType } from '@wix/auto_sdk_bookings_services';
9
+ import { LocationTypeEnumLocationType as LocationType } from '@wix/auto_sdk_bookings_services';
10
10
  import type { AddressData as AddressDataType } from '@wix/headless-components/react';
11
11
  import type { Location } from '../../../services/location-list/location-list.def.js';
12
12
  /**
@@ -8,7 +8,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
8
8
  */
9
9
  import React, { createContext, useContext } from 'react';
10
10
  import { useService } from '@wix/services-manager-react';
11
- import { LocationType } from '@wix/auto_sdk_bookings_services';
11
+ import { LocationTypeEnumLocationType as LocationType } from '@wix/auto_sdk_bookings_services';
12
12
  import { BookingServiceDefinition } from '../../../services/booking/booking.js';
13
13
  import { LocationListServiceDefinition } from '../../../services/location-list/location-list.def.js';
14
14
  // ==========================================
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import React from 'react';
6
6
  import { type ServiceServiceConfig } from '../../../services/service/service.js';
7
- import type { Service, Payment, BookingPolicy, Schedule, StaffMember } from '@wix/auto_sdk_bookings_services';
7
+ import type { Service, Payment, BookingPolicy, Schedule, StaffMember, DurationRange } from '@wix/auto_sdk_bookings_services';
8
8
  import type { MoneyData } from '@wix/headless-components/react';
9
9
  /**
10
10
  * Props for Service.Root component
@@ -50,6 +50,15 @@ export interface InfoProps {
50
50
  description: string;
51
51
  tagline?: string;
52
52
  duration?: number;
53
+ /**
54
+ * Typed range of supported session durations, derived from
55
+ * `service.schedule.availabilityConstraints.sessionDurations`. Set when the
56
+ * service supports two or more distinct durations; otherwise undefined and
57
+ * the single-value `duration` field above should be used. Consumers branch
58
+ * on `range.unitType` (the SDK `UnitType` enum) and read the matching
59
+ * `range.hourOptions` / `range.dayOptions` config.
60
+ */
61
+ durationRange?: DurationRange;
53
62
  type?: string;
54
63
  category?: {
55
64
  name?: string;
@@ -87,9 +87,9 @@ export function Info(props) {
87
87
  currency,
88
88
  };
89
89
  }
90
- // Extract duration from schedule.availabilityConstraints.sessionDurations
91
- // Use the first duration if multiple are available
92
- const duration = service.schedule?.availabilityConstraints?.sessionDurations?.[0];
90
+ const constraints = service.schedule?.availabilityConstraints;
91
+ const duration = constraints?.sessionDurations?.[0];
92
+ const durationRange = constraints?.durationRange;
93
93
  // Get staff members from staffMemberDetails.staffMembers
94
94
  // (available when using conditionalFields: ['STAFF_MEMBER_DETAILS'] in queryServices)
95
95
  const staff = service.staffMembers || [];
@@ -119,7 +119,8 @@ export function Info(props) {
119
119
  name: service.name || '',
120
120
  description: service.description || '',
121
121
  tagline: service.tagLine || undefined,
122
- duration: duration,
122
+ duration,
123
+ durationRange,
123
124
  type: service.type,
124
125
  category: service.category
125
126
  ? {
@@ -5,7 +5,7 @@
5
5
  import React from 'react';
6
6
  import { AsChildChildren } from '@wix/headless-utils/react';
7
7
  import { MoneyData } from '@wix/headless-components/react';
8
- import { type Service, type Payment } from '@wix/auto_sdk_bookings_services';
8
+ import { type Service, type Payment, type DurationRange as DurationRangeData } from '@wix/auto_sdk_bookings_services';
9
9
  import * as ServiceMediaModule from './ServiceMedia.js';
10
10
  export declare const TestIds: {
11
11
  readonly serviceRoot: "service-root";
@@ -14,6 +14,7 @@ export declare const TestIds: {
14
14
  readonly servicePrice: "service-price";
15
15
  readonly serviceTagline: "service-tagline";
16
16
  readonly serviceDurationInMinutes: "service-duration-in-minutes";
17
+ readonly serviceDurationRange: "service-duration-range";
17
18
  readonly serviceType: "service-type";
18
19
  readonly serviceCategory: "service-category";
19
20
  readonly serviceLocations: "service-locations";
@@ -340,6 +341,72 @@ export interface DurationInMinutesProps extends Omit<React.HTMLAttributes<HTMLEl
340
341
  * ```
341
342
  */
342
343
  export declare const DurationInMinutes: React.ForwardRefExoticComponent<DurationInMinutesProps & React.RefAttributes<HTMLElement>>;
344
+ /**
345
+ * Props for Service DurationRange component
346
+ */
347
+ export interface DurationRangeProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children'> {
348
+ asChild?: boolean;
349
+ children?: AsChildChildren<{
350
+ range: DurationRangeData;
351
+ }>;
352
+ }
353
+ /**
354
+ * Provides the service's supported session duration range as raw SDK data.
355
+ * Renders nothing when the service has fewer than two distinct supported
356
+ * durations — use {@link DurationInMinutes} for that case.
357
+ *
358
+ * The component is intentionally UI-agnostic: it does not pick formatting,
359
+ * units, or labels for you. The default render outputs only the raw
360
+ * `min - max` numbers (no unit text). Consumers wanting unit-aware UI use
361
+ * `asChild` with a custom render and narrow on the SDK `range` payload
362
+ * (`range.hourOptions` / `range.dayOptions` / `range.unitType`, or any
363
+ * other unit configuration the SDK adds in the future).
364
+ *
365
+ * @component
366
+ * @example
367
+ * ```tsx
368
+ * // Default usage - displays raw min/max, e.g. "120 - 540" or "2 - 5"
369
+ * <Service.DurationRange className="text-base text-secondary-foreground" />
370
+ * ```
371
+ *
372
+ * @example
373
+ * ```tsx
374
+ * // asChild with primitive element
375
+ * <Service.DurationRange asChild>
376
+ * <span className="font-semibold" />
377
+ * </Service.DurationRange>
378
+ * ```
379
+ *
380
+ * @example
381
+ * ```tsx
382
+ * // asChild with custom component - narrow on the SDK range payload to
383
+ * // decide unit-specific formatting.
384
+ * <Service.DurationRange asChild>
385
+ * {React.forwardRef(({ range, ...props }, ref) => {
386
+ * if (range.hourOptions) {
387
+ * const { minDurationInMinutes: min, maxDurationInMinutes: max } =
388
+ * range.hourOptions;
389
+ * return (
390
+ * <span ref={ref} {...props}>
391
+ * {min}-{max} min
392
+ * </span>
393
+ * );
394
+ * }
395
+ * if (range.dayOptions) {
396
+ * const { minDurationInDays: min, maxDurationInDays: max } =
397
+ * range.dayOptions;
398
+ * return (
399
+ * <span ref={ref} {...props}>
400
+ * {min}-{max} days
401
+ * </span>
402
+ * );
403
+ * }
404
+ * return <span ref={ref} {...props} />;
405
+ * })}
406
+ * </Service.DurationRange>
407
+ * ```
408
+ */
409
+ export declare const DurationRange: React.ForwardRefExoticComponent<DurationRangeProps & React.RefAttributes<HTMLElement>>;
343
410
  /**
344
411
  * Props for Service Type component
345
412
  */
@@ -9,7 +9,7 @@ import * as CoreServiceMediaGallery from '../core/service/ServiceMediaGallery.js
9
9
  import { AsChildSlot } from '@wix/headless-utils/react';
10
10
  import { Money } from '@wix/headless-components/react';
11
11
  import { MediaGallery } from '@wix/headless-media/react';
12
- import { RateType, } from '@wix/auto_sdk_bookings_services';
12
+ import { RateType, UnitType, } from '@wix/auto_sdk_bookings_services';
13
13
  import * as LocationList from '../location/LocationList.js';
14
14
  // Note: Location components are used inside LocationList.LocationRepeater
15
15
  // Users should import { Location } from '@wix/headless-bookings/react' for Location.Name, Location.Address, etc.
@@ -24,6 +24,7 @@ export const TestIds = {
24
24
  servicePrice: 'service-price',
25
25
  serviceTagline: 'service-tagline',
26
26
  serviceDurationInMinutes: 'service-duration-in-minutes',
27
+ serviceDurationRange: 'service-duration-range',
27
28
  serviceType: 'service-type',
28
29
  serviceCategory: 'service-category',
29
30
  serviceLocations: 'service-locations',
@@ -302,6 +303,85 @@ export const DurationInMinutes = React.forwardRef((props, ref) => {
302
303
  } }));
303
304
  });
304
305
  DurationInMinutes.displayName = 'Service.DurationInMinutes';
306
+ /**
307
+ * Provides the service's supported session duration range as raw SDK data.
308
+ * Renders nothing when the service has fewer than two distinct supported
309
+ * durations — use {@link DurationInMinutes} for that case.
310
+ *
311
+ * The component is intentionally UI-agnostic: it does not pick formatting,
312
+ * units, or labels for you. The default render outputs only the raw
313
+ * `min - max` numbers (no unit text). Consumers wanting unit-aware UI use
314
+ * `asChild` with a custom render and narrow on the SDK `range` payload
315
+ * (`range.hourOptions` / `range.dayOptions` / `range.unitType`, or any
316
+ * other unit configuration the SDK adds in the future).
317
+ *
318
+ * @component
319
+ * @example
320
+ * ```tsx
321
+ * // Default usage - displays raw min/max, e.g. "120 - 540" or "2 - 5"
322
+ * <Service.DurationRange className="text-base text-secondary-foreground" />
323
+ * ```
324
+ *
325
+ * @example
326
+ * ```tsx
327
+ * // asChild with primitive element
328
+ * <Service.DurationRange asChild>
329
+ * <span className="font-semibold" />
330
+ * </Service.DurationRange>
331
+ * ```
332
+ *
333
+ * @example
334
+ * ```tsx
335
+ * // asChild with custom component - narrow on the SDK range payload to
336
+ * // decide unit-specific formatting.
337
+ * <Service.DurationRange asChild>
338
+ * {React.forwardRef(({ range, ...props }, ref) => {
339
+ * if (range.hourOptions) {
340
+ * const { minDurationInMinutes: min, maxDurationInMinutes: max } =
341
+ * range.hourOptions;
342
+ * return (
343
+ * <span ref={ref} {...props}>
344
+ * {min}-{max} min
345
+ * </span>
346
+ * );
347
+ * }
348
+ * if (range.dayOptions) {
349
+ * const { minDurationInDays: min, maxDurationInDays: max } =
350
+ * range.dayOptions;
351
+ * return (
352
+ * <span ref={ref} {...props}>
353
+ * {min}-{max} days
354
+ * </span>
355
+ * );
356
+ * }
357
+ * return <span ref={ref} {...props} />;
358
+ * })}
359
+ * </Service.DurationRange>
360
+ * ```
361
+ */
362
+ export const DurationRange = React.forwardRef((props, ref) => {
363
+ const { asChild, children, ...rest } = props;
364
+ return (_jsx(CoreService.Info, { children: ({ durationRange }) => {
365
+ if (!durationRange)
366
+ return null;
367
+ // When `unitType` is missing or unrecognised, no default content is
368
+ // rendered — consumers can still read the raw `range` via asChild.
369
+ const { unitType, hourOptions, dayOptions } = durationRange;
370
+ let min;
371
+ let max;
372
+ if (unitType === UnitType.HOUR) {
373
+ min = hourOptions?.minDurationInMinutes;
374
+ max = hourOptions?.maxDurationInMinutes;
375
+ }
376
+ else if (unitType === UnitType.DAY) {
377
+ min = dayOptions?.minDurationInDays;
378
+ max = dayOptions?.maxDurationInDays;
379
+ }
380
+ const hasRange = min != null && max != null;
381
+ return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, ...rest, "data-testid": TestIds.serviceDurationRange, customElement: children, customElementProps: { range: durationRange }, children: hasRange ? _jsx("span", { children: `${min} - ${max}` }) : null }));
382
+ } }));
383
+ });
384
+ DurationRange.displayName = 'Service.DurationRange';
305
385
  /**
306
386
  * Displays the service type (APPOINTMENT, CLASS, COURSE, etc.) with customizable rendering.
307
387
  *
@@ -1,24 +1,2 @@
1
- /**
2
- * Book Action - Orchestrates the booking flow
3
- *
4
- * 1. Validates booking data with canBook()
5
- * 2. Creates a booking via createBooking() from API layer
6
- * 3. Creates a checkout via createCheckout() from API layer
7
- * 4. Determines if checkout is required or can be skipped
8
- * 5. Returns appropriate result for navigation
9
- */
10
1
  import { type BookActionParams, type BookResult } from './types.js';
11
- /**
12
- * Executes the complete booking flow:
13
- * 1. Validates that all required data is present
14
- * 2. Creates a booking with the selected service, time slot, and form data
15
- * 3. Creates a checkout session for payment (includes contact details from booking)
16
- * 4. Determines if checkout page is required or can be skipped
17
- * 5. If checkout can be skipped (free/offline), creates order directly
18
- * 6. Returns appropriate result for navigation
19
- *
20
- * @param params - The booking action parameters
21
- * @returns BookResult with either checkoutId or orderId
22
- * @throws Error if validation fails, or booking/checkout/order creation fails
23
- */
24
2
  export declare function executeBookAction(params: BookActionParams): Promise<BookResult>;
@@ -1,35 +1,13 @@
1
- /**
2
- * Book Action - Orchestrates the booking flow
3
- *
4
- * 1. Validates booking data with canBook()
5
- * 2. Creates a booking via createBooking() from API layer
6
- * 3. Creates a checkout via createCheckout() from API layer
7
- * 4. Determines if checkout is required or can be skipped
8
- * 5. Returns appropriate result for navigation
9
- */
10
1
  import { createBooking } from '../../../api/create-booking/index.js';
11
- import { createCheckout } from '../../../api/create-checkout/index.js';
12
- import { createOrder } from '../../../api/create-order/index.js';
2
+ import { createCart } from '../../../api/create-cart/index.js';
3
+ import { calculateCart } from '../../../api/calculate-cart/index.js';
4
+ import { placeOrder } from '../../../api/place-order/index.js';
13
5
  import { buildBookingRequest } from './buildBookingRequest.js';
14
- import { buildCheckoutRequest } from './buildCheckoutRequest.js';
6
+ import { buildCartRequest } from './buildCartRequest.js';
15
7
  import { canBook } from './canBook.js';
16
8
  import { isCheckoutRequired } from './isCheckoutRequired.js';
17
9
  import { BookResultType, } from './types.js';
18
- /**
19
- * Executes the complete booking flow:
20
- * 1. Validates that all required data is present
21
- * 2. Creates a booking with the selected service, time slot, and form data
22
- * 3. Creates a checkout session for payment (includes contact details from booking)
23
- * 4. Determines if checkout page is required or can be skipped
24
- * 5. If checkout can be skipped (free/offline), creates order directly
25
- * 6. Returns appropriate result for navigation
26
- *
27
- * @param params - The booking action parameters
28
- * @returns BookResult with either checkoutId or orderId
29
- * @throws Error if validation fails, or booking/checkout/order creation fails
30
- */
31
10
  export async function executeBookAction(params) {
32
- // Step 0: Validate
33
11
  if (!canBook({
34
12
  serviceSelections: params.serviceSelections,
35
13
  formSubmission: params.formSubmission,
@@ -48,34 +26,37 @@ export async function executeBookAction(params) {
48
26
  if (!bookingId) {
49
27
  throw new Error('Failed to create booking');
50
28
  }
51
- // Step 2: Create checkout
52
- // businessLocationId: prefer timeSlot.location, fallback to global location
29
+ // Step 2: Create cart
53
30
  const firstSelection = params.serviceSelections[0];
54
31
  if (!firstSelection) {
55
32
  throw new Error('No service selection found');
56
33
  }
57
34
  const businessLocationId = firstSelection.timeSlot?.location?._id ?? undefined;
58
- const checkoutRequest = buildCheckoutRequest({
35
+ const cartRequest = buildCartRequest({
59
36
  bookingId,
60
37
  contactDetails,
61
38
  businessLocationId,
62
39
  appId: params.appId,
63
40
  });
64
- const checkoutResponse = await createCheckout(checkoutRequest);
65
- const checkout = checkoutResponse.checkout;
66
- if (!checkout?._id) {
67
- throw new Error('Failed to create checkout');
41
+ const cart = await createCart(cartRequest);
42
+ if (!cart._id) {
43
+ throw new Error('Failed to create cart');
68
44
  }
69
- // Step 3: Determine if checkout is required or can be skipped
45
+ // Step 3: Calculate cart to get totals (not stored on Cart V2 entity)
46
+ const { cart: calculatedCart, summary } = await calculateCart(cart._id);
47
+ if (!calculatedCart || !summary) {
48
+ throw new Error('Failed to calculate cart');
49
+ }
50
+ // Step 4: Determine if checkout is required or can be skipped
70
51
  const service = firstSelection.service;
71
- if (isCheckoutRequired(checkout, service)) {
72
- return { type: BookResultType.CheckoutRequired, checkoutId: checkout._id };
52
+ if (isCheckoutRequired(calculatedCart, summary, service)) {
53
+ return { type: BookResultType.CheckoutRequired, cartId: cart._id };
73
54
  }
74
- // Step 4: Skip checkout - create order directly
75
- const orderResponse = await createOrder(checkout._id);
55
+ // Step 5: Skip checkout — place order directly
56
+ const orderResponse = await placeOrder(cart._id);
76
57
  const orderId = orderResponse.orderId;
77
58
  if (!orderId) {
78
- throw new Error('Failed to create order');
59
+ throw new Error('Failed to place order');
79
60
  }
80
61
  return { type: BookResultType.CheckoutSkipped, orderId };
81
62
  }
@@ -0,0 +1,10 @@
1
+ import { type CreateCartOptions } from '../../../api/create-cart/index.js';
2
+ import type { ContactDetails } from '../../../api/create-booking/index.js';
3
+ export interface BuildCartParams {
4
+ bookingId: string;
5
+ contactDetails?: ContactDetails;
6
+ businessLocationId?: string;
7
+ /** Optional app ID override for the catalog reference. Defaults to BOOKING_APP_ID. */
8
+ appId?: string;
9
+ }
10
+ export declare function buildCartRequest(params: BuildCartParams): CreateCartOptions;
@@ -0,0 +1,34 @@
1
+ import { ChannelType, } from '../../../api/create-cart/index.js';
2
+ import { BOOKING_APP_ID } from '../../constants.js';
3
+ export function buildCartRequest(params) {
4
+ const { bookingId, contactDetails, businessLocationId, appId } = params;
5
+ const cart = {
6
+ source: { channelType: ChannelType.WEB },
7
+ };
8
+ if (businessLocationId) {
9
+ cart.businessInfo = { locationId: businessLocationId };
10
+ }
11
+ if (contactDetails) {
12
+ cart.customerInfo = {
13
+ ...(contactDetails.email ? { email: contactDetails.email } : {}),
14
+ };
15
+ if (contactDetails.fullAddress?.country) {
16
+ cart.deliveryInfo = { address: { ...contactDetails.fullAddress } };
17
+ cart.paymentInfo = {
18
+ billingAddress: { ...contactDetails.fullAddress },
19
+ };
20
+ }
21
+ }
22
+ return {
23
+ catalogItems: [
24
+ {
25
+ quantity: 1,
26
+ catalogReference: {
27
+ catalogItemId: bookingId,
28
+ appId: appId ?? BOOKING_APP_ID,
29
+ },
30
+ },
31
+ ],
32
+ cart,
33
+ };
34
+ }
@@ -4,6 +4,6 @@
4
4
  export { executeBookAction } from './bookAction.js';
5
5
  export { canBook, type CanBookParams } from './canBook.js';
6
6
  export { buildBookingRequest } from './buildBookingRequest.js';
7
- export { buildCheckoutRequest, type BuildCheckoutParams, } from './buildCheckoutRequest.js';
7
+ export { buildCartRequest, type BuildCartParams } from './buildCartRequest.js';
8
8
  export { isCheckoutRequired } from './isCheckoutRequired.js';
9
9
  export { BookResultType, type BookProps, type BookResult, type BookingError, type BookActionParams, type BookChildProps, } from './types.js';
@@ -4,6 +4,6 @@
4
4
  export { executeBookAction } from './bookAction.js';
5
5
  export { canBook } from './canBook.js';
6
6
  export { buildBookingRequest } from './buildBookingRequest.js';
7
- export { buildCheckoutRequest, } from './buildCheckoutRequest.js';
7
+ export { buildCartRequest } from './buildCartRequest.js';
8
8
  export { isCheckoutRequired } from './isCheckoutRequired.js';
9
9
  export { BookResultType, } from './types.js';
@@ -1,20 +1,4 @@
1
- /**
2
- * Determines if checkout page is required based on payment amounts
3
- */
4
- import type { Checkout } from '@wix/auto_sdk_ecom_checkout';
1
+ import type { Cart } from '../../../api/create-cart/index.js';
2
+ import type { CartSummary } from '../../../api/calculate-cart/index.js';
5
3
  import type { Service } from '@wix/auto_sdk_bookings_services';
6
- /**
7
- * Determines if checkout page is required based on payment amounts.
8
- *
9
- * Skip checkout when:
10
- * - Free booking: payNow = 0 AND payLater = 0
11
- * - Offline payment: payNow = 0
12
- *
13
- * Force checkout when:
14
- * - Service has cancellation fee policy
15
- *
16
- * @param checkout - The checkout response from createCheckout
17
- * @param service - The service being booked
18
- * @returns true if checkout page is required, false if can skip to order
19
- */
20
- export declare function isCheckoutRequired(checkout: Checkout, service: Service): boolean;
4
+ export declare function isCheckoutRequired(cart: Cart, summary: CartSummary, service: Service): boolean;
@@ -1,32 +1,14 @@
1
- /**
2
- * Determines if checkout page is required based on payment amounts
3
- */
4
- /**
5
- * Determines if checkout page is required based on payment amounts.
6
- *
7
- * Skip checkout when:
8
- * - Free booking: payNow = 0 AND payLater = 0
9
- * - Offline payment: payNow = 0
10
- *
11
- * Force checkout when:
12
- * - Service has cancellation fee policy
13
- *
14
- * @param checkout - The checkout response from createCheckout
15
- * @param service - The service being booked
16
- * @returns true if checkout page is required, false if can skip to order
17
- */
18
- export function isCheckoutRequired(checkout, service) {
19
- // Force checkout for cancellation fee policy
20
- const hasCancellationFee = service.bookingPolicy?.cancellationFeePolicy?.enabled;
21
- if (hasCancellationFee) {
1
+ export function isCheckoutRequired(cart, summary, service) {
2
+ if (service.bookingPolicy?.cancellationFeePolicy?.enabled) {
22
3
  return true;
23
4
  }
24
- const payNowAmount = Number(checkout.payNow?.total?.amount ?? 0);
25
- const payLaterAmount = Number(checkout.payLater?.total?.amount ?? 0);
26
- // Free or price plan: both amounts are 0
27
- const isFreeOrPricePlan = payNowAmount === 0 && payLaterAmount === 0;
28
- // Offline payment: payNow is 0
29
- const isOfflinePayment = payNowAmount === 0;
30
- // Skip checkout if free/price plan OR offline payment
31
- return !(isFreeOrPricePlan || isOfflinePayment);
5
+ const total = Number(summary.priceSummary?.total?.amount ?? 0);
6
+ if (total === 0) {
7
+ return false;
8
+ }
9
+ const paymentOption = cart.lineItems?.[0]?.paymentConfig?.paymentOption;
10
+ if (paymentOption === 'FULL_PAYMENT_OFFLINE') {
11
+ return false;
12
+ }
13
+ return true;
32
14
  }
@@ -16,7 +16,7 @@ export declare enum BookResultType {
16
16
  */
17
17
  export type BookResult = {
18
18
  type: BookResultType.CheckoutRequired;
19
- checkoutId: string;
19
+ cartId: string;
20
20
  } | {
21
21
  type: BookResultType.CheckoutSkipped;
22
22
  orderId: string;
@@ -4,7 +4,7 @@
4
4
  * Persists across page navigation in SPA until page refresh
5
5
  */
6
6
  import { type Signal } from '@wix/services-definitions/core-services/signals';
7
- import type { Service, Location as ServiceLocationType } from '@wix/auto_sdk_bookings_services';
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
9
  import type { FormValues } from '@wix/forms/components';
10
10
  import type { BookResult } from './book-action/types.js';
@@ -7,7 +7,7 @@ export { BookingService, BookingServiceDefinition, type BookingServiceConfig, ty
7
7
  export { TimeSlotListService, TimeSlotListServiceDefinition, TimeSlotService, TimeSlotServiceDefinition, ViewMode, loadTimeSlotListConfig, type TimeSlotListServiceAPI, type TimeSlotListServiceActions, type TimeSlotListServiceConfig, type TimeSlotServiceAPI, type TimeSlotServiceConfig, type LoadTimeSlotListConfigOptions, type LoadTimeSlotListConfigResult, } from './time-slot-list/index.js';
8
8
  export { ServiceListService, ServiceListServiceDefinition, type ServiceListServiceAPI, type ServiceListServiceConfig, type ServiceListActions, type QueryOptions, loadServiceListServiceInitialData, type SuccessServiceListServiceConfigResult, type ErrorServiceListServiceConfigResult, } from './service-list/service-list.js';
9
9
  export { SYNTHETIC_CUSTOM_ID, SYNTHETIC_CUSTOMER_ID, } from '../api/query-services/index.js';
10
- 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
+ export { executeBookAction, canBook, buildBookingRequest, buildCartRequest, type CanBookParams, type BookResult, type BookingError, type BookActionParams, type BookChildProps, type BookProps, type BuildCartParams, } from './booking/book-action/index.js';
11
11
  export { BookingFormService, BookingFormServiceDefinition, type BookingFormServiceAPI, type BookingFormServiceConfig, } from './booking-form/booking-form.js';
12
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';
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';
@@ -7,7 +7,7 @@ export { BookingService, BookingServiceDefinition, } from './booking/booking.js'
7
7
  export { TimeSlotListService, TimeSlotListServiceDefinition, TimeSlotService, TimeSlotServiceDefinition, ViewMode, loadTimeSlotListConfig, } from './time-slot-list/index.js';
8
8
  export { ServiceListService, ServiceListServiceDefinition, loadServiceListServiceInitialData, } from './service-list/service-list.js';
9
9
  export { SYNTHETIC_CUSTOM_ID, SYNTHETIC_CUSTOMER_ID, } from '../api/query-services/index.js';
10
- export { executeBookAction, canBook, buildBookingRequest, buildCheckoutRequest, } from './booking/book-action/index.js';
10
+ export { executeBookAction, canBook, buildBookingRequest, buildCartRequest, } from './booking/book-action/index.js';
11
11
  export { BookingFormService, BookingFormServiceDefinition, } from './booking-form/booking-form.js';
12
12
  export { PaymentService, PaymentServiceDefinition, loadPaymentConfig, } from './payment/payment.js';
13
13
  export { LocationListService, LocationListServiceDefinition, LocationType, loadLocationListServiceInitialData, locationListServiceBinding, getLocationById, } from './location-list/location-list.js';
@@ -5,7 +5,7 @@
5
5
  * @module Services/LocationList/Definition
6
6
  */
7
7
  import type { Signal, ReadOnlySignal } from '@wix/services-definitions/core-services/signals';
8
- import { LocationType, type Service } from '@wix/auto_sdk_bookings_services';
8
+ import { LocationTypeEnumLocationType as LocationType, type Service } from '@wix/auto_sdk_bookings_services';
9
9
  /**
10
10
  * Location type from the SDK
11
11
  * Represents a service location (BUSINESS, CUSTOM, or CUSTOMER type)
@@ -5,7 +5,7 @@
5
5
  * @module Services/LocationList/Definition
6
6
  */
7
7
  import { defineService } from '@wix/services-definitions';
8
- import { LocationType } from '@wix/auto_sdk_bookings_services';
8
+ import { LocationTypeEnumLocationType as LocationType, } from '@wix/auto_sdk_bookings_services';
9
9
  // ============================================================================
10
10
  // Service Definition
11
11
  // ============================================================================
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import { implementService } from '@wix/services-definitions';
8
8
  import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
9
- import { LocationType } from '@wix/auto_sdk_bookings_services';
9
+ import { LocationTypeEnumLocationType as LocationType } from '@wix/auto_sdk_bookings_services';
10
10
  import { LocationListServiceDefinition, } from './location-list.def.js';
11
11
  import { BookingServiceDefinition } from '../booking/booking.js';
12
12
  import { queryLocations } from '../../api/query-locations/index.js';
@@ -1,7 +1,7 @@
1
1
  export interface NavigationInfo {
2
2
  postFlowUrl: string;
3
3
  }
4
- export declare function navigateToCheckout({ checkoutId, navigationInfo, }: {
5
- checkoutId: string;
4
+ export declare function navigateToCheckout({ cartId, navigationInfo, }: {
5
+ cartId: string;
6
6
  navigationInfo: NavigationInfo;
7
7
  }): Promise<void>;