@wix/headless-bookings 0.0.43 → 0.0.45
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.d.ts +9 -4
- package/cjs/dist/__mocks__/booking.js +48 -3
- package/cjs/dist/__mocks__/time-slots.d.ts +28 -0
- package/cjs/dist/__mocks__/time-slots.js +116 -0
- package/cjs/dist/api/index.d.ts +1 -0
- package/cjs/dist/api/index.js +1 -0
- package/cjs/dist/api/query-locations/index.d.ts +38 -0
- package/cjs/dist/api/query-locations/index.js +30 -0
- package/cjs/dist/react/core/location/Location.d.ts +113 -14
- package/cjs/dist/react/core/location/Location.js +189 -30
- package/cjs/dist/react/core/location-list/LocationList.d.ts +102 -0
- package/cjs/dist/react/core/location-list/LocationList.js +71 -0
- package/cjs/dist/react/index.d.ts +1 -0
- package/cjs/dist/react/index.js +1 -0
- package/cjs/dist/react/location/Location.d.ts +211 -41
- package/cjs/dist/react/location/Location.js +219 -46
- package/cjs/dist/react/location/LocationList.d.ts +98 -0
- package/cjs/dist/react/location/LocationList.js +120 -0
- package/cjs/dist/react/service/Service.d.ts +17 -24
- package/cjs/dist/react/service/Service.js +24 -36
- package/cjs/dist/services/index.d.ts +1 -0
- package/cjs/dist/services/index.js +1 -0
- package/cjs/dist/services/location-list/location-list.d.ts +100 -0
- package/cjs/dist/services/location-list/location-list.def.d.ts +62 -0
- package/cjs/dist/services/location-list/location-list.def.js +17 -0
- package/cjs/dist/services/location-list/location-list.js +212 -0
- package/dist/__mocks__/booking.d.ts +9 -4
- package/dist/__mocks__/booking.js +48 -3
- package/dist/__mocks__/time-slots.d.ts +28 -0
- package/dist/__mocks__/time-slots.js +116 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +1 -0
- package/dist/api/query-locations/index.d.ts +38 -0
- package/dist/api/query-locations/index.js +30 -0
- package/dist/react/core/location/Location.d.ts +113 -14
- package/dist/react/core/location/Location.js +189 -30
- package/dist/react/core/location-list/LocationList.d.ts +102 -0
- package/dist/react/core/location-list/LocationList.js +71 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +1 -0
- package/dist/react/location/Location.d.ts +211 -41
- package/dist/react/location/Location.js +219 -46
- package/dist/react/location/LocationList.d.ts +98 -0
- package/dist/react/location/LocationList.js +120 -0
- package/dist/react/service/Service.d.ts +17 -24
- package/dist/react/service/Service.js +24 -36
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/services/location-list/location-list.d.ts +100 -0
- package/dist/services/location-list/location-list.def.d.ts +62 -0
- package/dist/services/location-list/location-list.def.js +17 -0
- package/dist/services/location-list/location-list.js +212 -0
- package/package.json +2 -2
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Location List Service Implementation
|
|
3
|
+
* Manages location state, auto-detection, and BookingService integration
|
|
4
|
+
*
|
|
5
|
+
* @module Services/LocationList
|
|
6
|
+
*/
|
|
7
|
+
import { implementService } from '@wix/services-definitions';
|
|
8
|
+
import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
|
|
9
|
+
import { LocationType } from '@wix/auto_sdk_bookings_services';
|
|
10
|
+
import { LocationListServiceDefinition, } from './location-list.def.js';
|
|
11
|
+
import { BookingServiceDefinition } from '../booking/booking.js';
|
|
12
|
+
import { queryLocations } from '../../api/query-locations/index.js';
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Constants
|
|
15
|
+
// ============================================================================
|
|
16
|
+
/**
|
|
17
|
+
* Synthetic location IDs for non-business locations
|
|
18
|
+
*/
|
|
19
|
+
const SYNTHETIC_CUSTOM_ID = '__synthetic_custom__';
|
|
20
|
+
const SYNTHETIC_CUSTOMER_ID = '__synthetic_customer__';
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Helper Functions
|
|
23
|
+
// ============================================================================
|
|
24
|
+
/**
|
|
25
|
+
* Build display locations from raw locations and flags
|
|
26
|
+
*/
|
|
27
|
+
function buildDisplayLocations(locations, hasCustomLocations, hasCustomerLocations) {
|
|
28
|
+
const displayLocations = [];
|
|
29
|
+
// 1. Add all BUSINESS locations
|
|
30
|
+
const businessLocations = locations.filter((loc) => loc.type === LocationType.BUSINESS || loc.type === undefined);
|
|
31
|
+
for (const loc of businessLocations) {
|
|
32
|
+
displayLocations.push({
|
|
33
|
+
location: loc,
|
|
34
|
+
type: LocationType.BUSINESS,
|
|
35
|
+
isSynthetic: false,
|
|
36
|
+
id: loc.business?._id || loc._id || String(displayLocations.length),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
// Check for existing CUSTOM/CUSTOMER in array
|
|
40
|
+
const customFromArray = locations.find((loc) => loc.type === LocationType.CUSTOM);
|
|
41
|
+
const customerFromArray = locations.find((loc) => loc.type === LocationType.CUSTOMER);
|
|
42
|
+
// 2. Add CUSTOM location (from array or synthetic)
|
|
43
|
+
if (customFromArray) {
|
|
44
|
+
displayLocations.push({
|
|
45
|
+
location: customFromArray,
|
|
46
|
+
type: LocationType.CUSTOM,
|
|
47
|
+
isSynthetic: false,
|
|
48
|
+
id: customFromArray.custom?._id || SYNTHETIC_CUSTOM_ID,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
else if (hasCustomLocations) {
|
|
52
|
+
// Synthetic custom location (only from explicit flag, not array)
|
|
53
|
+
displayLocations.push({
|
|
54
|
+
location: null,
|
|
55
|
+
type: LocationType.CUSTOM,
|
|
56
|
+
isSynthetic: true,
|
|
57
|
+
id: SYNTHETIC_CUSTOM_ID,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
// 3. Add CUSTOMER location (always synthetic display, real or flag-based)
|
|
61
|
+
if (customerFromArray || hasCustomerLocations) {
|
|
62
|
+
displayLocations.push({
|
|
63
|
+
location: customerFromArray || null,
|
|
64
|
+
type: LocationType.CUSTOMER,
|
|
65
|
+
isSynthetic: !customerFromArray,
|
|
66
|
+
id: SYNTHETIC_CUSTOMER_ID,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return displayLocations;
|
|
70
|
+
}
|
|
71
|
+
// ============================================================================
|
|
72
|
+
// Service Implementation
|
|
73
|
+
// ============================================================================
|
|
74
|
+
/**
|
|
75
|
+
* Implementation of the LocationList service
|
|
76
|
+
* Manages location state and integrates with BookingService for selection (optional)
|
|
77
|
+
*/
|
|
78
|
+
export const LocationListService = implementService.withConfig()(LocationListServiceDefinition, ({ getService, config }) => {
|
|
79
|
+
const signalsService = getService(SignalsServiceDefinition);
|
|
80
|
+
// Try to get BookingService - it's optional (Location can be standalone)
|
|
81
|
+
let bookingService = null;
|
|
82
|
+
try {
|
|
83
|
+
bookingService = getService(BookingServiceDefinition);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// BookingService not available - Location is used standalone
|
|
87
|
+
bookingService = null;
|
|
88
|
+
}
|
|
89
|
+
// Initialize raw locations signal
|
|
90
|
+
const locationsSignal = signalsService.signal(config.locations || []);
|
|
91
|
+
// Auto-detect from array
|
|
92
|
+
const hasCustomInArray = (config.locations || []).some((loc) => loc.type === LocationType.CUSTOM);
|
|
93
|
+
const hasCustomerInArray = (config.locations || []).some((loc) => loc.type === LocationType.CUSTOMER);
|
|
94
|
+
// Final flags: explicit config OR auto-detected
|
|
95
|
+
const hasCustomLocationsSignal = signalsService.computed(() => config.hasCustomLocations ?? hasCustomInArray);
|
|
96
|
+
const hasCustomerLocationsSignal = signalsService.computed(() => config.hasCustomerLocations ?? hasCustomerInArray);
|
|
97
|
+
// Display locations - computed from raw + flags
|
|
98
|
+
const displayLocationsSignal = signalsService.computed(() => buildDisplayLocations(locationsSignal.get(), hasCustomLocationsSignal.get(), hasCustomerLocationsSignal.get()));
|
|
99
|
+
const isLoadingSignal = signalsService.signal(false);
|
|
100
|
+
const errorSignal = signalsService.signal(null);
|
|
101
|
+
// Selected location from BookingService (null if standalone)
|
|
102
|
+
const selectedLocationSignal = signalsService.computed(() => {
|
|
103
|
+
if (!bookingService)
|
|
104
|
+
return null;
|
|
105
|
+
return bookingService.location.get();
|
|
106
|
+
});
|
|
107
|
+
// Actions - integrate with BookingService if available
|
|
108
|
+
const actions = {
|
|
109
|
+
select: (displayLocation) => {
|
|
110
|
+
if (bookingService) {
|
|
111
|
+
bookingService.actions.setLocation(displayLocation.location);
|
|
112
|
+
}
|
|
113
|
+
// If standalone, selection is handled by consumer via asChild
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
return {
|
|
117
|
+
locations: locationsSignal,
|
|
118
|
+
displayLocations: displayLocationsSignal,
|
|
119
|
+
hasCustomLocations: hasCustomLocationsSignal,
|
|
120
|
+
hasCustomerLocations: hasCustomerLocationsSignal,
|
|
121
|
+
isLoading: isLoadingSignal,
|
|
122
|
+
error: errorSignal,
|
|
123
|
+
selectedLocation: selectedLocationSignal,
|
|
124
|
+
actions,
|
|
125
|
+
};
|
|
126
|
+
});
|
|
127
|
+
/**
|
|
128
|
+
* SSR Loader: Fetches locations from API for server-side rendering.
|
|
129
|
+
*
|
|
130
|
+
* @param options - Optional configuration
|
|
131
|
+
* @returns Configuration result for LocationListService with pre-fetched locations
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```typescript
|
|
135
|
+
* // Fetch from API
|
|
136
|
+
* const result = await loadLocationListServiceInitialData();
|
|
137
|
+
*
|
|
138
|
+
* if (result.type === 'error') {
|
|
139
|
+
* return Astro.redirect('/500');
|
|
140
|
+
* }
|
|
141
|
+
*
|
|
142
|
+
* const locationListConfig = result.config;
|
|
143
|
+
* ```
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* // Pass locations directly (e.g., from service.locations)
|
|
148
|
+
* const result = await loadLocationListServiceInitialData({
|
|
149
|
+
* locations: service.locations,
|
|
150
|
+
* // hasCustom/hasCustomer will be auto-detected from array
|
|
151
|
+
* });
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
export async function loadLocationListServiceInitialData(options) {
|
|
155
|
+
try {
|
|
156
|
+
// If locations are passed directly, use them (flags auto-detected if not provided)
|
|
157
|
+
if (options?.locations) {
|
|
158
|
+
return {
|
|
159
|
+
type: 'success',
|
|
160
|
+
config: {
|
|
161
|
+
locations: options.locations,
|
|
162
|
+
hasCustomLocations: options.hasCustomLocations,
|
|
163
|
+
hasCustomerLocations: options.hasCustomerLocations,
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
// Otherwise, fetch from API
|
|
168
|
+
const result = await queryLocations();
|
|
169
|
+
return {
|
|
170
|
+
type: 'success',
|
|
171
|
+
config: {
|
|
172
|
+
locations: result.locations,
|
|
173
|
+
hasCustomLocations: result.hasCustomLocations,
|
|
174
|
+
hasCustomerLocations: result.hasCustomerLocations,
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
const message = error instanceof Error ? error.message : 'Failed to load locations';
|
|
180
|
+
console.error('loadLocationListServiceInitialData error:', error);
|
|
181
|
+
return { type: 'error', error: message };
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// ============================================================================
|
|
185
|
+
// Service Binding Helper
|
|
186
|
+
// ============================================================================
|
|
187
|
+
/**
|
|
188
|
+
* Service binding helper for LocationListService.
|
|
189
|
+
* Bundles definition, implementation, and config for ServicesManager.
|
|
190
|
+
*
|
|
191
|
+
* @param servicesConfigs - Object containing LocationListServiceDefinition config
|
|
192
|
+
* @returns Tuple of [Definition, Implementation, Config] for addService()
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```typescript
|
|
196
|
+
* const servicesManager = createServicesManager(
|
|
197
|
+
* createServicesMap()
|
|
198
|
+
* .addService(...locationListServiceBinding(configs))
|
|
199
|
+
* );
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
export const locationListServiceBinding = (servicesConfigs) => {
|
|
203
|
+
return [
|
|
204
|
+
LocationListServiceDefinition,
|
|
205
|
+
LocationListService,
|
|
206
|
+
servicesConfigs['location-list'],
|
|
207
|
+
];
|
|
208
|
+
};
|
|
209
|
+
// ============================================================================
|
|
210
|
+
// Re-exports
|
|
211
|
+
// ============================================================================
|
|
212
|
+
export { LocationListServiceDefinition, LocationType, } from './location-list.def.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/headless-bookings",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.45",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -72,5 +72,5 @@
|
|
|
72
72
|
"groupId": "com.wixpress.headless-components"
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
|
-
"falconPackageHash": "
|
|
75
|
+
"falconPackageHash": "122a9bd0c5095741e936f6e76ab60fa20cb7c69c33763af1a38937c5"
|
|
76
76
|
}
|