@wix/headless-bookings 0.0.9 → 0.0.11

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 (69) hide show
  1. package/cjs/dist/api/index.d.ts +10 -1
  2. package/cjs/dist/api/index.js +10 -1
  3. package/cjs/dist/api/query-services/index.d.ts +78 -0
  4. package/cjs/dist/api/query-services/index.js +137 -0
  5. package/cjs/dist/react/core/booking/Booking.d.ts +4 -4
  6. package/cjs/dist/react/core/booking/Booking.js +3 -3
  7. package/cjs/dist/react/core/location/Location.d.ts +44 -0
  8. package/cjs/dist/react/core/location/Location.js +78 -0
  9. package/cjs/dist/react/core/service/Service.d.ts +160 -17
  10. package/cjs/dist/react/core/service/Service.js +211 -13
  11. package/cjs/dist/react/core/service-list/ServiceList.d.ts +75 -0
  12. package/cjs/dist/react/core/service-list/ServiceList.js +58 -0
  13. package/cjs/dist/react/index.d.ts +2 -0
  14. package/cjs/dist/react/index.js +2 -0
  15. package/cjs/dist/react/location/Location.d.ts +77 -0
  16. package/cjs/dist/react/location/Location.js +89 -0
  17. package/cjs/dist/react/service/Service.d.ts +1036 -31
  18. package/cjs/dist/react/service/Service.js +1060 -47
  19. package/cjs/dist/react/service-list/ServiceList.d.ts +185 -0
  20. package/cjs/dist/react/service-list/ServiceList.js +184 -0
  21. package/cjs/dist/services/booking/booking.d.ts +50 -33
  22. package/cjs/dist/services/booking/booking.js +72 -38
  23. package/cjs/dist/services/index.d.ts +3 -2
  24. package/cjs/dist/services/index.js +3 -2
  25. package/cjs/dist/services/service/service.d.ts +71 -18
  26. package/cjs/dist/services/service/service.js +187 -52
  27. package/cjs/dist/services/service-list/service-list.d.ts +157 -0
  28. package/cjs/dist/services/service-list/service-list.js +274 -0
  29. package/cjs/dist/utils/dateAndTime.d.ts +2 -0
  30. package/cjs/dist/utils/dateAndTime.js +18 -0
  31. package/cjs/dist/utils/money.d.ts +21 -0
  32. package/cjs/dist/utils/money.js +34 -0
  33. package/dist/api/index.d.ts +10 -1
  34. package/dist/api/index.js +10 -1
  35. package/dist/api/query-services/index.d.ts +78 -0
  36. package/dist/api/query-services/index.js +137 -0
  37. package/dist/react/core/booking/Booking.d.ts +4 -4
  38. package/dist/react/core/booking/Booking.js +3 -3
  39. package/dist/react/core/location/Location.d.ts +44 -0
  40. package/dist/react/core/location/Location.js +78 -0
  41. package/dist/react/core/service/Service.d.ts +160 -17
  42. package/dist/react/core/service/Service.js +211 -13
  43. package/dist/react/core/service-list/ServiceList.d.ts +75 -0
  44. package/dist/react/core/service-list/ServiceList.js +58 -0
  45. package/dist/react/index.d.ts +2 -0
  46. package/dist/react/index.js +2 -0
  47. package/dist/react/location/Location.d.ts +77 -0
  48. package/dist/react/location/Location.js +89 -0
  49. package/dist/react/service/Service.d.ts +1036 -31
  50. package/dist/react/service/Service.js +1060 -47
  51. package/dist/react/service-list/ServiceList.d.ts +185 -0
  52. package/dist/react/service-list/ServiceList.js +184 -0
  53. package/dist/services/booking/booking.d.ts +50 -33
  54. package/dist/services/booking/booking.js +72 -38
  55. package/dist/services/index.d.ts +3 -2
  56. package/dist/services/index.js +3 -2
  57. package/dist/services/service/service.d.ts +71 -18
  58. package/dist/services/service/service.js +187 -52
  59. package/dist/services/service-list/service-list.d.ts +157 -0
  60. package/dist/services/service-list/service-list.js +274 -0
  61. package/dist/utils/dateAndTime.d.ts +2 -0
  62. package/dist/utils/dateAndTime.js +18 -0
  63. package/dist/utils/money.d.ts +21 -0
  64. package/dist/utils/money.js +34 -0
  65. package/package.json +3 -2
  66. package/cjs/dist/api/query-service/index.d.ts +0 -23
  67. package/cjs/dist/api/query-service/index.js +0 -41
  68. package/dist/api/query-service/index.d.ts +0 -23
  69. package/dist/api/query-service/index.js +0 -41
@@ -0,0 +1,185 @@
1
+ /**
2
+ * ServiceList - High-level component for displaying services list
3
+ * Provides components for displaying services list with pagination
4
+ */
5
+ import React from 'react';
6
+ import { ListVariant, GenericListLoadMoreRenderProps } from '@wix/headless-components/react';
7
+ import { AsChildChildren } from '@wix/headless-utils/react';
8
+ import type { ServiceListServiceConfig } from '../../services/service-list/service-list.js';
9
+ import type { services } from '@wix/bookings';
10
+ /**
11
+ * Props for the ServiceList root component
12
+ */
13
+ export interface ServiceListRootProps {
14
+ children: React.ReactNode;
15
+ serviceListConfig?: ServiceListServiceConfig;
16
+ className?: string;
17
+ variant?: ListVariant;
18
+ }
19
+ /**
20
+ * Root component that provides the ServiceList service context for rendering services lists.
21
+ *
22
+ * @order 1
23
+ * @component
24
+ * @example
25
+ * ```tsx
26
+ * import { ServiceList } from '@wix/bookings/components';
27
+ *
28
+ * function ServicesPage({ serviceListConfig }) {
29
+ * return (
30
+ * <ServiceList.Root serviceListConfig={serviceListConfig}>
31
+ * <ServiceList.Services emptyState={<div>No services available</div>}>
32
+ * <ServiceList.ServiceRepeater>
33
+ * <Service.Name />
34
+ * <Service.Price />
35
+ * </ServiceList.ServiceRepeater>
36
+ * </ServiceList.Services>
37
+ * </ServiceList.Root>
38
+ * );
39
+ * }
40
+ * ```
41
+ */
42
+ export declare const Root: React.ForwardRefExoticComponent<ServiceListRootProps & React.RefAttributes<HTMLElement>>;
43
+ /**
44
+ * Props for ServiceList Services component
45
+ */
46
+ export interface ServicesProps {
47
+ children: React.ReactNode;
48
+ emptyState?: React.ReactNode;
49
+ infiniteScroll?: boolean;
50
+ pageSize?: number;
51
+ className?: string;
52
+ }
53
+ /**
54
+ * Container for the services list with empty state support.
55
+ * Wraps GenericList.Items. Follows List Container Level pattern.
56
+ *
57
+ * @component
58
+ * @example
59
+ * ```tsx
60
+ * <ServiceList.Services emptyState={<div>No services found</div>}>
61
+ * <ServiceList.ServiceRepeater>
62
+ * <Service.Name />
63
+ * <Service.Price />
64
+ * </ServiceList.ServiceRepeater>
65
+ * </ServiceList.Services>
66
+ * ```
67
+ */
68
+ export declare const Services: React.ForwardRefExoticComponent<ServicesProps & React.RefAttributes<HTMLElement>>;
69
+ /**
70
+ * Function children type for Service.Root component
71
+ * Receives { selected, bookable } props from Service.Root
72
+ */
73
+ export type ServiceRootChildren = AsChildChildren<{
74
+ selected: boolean;
75
+ bookable: boolean;
76
+ }>;
77
+ /**
78
+ * Props for the itemWrapper function in asChild pattern
79
+ * Supports both ReactNode and function children that receive { selected, bookable }
80
+ */
81
+ export interface ServiceItemWrapperProps {
82
+ item: services.Service;
83
+ index?: number;
84
+ /** Children can be ReactNode or a function that receives { selected, bookable } from Service.Root */
85
+ children: React.ReactNode | ServiceRootChildren;
86
+ }
87
+ /**
88
+ * Render props for ServiceRepeater asChild pattern
89
+ * Provides items array and itemWrapper function for custom rendering
90
+ */
91
+ export interface ServiceRepeaterRenderProps {
92
+ items: services.Service[];
93
+ variant?: ListVariant;
94
+ /** Wraps each item in Service.Root - children can be ReactNode or function receiving { selected, bookable } */
95
+ itemWrapper: (props: ServiceItemWrapperProps) => React.ReactNode;
96
+ }
97
+ /**
98
+ * Props for ServiceList ServiceRepeater component
99
+ */
100
+ export interface ServiceRepeaterProps {
101
+ /**
102
+ * Children can be:
103
+ * - ReactNode: Static content rendered for each service
104
+ * - ServiceRootChildren: Function receiving { selected, bookable } from Service.Root
105
+ * - Function (with asChild=true): Receives { items, itemWrapper } for custom rendering
106
+ */
107
+ children: React.ReactNode | ((props: ServiceRepeaterRenderProps, ref?: React.Ref<HTMLElement>) => React.ReactNode) | ServiceRootChildren;
108
+ /** Whether to render as child component (asChild pattern) */
109
+ asChild?: boolean;
110
+ }
111
+ /**
112
+ * Repeater component that renders Service.Root for each service.
113
+ * Follows Repeater Level pattern and uses GenericList.Repeater for consistency.
114
+ * Supports asChild pattern for advanced layout components.
115
+ *
116
+ * @component
117
+ * @example
118
+ * ```tsx
119
+ * // Standard usage
120
+ * <ServiceList.ServiceRepeater>
121
+ * <Service.Name />
122
+ * <Service.Price />
123
+ * </ServiceList.ServiceRepeater>
124
+ *
125
+ * // AsChild usage with custom wrapper
126
+ * <ServiceList.ServiceRepeater asChild>
127
+ * {({ items, variant, itemWrapper }) => (
128
+ * <CustomWrapper
129
+ * items={items}
130
+ * variant={variant}
131
+ * itemRenderer={(item, index) =>
132
+ * itemWrapper({ item, index, children: <>
133
+ * <Service.Name />
134
+ * <Service.Price />
135
+ * </> })
136
+ * }
137
+ * />
138
+ * )}
139
+ * </ServiceList.ServiceRepeater>
140
+ * ```
141
+ */
142
+ export declare const ServiceRepeater: React.ForwardRefExoticComponent<ServiceRepeaterProps & React.RefAttributes<HTMLElement>>;
143
+ /**
144
+ * Props for ServiceList LoadMore component
145
+ */
146
+ export interface LoadMoreProps {
147
+ /** Custom render function when using asChild */
148
+ children?: React.ReactNode | React.ForwardRefRenderFunction<HTMLButtonElement, GenericListLoadMoreRenderProps>;
149
+ /**
150
+ * Whether to render as a child component.
151
+ * @default false
152
+ */
153
+ asChild?: boolean;
154
+ /**
155
+ * The CSS classes to apply to the button.
156
+ */
157
+ className?: string;
158
+ /**
159
+ * The label to display inside the button.
160
+ */
161
+ label?: string;
162
+ /**
163
+ * The loading state to display inside the button.
164
+ */
165
+ loadingState?: React.ReactNode;
166
+ }
167
+ /**
168
+ * Displays a button to load more services. Not rendered if infiniteScroll is false or no services are left to load.
169
+ * Follows the architecture rules - does not support asChild as it's a simple trigger component.
170
+ *
171
+ * @component
172
+ * @example
173
+ * ```tsx
174
+ * <ServiceList.Actions.LoadMore asChild>
175
+ * <button>Load More</button>
176
+ * </ServiceList.Actions.LoadMore>
177
+ * ```
178
+ */
179
+ export declare const LoadMore: React.ForwardRefExoticComponent<LoadMoreProps & React.RefAttributes<HTMLButtonElement>>;
180
+ /**
181
+ * Actions namespace for ServiceList
182
+ */
183
+ export declare const Actions: {
184
+ LoadMore: React.ForwardRefExoticComponent<LoadMoreProps & React.RefAttributes<HTMLButtonElement>>;
185
+ };
@@ -0,0 +1,184 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * ServiceList - High-level component for displaying services list
4
+ * Provides components for displaying services list with pagination
5
+ */
6
+ import React from 'react';
7
+ import { GenericList, } from '@wix/headless-components/react';
8
+ import { useService } from '@wix/services-manager-react';
9
+ import { ServiceListServiceDefinition } from '../../services/service-list/service-list.js';
10
+ import * as CoreServiceList from '../core/service-list/ServiceList.js';
11
+ import * as Service from '../service/Service.js';
12
+ /**
13
+ * Booking app ID constant
14
+ */
15
+ const BOOKING_APP_ID = '13d21c63-b5ec-5912-8397-c3a5ddb27a97';
16
+ var TestIds;
17
+ (function (TestIds) {
18
+ TestIds["serviceListRoot"] = "service-list-root";
19
+ TestIds["serviceListServices"] = "service-list-services";
20
+ TestIds["serviceListService"] = "service-list-service";
21
+ TestIds["serviceListLoadMore"] = "service-list-load-more";
22
+ })(TestIds || (TestIds = {}));
23
+ /**
24
+ * Root component that provides the ServiceList service context for rendering services lists.
25
+ *
26
+ * @order 1
27
+ * @component
28
+ * @example
29
+ * ```tsx
30
+ * import { ServiceList } from '@wix/bookings/components';
31
+ *
32
+ * function ServicesPage({ serviceListConfig }) {
33
+ * return (
34
+ * <ServiceList.Root serviceListConfig={serviceListConfig}>
35
+ * <ServiceList.Services emptyState={<div>No services available</div>}>
36
+ * <ServiceList.ServiceRepeater>
37
+ * <Service.Name />
38
+ * <Service.Price />
39
+ * </ServiceList.ServiceRepeater>
40
+ * </ServiceList.Services>
41
+ * </ServiceList.Root>
42
+ * );
43
+ * }
44
+ * ```
45
+ */
46
+ export const Root = React.forwardRef((props, ref) => {
47
+ const { children, serviceListConfig, className, variant } = props;
48
+ const serviceConfig = serviceListConfig || {
49
+ services: [],
50
+ options: {
51
+ appId: BOOKING_APP_ID,
52
+ pagingMetadata: {
53
+ limit: 0,
54
+ offset: 0,
55
+ hasNext: false,
56
+ },
57
+ },
58
+ };
59
+ return (_jsx(CoreServiceList.Root, { serviceListConfig: serviceConfig, children: _jsx(RootContent, { className: className, ref: ref, variant: variant, children: children }) }));
60
+ });
61
+ Root.displayName = 'ServiceList.Root';
62
+ /**
63
+ * Internal component to handle the Root content with service access
64
+ */
65
+ const RootContent = React.forwardRef((props, ref) => {
66
+ const { children, className, variant } = props;
67
+ const serviceListService = useService(ServiceListServiceDefinition);
68
+ const items = serviceListService.servicesSignal
69
+ .get()
70
+ .map((service) => ({
71
+ ...service,
72
+ id: service._id,
73
+ }));
74
+ return (_jsx(GenericList.Root, { items: items, loadMore: () => serviceListService.actions.loadMore(10), hasMore: serviceListService.hasMoreServicesSignal.get(), isLoading: serviceListService.isLoadingSignal.get(), className: className, ref: ref, "data-testid": TestIds.serviceListRoot, variant: variant, children: children }));
75
+ });
76
+ /**
77
+ * Container for the services list with empty state support.
78
+ * Wraps GenericList.Items. Follows List Container Level pattern.
79
+ *
80
+ * @component
81
+ * @example
82
+ * ```tsx
83
+ * <ServiceList.Services emptyState={<div>No services found</div>}>
84
+ * <ServiceList.ServiceRepeater>
85
+ * <Service.Name />
86
+ * <Service.Price />
87
+ * </ServiceList.ServiceRepeater>
88
+ * </ServiceList.Services>
89
+ * ```
90
+ */
91
+ export const Services = React.forwardRef((props, ref) => {
92
+ const { children, ...otherProps } = props;
93
+ return (_jsx(GenericList.Items, { ref: ref, "data-testid": TestIds.serviceListServices, ...otherProps, children: children }));
94
+ });
95
+ Services.displayName = 'ServiceList.Services';
96
+ /**
97
+ * Repeater component that renders Service.Root for each service.
98
+ * Follows Repeater Level pattern and uses GenericList.Repeater for consistency.
99
+ * Supports asChild pattern for advanced layout components.
100
+ *
101
+ * @component
102
+ * @example
103
+ * ```tsx
104
+ * // Standard usage
105
+ * <ServiceList.ServiceRepeater>
106
+ * <Service.Name />
107
+ * <Service.Price />
108
+ * </ServiceList.ServiceRepeater>
109
+ *
110
+ * // AsChild usage with custom wrapper
111
+ * <ServiceList.ServiceRepeater asChild>
112
+ * {({ items, variant, itemWrapper }) => (
113
+ * <CustomWrapper
114
+ * items={items}
115
+ * variant={variant}
116
+ * itemRenderer={(item, index) =>
117
+ * itemWrapper({ item, index, children: <>
118
+ * <Service.Name />
119
+ * <Service.Price />
120
+ * </> })
121
+ * }
122
+ * />
123
+ * )}
124
+ * </ServiceList.ServiceRepeater>
125
+ * ```
126
+ */
127
+ export const ServiceRepeater = React.forwardRef((props, ref) => {
128
+ const { children, asChild } = props;
129
+ const serviceListService = useService(ServiceListServiceDefinition);
130
+ const appId = serviceListService.queryOptionsSignal.get().appId;
131
+ // Check if children is a function that matches ServiceRootChildren pattern
132
+ // (function with single parameter that receives { selected, bookable })
133
+ const isServiceRootFunction = typeof children === 'function' && children.length === 1 && !asChild;
134
+ // Custom itemWrapper that matches ItemWrapperProps signature
135
+ const serviceItemWrapper = (wrapperProps) => {
136
+ const { item: service, children: itemChildren } = wrapperProps;
137
+ return (_jsx(Service.Root, { service: service, appId: appId, "data-testid": TestIds.serviceListService, "data-service-id": service._id, "data-item-id": service._id, children: isServiceRootFunction
138
+ ? children
139
+ : itemChildren }, service._id));
140
+ };
141
+ // Transform children for asChild pattern to provide custom render props
142
+ const transformedChildren = asChild && typeof children === 'function'
143
+ ? (genericProps) => {
144
+ // Create properly typed render props for the consumer
145
+ const renderProps = {
146
+ items: genericProps.items,
147
+ variant: genericProps.variant,
148
+ itemWrapper: (props) => serviceItemWrapper({
149
+ item: props.item,
150
+ index: props.index ?? 0,
151
+ children: props.children,
152
+ }),
153
+ };
154
+ return children(renderProps, ref);
155
+ }
156
+ : isServiceRootFunction
157
+ ? undefined
158
+ : children;
159
+ return (_jsx(GenericList.Repeater, { ref: ref, asChild: asChild, itemWrapper: serviceItemWrapper, children: transformedChildren }));
160
+ });
161
+ ServiceRepeater.displayName = 'ServiceList.ServiceRepeater';
162
+ /**
163
+ * Displays a button to load more services. Not rendered if infiniteScroll is false or no services are left to load.
164
+ * Follows the architecture rules - does not support asChild as it's a simple trigger component.
165
+ *
166
+ * @component
167
+ * @example
168
+ * ```tsx
169
+ * <ServiceList.Actions.LoadMore asChild>
170
+ * <button>Load More</button>
171
+ * </ServiceList.Actions.LoadMore>
172
+ * ```
173
+ */
174
+ export const LoadMore = React.forwardRef((props, ref) => {
175
+ const { children = _jsx("button", {}), ...otherProps } = props;
176
+ return (_jsx(GenericList.Actions.LoadMore, { ref: ref, "data-testid": TestIds.serviceListLoadMore, ...otherProps, children: children }));
177
+ });
178
+ LoadMore.displayName = 'ServiceList.Actions.LoadMore';
179
+ /**
180
+ * Actions namespace for ServiceList
181
+ */
182
+ export const Actions = {
183
+ LoadMore,
184
+ };
@@ -1,19 +1,55 @@
1
1
  /**
2
2
  * Booking Service - Global booking store
3
- * Manages booking flow state (selected service, and future: time slot, payment option, participants)
3
+ * Manages booking flow state (selected services, time slot, location, form values)
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
7
  import type { services, availabilityTimeSlots } from '@wix/bookings';
8
+ import type { FormValues } from '@wix/form-public';
9
+ /**
10
+ * ServiceSelection contains the service AND its related selections
11
+ */
12
+ export interface ServiceSelection {
13
+ service: services.Service;
14
+ /** Selected resources (staff members, rooms, etc.) */
15
+ resources?: availabilityTimeSlots.Resource[];
16
+ }
17
+ export interface Location {
18
+ id: string;
19
+ name?: string;
20
+ }
21
+ /**
22
+ * BookingService actions - setters only, no API calls
23
+ */
24
+ export interface BookingServiceActions {
25
+ setServices(services: ServiceSelection[]): void;
26
+ addService(service: ServiceSelection): void;
27
+ updateService(serviceId: string, updates: Partial<ServiceSelection>): void;
28
+ removeService(serviceId: string): void;
29
+ clearServices(): void;
30
+ setTimeSlot(slot: availabilityTimeSlots.TimeSlot | null): void;
31
+ clearTimeSlot(): void;
32
+ setLocation(location: Location | null): void;
33
+ clearLocation(): void;
34
+ setFormValues(values: FormValues | null): void;
35
+ clearFormValues(): void;
36
+ clearAll(): void;
37
+ }
8
38
  /**
9
39
  * Booking Service interface
10
- * Note: This is NOT an "API" service - it only exposes signals for state storage
40
+ * Pure state management - no API calls
11
41
  */
12
42
  export interface BookingService {
13
- /** Signal containing the currently selected services (can be multiple) */
14
- selectedServices: Signal<services.Service[]>;
43
+ /** Signal containing the currently selected services with their selections */
44
+ services: Signal<ServiceSelection[]>;
15
45
  /** Signal containing the currently selected time slot */
16
- selectedTimeSlot: Signal<availabilityTimeSlots.TimeSlot | null>;
46
+ timeSlot: Signal<availabilityTimeSlots.TimeSlot | null>;
47
+ /** Signal containing the selected location (derived from timeSlot) */
48
+ location: Signal<Location | null>;
49
+ /** Signal containing the form values */
50
+ formValues: Signal<FormValues | null>;
51
+ /** Actions for modifying booking state */
52
+ actions: BookingServiceActions;
17
53
  }
18
54
  /**
19
55
  * Service definition for Booking
@@ -25,12 +61,15 @@ export declare const BookingServiceDefinition: string & {
25
61
  } & BookingService;
26
62
  /**
27
63
  * Configuration interface for BookingService
64
+ * Note: location is NOT in config - it's derived internally from timeSlot
28
65
  */
29
66
  export interface BookingServiceConfig {
30
- /** Optional initial services to pre-populate (default: empty array) */
31
- initialServices?: services.Service[];
32
- /** Optional initial time slot to pre-populate (default: null) */
67
+ /** Optional initial services to pre-populate */
68
+ initialServices?: ServiceSelection[];
69
+ /** Optional initial time slot to pre-populate */
33
70
  initialTimeSlot?: availabilityTimeSlots.TimeSlot | null;
71
+ /** Optional initial form values */
72
+ initialFormValues?: FormValues | null;
34
73
  }
35
74
  /**
36
75
  * Implementation of BookingService
@@ -44,20 +83,16 @@ export interface BookingServiceConfig {
44
83
  * const bookingConfig = await loadBookingServiceConfig();
45
84
  *
46
85
  * // Wrap app with provider
47
- * <Booking.Root bookingServiceConfig={bookingConfig}>
86
+ * <Booking.Root config={bookingConfig}>
48
87
  * {children}
49
88
  * </Booking.Root>
50
89
  *
51
90
  * // In any page - access booking data
52
91
  * <Booking.Data>
53
- * {({ selectedServices }) => (
54
- * <div>{selectedServices.map(s => s.name).join(', ')}</div>
92
+ * {({ services, timeSlot, location, formValues, actions }) => (
93
+ * <div>{services.map(s => s.service.name).join(', ')}</div>
55
94
  * )}
56
95
  * </Booking.Data>
57
- *
58
- * // Modify booking data (via action to be added later)
59
- * const booking = useService(BookingServiceDefinition);
60
- * booking.selectedServices.set([...currentServices, newService]);
61
96
  * ```
62
97
  */
63
98
  export declare const BookingService: import("@wix/services-definitions").ServiceFactory<string & {
@@ -65,21 +100,3 @@ export declare const BookingService: import("@wix/services-definitions").Service
65
100
  __config: {};
66
101
  isServiceDefinition?: boolean;
67
102
  } & BookingService, BookingServiceConfig>;
68
- /**
69
- * Load configuration for BookingService
70
- *
71
- * This function is called during SSR to initialize the service.
72
- * Currently returns null state - can be extended to load from API in future.
73
- *
74
- * @returns Promise resolving to BookingServiceConfig
75
- *
76
- * @example
77
- * ```astro
78
- * ---
79
- * import { loadBookingServiceConfig } from '@wix/headless-bookings/services';
80
- *
81
- * const bookingConfig = await loadBookingServiceConfig();
82
- * ---
83
- * ```
84
- */
85
- export declare function loadBookingServiceConfig(): Promise<BookingServiceConfig>;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Booking Service - Global booking store
3
- * Manages booking flow state (selected service, and future: time slot, payment option, participants)
3
+ * Manages booking flow state (selected services, time slot, location, form values)
4
4
  * Persists across page navigation in SPA until page refresh
5
5
  */
6
6
  import { defineService, implementService } from '@wix/services-definitions';
@@ -9,6 +9,9 @@ import { SignalsServiceDefinition, } from '@wix/services-definitions/core-servic
9
9
  * Service definition for Booking
10
10
  */
11
11
  export const BookingServiceDefinition = defineService('booking');
12
+ // ============================================================================
13
+ // Service Implementation
14
+ // ============================================================================
12
15
  /**
13
16
  * Implementation of BookingService
14
17
  *
@@ -21,54 +24,85 @@ export const BookingServiceDefinition = defineService('booking');
21
24
  * const bookingConfig = await loadBookingServiceConfig();
22
25
  *
23
26
  * // Wrap app with provider
24
- * <Booking.Root bookingServiceConfig={bookingConfig}>
27
+ * <Booking.Root config={bookingConfig}>
25
28
  * {children}
26
29
  * </Booking.Root>
27
30
  *
28
31
  * // In any page - access booking data
29
32
  * <Booking.Data>
30
- * {({ selectedServices }) => (
31
- * <div>{selectedServices.map(s => s.name).join(', ')}</div>
33
+ * {({ services, timeSlot, location, formValues, actions }) => (
34
+ * <div>{services.map(s => s.service.name).join(', ')}</div>
32
35
  * )}
33
36
  * </Booking.Data>
34
- *
35
- * // Modify booking data (via action to be added later)
36
- * const booking = useService(BookingServiceDefinition);
37
- * booking.selectedServices.set([...currentServices, newService]);
38
37
  * ```
39
38
  */
40
39
  export const BookingService = implementService.withConfig()(BookingServiceDefinition, ({ getService, config }) => {
41
40
  const signalsService = getService(SignalsServiceDefinition);
42
- // Initialize selectedServices signal with config or empty array
43
- const selectedServices = signalsService.signal(config.initialServices || []);
44
- // Initialize selectedTimeSlot signal with config or null
45
- const selectedTimeSlot = signalsService.signal(config.initialTimeSlot || null);
46
- return {
47
- selectedServices,
48
- selectedTimeSlot,
41
+ // Initialize signals with config values
42
+ const servicesSignal = signalsService.signal(config.initialServices || []);
43
+ const timeSlotSignal = signalsService.signal(config.initialTimeSlot || null);
44
+ // Location is derived internally - initialize as null
45
+ const locationSignal = signalsService.signal(null);
46
+ const formValuesSignal = signalsService.signal(config.initialFormValues || null);
47
+ // ========================================================================
48
+ // Actions Implementation
49
+ // ========================================================================
50
+ const actions = {
51
+ // Services actions
52
+ setServices(newServices) {
53
+ servicesSignal.set(newServices);
54
+ },
55
+ addService(service) {
56
+ const current = servicesSignal.get();
57
+ servicesSignal.set([...current, service]);
58
+ },
59
+ updateService(serviceId, updates) {
60
+ const current = servicesSignal.get();
61
+ const updated = current.map((s) => s.service._id === serviceId ? { ...s, ...updates } : s);
62
+ servicesSignal.set(updated);
63
+ },
64
+ removeService(serviceId) {
65
+ const current = servicesSignal.get();
66
+ const filtered = current.filter((s) => s.service._id !== serviceId);
67
+ servicesSignal.set(filtered);
68
+ },
69
+ clearServices() {
70
+ servicesSignal.set([]);
71
+ },
72
+ // Time Slot actions
73
+ setTimeSlot(slot) {
74
+ timeSlotSignal.set(slot);
75
+ },
76
+ clearTimeSlot() {
77
+ timeSlotSignal.set(null);
78
+ },
79
+ // Location actions
80
+ setLocation(location) {
81
+ locationSignal.set(location);
82
+ },
83
+ clearLocation() {
84
+ locationSignal.set(null);
85
+ },
86
+ // Form Values actions
87
+ setFormValues(values) {
88
+ formValuesSignal.set(values);
89
+ },
90
+ clearFormValues() {
91
+ formValuesSignal.set(null);
92
+ },
93
+ // Clear all
94
+ clearAll() {
95
+ servicesSignal.set([]);
96
+ timeSlotSignal.set(null);
97
+ locationSignal.set(null);
98
+ formValuesSignal.set(null);
99
+ },
49
100
  };
50
- });
51
- /**
52
- * Load configuration for BookingService
53
- *
54
- * This function is called during SSR to initialize the service.
55
- * Currently returns null state - can be extended to load from API in future.
56
- *
57
- * @returns Promise resolving to BookingServiceConfig
58
- *
59
- * @example
60
- * ```astro
61
- * ---
62
- * import { loadBookingServiceConfig } from '@wix/headless-bookings/services';
63
- *
64
- * const bookingConfig = await loadBookingServiceConfig();
65
- * ---
66
- * ```
67
- */
68
- export async function loadBookingServiceConfig() {
69
- // Future: Load persisted selections from API by selection ID
70
101
  return {
71
- initialServices: [],
72
- initialTimeSlot: null,
102
+ services: servicesSignal,
103
+ timeSlot: timeSlotSignal,
104
+ location: locationSignal,
105
+ formValues: formValuesSignal,
106
+ actions,
73
107
  };
74
- }
108
+ });
@@ -2,5 +2,6 @@
2
2
  * Bookings Services
3
3
  * Main export file for all service definitions and implementations
4
4
  */
5
- export { ServiceService, ServiceServiceDefinition, type ServiceServiceAPI, type ServiceServiceConfig, loadServiceServiceConfig, type SuccessServiceServiceConfigResult, type NotFoundServiceServiceConfigResult, } from './service/service.js';
6
- export { BookingService, BookingServiceDefinition, type BookingServiceConfig, loadBookingServiceConfig, } from './booking/booking.js';
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 ServiceSelection, type Location, type BookingServiceActions, } from './booking/booking.js';
7
+ export { ServiceListService, ServiceListServiceDefinition, type ServiceListServiceAPI, type ServiceListServiceConfig, type ServiceListActions, type QueryOptions, loadServiceListServiceInitialData, type SuccessServiceListServiceConfigResult, type ErrorServiceListServiceConfigResult, } from './service-list/service-list.js';
@@ -2,5 +2,6 @@
2
2
  * Bookings Services
3
3
  * Main export file for all service definitions and implementations
4
4
  */
5
- export { ServiceService, ServiceServiceDefinition, loadServiceServiceConfig, } from './service/service.js';
6
- export { BookingService, BookingServiceDefinition, loadBookingServiceConfig, } from './booking/booking.js';
5
+ export { ServiceService, ServiceServiceDefinition, loadServiceServiceInitialData, } from './service/service.js';
6
+ export { BookingService, BookingServiceDefinition, } from './booking/booking.js';
7
+ export { ServiceListService, ServiceListServiceDefinition, loadServiceListServiceInitialData, } from './service-list/service-list.js';