@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.
Files changed (53) hide show
  1. package/cjs/dist/__mocks__/booking.d.ts +9 -4
  2. package/cjs/dist/__mocks__/booking.js +48 -3
  3. package/cjs/dist/__mocks__/time-slots.d.ts +28 -0
  4. package/cjs/dist/__mocks__/time-slots.js +116 -0
  5. package/cjs/dist/api/index.d.ts +1 -0
  6. package/cjs/dist/api/index.js +1 -0
  7. package/cjs/dist/api/query-locations/index.d.ts +38 -0
  8. package/cjs/dist/api/query-locations/index.js +30 -0
  9. package/cjs/dist/react/core/location/Location.d.ts +113 -14
  10. package/cjs/dist/react/core/location/Location.js +189 -30
  11. package/cjs/dist/react/core/location-list/LocationList.d.ts +102 -0
  12. package/cjs/dist/react/core/location-list/LocationList.js +71 -0
  13. package/cjs/dist/react/index.d.ts +1 -0
  14. package/cjs/dist/react/index.js +1 -0
  15. package/cjs/dist/react/location/Location.d.ts +211 -41
  16. package/cjs/dist/react/location/Location.js +219 -46
  17. package/cjs/dist/react/location/LocationList.d.ts +98 -0
  18. package/cjs/dist/react/location/LocationList.js +120 -0
  19. package/cjs/dist/react/service/Service.d.ts +17 -24
  20. package/cjs/dist/react/service/Service.js +24 -36
  21. package/cjs/dist/services/index.d.ts +1 -0
  22. package/cjs/dist/services/index.js +1 -0
  23. package/cjs/dist/services/location-list/location-list.d.ts +100 -0
  24. package/cjs/dist/services/location-list/location-list.def.d.ts +62 -0
  25. package/cjs/dist/services/location-list/location-list.def.js +17 -0
  26. package/cjs/dist/services/location-list/location-list.js +212 -0
  27. package/dist/__mocks__/booking.d.ts +9 -4
  28. package/dist/__mocks__/booking.js +48 -3
  29. package/dist/__mocks__/time-slots.d.ts +28 -0
  30. package/dist/__mocks__/time-slots.js +116 -0
  31. package/dist/api/index.d.ts +1 -0
  32. package/dist/api/index.js +1 -0
  33. package/dist/api/query-locations/index.d.ts +38 -0
  34. package/dist/api/query-locations/index.js +30 -0
  35. package/dist/react/core/location/Location.d.ts +113 -14
  36. package/dist/react/core/location/Location.js +189 -30
  37. package/dist/react/core/location-list/LocationList.d.ts +102 -0
  38. package/dist/react/core/location-list/LocationList.js +71 -0
  39. package/dist/react/index.d.ts +1 -0
  40. package/dist/react/index.js +1 -0
  41. package/dist/react/location/Location.d.ts +211 -41
  42. package/dist/react/location/Location.js +219 -46
  43. package/dist/react/location/LocationList.d.ts +98 -0
  44. package/dist/react/location/LocationList.js +120 -0
  45. package/dist/react/service/Service.d.ts +17 -24
  46. package/dist/react/service/Service.js +24 -36
  47. package/dist/services/index.d.ts +1 -0
  48. package/dist/services/index.js +1 -0
  49. package/dist/services/location-list/location-list.d.ts +100 -0
  50. package/dist/services/location-list/location-list.def.d.ts +62 -0
  51. package/dist/services/location-list/location-list.def.js +17 -0
  52. package/dist/services/location-list/location-list.js +212 -0
  53. 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.43",
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": "7fc1fdfa9ef983dbdae64fb719cdb4674afcf085f05ecbc425214a9e"
75
+ "falconPackageHash": "122a9bd0c5095741e936f6e76ab60fa20cb7c69c33763af1a38937c5"
76
76
  }