@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.
- package/cjs/dist/__mocks__/booking/booking-mocks.d.ts +1 -1
- package/cjs/dist/__mocks__/services/services-mocks.d.ts +23 -0
- package/cjs/dist/__mocks__/services/services-mocks.js +65 -1
- package/cjs/dist/api/calculate-cart/index.d.ts +3 -0
- package/cjs/dist/api/calculate-cart/index.js +7 -0
- package/cjs/dist/api/create-cart/index.d.ts +3 -0
- package/cjs/dist/api/create-cart/index.js +10 -0
- package/cjs/dist/api/index.d.ts +3 -9
- package/cjs/dist/api/index.js +12 -17
- package/cjs/dist/api/place-order/index.d.ts +3 -0
- package/cjs/dist/api/place-order/index.js +7 -0
- package/cjs/dist/api/query-services/index.js +2 -2
- package/cjs/dist/react/booking/Book.js +1 -1
- package/cjs/dist/react/core/booking/Book.d.ts +1 -1
- package/cjs/dist/react/core/booking/Book.js +1 -1
- package/cjs/dist/react/core/booking/Booking.d.ts +1 -1
- package/cjs/dist/react/core/booking/Booking.js +14 -5
- package/cjs/dist/react/core/location/Location.d.ts +1 -1
- package/cjs/dist/react/core/location/Location.js +5 -5
- package/cjs/dist/react/core/service/Service.d.ts +10 -1
- package/cjs/dist/react/core/service/Service.js +5 -4
- package/cjs/dist/react/service/Service.d.ts +68 -1
- package/cjs/dist/react/service/Service.js +81 -1
- package/cjs/dist/services/booking/book-action/bookAction.d.ts +0 -22
- package/cjs/dist/services/booking/book-action/bookAction.js +20 -39
- package/cjs/dist/services/booking/book-action/buildCartRequest.d.ts +10 -0
- package/cjs/dist/services/booking/book-action/buildCartRequest.js +37 -0
- package/cjs/dist/services/booking/book-action/index.d.ts +1 -1
- package/cjs/dist/services/booking/book-action/index.js +3 -3
- package/cjs/dist/services/booking/book-action/isCheckoutRequired.d.ts +3 -19
- package/cjs/dist/services/booking/book-action/isCheckoutRequired.js +11 -29
- package/cjs/dist/services/booking/book-action/types.d.ts +1 -1
- package/cjs/dist/services/booking/booking.d.ts +1 -1
- package/cjs/dist/services/index.d.ts +1 -1
- package/cjs/dist/services/index.js +2 -2
- package/cjs/dist/services/location-list/location-list.def.d.ts +1 -1
- package/cjs/dist/services/location-list/location-list.def.js +1 -1
- package/cjs/dist/services/location-list/location-list.js +7 -7
- package/cjs/dist/utils/navigation.d.ts +2 -2
- package/cjs/dist/utils/navigation.js +2 -2
- package/dist/__mocks__/booking/booking-mocks.d.ts +1 -1
- package/dist/__mocks__/services/services-mocks.d.ts +23 -0
- package/dist/__mocks__/services/services-mocks.js +64 -0
- package/dist/api/calculate-cart/index.d.ts +3 -0
- package/dist/api/calculate-cart/index.js +4 -0
- package/dist/api/create-cart/index.d.ts +3 -0
- package/dist/api/create-cart/index.js +5 -0
- package/dist/api/index.d.ts +3 -9
- package/dist/api/index.js +3 -9
- package/dist/api/place-order/index.d.ts +3 -0
- package/dist/api/place-order/index.js +4 -0
- package/dist/api/query-services/index.js +1 -1
- package/dist/react/booking/Book.js +1 -1
- package/dist/react/core/booking/Book.d.ts +1 -1
- package/dist/react/core/booking/Book.js +1 -1
- package/dist/react/core/booking/Booking.d.ts +1 -1
- package/dist/react/core/booking/Booking.js +14 -5
- package/dist/react/core/location/Location.d.ts +1 -1
- package/dist/react/core/location/Location.js +1 -1
- package/dist/react/core/service/Service.d.ts +10 -1
- package/dist/react/core/service/Service.js +5 -4
- package/dist/react/service/Service.d.ts +68 -1
- package/dist/react/service/Service.js +81 -1
- package/dist/services/booking/book-action/bookAction.d.ts +0 -22
- package/dist/services/booking/book-action/bookAction.js +20 -39
- package/dist/services/booking/book-action/buildCartRequest.d.ts +10 -0
- package/dist/services/booking/book-action/buildCartRequest.js +34 -0
- package/dist/services/booking/book-action/index.d.ts +1 -1
- package/dist/services/booking/book-action/index.js +1 -1
- package/dist/services/booking/book-action/isCheckoutRequired.d.ts +3 -19
- package/dist/services/booking/book-action/isCheckoutRequired.js +11 -29
- package/dist/services/booking/book-action/types.d.ts +1 -1
- package/dist/services/booking/booking.d.ts +1 -1
- package/dist/services/index.d.ts +1 -1
- package/dist/services/index.js +1 -1
- package/dist/services/location-list/location-list.def.d.ts +1 -1
- package/dist/services/location-list/location-list.def.js +1 -1
- package/dist/services/location-list/location-list.js +1 -1
- package/dist/utils/navigation.d.ts +2 -2
- package/dist/utils/navigation.js +2 -2
- package/package.json +5 -4
- package/cjs/dist/api/create-checkout/index.d.ts +0 -40
- package/cjs/dist/api/create-checkout/index.js +0 -42
- package/cjs/dist/api/create-order/index.d.ts +0 -20
- package/cjs/dist/api/create-order/index.js +0 -24
- package/cjs/dist/services/booking/book-action/buildCheckoutRequest.d.ts +0 -28
- package/cjs/dist/services/booking/book-action/buildCheckoutRequest.js +0 -65
- package/dist/api/create-checkout/index.d.ts +0 -40
- package/dist/api/create-checkout/index.js +0 -37
- package/dist/api/create-order/index.d.ts +0 -20
- package/dist/api/create-order/index.js +0 -21
- package/dist/services/booking/book-action/buildCheckoutRequest.d.ts +0 -28
- 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
|
|
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
|
|
69
|
-
...(
|
|
77
|
+
type,
|
|
78
|
+
...(isCustomer
|
|
70
79
|
? null
|
|
71
|
-
:
|
|
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
|
-
|
|
91
|
-
|
|
92
|
-
const
|
|
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
|
|
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 {
|
|
12
|
-
import {
|
|
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 {
|
|
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
|
|
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
|
|
35
|
+
const cartRequest = buildCartRequest({
|
|
59
36
|
bookingId,
|
|
60
37
|
contactDetails,
|
|
61
38
|
businessLocationId,
|
|
62
39
|
appId: params.appId,
|
|
63
40
|
});
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
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:
|
|
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(
|
|
72
|
-
return { type: BookResultType.CheckoutRequired,
|
|
52
|
+
if (isCheckoutRequired(calculatedCart, summary, service)) {
|
|
53
|
+
return { type: BookResultType.CheckoutRequired, cartId: cart._id };
|
|
73
54
|
}
|
|
74
|
-
// Step
|
|
75
|
-
const orderResponse = await
|
|
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
|
|
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 {
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
}
|
|
@@ -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,
|
|
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';
|
package/dist/services/index.d.ts
CHANGED
|
@@ -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,
|
|
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';
|
package/dist/services/index.js
CHANGED
|
@@ -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,
|
|
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({
|
|
5
|
-
|
|
4
|
+
export declare function navigateToCheckout({ cartId, navigationInfo, }: {
|
|
5
|
+
cartId: string;
|
|
6
6
|
navigationInfo: NavigationInfo;
|
|
7
7
|
}): Promise<void>;
|