@wix/headless-bookings 0.0.11 → 0.0.13
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/api/index.d.ts +1 -0
- package/cjs/dist/api/index.js +1 -0
- package/cjs/dist/api/query-services/index.d.ts +6 -7
- package/cjs/dist/api/query-services/index.js +4 -4
- package/cjs/dist/api/time-slot-list/index.d.ts +53 -0
- package/cjs/dist/api/time-slot-list/index.js +133 -0
- package/cjs/dist/react/core/booking/Booking.d.ts +7 -7
- package/cjs/dist/react/core/booking/Booking.js +5 -5
- package/cjs/dist/react/core/location/Location.d.ts +3 -3
- package/cjs/dist/react/core/location/Location.js +2 -2
- package/cjs/dist/react/core/service/Service.d.ts +8 -8
- package/cjs/dist/react/core/service-list/ServiceList.d.ts +2 -2
- package/cjs/dist/react/location/Location.d.ts +3 -3
- package/cjs/dist/react/service/Service.d.ts +9 -9
- package/cjs/dist/react/service/Service.js +5 -5
- package/cjs/dist/react/service-list/ServiceList.d.ts +3 -3
- package/cjs/dist/services/booking/booking.d.ts +25 -16
- package/cjs/dist/services/booking/booking.js +50 -16
- package/cjs/dist/services/index.d.ts +2 -1
- package/cjs/dist/services/index.js +1 -0
- package/cjs/dist/services/service/service.d.ts +5 -5
- package/cjs/dist/services/service/service.js +20 -21
- package/cjs/dist/services/service-list/service-list.d.ts +3 -3
- package/cjs/dist/services/time-slot-list/index.d.ts +6 -0
- package/cjs/dist/services/time-slot-list/index.js +6 -0
- package/cjs/dist/services/time-slot-list/time-slot-list.d.ts +58 -0
- package/cjs/dist/services/time-slot-list/time-slot-list.def.d.ts +84 -0
- package/cjs/dist/services/time-slot-list/time-slot-list.def.js +17 -0
- package/cjs/dist/services/time-slot-list/time-slot-list.js +349 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +1 -0
- package/dist/api/query-services/index.d.ts +6 -7
- package/dist/api/query-services/index.js +4 -4
- package/dist/api/time-slot-list/index.d.ts +53 -0
- package/dist/api/time-slot-list/index.js +133 -0
- package/dist/react/core/booking/Booking.d.ts +7 -7
- package/dist/react/core/booking/Booking.js +5 -5
- package/dist/react/core/location/Location.d.ts +3 -3
- package/dist/react/core/location/Location.js +2 -2
- package/dist/react/core/service/Service.d.ts +8 -8
- package/dist/react/core/service-list/ServiceList.d.ts +2 -2
- package/dist/react/location/Location.d.ts +3 -3
- package/dist/react/service/Service.d.ts +9 -9
- package/dist/react/service/Service.js +5 -5
- package/dist/react/service-list/ServiceList.d.ts +3 -3
- package/dist/services/booking/booking.d.ts +25 -16
- package/dist/services/booking/booking.js +50 -16
- package/dist/services/index.d.ts +2 -1
- package/dist/services/index.js +1 -0
- package/dist/services/service/service.d.ts +5 -5
- package/dist/services/service/service.js +20 -21
- package/dist/services/service-list/service-list.d.ts +3 -3
- package/dist/services/time-slot-list/index.d.ts +6 -0
- package/dist/services/time-slot-list/index.js +6 -0
- package/dist/services/time-slot-list/time-slot-list.d.ts +58 -0
- package/dist/services/time-slot-list/time-slot-list.def.d.ts +84 -0
- package/dist/services/time-slot-list/time-slot-list.def.js +17 -0
- package/dist/services/time-slot-list/time-slot-list.js +349 -0
- package/package.json +2 -2
|
@@ -28,9 +28,9 @@ export function Root(props) {
|
|
|
28
28
|
* @example
|
|
29
29
|
* ```tsx
|
|
30
30
|
* <Booking.Data>
|
|
31
|
-
* {({
|
|
32
|
-
*
|
|
33
|
-
* <div>{
|
|
31
|
+
* {({ bookingSelections }) => (
|
|
32
|
+
* bookingSelections.length > 0 ? (
|
|
33
|
+
* <div>{bookingSelections.map(s => s.service.name).join(', ')}</div>
|
|
34
34
|
* ) : (
|
|
35
35
|
* <div>No services selected</div>
|
|
36
36
|
* )
|
|
@@ -41,10 +41,10 @@ export function Root(props) {
|
|
|
41
41
|
export function Data(props) {
|
|
42
42
|
const { children } = props;
|
|
43
43
|
const bookingService = useService(BookingServiceDefinition);
|
|
44
|
-
const
|
|
44
|
+
const bookingSelections = bookingService.bookingSelections.get();
|
|
45
45
|
const selectedTimeSlot = bookingService.timeSlot.get();
|
|
46
46
|
return children({
|
|
47
|
-
|
|
47
|
+
bookingSelections,
|
|
48
48
|
selectedTimeSlot,
|
|
49
49
|
});
|
|
50
50
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Converts location data to Address component format
|
|
5
5
|
*/
|
|
6
6
|
import React from 'react';
|
|
7
|
-
import {
|
|
7
|
+
import { LocationType, type Service } from '@wix/auto_sdk_bookings_services';
|
|
8
8
|
import type { AddressData as AddressDataType } from '@wix/headless-components/react';
|
|
9
9
|
/**
|
|
10
10
|
* Re-export AddressData type from Address component for convenience
|
|
@@ -14,14 +14,14 @@ export type AddressData = AddressDataType;
|
|
|
14
14
|
* Location render props passed to children
|
|
15
15
|
*/
|
|
16
16
|
export interface LocationRenderProps {
|
|
17
|
-
locationType:
|
|
17
|
+
locationType: LocationType;
|
|
18
18
|
address: AddressData | null;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
21
|
* Props for the core Location component
|
|
22
22
|
*/
|
|
23
23
|
export interface LocationProps {
|
|
24
|
-
location: NonNullable<
|
|
24
|
+
location: NonNullable<Service['locations']>[number];
|
|
25
25
|
children: (props: LocationRenderProps) => React.ReactNode;
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
* Handles business, custom, and customer location types
|
|
4
4
|
* Converts location data to Address component format
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { LocationType } from '@wix/auto_sdk_bookings_services';
|
|
7
7
|
/**
|
|
8
8
|
* Parses location data into Address component format
|
|
9
9
|
*/
|
|
10
10
|
function parseLocationAddress(location, locationType) {
|
|
11
11
|
// Handle customer location specially
|
|
12
|
-
if (locationType ===
|
|
12
|
+
if (locationType === LocationType.CUSTOMER) {
|
|
13
13
|
// For customer location, return an AddressData object with Customer's Place
|
|
14
14
|
return {
|
|
15
15
|
address: {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import React from 'react';
|
|
6
6
|
import { type ServiceServiceConfig } from '../../../services/service/service.js';
|
|
7
|
-
import {
|
|
7
|
+
import type { Service, Payment, BookingPolicy, Schedule } 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
|
|
@@ -22,7 +22,7 @@ export declare function Root(props: RootProps): React.ReactNode;
|
|
|
22
22
|
*/
|
|
23
23
|
export interface ServiceProps {
|
|
24
24
|
children: (data: {
|
|
25
|
-
service:
|
|
25
|
+
service: Service;
|
|
26
26
|
isLoading: boolean;
|
|
27
27
|
error: string | null;
|
|
28
28
|
}) => React.ReactNode;
|
|
@@ -55,7 +55,7 @@ export interface InfoProps {
|
|
|
55
55
|
name?: string;
|
|
56
56
|
_id?: string;
|
|
57
57
|
};
|
|
58
|
-
locations?: Array<NonNullable<
|
|
58
|
+
locations?: Array<NonNullable<Service['locations']>[number]>;
|
|
59
59
|
staff?: Array<{
|
|
60
60
|
name?: string;
|
|
61
61
|
_id?: string;
|
|
@@ -110,8 +110,8 @@ export declare function Info(props: InfoProps): React.ReactNode;
|
|
|
110
110
|
*/
|
|
111
111
|
export interface PriceProps {
|
|
112
112
|
children: (data: {
|
|
113
|
-
servicePayment:
|
|
114
|
-
rateType:
|
|
113
|
+
servicePayment: Payment | undefined;
|
|
114
|
+
rateType: Payment['rateType'] | undefined;
|
|
115
115
|
money: MoneyData | null;
|
|
116
116
|
minPrice: MoneyData | null;
|
|
117
117
|
maxPrice: MoneyData | null;
|
|
@@ -151,7 +151,7 @@ export interface ActionsProps {
|
|
|
151
151
|
select: () => void;
|
|
152
152
|
add: () => void;
|
|
153
153
|
remove: () => void;
|
|
154
|
-
rawService:
|
|
154
|
+
rawService: Service;
|
|
155
155
|
bookable: boolean;
|
|
156
156
|
selected: boolean;
|
|
157
157
|
requiresAvailability: boolean;
|
|
@@ -180,7 +180,7 @@ export declare function Actions(props: ActionsProps): React.ReactNode;
|
|
|
180
180
|
*/
|
|
181
181
|
export interface PolicyProps {
|
|
182
182
|
children: (data: {
|
|
183
|
-
bookingPolicy:
|
|
183
|
+
bookingPolicy: BookingPolicy | null;
|
|
184
184
|
cancellationPolicyEnabled: boolean;
|
|
185
185
|
limitLatestCancellationEnabled: boolean;
|
|
186
186
|
latestCancellationInMinutes: number | undefined;
|
|
@@ -219,7 +219,7 @@ export declare function Policy(props: PolicyProps): React.ReactNode;
|
|
|
219
219
|
*/
|
|
220
220
|
export interface ScheduleProps {
|
|
221
221
|
children: (data: {
|
|
222
|
-
schedule:
|
|
222
|
+
schedule: Schedule | null;
|
|
223
223
|
isClassOrCourse: boolean;
|
|
224
224
|
}) => React.ReactNode;
|
|
225
225
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import React from 'react';
|
|
6
6
|
import { type ServiceListServiceConfig, type QueryOptions } from '../../../services/service-list/service-list.js';
|
|
7
|
-
import type {
|
|
7
|
+
import type { Service } from '@wix/auto_sdk_bookings_services';
|
|
8
8
|
import type { PagingMetadata } from '../../../api/query-services/index.js';
|
|
9
9
|
/**
|
|
10
10
|
* Props for ServiceList.Root component
|
|
@@ -37,7 +37,7 @@ export interface ServicesProps {
|
|
|
37
37
|
*/
|
|
38
38
|
export interface ServicesRenderProps {
|
|
39
39
|
/** Array of services */
|
|
40
|
-
services:
|
|
40
|
+
services: Service[];
|
|
41
41
|
/** Whether services are currently loading */
|
|
42
42
|
isLoading: boolean;
|
|
43
43
|
/** Error message, or null if no error */
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
import * as CoreLocation from '../core/location/Location.js';
|
|
7
7
|
import { AsChildChildren } from '@wix/headless-utils/react';
|
|
8
|
-
import type
|
|
8
|
+
import { LocationType, type Service } from '@wix/auto_sdk_bookings_services';
|
|
9
9
|
/**
|
|
10
10
|
* Re-export AddressData type from core for convenience
|
|
11
11
|
*/
|
|
@@ -14,10 +14,10 @@ export type { AddressData } from '../core/location/Location.js';
|
|
|
14
14
|
* Props for Location.Root component
|
|
15
15
|
*/
|
|
16
16
|
export interface LocationRootProps {
|
|
17
|
-
location: NonNullable<
|
|
17
|
+
location: NonNullable<Service['locations']>[number];
|
|
18
18
|
asChild?: boolean;
|
|
19
19
|
children?: React.ReactNode | AsChildChildren<{
|
|
20
|
-
locationType:
|
|
20
|
+
locationType: LocationType;
|
|
21
21
|
address: CoreLocation.AddressData | null;
|
|
22
22
|
}>;
|
|
23
23
|
className?: string;
|
|
@@ -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 {
|
|
8
|
+
import { type Service, type Payment } from '@wix/auto_sdk_bookings_services';
|
|
9
9
|
/**
|
|
10
10
|
* Props for Service.Root component
|
|
11
11
|
*/
|
|
@@ -14,7 +14,7 @@ export interface ServiceRootProps {
|
|
|
14
14
|
selected: boolean;
|
|
15
15
|
bookable: boolean;
|
|
16
16
|
}>;
|
|
17
|
-
service:
|
|
17
|
+
service: Service;
|
|
18
18
|
appId?: string;
|
|
19
19
|
asChild?: boolean;
|
|
20
20
|
className?: string;
|
|
@@ -106,8 +106,8 @@ export declare const Description: React.ForwardRefExoticComponent<DescriptionPro
|
|
|
106
106
|
export interface PriceProps {
|
|
107
107
|
asChild?: boolean;
|
|
108
108
|
children?: AsChildChildren<{
|
|
109
|
-
servicePayment:
|
|
110
|
-
rateType:
|
|
109
|
+
servicePayment: Payment | undefined;
|
|
110
|
+
rateType: Payment['rateType'] | undefined;
|
|
111
111
|
money: MoneyData | null;
|
|
112
112
|
minPrice: MoneyData | null;
|
|
113
113
|
maxPrice: MoneyData | null;
|
|
@@ -327,7 +327,7 @@ export declare const Category: React.ForwardRefExoticComponent<CategoryProps & R
|
|
|
327
327
|
/**
|
|
328
328
|
* Type for location
|
|
329
329
|
*/
|
|
330
|
-
type LocationType = NonNullable<
|
|
330
|
+
type LocationType = NonNullable<Service['locations']>[number] & {
|
|
331
331
|
id: string;
|
|
332
332
|
};
|
|
333
333
|
/**
|
|
@@ -717,7 +717,7 @@ export declare const MediaItems: React.ForwardRefExoticComponent<MediaItemsProps
|
|
|
717
717
|
export interface RawProps {
|
|
718
718
|
asChild?: boolean;
|
|
719
719
|
children?: AsChildChildren<{
|
|
720
|
-
service:
|
|
720
|
+
service: Service;
|
|
721
721
|
isLoading: boolean;
|
|
722
722
|
error: string | null;
|
|
723
723
|
}>;
|
|
@@ -755,7 +755,7 @@ export declare namespace Actions {
|
|
|
755
755
|
selected: boolean;
|
|
756
756
|
requiresAvailability: boolean;
|
|
757
757
|
onClick: () => void;
|
|
758
|
-
service:
|
|
758
|
+
service: Service;
|
|
759
759
|
}) => React.ReactNode);
|
|
760
760
|
className?: string;
|
|
761
761
|
label?: string;
|
|
@@ -795,7 +795,7 @@ export declare namespace Actions {
|
|
|
795
795
|
selected: boolean;
|
|
796
796
|
requiresAvailability: boolean;
|
|
797
797
|
onClick: () => void;
|
|
798
|
-
service:
|
|
798
|
+
service: Service;
|
|
799
799
|
}) => React.ReactNode);
|
|
800
800
|
className?: string;
|
|
801
801
|
label?: string;
|
|
@@ -835,7 +835,7 @@ export declare namespace Actions {
|
|
|
835
835
|
selected: boolean;
|
|
836
836
|
requiresAvailability: boolean;
|
|
837
837
|
onClick: () => void;
|
|
838
|
-
service:
|
|
838
|
+
service: Service;
|
|
839
839
|
}) => React.ReactNode);
|
|
840
840
|
className?: string;
|
|
841
841
|
label?: string;
|
|
@@ -9,7 +9,7 @@ import { AsChildSlot } from '@wix/headless-utils/react';
|
|
|
9
9
|
import { Money, GenericList } from '@wix/headless-components/react';
|
|
10
10
|
import { WixMediaImage } from '@wix/headless-media/react';
|
|
11
11
|
import { MediaGallery } from '@wix/headless-media/react';
|
|
12
|
-
import {
|
|
12
|
+
import { RateType, } from '@wix/auto_sdk_bookings_services';
|
|
13
13
|
import * as Location from '../location/Location.js';
|
|
14
14
|
var TestIds;
|
|
15
15
|
(function (TestIds) {
|
|
@@ -160,17 +160,17 @@ export const Price = React.forwardRef((props, ref) => {
|
|
|
160
160
|
// Default rendering based on rate type
|
|
161
161
|
const renderDefaultPrice = () => {
|
|
162
162
|
switch (rateType) {
|
|
163
|
-
case
|
|
163
|
+
case RateType.FIXED:
|
|
164
164
|
return money ? (_jsx(Money, { money: money, className: className })) : null;
|
|
165
|
-
case
|
|
165
|
+
case RateType.VARIED:
|
|
166
166
|
if (minPrice && maxPrice) {
|
|
167
167
|
return (_jsxs("span", { className: className, "data-testid": TestIds.servicePrice, children: [_jsx(Money, { money: minPrice }), " - ", _jsx(Money, { money: maxPrice })] }));
|
|
168
168
|
}
|
|
169
169
|
// Fallback to defaultPrice if min/max not available
|
|
170
170
|
return money ? (_jsx(Money, { money: money, className: className })) : null;
|
|
171
|
-
case
|
|
171
|
+
case RateType.CUSTOM:
|
|
172
172
|
return priceDescription ? (_jsx("span", { className: className, "data-testid": TestIds.servicePrice, children: priceDescription })) : null;
|
|
173
|
-
case
|
|
173
|
+
case RateType.NO_FEE:
|
|
174
174
|
return money ? (_jsx(Money, { money: money, className: className })) : null;
|
|
175
175
|
default:
|
|
176
176
|
// UNKNOWN_RATE_TYPE or undefined
|
|
@@ -6,7 +6,7 @@ import React from 'react';
|
|
|
6
6
|
import { ListVariant, GenericListLoadMoreRenderProps } from '@wix/headless-components/react';
|
|
7
7
|
import { AsChildChildren } from '@wix/headless-utils/react';
|
|
8
8
|
import type { ServiceListServiceConfig } from '../../services/service-list/service-list.js';
|
|
9
|
-
import type {
|
|
9
|
+
import type { Service as ServiceType } from '@wix/auto_sdk_bookings_services';
|
|
10
10
|
/**
|
|
11
11
|
* Props for the ServiceList root component
|
|
12
12
|
*/
|
|
@@ -79,7 +79,7 @@ export type ServiceRootChildren = AsChildChildren<{
|
|
|
79
79
|
* Supports both ReactNode and function children that receive { selected, bookable }
|
|
80
80
|
*/
|
|
81
81
|
export interface ServiceItemWrapperProps {
|
|
82
|
-
item:
|
|
82
|
+
item: ServiceType;
|
|
83
83
|
index?: number;
|
|
84
84
|
/** Children can be ReactNode or a function that receives { selected, bookable } from Service.Root */
|
|
85
85
|
children: React.ReactNode | ServiceRootChildren;
|
|
@@ -89,7 +89,7 @@ export interface ServiceItemWrapperProps {
|
|
|
89
89
|
* Provides items array and itemWrapper function for custom rendering
|
|
90
90
|
*/
|
|
91
91
|
export interface ServiceRepeaterRenderProps {
|
|
92
|
-
items:
|
|
92
|
+
items: ServiceType[];
|
|
93
93
|
variant?: ListVariant;
|
|
94
94
|
/** Wraps each item in Service.Root - children can be ReactNode or function receiving { selected, bookable } */
|
|
95
95
|
itemWrapper: (props: ServiceItemWrapperProps) => React.ReactNode;
|
|
@@ -4,15 +4,20 @@
|
|
|
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 {
|
|
7
|
+
import type { Service } from '@wix/auto_sdk_bookings_services';
|
|
8
|
+
import type { TimeSlot, Resource, NestedTimeSlot } from '@wix/auto_sdk_bookings_availability-time-slots';
|
|
8
9
|
import type { FormValues } from '@wix/form-public';
|
|
9
10
|
/**
|
|
10
|
-
*
|
|
11
|
+
* BookingSelection contains the service AND its related selections
|
|
11
12
|
*/
|
|
12
|
-
export interface
|
|
13
|
-
service
|
|
13
|
+
export interface BookingSelection {
|
|
14
|
+
/** Unique identifier for this booking instance (allows same service multiple times) */
|
|
15
|
+
instanceId: string;
|
|
16
|
+
service: Service;
|
|
14
17
|
/** Selected resources (staff members, rooms, etc.) */
|
|
15
|
-
|
|
18
|
+
staff?: Resource;
|
|
19
|
+
/** Per-service slot data from nested slots (for multi-service bookings) */
|
|
20
|
+
nestedSlotData?: NestedTimeSlot;
|
|
16
21
|
}
|
|
17
22
|
export interface Location {
|
|
18
23
|
id: string;
|
|
@@ -22,12 +27,16 @@ export interface Location {
|
|
|
22
27
|
* BookingService actions - setters only, no API calls
|
|
23
28
|
*/
|
|
24
29
|
export interface BookingServiceActions {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
30
|
+
/** Clears all booking selections and sets a single service (instanceId is auto-generated) */
|
|
31
|
+
setService(service: Omit<BookingSelection, 'instanceId'>): string;
|
|
32
|
+
/** Adds a service and returns the generated instanceId */
|
|
33
|
+
addService(service: Omit<BookingSelection, 'instanceId'>): string;
|
|
34
|
+
/** Updates a booking selection. If no instanceId provided, updates the first selection. */
|
|
35
|
+
updateBookingSelection(updates: Partial<Omit<BookingSelection, 'instanceId'>>, instanceId?: string): void;
|
|
36
|
+
/** Removes a booking selection. If no instanceId provided, removes the first selection. */
|
|
37
|
+
removeBookingSelection(instanceId?: string): void;
|
|
29
38
|
clearServices(): void;
|
|
30
|
-
setTimeSlot(slot:
|
|
39
|
+
setTimeSlot(slot: TimeSlot | null): void;
|
|
31
40
|
clearTimeSlot(): void;
|
|
32
41
|
setLocation(location: Location | null): void;
|
|
33
42
|
clearLocation(): void;
|
|
@@ -40,10 +49,10 @@ export interface BookingServiceActions {
|
|
|
40
49
|
* Pure state management - no API calls
|
|
41
50
|
*/
|
|
42
51
|
export interface BookingService {
|
|
43
|
-
/** Signal containing the
|
|
44
|
-
|
|
52
|
+
/** Signal containing the booking selections (services with their related data) */
|
|
53
|
+
bookingSelections: Signal<BookingSelection[]>;
|
|
45
54
|
/** Signal containing the currently selected time slot */
|
|
46
|
-
timeSlot: Signal<
|
|
55
|
+
timeSlot: Signal<TimeSlot | null>;
|
|
47
56
|
/** Signal containing the selected location (derived from timeSlot) */
|
|
48
57
|
location: Signal<Location | null>;
|
|
49
58
|
/** Signal containing the form values */
|
|
@@ -64,10 +73,10 @@ export declare const BookingServiceDefinition: string & {
|
|
|
64
73
|
* Note: location is NOT in config - it's derived internally from timeSlot
|
|
65
74
|
*/
|
|
66
75
|
export interface BookingServiceConfig {
|
|
67
|
-
/** Optional initial
|
|
68
|
-
|
|
76
|
+
/** Optional initial booking selections to pre-populate */
|
|
77
|
+
initialBookingSelections?: BookingSelection[];
|
|
69
78
|
/** Optional initial time slot to pre-populate */
|
|
70
|
-
initialTimeSlot?:
|
|
79
|
+
initialTimeSlot?: TimeSlot | null;
|
|
71
80
|
/** Optional initial form values */
|
|
72
81
|
initialFormValues?: FormValues | null;
|
|
73
82
|
}
|
|
@@ -5,6 +5,15 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { defineService, implementService } from '@wix/services-definitions';
|
|
7
7
|
import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Types
|
|
10
|
+
// ============================================================================
|
|
11
|
+
/**
|
|
12
|
+
* Generates a unique instance ID for service selections
|
|
13
|
+
*/
|
|
14
|
+
function generateInstanceId() {
|
|
15
|
+
return crypto.randomUUID();
|
|
16
|
+
}
|
|
8
17
|
/**
|
|
9
18
|
* Service definition for Booking
|
|
10
19
|
*/
|
|
@@ -39,7 +48,12 @@ export const BookingServiceDefinition = defineService('booking');
|
|
|
39
48
|
export const BookingService = implementService.withConfig()(BookingServiceDefinition, ({ getService, config }) => {
|
|
40
49
|
const signalsService = getService(SignalsServiceDefinition);
|
|
41
50
|
// Initialize signals with config values
|
|
42
|
-
|
|
51
|
+
// Ensure all initial booking selections have instanceIds
|
|
52
|
+
const initialSelectionsWithIds = (config.initialBookingSelections || []).map((s) => ({
|
|
53
|
+
...s,
|
|
54
|
+
instanceId: s.instanceId || generateInstanceId(),
|
|
55
|
+
}));
|
|
56
|
+
const bookingSelectionsSignal = signalsService.signal(initialSelectionsWithIds);
|
|
43
57
|
const timeSlotSignal = signalsService.signal(config.initialTimeSlot || null);
|
|
44
58
|
// Location is derived internally - initialize as null
|
|
45
59
|
const locationSignal = signalsService.signal(null);
|
|
@@ -49,25 +63,45 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
|
|
|
49
63
|
// ========================================================================
|
|
50
64
|
const actions = {
|
|
51
65
|
// Services actions
|
|
52
|
-
|
|
53
|
-
|
|
66
|
+
setService(service) {
|
|
67
|
+
const instanceId = generateInstanceId();
|
|
68
|
+
const newSelection = {
|
|
69
|
+
...service,
|
|
70
|
+
instanceId,
|
|
71
|
+
};
|
|
72
|
+
bookingSelectionsSignal.set([newSelection]);
|
|
73
|
+
return instanceId;
|
|
54
74
|
},
|
|
55
75
|
addService(service) {
|
|
56
|
-
const
|
|
57
|
-
|
|
76
|
+
const instanceId = generateInstanceId();
|
|
77
|
+
const current = bookingSelectionsSignal.get();
|
|
78
|
+
const newSelection = {
|
|
79
|
+
...service,
|
|
80
|
+
instanceId,
|
|
81
|
+
};
|
|
82
|
+
bookingSelectionsSignal.set([...current, newSelection]);
|
|
83
|
+
return instanceId;
|
|
58
84
|
},
|
|
59
|
-
|
|
60
|
-
const current =
|
|
61
|
-
|
|
62
|
-
|
|
85
|
+
updateBookingSelection(updates, instanceId) {
|
|
86
|
+
const current = bookingSelectionsSignal.get();
|
|
87
|
+
// If no instanceId provided, update the first selection (index 0)
|
|
88
|
+
const targetId = instanceId ?? current[0]?.instanceId;
|
|
89
|
+
const updated = current.map((s) => s.instanceId === targetId ? { ...s, ...updates } : s);
|
|
90
|
+
bookingSelectionsSignal.set(updated);
|
|
63
91
|
},
|
|
64
|
-
|
|
65
|
-
const current =
|
|
66
|
-
|
|
67
|
-
|
|
92
|
+
removeBookingSelection(instanceId) {
|
|
93
|
+
const current = bookingSelectionsSignal.get();
|
|
94
|
+
if (!instanceId) {
|
|
95
|
+
// Remove first selection if no instanceId provided
|
|
96
|
+
bookingSelectionsSignal.set(current.slice(1));
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
const filtered = current.filter((s) => s.instanceId !== instanceId);
|
|
100
|
+
bookingSelectionsSignal.set(filtered);
|
|
101
|
+
}
|
|
68
102
|
},
|
|
69
103
|
clearServices() {
|
|
70
|
-
|
|
104
|
+
bookingSelectionsSignal.set([]);
|
|
71
105
|
},
|
|
72
106
|
// Time Slot actions
|
|
73
107
|
setTimeSlot(slot) {
|
|
@@ -92,14 +126,14 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
|
|
|
92
126
|
},
|
|
93
127
|
// Clear all
|
|
94
128
|
clearAll() {
|
|
95
|
-
|
|
129
|
+
bookingSelectionsSignal.set([]);
|
|
96
130
|
timeSlotSignal.set(null);
|
|
97
131
|
locationSignal.set(null);
|
|
98
132
|
formValuesSignal.set(null);
|
|
99
133
|
},
|
|
100
134
|
};
|
|
101
135
|
return {
|
|
102
|
-
|
|
136
|
+
bookingSelections: bookingSelectionsSignal,
|
|
103
137
|
timeSlot: timeSlotSignal,
|
|
104
138
|
location: locationSignal,
|
|
105
139
|
formValues: formValuesSignal,
|
package/dist/services/index.d.ts
CHANGED
|
@@ -3,5 +3,6 @@
|
|
|
3
3
|
* Main export file for all service definitions and implementations
|
|
4
4
|
*/
|
|
5
5
|
export { ServiceService, ServiceServiceDefinition, type ServiceServiceAPI, type ServiceServiceConfig, type ServiceActions, type ServicePaymentData, loadServiceServiceInitialData, type SuccessServiceServiceConfigResult, type NotFoundServiceServiceConfigResult, } from './service/service.js';
|
|
6
|
-
export { BookingService, BookingServiceDefinition, type BookingServiceConfig, type
|
|
6
|
+
export { BookingService, BookingServiceDefinition, type BookingServiceConfig, type BookingSelection, type Location, type BookingServiceActions, } from './booking/booking.js';
|
|
7
|
+
export { TimeSlotListService, TimeSlotListServiceDefinition, ViewMode, loadTimeSlotListConfig, type TimeSlotListServiceAPI, type TimeSlotListServiceActions, type TimeSlotListServiceConfig, type SlotSelection, type LoadTimeSlotListConfigOptions, type LoadTimeSlotListConfigResult, } from './time-slot-list/index.js';
|
|
7
8
|
export { ServiceListService, ServiceListServiceDefinition, type ServiceListServiceAPI, type ServiceListServiceConfig, type ServiceListActions, type QueryOptions, loadServiceListServiceInitialData, type SuccessServiceListServiceConfigResult, type ErrorServiceListServiceConfigResult, } from './service-list/service-list.js';
|
package/dist/services/index.js
CHANGED
|
@@ -4,4 +4,5 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { ServiceService, ServiceServiceDefinition, loadServiceServiceInitialData, } from './service/service.js';
|
|
6
6
|
export { BookingService, BookingServiceDefinition, } from './booking/booking.js';
|
|
7
|
+
export { TimeSlotListService, TimeSlotListServiceDefinition, ViewMode, loadTimeSlotListConfig, } from './time-slot-list/index.js';
|
|
7
8
|
export { ServiceListService, ServiceListServiceDefinition, loadServiceListServiceInitialData, } from './service-list/service-list.js';
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Handles loading and managing a single service's data, loading state, and errors.
|
|
4
4
|
*/
|
|
5
5
|
import { type Signal, type ReadOnlySignal } from '@wix/services-definitions/core-services/signals';
|
|
6
|
-
import {
|
|
6
|
+
import { type Service, type Payment } from '@wix/auto_sdk_bookings_services';
|
|
7
7
|
import type { MoneyData } from '@wix/headless-components/react';
|
|
8
8
|
/**
|
|
9
9
|
* Actions object for service selection
|
|
@@ -23,9 +23,9 @@ export interface ServiceActions {
|
|
|
23
23
|
*/
|
|
24
24
|
export interface ServicePaymentData {
|
|
25
25
|
/** The service payment information from the service */
|
|
26
|
-
servicePayment:
|
|
26
|
+
servicePayment: Payment | undefined;
|
|
27
27
|
/** The rate type of the service (FIXED, VARIED, CUSTOM, NO_FEE, etc.) */
|
|
28
|
-
rateType:
|
|
28
|
+
rateType: Payment['rateType'] | undefined;
|
|
29
29
|
/** Primary price (used for FIXED or VARIED default) */
|
|
30
30
|
money: MoneyData | null;
|
|
31
31
|
/** Minimum price (used for VARIED) */
|
|
@@ -46,7 +46,7 @@ export interface ServicePaymentData {
|
|
|
46
46
|
*/
|
|
47
47
|
export interface ServiceServiceAPI {
|
|
48
48
|
/** Reactive signal containing the current service data */
|
|
49
|
-
serviceSignal: Signal<
|
|
49
|
+
serviceSignal: Signal<Service>;
|
|
50
50
|
/** Reactive signal indicating if a service is currently being loaded */
|
|
51
51
|
isLoadingSignal: Signal<boolean>;
|
|
52
52
|
/** Reactive signal containing any error message, or null if no error */
|
|
@@ -83,7 +83,7 @@ export declare const ServiceServiceDefinition: string & {
|
|
|
83
83
|
*/
|
|
84
84
|
export interface ServiceServiceConfig {
|
|
85
85
|
/** The initial service data to configure the service with */
|
|
86
|
-
service?:
|
|
86
|
+
service?: Service;
|
|
87
87
|
/** The service ID to load if no initial service is provided */
|
|
88
88
|
serviceId?: string;
|
|
89
89
|
/** The service slug to load if no initial service is provided */
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { defineService, implementService } from '@wix/services-definitions';
|
|
6
6
|
import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
|
|
7
|
-
import {
|
|
7
|
+
import { ServiceType, RateType, } from '@wix/auto_sdk_bookings_services';
|
|
8
8
|
import { getServiceById, getServiceBySlug, } from '../../api/query-services/index.js';
|
|
9
|
-
import { BookingServiceDefinition
|
|
9
|
+
import { BookingServiceDefinition } from '../booking/booking.js';
|
|
10
10
|
import { convertToMoneyData } from '../../utils/money.js';
|
|
11
11
|
/**
|
|
12
12
|
* Booking app ID constant
|
|
@@ -81,15 +81,15 @@ export const ServiceService = implementService.withConfig()(ServiceServiceDefini
|
|
|
81
81
|
const currentService = serviceSignal.get();
|
|
82
82
|
if (!currentService._id)
|
|
83
83
|
return false;
|
|
84
|
-
const
|
|
85
|
-
return
|
|
84
|
+
const selections = bookingService.bookingSelections.get();
|
|
85
|
+
return selections.some((selection) => selection.service._id === currentService._id);
|
|
86
86
|
});
|
|
87
87
|
// requiresAvailability signal - true for APPOINTMENT and CLASS types
|
|
88
88
|
const requiresAvailabilitySignal = signalsService.computed(() => {
|
|
89
89
|
const currentService = serviceSignal.get();
|
|
90
90
|
const serviceType = currentService.type;
|
|
91
|
-
return (serviceType ===
|
|
92
|
-
serviceType ===
|
|
91
|
+
return (serviceType === ServiceType.APPOINTMENT ||
|
|
92
|
+
serviceType === ServiceType.CLASS);
|
|
93
93
|
});
|
|
94
94
|
// paymentData signal - computed payment data from service
|
|
95
95
|
const paymentDataSignal = signalsService.computed(() => {
|
|
@@ -104,21 +104,21 @@ export const ServiceService = implementService.withConfig()(ServiceServiceDefini
|
|
|
104
104
|
// Extract pricing based on rate type
|
|
105
105
|
if (payment) {
|
|
106
106
|
switch (rateType) {
|
|
107
|
-
case
|
|
107
|
+
case RateType.FIXED:
|
|
108
108
|
// FIXED: Use payment.fixed.price
|
|
109
109
|
money = convertToMoneyData(payment.fixed?.price);
|
|
110
110
|
break;
|
|
111
|
-
case
|
|
111
|
+
case RateType.VARIED:
|
|
112
112
|
// VARIED: Use defaultPrice as money, plus min/max for range
|
|
113
113
|
money = convertToMoneyData(payment.varied?.defaultPrice);
|
|
114
114
|
minPrice = convertToMoneyData(payment.varied?.minPrice);
|
|
115
115
|
maxPrice = convertToMoneyData(payment.varied?.maxPrice);
|
|
116
116
|
break;
|
|
117
|
-
case
|
|
117
|
+
case RateType.CUSTOM:
|
|
118
118
|
// CUSTOM: Use description text (no numeric price)
|
|
119
119
|
priceDescription = payment.custom?.description || null;
|
|
120
120
|
break;
|
|
121
|
-
case
|
|
121
|
+
case RateType.NO_FEE:
|
|
122
122
|
// NO_FEE: Free service (amount = 0)
|
|
123
123
|
money = { amount: 0, currency: 'USD' };
|
|
124
124
|
break;
|
|
@@ -185,27 +185,26 @@ export const ServiceService = implementService.withConfig()(ServiceServiceDefini
|
|
|
185
185
|
if (!bookableSignal.get() || !bookingService)
|
|
186
186
|
return;
|
|
187
187
|
const currentService = serviceSignal.get();
|
|
188
|
-
|
|
189
|
-
service: currentService,
|
|
190
|
-
};
|
|
191
|
-
bookingService.actions.setServices([selection]);
|
|
188
|
+
bookingService.actions.setService({ service: currentService });
|
|
192
189
|
},
|
|
193
190
|
add: () => {
|
|
194
191
|
if (!bookableSignal.get() || !bookingService)
|
|
195
192
|
return;
|
|
196
193
|
const currentService = serviceSignal.get();
|
|
197
|
-
|
|
198
|
-
service: currentService,
|
|
199
|
-
};
|
|
200
|
-
bookingService.actions.addService(selection);
|
|
194
|
+
bookingService.actions.addService({ service: currentService });
|
|
201
195
|
},
|
|
202
196
|
remove: () => {
|
|
203
197
|
if (!bookableSignal.get() || !bookingService)
|
|
204
198
|
return;
|
|
205
199
|
const currentService = serviceSignal.get();
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
200
|
+
// Remove all instances of this service (by serviceId)
|
|
201
|
+
const selections = bookingService.bookingSelections.get();
|
|
202
|
+
const instancesToRemove = selections
|
|
203
|
+
.filter((s) => s.service._id === currentService._id)
|
|
204
|
+
.map((s) => s.instanceId);
|
|
205
|
+
instancesToRemove.forEach((instanceId) => {
|
|
206
|
+
bookingService.actions.removeBookingSelection(instanceId);
|
|
207
|
+
});
|
|
209
208
|
},
|
|
210
209
|
};
|
|
211
210
|
return {
|