@wix/headless-bookings 0.0.10 → 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.
- package/cjs/dist/api/index.d.ts +10 -1
- package/cjs/dist/api/index.js +10 -1
- package/cjs/dist/api/query-services/index.d.ts +78 -0
- package/cjs/dist/api/query-services/index.js +137 -0
- package/cjs/dist/react/core/location/Location.d.ts +44 -0
- package/cjs/dist/react/core/location/Location.js +78 -0
- package/cjs/dist/react/core/service/Service.d.ts +160 -17
- package/cjs/dist/react/core/service/Service.js +211 -13
- package/cjs/dist/react/core/service-list/ServiceList.d.ts +75 -0
- package/cjs/dist/react/core/service-list/ServiceList.js +58 -0
- package/cjs/dist/react/index.d.ts +2 -0
- package/cjs/dist/react/index.js +2 -0
- package/cjs/dist/react/location/Location.d.ts +77 -0
- package/cjs/dist/react/location/Location.js +89 -0
- package/cjs/dist/react/service/Service.d.ts +1036 -31
- package/cjs/dist/react/service/Service.js +1060 -47
- package/cjs/dist/react/service-list/ServiceList.d.ts +185 -0
- package/cjs/dist/react/service-list/ServiceList.js +184 -0
- package/cjs/dist/services/index.d.ts +2 -1
- package/cjs/dist/services/index.js +2 -1
- package/cjs/dist/services/service/service.d.ts +71 -18
- package/cjs/dist/services/service/service.js +186 -50
- package/cjs/dist/services/service-list/service-list.d.ts +157 -0
- package/cjs/dist/services/service-list/service-list.js +274 -0
- package/cjs/dist/utils/dateAndTime.d.ts +2 -0
- package/cjs/dist/utils/dateAndTime.js +18 -0
- package/cjs/dist/utils/money.d.ts +21 -0
- package/cjs/dist/utils/money.js +34 -0
- package/dist/api/index.d.ts +10 -1
- package/dist/api/index.js +10 -1
- package/dist/api/query-services/index.d.ts +78 -0
- package/dist/api/query-services/index.js +137 -0
- package/dist/react/core/location/Location.d.ts +44 -0
- package/dist/react/core/location/Location.js +78 -0
- package/dist/react/core/service/Service.d.ts +160 -17
- package/dist/react/core/service/Service.js +211 -13
- package/dist/react/core/service-list/ServiceList.d.ts +75 -0
- package/dist/react/core/service-list/ServiceList.js +58 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +2 -0
- package/dist/react/location/Location.d.ts +77 -0
- package/dist/react/location/Location.js +89 -0
- package/dist/react/service/Service.d.ts +1036 -31
- package/dist/react/service/Service.js +1060 -47
- package/dist/react/service-list/ServiceList.d.ts +185 -0
- package/dist/react/service-list/ServiceList.js +184 -0
- package/dist/services/index.d.ts +2 -1
- package/dist/services/index.js +2 -1
- package/dist/services/service/service.d.ts +71 -18
- package/dist/services/service/service.js +186 -50
- package/dist/services/service-list/service-list.d.ts +157 -0
- package/dist/services/service-list/service-list.js +274 -0
- package/dist/utils/dateAndTime.d.ts +2 -0
- package/dist/utils/dateAndTime.js +18 -0
- package/dist/utils/money.d.ts +21 -0
- package/dist/utils/money.js +34 -0
- package/package.json +2 -2
- package/cjs/dist/api/query-service/index.d.ts +0 -23
- package/cjs/dist/api/query-service/index.js +0 -41
- package/dist/api/query-service/index.d.ts +0 -23
- package/dist/api/query-service/index.js +0 -41
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ServiceList Service - Reactive service list data management
|
|
3
|
+
* Handles querying and pagination of services list (NO selection management)
|
|
4
|
+
*/
|
|
5
|
+
import { defineService, implementService } from '@wix/services-definitions';
|
|
6
|
+
import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
|
|
7
|
+
import { queryServices } from '../../api/query-services/index.js';
|
|
8
|
+
/**
|
|
9
|
+
* Booking app ID constant
|
|
10
|
+
*/
|
|
11
|
+
const BOOKING_APP_ID = '13d21c63-b5ec-5912-8397-c3a5ddb27a97';
|
|
12
|
+
/**
|
|
13
|
+
* Default query limit
|
|
14
|
+
*/
|
|
15
|
+
const DEFAULT_QUERY_LIMIT = 100;
|
|
16
|
+
/**
|
|
17
|
+
* Service definition for the ServiceList service
|
|
18
|
+
*/
|
|
19
|
+
export const ServiceListServiceDefinition = defineService('service-list');
|
|
20
|
+
/**
|
|
21
|
+
* Implementation of the ServiceList service that manages reactive services list data.
|
|
22
|
+
* This service provides signals for services data, query options, pagination metadata
|
|
23
|
+
* (including hasNext flag), loading state, and error handling.
|
|
24
|
+
* It automatically re-fetches services when query options change.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```tsx
|
|
28
|
+
* import { ServiceListService, ServiceListServiceDefinition } from '@wix/bookings/services';
|
|
29
|
+
* import { useService } from '@wix/services-manager-react';
|
|
30
|
+
*
|
|
31
|
+
* function ServicesComponent({ serviceListConfig }) {
|
|
32
|
+
* return (
|
|
33
|
+
* <ServiceProvider services={createServicesMap([
|
|
34
|
+
* [ServiceListServiceDefinition, ServiceListService.withConfig(serviceListConfig)]
|
|
35
|
+
* ])}>
|
|
36
|
+
* <ServicesDisplay />
|
|
37
|
+
* </ServiceProvider>
|
|
38
|
+
* );
|
|
39
|
+
* }
|
|
40
|
+
*
|
|
41
|
+
* function ServicesDisplay() {
|
|
42
|
+
* const serviceListService = useService(ServiceListServiceDefinition);
|
|
43
|
+
* const services = serviceListService.servicesSignal.get();
|
|
44
|
+
* const isLoading = serviceListService.isLoadingSignal.get();
|
|
45
|
+
* const error = serviceListService.errorSignal.get();
|
|
46
|
+
* const pagingMetadata = serviceListService.pagingMetadataSignal.get();
|
|
47
|
+
* const hasMore = serviceListService.hasMoreServicesSignal.get();
|
|
48
|
+
*
|
|
49
|
+
* if (isLoading) return <div>Loading services...</div>;
|
|
50
|
+
* if (error) return <div>Error: {error}</div>;
|
|
51
|
+
*
|
|
52
|
+
* return (
|
|
53
|
+
* <div>
|
|
54
|
+
* {services.map(service => (
|
|
55
|
+
* <div key={service._id}>
|
|
56
|
+
* <h3>{service.name}</h3>
|
|
57
|
+
* <p>{service.description}</p>
|
|
58
|
+
* </div>
|
|
59
|
+
* ))}
|
|
60
|
+
* {hasMore && (
|
|
61
|
+
* <button onClick={() => serviceListService.actions.loadMore(10)}>
|
|
62
|
+
* Load More
|
|
63
|
+
* </button>
|
|
64
|
+
* )}
|
|
65
|
+
* {pagingMetadata.hasNext && (
|
|
66
|
+
* <span>More services available</span>
|
|
67
|
+
* )}
|
|
68
|
+
* </div>
|
|
69
|
+
* );
|
|
70
|
+
* }
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export const ServiceListService = implementService.withConfig()(ServiceListServiceDefinition, ({ getService, config }) => {
|
|
74
|
+
let firstRun = true;
|
|
75
|
+
const signalsService = getService(SignalsServiceDefinition);
|
|
76
|
+
// Default appId to BOOKING_APP_ID if not provided
|
|
77
|
+
const appId = config.options?.appId ?? BOOKING_APP_ID;
|
|
78
|
+
// Check if services are provided (showcase mode vs query mode)
|
|
79
|
+
const hasInitialServices = config.services && config.services.length > 0;
|
|
80
|
+
// Initialize services signal - use empty array if not provided
|
|
81
|
+
const initialServices = config.services || [];
|
|
82
|
+
const servicesSignal = signalsService.signal(initialServices);
|
|
83
|
+
// Initialize query options based on mode:
|
|
84
|
+
// - If services provided: reset to defaults (appId only) - showcase mode
|
|
85
|
+
// - If no services: use full queryOptions from config - query mode
|
|
86
|
+
const initialQueryOptions = hasInitialServices
|
|
87
|
+
? { appId } // Reset to defaults when services are provided
|
|
88
|
+
: {
|
|
89
|
+
appId,
|
|
90
|
+
filters: config.options?.filters,
|
|
91
|
+
sort: config.options?.sort,
|
|
92
|
+
};
|
|
93
|
+
// Initialize paging metadata separately (response data - doesn't trigger effect)
|
|
94
|
+
const initialPagingMetadata = config.options
|
|
95
|
+
?.pagingMetadata || {
|
|
96
|
+
limit: DEFAULT_QUERY_LIMIT,
|
|
97
|
+
offset: 0,
|
|
98
|
+
count: initialServices.length,
|
|
99
|
+
hasNext: false,
|
|
100
|
+
};
|
|
101
|
+
// Ensure count and hasNext are set
|
|
102
|
+
if (!initialPagingMetadata.count) {
|
|
103
|
+
initialPagingMetadata.count = initialServices.length;
|
|
104
|
+
}
|
|
105
|
+
if (initialPagingMetadata.hasNext === undefined) {
|
|
106
|
+
initialPagingMetadata.hasNext = false;
|
|
107
|
+
}
|
|
108
|
+
// Query options signal - effect subscribes to this, changes trigger re-fetch
|
|
109
|
+
const queryOptionsSignal = signalsService.signal(initialQueryOptions);
|
|
110
|
+
// Paging metadata signal - updated after fetches, does NOT trigger effect
|
|
111
|
+
const pagingMetadataSignal = signalsService.signal(initialPagingMetadata);
|
|
112
|
+
const isLoadingSignal = signalsService.signal(false);
|
|
113
|
+
const errorSignal = signalsService.signal(null);
|
|
114
|
+
// Auto-query on queryOptions changes (client-side only)
|
|
115
|
+
// IMPORTANT: Only subscribes to queryOptionsSignal, NOT pagingMetadataSignal
|
|
116
|
+
if (typeof window !== 'undefined') {
|
|
117
|
+
signalsService.effect(async () => {
|
|
118
|
+
// CRITICAL: Read queryOptionsSignal to establish dependency
|
|
119
|
+
// Do NOT read pagingMetadataSignal here to avoid infinite loop
|
|
120
|
+
const queryOptions = queryOptionsSignal.get();
|
|
121
|
+
if (firstRun) {
|
|
122
|
+
firstRun = false;
|
|
123
|
+
// If we have initial services (showcase mode), don't query on first run
|
|
124
|
+
if (hasInitialServices) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// Read paging metadata outside of dependency tracking for the fetch
|
|
129
|
+
const currentPaging = pagingMetadataSignal.get();
|
|
130
|
+
try {
|
|
131
|
+
isLoadingSignal.set(true);
|
|
132
|
+
errorSignal.set(null);
|
|
133
|
+
const result = await queryServices({
|
|
134
|
+
appId: queryOptions.appId,
|
|
135
|
+
filters: queryOptions.filters,
|
|
136
|
+
pagingMetadata: {
|
|
137
|
+
limit: currentPaging.limit,
|
|
138
|
+
offset: 0, // Reset to first page when query options change
|
|
139
|
+
},
|
|
140
|
+
sort: queryOptions.sort,
|
|
141
|
+
});
|
|
142
|
+
servicesSignal.set(result.services);
|
|
143
|
+
// Update ONLY pagingMetadataSignal (not queryOptionsSignal) to avoid re-triggering effect
|
|
144
|
+
pagingMetadataSignal.set(result.pagingMetadata);
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
errorSignal.set(error instanceof Error ? error.message : 'Unknown error');
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
isLoadingSignal.set(false);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
firstRun = false;
|
|
155
|
+
const loadMoreCursor = async (count) => {
|
|
156
|
+
const currentQueryOptions = queryOptionsSignal.get();
|
|
157
|
+
// Calculate next page offset based on current services count
|
|
158
|
+
const currentServicesCount = servicesSignal.get().length;
|
|
159
|
+
const nextOffset = currentServicesCount;
|
|
160
|
+
const nextPaging = {
|
|
161
|
+
limit: count || DEFAULT_QUERY_LIMIT,
|
|
162
|
+
offset: nextOffset,
|
|
163
|
+
hasNext: false, // Will be updated after query
|
|
164
|
+
};
|
|
165
|
+
try {
|
|
166
|
+
isLoadingSignal.set(true);
|
|
167
|
+
errorSignal.set(null);
|
|
168
|
+
const result = await queryServices({
|
|
169
|
+
appId: currentQueryOptions.appId,
|
|
170
|
+
filters: currentQueryOptions.filters,
|
|
171
|
+
pagingMetadata: nextPaging,
|
|
172
|
+
sort: currentQueryOptions.sort,
|
|
173
|
+
});
|
|
174
|
+
// Append new services to existing ones
|
|
175
|
+
servicesSignal.set([...servicesSignal.get(), ...result.services]);
|
|
176
|
+
// Update ONLY pagingMetadataSignal (not queryOptionsSignal)
|
|
177
|
+
pagingMetadataSignal.set(result.pagingMetadata);
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
errorSignal.set(error instanceof Error ? error.message : 'Unknown error');
|
|
181
|
+
}
|
|
182
|
+
finally {
|
|
183
|
+
isLoadingSignal.set(false);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
return {
|
|
187
|
+
servicesSignal,
|
|
188
|
+
queryOptionsSignal,
|
|
189
|
+
pagingMetadataSignal,
|
|
190
|
+
isLoadingSignal,
|
|
191
|
+
errorSignal,
|
|
192
|
+
actions: {
|
|
193
|
+
loadMore: async (count) => {
|
|
194
|
+
await loadMoreCursor(count);
|
|
195
|
+
},
|
|
196
|
+
setQueryOptions: (options) => {
|
|
197
|
+
// Reset services and paging when query options change
|
|
198
|
+
servicesSignal.set([]);
|
|
199
|
+
pagingMetadataSignal.set({
|
|
200
|
+
limit: pagingMetadataSignal.get().limit || DEFAULT_QUERY_LIMIT,
|
|
201
|
+
offset: 0,
|
|
202
|
+
count: 0,
|
|
203
|
+
hasNext: false,
|
|
204
|
+
});
|
|
205
|
+
queryOptionsSignal.set(options);
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
hasMoreServicesSignal: signalsService.computed(() => {
|
|
209
|
+
const paging = pagingMetadataSignal.get();
|
|
210
|
+
// Use hasNext flag from pagingMetadata to determine if more services are available
|
|
211
|
+
return paging.hasNext ?? false;
|
|
212
|
+
}),
|
|
213
|
+
};
|
|
214
|
+
});
|
|
215
|
+
/**
|
|
216
|
+
* Load service list configuration for Server-Side Rendering (SSR).
|
|
217
|
+
* This function is designed to be called during the build or server-side rendering phase
|
|
218
|
+
* to pre-fetch services data before the React components are hydrated on the client.
|
|
219
|
+
* The returned config includes paging metadata with hasNext flag indicating if more services are available.
|
|
220
|
+
*
|
|
221
|
+
* @param options - Query options following QueryServicesRequest type, or a URL string (to be implemented)
|
|
222
|
+
* @returns A promise that resolves to either a success result with the config or an error result
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* ```ts
|
|
226
|
+
* // In an Astro page or API route
|
|
227
|
+
* import { loadServiceListServiceInitialData } from '@wix/bookings/services';
|
|
228
|
+
*
|
|
229
|
+
* // Load with query options
|
|
230
|
+
* const serviceListResult = await loadServiceListServiceInitialData({
|
|
231
|
+
* appId: '13d21c63-b5ec-5912-8397-c3a5ddb27a97',
|
|
232
|
+
* pagingMetadata: { limit: 20, offset: 0 },
|
|
233
|
+
* });
|
|
234
|
+
*
|
|
235
|
+
* if (serviceListResult.type === 'error') {
|
|
236
|
+
* console.error('Failed to load services:', serviceListResult.error);
|
|
237
|
+
* return Astro.redirect('/500');
|
|
238
|
+
* }
|
|
239
|
+
*
|
|
240
|
+
* const serviceListConfig = serviceListResult.config;
|
|
241
|
+
*
|
|
242
|
+
* // Check if more services are available
|
|
243
|
+
* if (serviceListConfig.options?.pagingMetadata?.hasNext) {
|
|
244
|
+
* // More services can be loaded
|
|
245
|
+
* }
|
|
246
|
+
* ```
|
|
247
|
+
*/
|
|
248
|
+
export async function loadServiceListServiceInitialData(options) {
|
|
249
|
+
try {
|
|
250
|
+
const result = await queryServices({
|
|
251
|
+
appId: options.appId,
|
|
252
|
+
filters: options.filters,
|
|
253
|
+
pagingMetadata: options.pagingMetadata,
|
|
254
|
+
sort: options.sort,
|
|
255
|
+
});
|
|
256
|
+
return {
|
|
257
|
+
type: 'success',
|
|
258
|
+
config: {
|
|
259
|
+
services: result.services,
|
|
260
|
+
options: {
|
|
261
|
+
...options,
|
|
262
|
+
pagingMetadata: result.pagingMetadata,
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
console.error('Failed to load service list config:', error);
|
|
269
|
+
return {
|
|
270
|
+
type: 'error',
|
|
271
|
+
error: error instanceof Error ? error : new Error('Unknown error'),
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const formatDate = (date) => {
|
|
2
|
+
return date.toLocaleDateString(undefined, {
|
|
3
|
+
year: 'numeric',
|
|
4
|
+
month: 'short',
|
|
5
|
+
day: 'numeric',
|
|
6
|
+
});
|
|
7
|
+
};
|
|
8
|
+
export const formatDuration = (minutes) => {
|
|
9
|
+
if (minutes < 60) {
|
|
10
|
+
return `${minutes} min`;
|
|
11
|
+
}
|
|
12
|
+
const hours = Math.floor(minutes / 60);
|
|
13
|
+
const mins = minutes % 60;
|
|
14
|
+
if (mins === 0) {
|
|
15
|
+
return `${hours} hour${hours > 1 ? 's' : ''}`;
|
|
16
|
+
}
|
|
17
|
+
return `${hours}h ${mins}m`;
|
|
18
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Money utility functions for converting between SDK Money types and MoneyData
|
|
3
|
+
*/
|
|
4
|
+
import type { MoneyData } from '@wix/headless-components/react';
|
|
5
|
+
/**
|
|
6
|
+
* Converts SDK Money format to MoneyData format
|
|
7
|
+
*
|
|
8
|
+
* @param sdkMoney - The SDK money object with value, currency, and optional formattedValue
|
|
9
|
+
* @returns MoneyData object with amount and currency, or null if conversion fails
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* const money = convertToMoneyData({ value: "25.50", currency: "USD" });
|
|
14
|
+
* // Returns: { amount: 25.50, currency: "USD" }
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare function convertToMoneyData(sdkMoney: {
|
|
18
|
+
value?: string;
|
|
19
|
+
currency?: string;
|
|
20
|
+
formattedValue?: string | null;
|
|
21
|
+
} | undefined): MoneyData | null;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Money utility functions for converting between SDK Money types and MoneyData
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Converts SDK Money format to MoneyData format
|
|
6
|
+
*
|
|
7
|
+
* @param sdkMoney - The SDK money object with value, currency, and optional formattedValue
|
|
8
|
+
* @returns MoneyData object with amount and currency, or null if conversion fails
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const money = convertToMoneyData({ value: "25.50", currency: "USD" });
|
|
13
|
+
* // Returns: { amount: 25.50, currency: "USD" }
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export function convertToMoneyData(sdkMoney) {
|
|
17
|
+
if (!sdkMoney)
|
|
18
|
+
return null;
|
|
19
|
+
const priceValue = sdkMoney.value;
|
|
20
|
+
const currency = sdkMoney.currency || 'USD';
|
|
21
|
+
// Convert price value to number
|
|
22
|
+
let amount = undefined;
|
|
23
|
+
if (typeof priceValue === 'string') {
|
|
24
|
+
const parsed = parseFloat(priceValue);
|
|
25
|
+
amount = !isNaN(parsed) ? parsed : undefined;
|
|
26
|
+
}
|
|
27
|
+
else if (typeof priceValue === 'number') {
|
|
28
|
+
amount = priceValue;
|
|
29
|
+
}
|
|
30
|
+
if (amount !== undefined && !isNaN(amount) && amount >= 0) {
|
|
31
|
+
return { amount, currency };
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/headless-bookings",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -68,5 +68,5 @@
|
|
|
68
68
|
"groupId": "com.wixpress.headless-components"
|
|
69
69
|
}
|
|
70
70
|
},
|
|
71
|
-
"falconPackageHash": "
|
|
71
|
+
"falconPackageHash": "2996fdf77f39e0cde0bf4bb18bd8bd0dd2630b3aa839f47d67059ca2"
|
|
72
72
|
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Query Service API
|
|
3
|
-
* Fetches a single service by ID or slug from Wix Bookings
|
|
4
|
-
*/
|
|
5
|
-
import { services } from '@wix/bookings';
|
|
6
|
-
/**
|
|
7
|
-
* Fetches a service by its ID
|
|
8
|
-
* @param id - The service ID
|
|
9
|
-
* @returns Object containing the service or null if not found
|
|
10
|
-
*/
|
|
11
|
-
export declare const getServiceById: (id: string) => Promise<{
|
|
12
|
-
service: services.Service;
|
|
13
|
-
} | {
|
|
14
|
-
service: null;
|
|
15
|
-
}>;
|
|
16
|
-
/**
|
|
17
|
-
* Fetches a service by its slug
|
|
18
|
-
* @param slug - The service slug
|
|
19
|
-
* @returns Object containing the service or null if not found
|
|
20
|
-
*/
|
|
21
|
-
export declare const getServiceBySlug: (slug: string) => Promise<{
|
|
22
|
-
service: services.Service | null;
|
|
23
|
-
}>;
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Query Service API
|
|
3
|
-
* Fetches a single service by ID or slug from Wix Bookings
|
|
4
|
-
*/
|
|
5
|
-
import { services } from '@wix/bookings';
|
|
6
|
-
/**
|
|
7
|
-
* Fetches a service by its ID
|
|
8
|
-
* @param id - The service ID
|
|
9
|
-
* @returns Object containing the service or null if not found
|
|
10
|
-
*/
|
|
11
|
-
export const getServiceById = async (id) => {
|
|
12
|
-
try {
|
|
13
|
-
const service = await services.getService(id);
|
|
14
|
-
return { service };
|
|
15
|
-
}
|
|
16
|
-
catch (error) {
|
|
17
|
-
console.error(`Failed to load service for id "${id}":`, error);
|
|
18
|
-
return { service: null };
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* Fetches a service by its slug
|
|
23
|
-
* @param slug - The service slug
|
|
24
|
-
* @returns Object containing the service or null if not found
|
|
25
|
-
*/
|
|
26
|
-
export const getServiceBySlug = async (slug) => {
|
|
27
|
-
try {
|
|
28
|
-
// Query services where mainSlug.name equals the provided slug
|
|
29
|
-
const result = await services
|
|
30
|
-
.queryServices()
|
|
31
|
-
.eq('mainSlug.name', slug)
|
|
32
|
-
.limit(1)
|
|
33
|
-
.find();
|
|
34
|
-
const service = result.items?.[0] || null;
|
|
35
|
-
return { service };
|
|
36
|
-
}
|
|
37
|
-
catch (error) {
|
|
38
|
-
console.error(`Failed to load service for slug "${slug}":`, error);
|
|
39
|
-
return { service: null };
|
|
40
|
-
}
|
|
41
|
-
};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Query Service API
|
|
3
|
-
* Fetches a single service by ID or slug from Wix Bookings
|
|
4
|
-
*/
|
|
5
|
-
import { services } from '@wix/bookings';
|
|
6
|
-
/**
|
|
7
|
-
* Fetches a service by its ID
|
|
8
|
-
* @param id - The service ID
|
|
9
|
-
* @returns Object containing the service or null if not found
|
|
10
|
-
*/
|
|
11
|
-
export declare const getServiceById: (id: string) => Promise<{
|
|
12
|
-
service: services.Service;
|
|
13
|
-
} | {
|
|
14
|
-
service: null;
|
|
15
|
-
}>;
|
|
16
|
-
/**
|
|
17
|
-
* Fetches a service by its slug
|
|
18
|
-
* @param slug - The service slug
|
|
19
|
-
* @returns Object containing the service or null if not found
|
|
20
|
-
*/
|
|
21
|
-
export declare const getServiceBySlug: (slug: string) => Promise<{
|
|
22
|
-
service: services.Service | null;
|
|
23
|
-
}>;
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Query Service API
|
|
3
|
-
* Fetches a single service by ID or slug from Wix Bookings
|
|
4
|
-
*/
|
|
5
|
-
import { services } from '@wix/bookings';
|
|
6
|
-
/**
|
|
7
|
-
* Fetches a service by its ID
|
|
8
|
-
* @param id - The service ID
|
|
9
|
-
* @returns Object containing the service or null if not found
|
|
10
|
-
*/
|
|
11
|
-
export const getServiceById = async (id) => {
|
|
12
|
-
try {
|
|
13
|
-
const service = await services.getService(id);
|
|
14
|
-
return { service };
|
|
15
|
-
}
|
|
16
|
-
catch (error) {
|
|
17
|
-
console.error(`Failed to load service for id "${id}":`, error);
|
|
18
|
-
return { service: null };
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* Fetches a service by its slug
|
|
23
|
-
* @param slug - The service slug
|
|
24
|
-
* @returns Object containing the service or null if not found
|
|
25
|
-
*/
|
|
26
|
-
export const getServiceBySlug = async (slug) => {
|
|
27
|
-
try {
|
|
28
|
-
// Query services where mainSlug.name equals the provided slug
|
|
29
|
-
const result = await services
|
|
30
|
-
.queryServices()
|
|
31
|
-
.eq('mainSlug.name', slug)
|
|
32
|
-
.limit(1)
|
|
33
|
-
.find();
|
|
34
|
-
const service = result.items?.[0] || null;
|
|
35
|
-
return { service };
|
|
36
|
-
}
|
|
37
|
-
catch (error) {
|
|
38
|
-
console.error(`Failed to load service for slug "${slug}":`, error);
|
|
39
|
-
return { service: null };
|
|
40
|
-
}
|
|
41
|
-
};
|