@wix/headless-bookings 0.0.96 → 0.0.98
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/dist/__mocks__/booking/booking-client-service.d.ts +9 -0
- package/cjs/dist/__mocks__/booking/booking-client-service.js +55 -0
- package/cjs/dist/__mocks__/booking/booking-mocks.d.ts +20 -0
- package/cjs/dist/__mocks__/booking/booking-mocks.js +76 -0
- package/{dist/__mocks__/services.d.ts → cjs/dist/__mocks__/services/services-mocks.d.ts} +5 -17
- package/cjs/dist/__mocks__/{services.js → services/services-mocks.js} +1 -27
- package/cjs/dist/__mocks__/time-slots/time-slots-client-service.d.ts +79 -0
- package/cjs/dist/__mocks__/time-slots/time-slots-client-service.js +120 -0
- package/{dist/__mocks__/time-slots.d.ts → cjs/dist/__mocks__/time-slots/time-slots-core.d.ts} +1 -28
- package/cjs/dist/__mocks__/{time-slots.js → time-slots/time-slots-core.js} +1 -115
- package/cjs/dist/__mocks__/time-slots/time-slots-mocks.d.ts +14 -0
- package/cjs/dist/__mocks__/time-slots/time-slots-mocks.js +50 -0
- package/cjs/dist/react/booking-form/BookingForm.d.ts +30 -154
- package/cjs/dist/react/booking-form/BookingForm.js +34 -126
- package/cjs/dist/react/core/booking-form/BookingForm.d.ts +1 -51
- package/cjs/dist/react/core/booking-form/BookingForm.js +29 -140
- package/cjs/dist/services/booking/booking.js +2 -1
- package/cjs/dist/services/booking-form/booking-form.d.ts +35 -42
- package/cjs/dist/services/booking-form/booking-form.js +104 -74
- package/cjs/dist/services/constants.d.ts +12 -0
- package/cjs/dist/services/constants.js +11 -0
- package/cjs/dist/services/index.d.ts +1 -1
- package/cjs/dist/services/time-slot-list/time-slot-list.def.js +2 -1
- package/cjs/dist/services/time-slot-list/time-slot.js +2 -1
- package/dist/__mocks__/booking/booking-client-service.d.ts +9 -0
- package/dist/__mocks__/booking/booking-client-service.js +55 -0
- package/dist/__mocks__/booking/booking-mocks.d.ts +20 -0
- package/dist/__mocks__/booking/booking-mocks.js +76 -0
- package/{cjs/dist/__mocks__/services.d.ts → dist/__mocks__/services/services-mocks.d.ts} +5 -17
- package/dist/__mocks__/{services.js → services/services-mocks.js} +1 -27
- package/dist/__mocks__/time-slots/time-slots-client-service.d.ts +79 -0
- package/dist/__mocks__/time-slots/time-slots-client-service.js +120 -0
- package/{cjs/dist/__mocks__/time-slots.d.ts → dist/__mocks__/time-slots/time-slots-core.d.ts} +1 -28
- package/dist/__mocks__/{time-slots.js → time-slots/time-slots-core.js} +1 -115
- package/dist/__mocks__/time-slots/time-slots-mocks.d.ts +14 -0
- package/dist/__mocks__/time-slots/time-slots-mocks.js +50 -0
- package/dist/react/booking-form/BookingForm.d.ts +30 -154
- package/dist/react/booking-form/BookingForm.js +34 -126
- package/dist/react/core/booking-form/BookingForm.d.ts +1 -51
- package/dist/react/core/booking-form/BookingForm.js +29 -140
- package/dist/services/booking/booking.js +2 -1
- package/dist/services/booking-form/booking-form.d.ts +35 -42
- package/dist/services/booking-form/booking-form.js +104 -74
- package/dist/services/constants.d.ts +12 -0
- package/dist/services/constants.js +11 -0
- package/dist/services/index.d.ts +1 -1
- package/dist/services/time-slot-list/time-slot-list.def.js +2 -1
- package/dist/services/time-slot-list/time-slot.js +2 -1
- package/package.json +2 -2
- package/cjs/dist/__mocks__/booking.d.ts +0 -87
- package/cjs/dist/__mocks__/booking.js +0 -229
- package/dist/__mocks__/booking.d.ts +0 -87
- package/dist/__mocks__/booking.js +0 -229
- /package/cjs/dist/__mocks__/{payment.d.ts → payment/payment-mocks.d.ts} +0 -0
- /package/cjs/dist/__mocks__/{payment.js → payment/payment-mocks.js} +0 -0
- /package/dist/__mocks__/{payment.d.ts → payment/payment-mocks.d.ts} +0 -0
- /package/dist/__mocks__/{payment.js → payment/payment-mocks.js} +0 -0
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { defineService, implementService } from '@wix/services-definitions';
|
|
7
7
|
import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
|
|
8
8
|
import { executeBookAction } from './book-action/bookAction.js';
|
|
9
|
+
import { ClientServiceIds } from '../constants.js';
|
|
9
10
|
// ============================================================================
|
|
10
11
|
// Constants
|
|
11
12
|
// ============================================================================
|
|
@@ -29,7 +30,7 @@ function getClientTimezone() {
|
|
|
29
30
|
/**
|
|
30
31
|
* Service definition for Booking
|
|
31
32
|
*/
|
|
32
|
-
export const BookingServiceDefinition = defineService(
|
|
33
|
+
export const BookingServiceDefinition = defineService(ClientServiceIds.booking);
|
|
33
34
|
// ============================================================================
|
|
34
35
|
// Service Implementation
|
|
35
36
|
// ============================================================================
|
|
@@ -7,24 +7,14 @@
|
|
|
7
7
|
*
|
|
8
8
|
* When using a pre-loaded form, it must belong to the bookings namespace.
|
|
9
9
|
*/
|
|
10
|
-
import { type
|
|
11
|
-
import type { FormValues } from '@wix/form-public';
|
|
10
|
+
import { type ReadOnlySignal } from '@wix/services-definitions/core-services/signals';
|
|
12
11
|
import { forms } from '@wix/forms';
|
|
12
|
+
import { FormServiceConfig } from '@wix/headless-forms/services';
|
|
13
13
|
/**
|
|
14
14
|
* The required namespace for booking forms.
|
|
15
15
|
* All booking forms must belong to this namespace.
|
|
16
16
|
*/
|
|
17
17
|
export declare const BOOKING_FORM_NAMESPACE = "wix.bookings.v2.bookings";
|
|
18
|
-
/**
|
|
19
|
-
* Validation result type for form validation.
|
|
20
|
-
* Fields with errors will be marked according to the validation failures.
|
|
21
|
-
*/
|
|
22
|
-
export interface ValidationResult {
|
|
23
|
-
/** Whether the form is valid */
|
|
24
|
-
valid: boolean;
|
|
25
|
-
/** Array of validation failure messages */
|
|
26
|
-
validationFailures: string[];
|
|
27
|
-
}
|
|
28
18
|
/**
|
|
29
19
|
* Error thrown when BookingFormService cannot be initialized due to missing configuration.
|
|
30
20
|
* This occurs when:
|
|
@@ -61,7 +51,9 @@ export declare class BookingFormConfigurationError extends Error {
|
|
|
61
51
|
export type BookingFormServiceConfig = {
|
|
62
52
|
/** The form ID to load (client-side loading) */
|
|
63
53
|
formId: string;
|
|
64
|
-
/** Optional
|
|
54
|
+
/** Optional additional metadata to pass to FormService */
|
|
55
|
+
additionalMetadata?: Record<string, string | string[]>;
|
|
56
|
+
/** Optional list of service IDs to pass to FormService */
|
|
65
57
|
serviceIds?: string[];
|
|
66
58
|
} | {
|
|
67
59
|
/** Pre-loaded form object (SSR/SSG) - must be from bookings namespace */
|
|
@@ -76,28 +68,11 @@ export type BookingFormServiceConfig = {
|
|
|
76
68
|
* - SSR/SSG: Pre-loaded form is provided via config
|
|
77
69
|
*/
|
|
78
70
|
export interface BookingFormServiceAPI {
|
|
79
|
-
/**
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
formSubmissionId: ReadOnlySignal<string | null>;
|
|
85
|
-
/** Signal containing the form ID (from config or extracted from form) */
|
|
86
|
-
formId: ReadOnlySignal<string>;
|
|
87
|
-
/** Signal containing the pre-loaded form (if provided via SSR) */
|
|
88
|
-
form: ReadOnlySignal<forms.Form | null>;
|
|
89
|
-
/** Action to store form submission data */
|
|
90
|
-
setFormSubmission: (formValues: FormValues) => void;
|
|
91
|
-
/** Action to validate form - internally delegates to Form.Fields ref */
|
|
92
|
-
validateFormSubmission: () => Promise<ValidationResult>;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Internal API interface that extends public API.
|
|
96
|
-
* Contains methods for internal use by core components.
|
|
97
|
-
*/
|
|
98
|
-
export interface BookingFormServiceInternalAPI extends BookingFormServiceAPI {
|
|
99
|
-
/** Internal: Register validate callback (called by core component) */
|
|
100
|
-
_setValidateCallback: (callback: () => Promise<ValidationResult>) => void;
|
|
71
|
+
/**
|
|
72
|
+
* Signal containing the form service config.
|
|
73
|
+
* Contains either a pre-loaded form (SSR/SSG) or formId with metadata (client-side).
|
|
74
|
+
*/
|
|
75
|
+
formServiceConfig: ReadOnlySignal<FormServiceConfig | null>;
|
|
101
76
|
}
|
|
102
77
|
export { hasFormId, hasForm, extractFormIdFromForm, extractFormIdFromConfig, type FormIdConfig, } from './utils.js';
|
|
103
78
|
/**
|
|
@@ -117,8 +92,16 @@ export declare const BookingFormServiceDefinition: string & {
|
|
|
117
92
|
* 1. Client-side: formId is provided, form is loaded dynamically
|
|
118
93
|
* 2. SSR/SSG: Pre-loaded form is provided (must be from bookings namespace)
|
|
119
94
|
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
95
|
+
* Initialization:
|
|
96
|
+
* - Requires either a config (formId or form) OR BookingService with selected services
|
|
97
|
+
* - If config is not provided, formId is extracted from selected services
|
|
98
|
+
* - For multiple services, uses DEFAULT_FORM_ID; for single service, uses service's form ID
|
|
99
|
+
* - Service IDs are extracted from config.serviceIds or from selected services
|
|
100
|
+
*
|
|
101
|
+
* Validation:
|
|
102
|
+
* - The Form.Fields core component registers a validation callback via setValidateCallback
|
|
103
|
+
* - The validateFormSubmission() method calls this registered callback
|
|
104
|
+
* - The callback may be null initially until the core component registers it
|
|
122
105
|
*
|
|
123
106
|
* @example
|
|
124
107
|
* ```tsx
|
|
@@ -127,17 +110,27 @@ export declare const BookingFormServiceDefinition: string & {
|
|
|
127
110
|
* BookingFormServiceDefinition.withConfig({ formId: 'form-123' })
|
|
128
111
|
* );
|
|
129
112
|
*
|
|
113
|
+
* // Pattern 1b: Client-side loading with service IDs
|
|
114
|
+
* const bookingFormService = useService(
|
|
115
|
+
* BookingFormServiceDefinition.withConfig({
|
|
116
|
+
* formId: 'form-123',
|
|
117
|
+
* serviceIds: ['service-1', 'service-2']
|
|
118
|
+
* })
|
|
119
|
+
* );
|
|
120
|
+
*
|
|
130
121
|
* // Pattern 2: SSR with pre-loaded form
|
|
131
122
|
* const bookingFormService = useService(
|
|
132
123
|
* BookingFormServiceDefinition.withConfig({ form: preloadedForm })
|
|
133
124
|
* );
|
|
134
125
|
*
|
|
135
|
-
* //
|
|
136
|
-
* bookingFormService
|
|
126
|
+
* // Pattern 3: No config - formId extracted from BookingService
|
|
127
|
+
* const bookingFormService = useService(
|
|
128
|
+
* BookingFormServiceDefinition.withConfig(undefined)
|
|
129
|
+
* );
|
|
137
130
|
*
|
|
138
|
-
* // Validate form
|
|
139
|
-
* const result = await bookingFormService.validateFormSubmission();
|
|
140
|
-
* if (result
|
|
131
|
+
* // Validate form (callback must be registered by core component first)
|
|
132
|
+
* const result = await bookingFormService.validateFormSubmission?.();
|
|
133
|
+
* if (result?.valid) {
|
|
141
134
|
* // Proceed with booking
|
|
142
135
|
* }
|
|
143
136
|
* ```
|
|
@@ -9,9 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { defineService, implementService } from '@wix/services-definitions';
|
|
11
11
|
import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
|
|
12
|
-
import { FormServiceDefinition } from '@wix/headless-forms/services';
|
|
13
12
|
import { BookingServiceDefinition, } from '../booking/booking.js';
|
|
14
|
-
import { hasForm, extractFormIdFromConfig } from './utils.js';
|
|
13
|
+
import { hasForm, extractFormIdFromConfig, hasFormId } from './utils.js';
|
|
15
14
|
// ============================================================================
|
|
16
15
|
// Constants
|
|
17
16
|
// ============================================================================
|
|
@@ -20,6 +19,7 @@ import { hasForm, extractFormIdFromConfig } from './utils.js';
|
|
|
20
19
|
* All booking forms must belong to this namespace.
|
|
21
20
|
*/
|
|
22
21
|
export const BOOKING_FORM_NAMESPACE = 'wix.bookings.v2.bookings';
|
|
22
|
+
const DEFAULT_FORM_ID = '00000000-0000-0000-0000-000000000000';
|
|
23
23
|
/**
|
|
24
24
|
* Error thrown when BookingFormService cannot be initialized due to missing configuration.
|
|
25
25
|
* This occurs when:
|
|
@@ -54,32 +54,51 @@ export const BookingFormServiceDefinition = defineService('bookingForm');
|
|
|
54
54
|
// ============================================================================
|
|
55
55
|
/**
|
|
56
56
|
* Validates that a form belongs to the bookings namespace.
|
|
57
|
-
* @param
|
|
57
|
+
* @param config The service config that may contain a pre-loaded form
|
|
58
58
|
* @throws Error if the form is not from the bookings namespace
|
|
59
59
|
*/
|
|
60
60
|
function validateBookingFormNamespace(form) {
|
|
61
|
-
|
|
62
|
-
// The namespace might be in different locations depending on the form structure
|
|
63
|
-
const formNamespace = form.namespace ||
|
|
64
|
-
form._namespace;
|
|
61
|
+
const formNamespace = form.namespace;
|
|
65
62
|
if (formNamespace && formNamespace !== BOOKING_FORM_NAMESPACE) {
|
|
66
63
|
throw new Error(`BookingFormService: Invalid form namespace. ` +
|
|
67
64
|
`Expected "${BOOKING_FORM_NAMESPACE}", but received "${formNamespace}". ` +
|
|
68
65
|
`Ensure the form is a booking form.`);
|
|
69
66
|
}
|
|
70
67
|
}
|
|
68
|
+
function validateBookingFormConfig({ config, services, }) {
|
|
69
|
+
if (!config) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (hasForm(config)) {
|
|
73
|
+
validateBookingFormNamespace(config.form);
|
|
74
|
+
const servicesFormId = services.length > 1 ? DEFAULT_FORM_ID : services?.[0]?.form?._id;
|
|
75
|
+
if (servicesFormId !== config.form._id) {
|
|
76
|
+
throw new Error(`BookingFormService: Invalid form ID. ` +
|
|
77
|
+
`Expected "${config.form._id}", but received "${servicesFormId}". ` +
|
|
78
|
+
`Ensure the form is the same as the selected services form.`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
71
82
|
/**
|
|
72
83
|
* Extracts the form ID from either config type or from services.
|
|
84
|
+
*
|
|
85
|
+
* Extraction priority:
|
|
86
|
+
* 1. From config (if formId is provided directly or extracted from pre-loaded form)
|
|
87
|
+
* 2. From services:
|
|
88
|
+
* - If multiple services: use DEFAULT_FORM_ID
|
|
89
|
+
* - If single service: use the service's form ID
|
|
90
|
+
*
|
|
73
91
|
* @param config The service config (optional)
|
|
74
92
|
* @param services The list of services to extract formId from if config is not provided
|
|
75
93
|
* @returns The form ID
|
|
94
|
+
* @throws BookingFormConfigurationError if no formId can be extracted
|
|
76
95
|
*/
|
|
77
96
|
function extractFormId(config, services) {
|
|
78
97
|
// Try to extract from config first
|
|
79
98
|
let formId = extractFormIdFromConfig(config);
|
|
80
99
|
// Fallback to extracting from services
|
|
81
100
|
if (!formId) {
|
|
82
|
-
formId = services.
|
|
101
|
+
formId = services.length > 1 ? DEFAULT_FORM_ID : services?.[0]?.form?._id;
|
|
83
102
|
}
|
|
84
103
|
if (!formId) {
|
|
85
104
|
throw new BookingFormConfigurationError('BookingFormService: no formId found in config or services. ' +
|
|
@@ -87,6 +106,23 @@ function extractFormId(config, services) {
|
|
|
87
106
|
}
|
|
88
107
|
return formId;
|
|
89
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Extracts service IDs from config or services.
|
|
111
|
+
*
|
|
112
|
+
* Extraction priority:
|
|
113
|
+
* 1. From config.serviceIds if config has formId and serviceIds are provided
|
|
114
|
+
* 2. From services array (extract _id from each service)
|
|
115
|
+
*
|
|
116
|
+
* @param config The service config (optional)
|
|
117
|
+
* @param services The list of services to extract IDs from if config doesn't provide them
|
|
118
|
+
* @returns Array of service IDs
|
|
119
|
+
*/
|
|
120
|
+
function getServiceIds(config, services) {
|
|
121
|
+
if (hasFormId(config) && config.serviceIds) {
|
|
122
|
+
return config.serviceIds;
|
|
123
|
+
}
|
|
124
|
+
return services.map((s) => s._id).filter(Boolean);
|
|
125
|
+
}
|
|
90
126
|
// ============================================================================
|
|
91
127
|
// Service Implementation
|
|
92
128
|
// ============================================================================
|
|
@@ -98,8 +134,16 @@ function extractFormId(config, services) {
|
|
|
98
134
|
* 1. Client-side: formId is provided, form is loaded dynamically
|
|
99
135
|
* 2. SSR/SSG: Pre-loaded form is provided (must be from bookings namespace)
|
|
100
136
|
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
137
|
+
* Initialization:
|
|
138
|
+
* - Requires either a config (formId or form) OR BookingService with selected services
|
|
139
|
+
* - If config is not provided, formId is extracted from selected services
|
|
140
|
+
* - For multiple services, uses DEFAULT_FORM_ID; for single service, uses service's form ID
|
|
141
|
+
* - Service IDs are extracted from config.serviceIds or from selected services
|
|
142
|
+
*
|
|
143
|
+
* Validation:
|
|
144
|
+
* - The Form.Fields core component registers a validation callback via setValidateCallback
|
|
145
|
+
* - The validateFormSubmission() method calls this registered callback
|
|
146
|
+
* - The callback may be null initially until the core component registers it
|
|
103
147
|
*
|
|
104
148
|
* @example
|
|
105
149
|
* ```tsx
|
|
@@ -108,24 +152,33 @@ function extractFormId(config, services) {
|
|
|
108
152
|
* BookingFormServiceDefinition.withConfig({ formId: 'form-123' })
|
|
109
153
|
* );
|
|
110
154
|
*
|
|
155
|
+
* // Pattern 1b: Client-side loading with service IDs
|
|
156
|
+
* const bookingFormService = useService(
|
|
157
|
+
* BookingFormServiceDefinition.withConfig({
|
|
158
|
+
* formId: 'form-123',
|
|
159
|
+
* serviceIds: ['service-1', 'service-2']
|
|
160
|
+
* })
|
|
161
|
+
* );
|
|
162
|
+
*
|
|
111
163
|
* // Pattern 2: SSR with pre-loaded form
|
|
112
164
|
* const bookingFormService = useService(
|
|
113
165
|
* BookingFormServiceDefinition.withConfig({ form: preloadedForm })
|
|
114
166
|
* );
|
|
115
167
|
*
|
|
116
|
-
* //
|
|
117
|
-
* bookingFormService
|
|
168
|
+
* // Pattern 3: No config - formId extracted from BookingService
|
|
169
|
+
* const bookingFormService = useService(
|
|
170
|
+
* BookingFormServiceDefinition.withConfig(undefined)
|
|
171
|
+
* );
|
|
118
172
|
*
|
|
119
|
-
* // Validate form
|
|
120
|
-
* const result = await bookingFormService.validateFormSubmission();
|
|
121
|
-
* if (result
|
|
173
|
+
* // Validate form (callback must be registered by core component first)
|
|
174
|
+
* const result = await bookingFormService.validateFormSubmission?.();
|
|
175
|
+
* if (result?.valid) {
|
|
122
176
|
* // Proceed with booking
|
|
123
177
|
* }
|
|
124
178
|
* ```
|
|
125
179
|
*/
|
|
126
180
|
export const BookingFormService = implementService.withConfig()(BookingFormServiceDefinition, ({ getService, config }) => {
|
|
127
181
|
const signalsService = getService(SignalsServiceDefinition);
|
|
128
|
-
const formService = getService(FormServiceDefinition);
|
|
129
182
|
// BookingService is optional - may not be available if not wrapped with Booking.Root
|
|
130
183
|
let bookingService = null;
|
|
131
184
|
try {
|
|
@@ -135,6 +188,10 @@ export const BookingFormService = implementService.withConfig()(BookingFormServi
|
|
|
135
188
|
// BookingService not available - that's ok if formId was provided explicitly
|
|
136
189
|
bookingService = null;
|
|
137
190
|
}
|
|
191
|
+
/**
|
|
192
|
+
* Helper to extract services from BookingService.
|
|
193
|
+
* Returns empty array if BookingService is not available.
|
|
194
|
+
*/
|
|
138
195
|
const getServices = () => {
|
|
139
196
|
if (!bookingService) {
|
|
140
197
|
return [];
|
|
@@ -150,64 +207,37 @@ export const BookingFormService = implementService.withConfig()(BookingFormServi
|
|
|
150
207
|
if (!config && (!bookingService || !hasServiceSelections)) {
|
|
151
208
|
throw new BookingFormConfigurationError();
|
|
152
209
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
// Action to validate form - delegates to internally registered callback
|
|
180
|
-
const validateFormSubmission = async () => {
|
|
181
|
-
if (!_validateCallback) {
|
|
182
|
-
console.error('BookingFormService: Validate callback not registered. ' +
|
|
183
|
-
'Ensure BookingForm component is mounted.');
|
|
184
|
-
return { valid: false, validationFailures: ['Form not initialized'] };
|
|
185
|
-
}
|
|
186
|
-
return _validateCallback();
|
|
187
|
-
};
|
|
188
|
-
// Auto-sync formValues to BookingService.formSubmission (client-side only)
|
|
189
|
-
// This keeps Booking.Data.formSubmission updated as the user types
|
|
190
|
-
// and ensures the book action gets the latest form values
|
|
191
|
-
// Only set up sync if BookingService is available
|
|
192
|
-
if (bookingService) {
|
|
193
|
-
signalsService.effect(() => {
|
|
194
|
-
const formValues = formService.formValuesSignal.get();
|
|
195
|
-
if (formValues && Object.keys(formValues).length > 0) {
|
|
196
|
-
bookingService.actions.setFormSubmission(formValues);
|
|
197
|
-
}
|
|
210
|
+
const serviceSelections = getServices();
|
|
211
|
+
// Validate config
|
|
212
|
+
validateBookingFormConfig({ config, services: serviceSelections });
|
|
213
|
+
// Extract formId from config (either directly or from form object) or from services
|
|
214
|
+
const formIdValue = extractFormId(config, serviceSelections);
|
|
215
|
+
// Extract service IDs to pass to FormService (from config or services)
|
|
216
|
+
const serviceIds = getServiceIds(config, serviceSelections);
|
|
217
|
+
/**
|
|
218
|
+
* Form service config signal.
|
|
219
|
+
*
|
|
220
|
+
* If pre-loaded form is provided (SSR/SSG):
|
|
221
|
+
* - Creates config with the form object
|
|
222
|
+
*
|
|
223
|
+
* Otherwise (client-side loading):
|
|
224
|
+
* - Creates config with formId, namespace, and metadata
|
|
225
|
+
* - Includes serviceIds in additionalMetadata for FormService
|
|
226
|
+
*/
|
|
227
|
+
const formServiceConfig = signalsService.signal(hasForm(config)
|
|
228
|
+
? { form: config.form }
|
|
229
|
+
: {
|
|
230
|
+
formId: formIdValue,
|
|
231
|
+
namespace: BOOKING_FORM_NAMESPACE,
|
|
232
|
+
additionalMetadata: {
|
|
233
|
+
...config?.additionalMetadata,
|
|
234
|
+
serviceIds,
|
|
235
|
+
},
|
|
198
236
|
});
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
formSubmissionId,
|
|
205
|
-
formId,
|
|
206
|
-
form,
|
|
207
|
-
setFormSubmission,
|
|
208
|
-
validateFormSubmission,
|
|
209
|
-
// Internal method for core component access
|
|
210
|
-
_setValidateCallback,
|
|
237
|
+
/**
|
|
238
|
+
* Public API implementation.
|
|
239
|
+
*/
|
|
240
|
+
return {
|
|
241
|
+
formServiceConfig,
|
|
211
242
|
};
|
|
212
|
-
return publicApi;
|
|
213
243
|
});
|
|
@@ -7,3 +7,15 @@
|
|
|
7
7
|
export declare const BOOKING_APP_ID = "13d21c63-b5ec-5912-8397-c3a5ddb27a97";
|
|
8
8
|
/** Resource type ID for staff members */
|
|
9
9
|
export declare const STAFF_MEMBER_RESOURCE_TYPE_ID = "1cd44cf8-756f-41c3-bd90-3e2ffcaf1155";
|
|
10
|
+
export declare const ClientServiceIds: {
|
|
11
|
+
readonly booking: "booking";
|
|
12
|
+
readonly bookingForm: "bookingForm";
|
|
13
|
+
readonly timeSlot: "time-slot";
|
|
14
|
+
readonly timeSlotList: "time-slot-list";
|
|
15
|
+
readonly service: "service";
|
|
16
|
+
readonly serviceList: "service-list";
|
|
17
|
+
readonly payment: "payment";
|
|
18
|
+
readonly staffMemberList: "staff-member-list";
|
|
19
|
+
readonly locationList: "location-list";
|
|
20
|
+
};
|
|
21
|
+
export type ClientServiceId = (typeof ClientServiceIds)[keyof typeof ClientServiceIds];
|
|
@@ -7,3 +7,14 @@
|
|
|
7
7
|
export const BOOKING_APP_ID = '13d21c63-b5ec-5912-8397-c3a5ddb27a97';
|
|
8
8
|
/** Resource type ID for staff members */
|
|
9
9
|
export const STAFF_MEMBER_RESOURCE_TYPE_ID = '1cd44cf8-756f-41c3-bd90-3e2ffcaf1155';
|
|
10
|
+
export const ClientServiceIds = {
|
|
11
|
+
booking: 'booking',
|
|
12
|
+
bookingForm: 'bookingForm',
|
|
13
|
+
timeSlot: 'time-slot',
|
|
14
|
+
timeSlotList: 'time-slot-list',
|
|
15
|
+
service: 'service',
|
|
16
|
+
serviceList: 'service-list',
|
|
17
|
+
payment: 'payment',
|
|
18
|
+
staffMemberList: 'staff-member-list',
|
|
19
|
+
locationList: 'location-list',
|
|
20
|
+
};
|
package/dist/services/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { TimeSlotListService, TimeSlotListServiceDefinition, TimeSlotService, Ti
|
|
|
8
8
|
export { ServiceListService, ServiceListServiceDefinition, type ServiceListServiceAPI, type ServiceListServiceConfig, type ServiceListActions, type QueryOptions, loadServiceListServiceInitialData, type SuccessServiceListServiceConfigResult, type ErrorServiceListServiceConfigResult, } from './service-list/service-list.js';
|
|
9
9
|
export { SYNTHETIC_CUSTOM_ID, SYNTHETIC_CUSTOMER_ID, } from '../api/query-services/index.js';
|
|
10
10
|
export { executeBookAction, canBook, buildBookingRequest, buildCheckoutRequest, type CanBookParams, type BookResult, type BookingError, type BookActionParams, type BookChildProps, type BookProps, type BuildCheckoutParams, } from './booking/book-action/index.js';
|
|
11
|
-
export { BookingFormService, BookingFormServiceDefinition, type BookingFormServiceAPI, type BookingFormServiceConfig,
|
|
11
|
+
export { BookingFormService, BookingFormServiceDefinition, type BookingFormServiceAPI, type BookingFormServiceConfig, } from './booking-form/booking-form.js';
|
|
12
12
|
export { PaymentService, PaymentServiceDefinition, type PaymentServiceAPI, type PaymentServiceConfig, type PaymentDetails, type PricingServiceSelection, type LineItemAdditionalInfo, loadPaymentConfig, type SuccessPaymentConfigResult, type ErrorPaymentConfigResult, } from './payment/payment.js';
|
|
13
13
|
export { LocationListService, LocationListServiceDefinition, LocationType, loadLocationListServiceInitialData, locationListServiceBinding, type LocationListServiceAPI, type LocationListServiceConfig, type LocationListActions, type Location, type LoadLocationListServiceResult, getLocationById, } from './location-list/location-list.js';
|
|
14
14
|
export { StaffMemberListService, StaffMemberListServiceDefinition, loadStaffMemberListServiceInitialData, staffMemberListServiceBinding, type StaffMemberListServiceAPI, type StaffMemberListServiceConfig, type StaffMemberListActions, type StaffMemberData, type LoadStaffMemberListServiceResult, } from './staff-member-list/staff-member-list.js';
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Defines interfaces and service contract for time slot management
|
|
4
4
|
*/
|
|
5
5
|
import { defineService } from '@wix/services-definitions';
|
|
6
|
+
import { ClientServiceIds } from '../constants.js';
|
|
6
7
|
// ============================================================================
|
|
7
8
|
// Enums
|
|
8
9
|
// ============================================================================
|
|
@@ -14,4 +15,4 @@ export var ViewMode;
|
|
|
14
15
|
// ============================================================================
|
|
15
16
|
// Service Definition
|
|
16
17
|
// ============================================================================
|
|
17
|
-
export const TimeSlotListServiceDefinition = defineService(
|
|
18
|
+
export const TimeSlotListServiceDefinition = defineService(ClientServiceIds.timeSlotList);
|
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { defineService, implementService } from '@wix/services-definitions';
|
|
6
6
|
import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
|
|
7
|
+
import { ClientServiceIds } from '../constants.js';
|
|
7
8
|
/**
|
|
8
9
|
* Service definition for TimeSlot
|
|
9
10
|
*/
|
|
10
|
-
export const TimeSlotServiceDefinition = defineService(
|
|
11
|
+
export const TimeSlotServiceDefinition = defineService(ClientServiceIds.timeSlot);
|
|
11
12
|
/**
|
|
12
13
|
* Implementation of TimeSlotService
|
|
13
14
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/headless-bookings",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.98",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"scripts": {
|
|
@@ -72,5 +72,5 @@
|
|
|
72
72
|
"groupId": "com.wixpress.headless-components"
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
|
-
"falconPackageHash": "
|
|
75
|
+
"falconPackageHash": "fbdac59032803915437800f3b84103cc1108e326ac3c2b91978f60f9"
|
|
76
76
|
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import type { FormValues } from '@wix/form-public';
|
|
2
|
-
import type { Location } from '@wix/auto_sdk_bookings_services';
|
|
3
|
-
import type { ServiceSelection, ServiceSelectionTimeSlot, BookingServiceConfig, BookingService, ExtendedResource } from '../services/booking/booking.js';
|
|
4
|
-
import type { Signal } from '@wix/services-definitions/core-services/signals';
|
|
5
|
-
export declare function mockSignal<T>(initialValue: T): Signal<T>;
|
|
6
|
-
export declare function createMockSignalsService(): {
|
|
7
|
-
signal: typeof mockSignal;
|
|
8
|
-
computed: <T>(fn: () => T) => Signal<T>;
|
|
9
|
-
effect: (fn: () => void) => void;
|
|
10
|
-
};
|
|
11
|
-
export declare function createMockBookingService(initialSelections?: ServiceSelection[]): BookingService;
|
|
12
|
-
/**
|
|
13
|
-
* Mock resource (staff member)
|
|
14
|
-
*/
|
|
15
|
-
export declare const mockResource: ExtendedResource;
|
|
16
|
-
/**
|
|
17
|
-
* Mock resource (another staff member)
|
|
18
|
-
*/
|
|
19
|
-
export declare const mockResourceTwo: ExtendedResource;
|
|
20
|
-
/**
|
|
21
|
-
* Mock resource (room)
|
|
22
|
-
*/
|
|
23
|
-
export declare const mockResourceRoom: ExtendedResource;
|
|
24
|
-
/**
|
|
25
|
-
* Mock location (BUSINESS type with nested business object)
|
|
26
|
-
*/
|
|
27
|
-
export declare const mockLocation: Location;
|
|
28
|
-
/**
|
|
29
|
-
* Mock location (second)
|
|
30
|
-
*/
|
|
31
|
-
export declare const mockLocationTwo: Location;
|
|
32
|
-
/**
|
|
33
|
-
* Mock time slot data
|
|
34
|
-
*/
|
|
35
|
-
export declare const mockTimeSlot: ServiceSelectionTimeSlot;
|
|
36
|
-
/**
|
|
37
|
-
* Mock time slot for afternoon
|
|
38
|
-
*/
|
|
39
|
-
export declare const mockTimeSlotAfternoon: ServiceSelectionTimeSlot;
|
|
40
|
-
/**
|
|
41
|
-
* Mock service selection with all data
|
|
42
|
-
*/
|
|
43
|
-
export declare const mockServiceSelection: ServiceSelection;
|
|
44
|
-
/**
|
|
45
|
-
* Mock service selection without time slot (incomplete)
|
|
46
|
-
*/
|
|
47
|
-
export declare const mockServiceSelectionWithoutTimeSlot: ServiceSelection;
|
|
48
|
-
/**
|
|
49
|
-
* Mock service selection for class
|
|
50
|
-
*/
|
|
51
|
-
export declare const mockServiceSelectionClass: ServiceSelection;
|
|
52
|
-
/**
|
|
53
|
-
* Mock form submission (contact info)
|
|
54
|
-
*/
|
|
55
|
-
export declare const mockFormSubmission: FormValues;
|
|
56
|
-
/**
|
|
57
|
-
* Mock form submission (minimal)
|
|
58
|
-
*/
|
|
59
|
-
export declare const mockFormSubmissionMinimal: FormValues;
|
|
60
|
-
/**
|
|
61
|
-
* Mock form submission with custom fields
|
|
62
|
-
*/
|
|
63
|
-
export declare const mockFormSubmissionWithCustomFields: FormValues;
|
|
64
|
-
/**
|
|
65
|
-
* Default timezone for tests
|
|
66
|
-
*/
|
|
67
|
-
export declare const mockTimezone = "America/New_York";
|
|
68
|
-
/**
|
|
69
|
-
* Mock booking service config (empty)
|
|
70
|
-
*/
|
|
71
|
-
export declare const mockEmptyBookingConfig: BookingServiceConfig;
|
|
72
|
-
/**
|
|
73
|
-
* Mock booking service config with initial data
|
|
74
|
-
*/
|
|
75
|
-
export declare const mockBookingConfigWithData: BookingServiceConfig;
|
|
76
|
-
/**
|
|
77
|
-
* Mock booking service config with multiple selections
|
|
78
|
-
*/
|
|
79
|
-
export declare const mockBookingConfigMultipleSelections: BookingServiceConfig;
|
|
80
|
-
/**
|
|
81
|
-
* Helper to create a service selection with custom instanceId
|
|
82
|
-
*/
|
|
83
|
-
export declare function createMockServiceSelection(overrides?: Partial<ServiceSelection>): Omit<ServiceSelection, 'instanceId'>;
|
|
84
|
-
/**
|
|
85
|
-
* Helper to create multiple service selections
|
|
86
|
-
*/
|
|
87
|
-
export declare function createMockServiceSelections(count: number): ServiceSelection[];
|