@wix/headless-bookings 0.0.7 → 0.0.8

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 +5 -0
  2. package/cjs/dist/api/index.js +5 -0
  3. package/cjs/dist/api/query-service/index.d.ts +23 -0
  4. package/cjs/dist/api/query-service/index.js +41 -0
  5. package/cjs/dist/react/booking/Booking.d.ts +35 -0
  6. package/cjs/dist/react/booking/Booking.js +25 -0
  7. package/cjs/dist/react/core/booking/Booking.d.ts +58 -0
  8. package/cjs/dist/react/core/booking/Booking.js +50 -0
  9. package/cjs/dist/react/core/service/Service.d.ts +106 -0
  10. package/cjs/dist/react/core/service/Service.js +90 -0
  11. package/cjs/dist/react/index.d.ts +2 -4
  12. package/cjs/dist/react/index.js +2 -5
  13. package/cjs/dist/react/service/Service.d.ts +208 -0
  14. package/cjs/dist/react/service/Service.js +202 -0
  15. package/cjs/dist/services/booking/booking.d.ts +85 -0
  16. package/cjs/dist/services/booking/booking.js +74 -0
  17. package/cjs/dist/services/index.d.ts +6 -1
  18. package/cjs/dist/services/index.js +6 -1
  19. package/cjs/dist/services/{service-service.d.ts → service/service.d.ts} +27 -42
  20. package/cjs/dist/services/{service-service.js → service/service.js} +49 -48
  21. package/dist/api/index.d.ts +5 -0
  22. package/dist/api/index.js +5 -0
  23. package/dist/api/query-service/index.d.ts +23 -0
  24. package/dist/api/query-service/index.js +41 -0
  25. package/dist/react/booking/Booking.d.ts +35 -0
  26. package/dist/react/booking/Booking.js +25 -0
  27. package/dist/react/core/booking/Booking.d.ts +58 -0
  28. package/dist/react/core/booking/Booking.js +50 -0
  29. package/dist/react/core/service/Service.d.ts +106 -0
  30. package/dist/react/core/service/Service.js +90 -0
  31. package/dist/react/index.d.ts +2 -4
  32. package/dist/react/index.js +2 -5
  33. package/dist/react/service/Service.d.ts +208 -0
  34. package/dist/react/service/Service.js +202 -0
  35. package/dist/services/booking/booking.d.ts +85 -0
  36. package/dist/services/booking/booking.js +74 -0
  37. package/dist/services/index.d.ts +6 -1
  38. package/dist/services/index.js +6 -1
  39. package/dist/services/{service-service.d.ts → service/service.d.ts} +27 -42
  40. package/dist/services/{service-service.js → service/service.js} +49 -48
  41. package/package.json +3 -2
  42. package/cjs/dist/react/ServiceList.d.ts +0 -50
  43. package/cjs/dist/react/ServiceList.js +0 -100
  44. package/cjs/dist/react/ServiceListSort.d.ts +0 -37
  45. package/cjs/dist/react/ServiceListSort.js +0 -35
  46. package/cjs/dist/react/core/Service.d.ts +0 -91
  47. package/cjs/dist/react/core/Service.js +0 -73
  48. package/cjs/dist/react/core/ServiceList.d.ts +0 -218
  49. package/cjs/dist/react/core/ServiceList.js +0 -199
  50. package/cjs/dist/react/test-ids.d.ts +0 -18
  51. package/cjs/dist/react/test-ids.js +0 -24
  52. package/cjs/dist/react/types.d.ts +0 -52
  53. package/cjs/dist/react/types.js +0 -1
  54. package/cjs/dist/services/services-list-service.d.ts +0 -184
  55. package/cjs/dist/services/services-list-service.js +0 -168
  56. package/dist/react/ServiceList.d.ts +0 -50
  57. package/dist/react/ServiceList.js +0 -100
  58. package/dist/react/ServiceListSort.d.ts +0 -37
  59. package/dist/react/ServiceListSort.js +0 -35
  60. package/dist/react/core/Service.d.ts +0 -91
  61. package/dist/react/core/Service.js +0 -73
  62. package/dist/react/core/ServiceList.d.ts +0 -218
  63. package/dist/react/core/ServiceList.js +0 -199
  64. package/dist/react/test-ids.d.ts +0 -18
  65. package/dist/react/test-ids.js +0 -24
  66. package/dist/react/types.d.ts +0 -52
  67. package/dist/react/types.js +0 -1
  68. package/dist/services/services-list-service.d.ts +0 -184
  69. package/dist/services/services-list-service.js +0 -168
@@ -0,0 +1,202 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * Service - High-level component for displaying service information
4
+ * Provides components for displaying service details and booking actions
5
+ */
6
+ import React from 'react';
7
+ import * as CoreService from '../core/service/Service.js';
8
+ import { AsChildSlot } from '@wix/headless-utils/react';
9
+ var TestIds;
10
+ (function (TestIds) {
11
+ TestIds["serviceRoot"] = "service-root";
12
+ TestIds["serviceName"] = "service-name";
13
+ TestIds["serviceDescription"] = "service-description";
14
+ TestIds["serviceActionSelect"] = "service-action-select";
15
+ TestIds["serviceActionAdd"] = "service-action-add";
16
+ TestIds["serviceActionRemove"] = "service-action-remove";
17
+ })(TestIds || (TestIds = {}));
18
+ /**
19
+ * Root component that provides service context to the entire app.
20
+ *
21
+ * @order 1
22
+ * @component
23
+ * @example
24
+ * ```tsx
25
+ * import { Service } from '@wix/bookings/components';
26
+ *
27
+ * function ServicePage({ service }) {
28
+ * return (
29
+ * <Service.Root service={service}>
30
+ * <Service.Name />
31
+ * <Service.Description />
32
+ * </Service.Root>
33
+ * );
34
+ * }
35
+ * ```
36
+ */
37
+ export const Root = React.forwardRef((props, ref) => {
38
+ const { children, service, asChild, className, ...attrs } = props;
39
+ return (_jsx(CoreService.Root, { serviceServiceConfig: { service }, children: _jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.serviceRoot, customElement: children, ...attrs, children: _jsx("div", { children: children }) }) }));
40
+ });
41
+ Root.displayName = 'Service.Root';
42
+ /**
43
+ * Displays the service name with customizable rendering.
44
+ *
45
+ * @component
46
+ * @example
47
+ * ```tsx
48
+ * // Default usage
49
+ * <Service.Name className="text-4xl font-bold" />
50
+ *
51
+ * // asChild with primitive
52
+ * <Service.Name asChild>
53
+ * <h1 className="text-4xl font-bold" />
54
+ * </Service.Name>
55
+ *
56
+ * // asChild with custom component
57
+ * <Service.Name asChild>
58
+ * {React.forwardRef(({name, ...props}, ref) => (
59
+ * <h1 ref={ref} {...props} className="text-4xl font-bold">
60
+ * {name}
61
+ * </h1>
62
+ * ))}
63
+ * </Service.Name>
64
+ * ```
65
+ */
66
+ export const Name = React.forwardRef((props, ref) => {
67
+ const { asChild, children, className } = props;
68
+ return (_jsx(CoreService.Info, { children: ({ name }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.serviceName, customElement: children, customElementProps: { name }, children: _jsx("span", { children: name }) })) }));
69
+ });
70
+ Name.displayName = 'Service.Name';
71
+ /**
72
+ * Displays the service description with customizable rendering.
73
+ *
74
+ * @component
75
+ * @example
76
+ * ```tsx
77
+ * // Default usage
78
+ * <Service.Description className="text-gray-600" />
79
+ *
80
+ * // asChild with primitive
81
+ * <Service.Description asChild>
82
+ * <p className="text-gray-600" />
83
+ * </Service.Description>
84
+ * ```
85
+ */
86
+ export const Description = React.forwardRef((props, ref) => {
87
+ const { asChild, children, className } = props;
88
+ return (_jsx(CoreService.Info, { children: ({ description }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.serviceDescription, customElement: children, customElementProps: { description }, children: _jsx("div", { children: description }) })) }));
89
+ });
90
+ Description.displayName = 'Service.Description';
91
+ /**
92
+ * Actions namespace with individual action components
93
+ */
94
+ export var Actions;
95
+ (function (Actions) {
96
+ /**
97
+ * Select action component - replaces selection with only this service.
98
+ *
99
+ * @component
100
+ * @example
101
+ * ```tsx
102
+ * // Default button
103
+ * <Service.Actions.Select label="Select This Service" />
104
+ *
105
+ * // With asChild using custom Button component
106
+ * <Service.Actions.Select asChild>
107
+ * <Button variant="primary">Select Service</Button>
108
+ * </Service.Actions.Select>
109
+ *
110
+ * // With onClicked callback for navigation
111
+ * <Service.Actions.Select
112
+ * asChild
113
+ * onClicked={(event, service) => {
114
+ * router.push(`/booking/time-slots/${service._id}`);
115
+ * }}
116
+ * >
117
+ * <Button variant="primary">Select Service</Button>
118
+ * </Service.Actions.Select>
119
+ * ```
120
+ */
121
+ Actions.Select = React.forwardRef((props, ref) => {
122
+ const { asChild, children, className, label = 'Select Service', onClicked, } = props;
123
+ return (_jsx(CoreService.Actions, { children: ({ select, service }) => {
124
+ const handleClick = (event) => {
125
+ select();
126
+ onClicked?.(event, service);
127
+ };
128
+ return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.serviceActionSelect, customElement: children, customElementProps: { onClick: handleClick }, children: _jsx("button", { onClick: handleClick, children: label }) }));
129
+ } }));
130
+ });
131
+ Actions.Select.displayName = 'Service.Actions.Select';
132
+ /**
133
+ * Add action component - adds service to selection array.
134
+ *
135
+ * @component
136
+ * @example
137
+ * ```tsx
138
+ * // Default button
139
+ * <Service.Actions.Add label="Add to Selection" />
140
+ *
141
+ * // With asChild using custom Button component
142
+ * <Service.Actions.Add asChild>
143
+ * <Button variant="secondary">Add Service</Button>
144
+ * </Service.Actions.Add>
145
+ *
146
+ * // With onClicked callback for tracking
147
+ * <Service.Actions.Add
148
+ * label="Add to Cart"
149
+ * onClicked={(event, service) => {
150
+ * analytics.track('service_added', { serviceId: service._id });
151
+ * }}
152
+ * />
153
+ * ```
154
+ */
155
+ Actions.Add = React.forwardRef((props, ref) => {
156
+ const { asChild, children, className, label = 'Add Service', onClicked, } = props;
157
+ return (_jsx(CoreService.Actions, { children: ({ add, service }) => {
158
+ const handleClick = (event) => {
159
+ add();
160
+ onClicked?.(event, service);
161
+ };
162
+ return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.serviceActionAdd, customElement: children, customElementProps: { onClick: handleClick }, children: _jsx("button", { onClick: handleClick, children: label }) }));
163
+ } }));
164
+ });
165
+ Actions.Add.displayName = 'Service.Actions.Add';
166
+ /**
167
+ * Remove action component - removes service from selection array.
168
+ *
169
+ * @component
170
+ * @example
171
+ * ```tsx
172
+ * // Default button
173
+ * <Service.Actions.Remove label="Remove from Selection" />
174
+ *
175
+ * // With asChild using custom Button component
176
+ * <Service.Actions.Remove asChild>
177
+ * <Button variant="destructive">Remove Service</Button>
178
+ * </Service.Actions.Remove>
179
+ *
180
+ * // With onClicked callback for notifications
181
+ * <Service.Actions.Remove
182
+ * asChild
183
+ * onClicked={(event, service) => {
184
+ * toast.success(`${service.name} removed from selection`);
185
+ * }}
186
+ * >
187
+ * <IconButton icon="trash" />
188
+ * </Service.Actions.Remove>
189
+ * ```
190
+ */
191
+ Actions.Remove = React.forwardRef((props, ref) => {
192
+ const { asChild, children, className, label = 'Remove Service', onClicked, } = props;
193
+ return (_jsx(CoreService.Actions, { children: ({ remove, service }) => {
194
+ const handleClick = (event) => {
195
+ remove();
196
+ onClicked?.(event, service);
197
+ };
198
+ return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.serviceActionRemove, customElement: children, customElementProps: { onClick: handleClick }, children: _jsx("button", { onClick: handleClick, children: label }) }));
199
+ } }));
200
+ });
201
+ Actions.Remove.displayName = 'Service.Actions.Remove';
202
+ })(Actions || (Actions = {}));
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Booking Service - Global booking store
3
+ * Manages booking flow state (selected service, and future: time slot, payment option, participants)
4
+ * Persists across page navigation in SPA until page refresh
5
+ */
6
+ import { type Signal } from '@wix/services-definitions/core-services/signals';
7
+ import type { services, availabilityTimeSlots } from '@wix/bookings';
8
+ /**
9
+ * Booking Service interface
10
+ * Note: This is NOT an "API" service - it only exposes signals for state storage
11
+ */
12
+ export interface BookingService {
13
+ /** Signal containing the currently selected services (can be multiple) */
14
+ selectedServices: Signal<services.Service[]>;
15
+ /** Signal containing the currently selected time slot */
16
+ selectedTimeSlot: Signal<availabilityTimeSlots.TimeSlot | null>;
17
+ }
18
+ /**
19
+ * Service definition for Booking
20
+ */
21
+ export declare const BookingServiceDefinition: string & {
22
+ __api: BookingService;
23
+ __config: {};
24
+ isServiceDefinition?: boolean;
25
+ } & BookingService;
26
+ /**
27
+ * Configuration interface for BookingService
28
+ */
29
+ 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) */
33
+ initialTimeSlot?: availabilityTimeSlots.TimeSlot | null;
34
+ }
35
+ /**
36
+ * Implementation of BookingService
37
+ *
38
+ * This service stores booking state in memory during the session.
39
+ * State persists across page navigation (SPA behavior) until page refresh.
40
+ *
41
+ * @example
42
+ * ```tsx
43
+ * // In BaseLayout.astro
44
+ * const bookingConfig = await loadBookingServiceConfig();
45
+ *
46
+ * // Wrap app with provider
47
+ * <Booking.Root bookingServiceConfig={bookingConfig}>
48
+ * {children}
49
+ * </Booking.Root>
50
+ *
51
+ * // In any page - access booking data
52
+ * <Booking.Data>
53
+ * {({ selectedServices }) => (
54
+ * <div>{selectedServices.map(s => s.name).join(', ')}</div>
55
+ * )}
56
+ * </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
+ * ```
62
+ */
63
+ export declare const BookingService: import("@wix/services-definitions").ServiceFactory<string & {
64
+ __api: BookingService;
65
+ __config: {};
66
+ isServiceDefinition?: boolean;
67
+ } & 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>;
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Booking Service - Global booking store
3
+ * Manages booking flow state (selected service, and future: time slot, payment option, participants)
4
+ * Persists across page navigation in SPA until page refresh
5
+ */
6
+ import { defineService, implementService } from '@wix/services-definitions';
7
+ import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
8
+ /**
9
+ * Service definition for Booking
10
+ */
11
+ export const BookingServiceDefinition = defineService('booking');
12
+ /**
13
+ * Implementation of BookingService
14
+ *
15
+ * This service stores booking state in memory during the session.
16
+ * State persists across page navigation (SPA behavior) until page refresh.
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * // In BaseLayout.astro
21
+ * const bookingConfig = await loadBookingServiceConfig();
22
+ *
23
+ * // Wrap app with provider
24
+ * <Booking.Root bookingServiceConfig={bookingConfig}>
25
+ * {children}
26
+ * </Booking.Root>
27
+ *
28
+ * // In any page - access booking data
29
+ * <Booking.Data>
30
+ * {({ selectedServices }) => (
31
+ * <div>{selectedServices.map(s => s.name).join(', ')}</div>
32
+ * )}
33
+ * </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
+ * ```
39
+ */
40
+ export const BookingService = implementService.withConfig()(BookingServiceDefinition, ({ getService, config }) => {
41
+ 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,
49
+ };
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
+ return {
71
+ initialServices: [],
72
+ initialTimeSlot: null,
73
+ };
74
+ }
@@ -1 +1,6 @@
1
- export * from './services-list-service.js';
1
+ /**
2
+ * Bookings Services
3
+ * Main export file for all service definitions and implementations
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';
@@ -1 +1,6 @@
1
- export * from './services-list-service.js';
1
+ /**
2
+ * Bookings Services
3
+ * Main export file for all service definitions and implementations
4
+ */
5
+ export { ServiceService, ServiceServiceDefinition, loadServiceServiceConfig, } from './service/service.js';
6
+ export { BookingService, BookingServiceDefinition, loadBookingServiceConfig, } from './booking/booking.js';
@@ -1,8 +1,11 @@
1
+ /**
2
+ * Service Service - Reactive service data management
3
+ * Handles loading and managing a single service's data, loading state, and errors.
4
+ */
1
5
  import { type Signal } from '@wix/services-definitions/core-services/signals';
2
6
  import { services } from '@wix/bookings';
3
7
  /**
4
8
  * API interface for the Service service, providing reactive service data management.
5
- * This service handles loading and managing a single service's data, loading state, and errors.
6
9
  *
7
10
  * @interface ServiceServiceAPI
8
11
  */
@@ -15,6 +18,12 @@ export interface ServiceServiceAPI {
15
18
  error: Signal<string | null>;
16
19
  /** Function to load a service by its id */
17
20
  loadService: (id: string) => Promise<void>;
21
+ /** Function to select this service (replaces entire selection) */
22
+ select: () => void;
23
+ /** Function to add this service to the selection */
24
+ add: () => void;
25
+ /** Function to remove this service from the selection */
26
+ remove: () => void;
18
27
  }
19
28
  /**
20
29
  * Service definition for the Service service.
@@ -46,7 +55,7 @@ export interface ServiceServiceConfig {
46
55
  *
47
56
  * @example
48
57
  * ```tsx
49
- * import { ServiceService, ServiceServiceDefinition } from '@wix/services/services';
58
+ * import { ServiceService, ServiceServiceDefinition } from '@wix/bookings/services';
50
59
  * import { useService } from '@wix/services-manager-react';
51
60
  *
52
61
  * function ServiceComponent({ serviceConfig }) {
@@ -78,59 +87,35 @@ export declare const ServiceService: import("@wix/services-definitions").Service
78
87
  isServiceDefinition?: boolean;
79
88
  } & ServiceServiceAPI, ServiceServiceConfig>;
80
89
  /**
81
- * Success result interface for service service configuration loading.
82
- * Returned when a service is successfully found and loaded.
83
- *
84
- * @interface SuccessServiceServiceConfigResult
90
+ * Result types for service loading operations
85
91
  */
86
- export interface SuccessServiceServiceConfigResult {
87
- /** Type "success" means that the service was found and the config is valid */
92
+ export type SuccessServiceServiceConfigResult = {
88
93
  type: 'success';
89
- /** The service config containing the loaded service data */
90
94
  config: ServiceServiceConfig;
91
- }
92
- /**
93
- * Not found result interface for service service configuration loading.
94
- * Returned when a service with the given id cannot be found.
95
- *
96
- * @interface NotFoundServiceServiceConfigResult
97
- */
98
- export interface NotFoundServiceServiceConfigResult {
99
- /** Type "notFound" means that the service was not found */
95
+ };
96
+ export type NotFoundServiceServiceConfigResult = {
100
97
  type: 'notFound';
101
- }
98
+ };
102
99
  /**
103
- * Loads service service configuration from the Wix Services API for SSR initialization.
104
- * This function is designed to be used during Server-Side Rendering (SSR) to preload
105
- * a specific service by id that will be used to configure the ServiceService.
100
+ * Load service configuration for Server-Side Rendering (SSR).
101
+ * This function is designed to be called during the build or server-side rendering phase
102
+ * to pre-fetch service data before the React components are hydrated on the client.
106
103
  *
107
- * @param serviceId The service id to load
108
- * @returns Promise that resolves to ServiceServiceConfigResult (success with config or notFound)
104
+ * @param slug - The slug of the service to load (e.g., "group-trainings", "yoga-class")
105
+ * @returns A promise that resolves to either a success result with the config or a notFound result
109
106
  *
110
107
  * @example
111
- * ```astro
112
- * ---
113
- * // Astro page example - pages/service/[id].astro
114
- * import { loadServiceServiceConfig } from '@wix/services/services';
115
- * import { Service } from '@wix/services/components';
116
- *
117
- * // Get service id from URL params
118
- * const { id } = Astro.params;
108
+ * ```ts
109
+ * // In an Astro page or API route
110
+ * import { loadServiceServiceConfig } from '@wix/headless-bookings/services';
119
111
  *
120
- * // Load service data during SSR
121
- * const serviceResult = await loadServiceServiceConfig(id);
112
+ * const serviceResult = await loadServiceServiceConfig('group-trainings');
122
113
  *
123
- * // Handle not found case
124
114
  * if (serviceResult.type === 'notFound') {
125
115
  * return Astro.redirect('/404');
126
116
  * }
127
- * ---
128
117
  *
129
- * <Service.Root serviceConfig={serviceResult.config}>
130
- * <Service.Name>
131
- * {({ name }) => <h1>{name}</h1>}
132
- * </Service.Name>
133
- * </Service.Root>
118
+ * const serviceConfig = serviceResult.config;
134
119
  * ```
135
120
  */
136
- export declare function loadServiceServiceConfig(serviceId: string): Promise<SuccessServiceServiceConfigResult | NotFoundServiceServiceConfigResult>;
121
+ export declare function loadServiceServiceConfig(slug: string): Promise<SuccessServiceServiceConfigResult | NotFoundServiceServiceConfigResult>;
@@ -1,6 +1,11 @@
1
+ /**
2
+ * Service Service - Reactive service data management
3
+ * Handles loading and managing a single service's data, loading state, and errors.
4
+ */
1
5
  import { defineService, implementService } from '@wix/services-definitions';
2
6
  import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
3
- import { services } from '@wix/bookings';
7
+ import { getServiceById, getServiceBySlug, } from '../../api/query-service/index.js';
8
+ import { BookingServiceDefinition } from '../booking/booking.js';
4
9
  /**
5
10
  * Service definition for the Service service.
6
11
  * This defines the contract that the ServiceService must implement.
@@ -15,7 +20,7 @@ export const ServiceServiceDefinition = defineService('service');
15
20
  *
16
21
  * @example
17
22
  * ```tsx
18
- * import { ServiceService, ServiceServiceDefinition } from '@wix/services/services';
23
+ * import { ServiceService, ServiceServiceDefinition } from '@wix/bookings/services';
19
24
  * import { useService } from '@wix/services-manager-react';
20
25
  *
21
26
  * function ServiceComponent({ serviceConfig }) {
@@ -43,86 +48,82 @@ export const ServiceServiceDefinition = defineService('service');
43
48
  */
44
49
  export const ServiceService = implementService.withConfig()(ServiceServiceDefinition, ({ getService, config }) => {
45
50
  const signalsService = getService(SignalsServiceDefinition);
51
+ const bookingService = getService(BookingServiceDefinition);
46
52
  const service = signalsService.signal(config.service);
47
53
  const isLoading = signalsService.signal(!!config.serviceId);
48
54
  const error = signalsService.signal(null);
49
55
  const loadService = async (id) => {
50
56
  isLoading.set(true);
51
- const serviceResponse = await loadServiceById(id);
57
+ error.set(null);
58
+ const serviceResponse = await getServiceById(id);
52
59
  if (!serviceResponse.service) {
53
60
  error.set('Service not found');
61
+ isLoading.set(false);
54
62
  }
55
63
  else {
56
64
  service.set(serviceResponse.service);
57
65
  error.set(null);
66
+ isLoading.set(false);
58
67
  }
59
- isLoading.set(false);
60
68
  };
61
- if (config.serviceId) {
69
+ // Auto-load if serviceId is provided but no service data
70
+ if (config.serviceId && !config.service) {
62
71
  loadService(config.serviceId);
63
72
  }
73
+ // Action methods for booking
74
+ const select = () => {
75
+ const currentService = service.get();
76
+ bookingService.selectedServices.set([currentService]);
77
+ };
78
+ const add = () => {
79
+ const currentService = service.get();
80
+ const selectedServices = bookingService.selectedServices.get();
81
+ bookingService.selectedServices.set([
82
+ ...selectedServices,
83
+ currentService,
84
+ ]);
85
+ };
86
+ const remove = () => {
87
+ const currentService = service.get();
88
+ const selectedServices = bookingService.selectedServices.get();
89
+ const filtered = selectedServices.filter((s) => s._id !== currentService._id);
90
+ bookingService.selectedServices.set(filtered);
91
+ };
64
92
  return {
65
93
  service,
66
94
  isLoading,
67
95
  error,
68
96
  loadService,
97
+ select,
98
+ add,
99
+ remove,
69
100
  };
70
101
  });
71
102
  /**
72
- * Internal helper function to load a service by its ID from the Wix Services API.
73
- * Fetches comprehensive service data including description, categories, media, etc.
103
+ * Load service configuration for Server-Side Rendering (SSR).
104
+ * This function is designed to be called during the build or server-side rendering phase
105
+ * to pre-fetch service data before the React components are hydrated on the client.
74
106
  *
75
- * @private
76
- * @param {string} id - The service ID to load
77
- * @returns {Promise} Service response from the API
78
- */
79
- const loadServiceById = async (id) => {
80
- try {
81
- const service = await services.getService(id);
82
- return { service };
83
- }
84
- catch (error) {
85
- console.error(`Failed to load service for id "${id}":`, error);
86
- return { service: null };
87
- }
88
- };
89
- /**
90
- * Loads service service configuration from the Wix Services API for SSR initialization.
91
- * This function is designed to be used during Server-Side Rendering (SSR) to preload
92
- * a specific service by id that will be used to configure the ServiceService.
93
- *
94
- * @param serviceId The service id to load
95
- * @returns Promise that resolves to ServiceServiceConfigResult (success with config or notFound)
107
+ * @param slug - The slug of the service to load (e.g., "group-trainings", "yoga-class")
108
+ * @returns A promise that resolves to either a success result with the config or a notFound result
96
109
  *
97
110
  * @example
98
- * ```astro
99
- * ---
100
- * // Astro page example - pages/service/[id].astro
101
- * import { loadServiceServiceConfig } from '@wix/services/services';
102
- * import { Service } from '@wix/services/components';
103
- *
104
- * // Get service id from URL params
105
- * const { id } = Astro.params;
111
+ * ```ts
112
+ * // In an Astro page or API route
113
+ * import { loadServiceServiceConfig } from '@wix/headless-bookings/services';
106
114
  *
107
- * // Load service data during SSR
108
- * const serviceResult = await loadServiceServiceConfig(id);
115
+ * const serviceResult = await loadServiceServiceConfig('group-trainings');
109
116
  *
110
- * // Handle not found case
111
117
  * if (serviceResult.type === 'notFound') {
112
118
  * return Astro.redirect('/404');
113
119
  * }
114
- * ---
115
120
  *
116
- * <Service.Root serviceConfig={serviceResult.config}>
117
- * <Service.Name>
118
- * {({ name }) => <h1>{name}</h1>}
119
- * </Service.Name>
120
- * </Service.Root>
121
+ * const serviceConfig = serviceResult.config;
121
122
  * ```
122
123
  */
123
- export async function loadServiceServiceConfig(serviceId) {
124
+ export async function loadServiceServiceConfig(slug) {
124
125
  try {
125
- const serviceResponse = await loadServiceById(serviceId);
126
+ const serviceResponse = await getServiceBySlug(slug);
126
127
  if (!serviceResponse.service) {
127
128
  return { type: 'notFound' };
128
129
  }
@@ -134,7 +135,7 @@ export async function loadServiceServiceConfig(serviceId) {
134
135
  };
135
136
  }
136
137
  catch (error) {
137
- console.error(`Failed to load service for id "${serviceId}":`, error);
138
+ console.error(`Failed to load service for slug "${slug}":`, error);
138
139
  return { type: 'notFound' };
139
140
  }
140
141
  }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * API Layer
3
+ * Exports all Wix Bookings API functions
4
+ */
5
+ export { getServiceById, getServiceBySlug } from './query-service/index.js';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * API Layer
3
+ * Exports all Wix Bookings API functions
4
+ */
5
+ export { getServiceById, getServiceBySlug } from './query-service/index.js';