@wix/headless-bookings 0.0.12 → 0.0.14
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 +1 -0
- package/cjs/dist/api/index.js +1 -0
- package/cjs/dist/api/query-services/index.d.ts +6 -7
- package/cjs/dist/api/query-services/index.js +4 -4
- package/cjs/dist/api/time-slot-list/index.d.ts +53 -0
- package/cjs/dist/api/time-slot-list/index.js +133 -0
- package/cjs/dist/react/core/booking/Booking.d.ts +2 -2
- package/cjs/dist/react/core/location/Location.d.ts +3 -3
- package/cjs/dist/react/core/location/Location.js +2 -2
- package/cjs/dist/react/core/service/Service.d.ts +8 -8
- package/cjs/dist/react/core/service-list/ServiceList.d.ts +2 -2
- package/cjs/dist/react/core/time-slot-list/TimeSlot.d.ts +368 -0
- package/cjs/dist/react/core/time-slot-list/TimeSlot.js +357 -0
- package/cjs/dist/react/core/time-slot-list/TimeSlotList.d.ts +84 -0
- package/cjs/dist/react/core/time-slot-list/TimeSlotList.js +68 -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 +3 -3
- package/cjs/dist/react/service/Service.d.ts +9 -9
- package/cjs/dist/react/service/Service.js +5 -5
- package/cjs/dist/react/service-list/ServiceList.d.ts +3 -3
- package/cjs/dist/react/time-slot-list/TimeSlot.d.ts +438 -0
- package/cjs/dist/react/time-slot-list/TimeSlot.js +427 -0
- package/cjs/dist/react/time-slot-list/TimeSlotList.d.ts +209 -0
- package/cjs/dist/react/time-slot-list/TimeSlotList.js +199 -0
- package/cjs/dist/services/booking/booking.d.ts +12 -11
- package/cjs/dist/services/booking/booking.js +5 -3
- package/cjs/dist/services/index.d.ts +1 -0
- package/cjs/dist/services/index.js +1 -0
- package/cjs/dist/services/service/service.d.ts +5 -5
- package/cjs/dist/services/service/service.js +8 -8
- package/cjs/dist/services/service-list/service-list.d.ts +3 -3
- package/cjs/dist/services/time-slot-list/index.d.ts +6 -0
- package/cjs/dist/services/time-slot-list/index.js +6 -0
- package/cjs/dist/services/time-slot-list/time-slot-list.d.ts +58 -0
- package/cjs/dist/services/time-slot-list/time-slot-list.def.d.ts +84 -0
- package/cjs/dist/services/time-slot-list/time-slot-list.def.js +17 -0
- package/cjs/dist/services/time-slot-list/time-slot-list.js +349 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +1 -0
- package/dist/api/query-services/index.d.ts +6 -7
- package/dist/api/query-services/index.js +4 -4
- package/dist/api/time-slot-list/index.d.ts +53 -0
- package/dist/api/time-slot-list/index.js +133 -0
- package/dist/react/core/booking/Booking.d.ts +2 -2
- package/dist/react/core/location/Location.d.ts +3 -3
- package/dist/react/core/location/Location.js +2 -2
- package/dist/react/core/service/Service.d.ts +8 -8
- package/dist/react/core/service-list/ServiceList.d.ts +2 -2
- package/dist/react/core/time-slot-list/TimeSlot.d.ts +368 -0
- package/dist/react/core/time-slot-list/TimeSlot.js +357 -0
- package/dist/react/core/time-slot-list/TimeSlotList.d.ts +84 -0
- package/dist/react/core/time-slot-list/TimeSlotList.js +68 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +1 -0
- package/dist/react/location/Location.d.ts +3 -3
- package/dist/react/service/Service.d.ts +9 -9
- package/dist/react/service/Service.js +5 -5
- package/dist/react/service-list/ServiceList.d.ts +3 -3
- package/dist/react/time-slot-list/TimeSlot.d.ts +438 -0
- package/dist/react/time-slot-list/TimeSlot.js +427 -0
- package/dist/react/time-slot-list/TimeSlotList.d.ts +209 -0
- package/dist/react/time-slot-list/TimeSlotList.js +199 -0
- package/dist/services/booking/booking.d.ts +12 -11
- package/dist/services/booking/booking.js +5 -3
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/services/service/service.d.ts +5 -5
- package/dist/services/service/service.js +8 -8
- package/dist/services/service-list/service-list.d.ts +3 -3
- package/dist/services/time-slot-list/index.d.ts +6 -0
- package/dist/services/time-slot-list/index.js +6 -0
- package/dist/services/time-slot-list/time-slot-list.d.ts +58 -0
- package/dist/services/time-slot-list/time-slot-list.def.d.ts +84 -0
- package/dist/services/time-slot-list/time-slot-list.def.js +17 -0
- package/dist/services/time-slot-list/time-slot-list.js +349 -0
- package/package.json +2 -2
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Core TimeSlot Components
|
|
4
|
+
* Provides low-level access to TimeSlot data via render props
|
|
5
|
+
*
|
|
6
|
+
* Note: These components must be used within TimeSlotList.TimeSlotRepeater
|
|
7
|
+
* which provides the TimeSlotProvider context.
|
|
8
|
+
*/
|
|
9
|
+
import React from 'react';
|
|
10
|
+
import { useTimeSlotListService } from './TimeSlotList.js';
|
|
11
|
+
const TimeSlotContext = React.createContext(null);
|
|
12
|
+
/**
|
|
13
|
+
* Hook to access TimeSlot context
|
|
14
|
+
* @throws Error if used outside of TimeSlotProvider
|
|
15
|
+
*/
|
|
16
|
+
export function useTimeSlotContext() {
|
|
17
|
+
const context = React.useContext(TimeSlotContext);
|
|
18
|
+
if (!context) {
|
|
19
|
+
throw new Error('TimeSlot components must be used within TimeSlotList.TimeSlotRepeater');
|
|
20
|
+
}
|
|
21
|
+
return context;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Provider component used by TimeSlotRepeater to provide context.
|
|
25
|
+
* Not used directly by consumers - only by TimeSlotList.TimeSlotRepeater.
|
|
26
|
+
*/
|
|
27
|
+
export function TimeSlotProvider(props) {
|
|
28
|
+
const { children, slot } = props;
|
|
29
|
+
const service = useTimeSlotListService();
|
|
30
|
+
const selection = service.selection.get();
|
|
31
|
+
const isSelected = selection?.slot?.id === slot.id;
|
|
32
|
+
const selectSlot = () => {
|
|
33
|
+
service.actions.selectSlot(slot);
|
|
34
|
+
};
|
|
35
|
+
const contextValue = {
|
|
36
|
+
slot,
|
|
37
|
+
isSelected,
|
|
38
|
+
selectSlot,
|
|
39
|
+
};
|
|
40
|
+
return (_jsx(TimeSlotContext.Provider, { value: contextValue, children: children }));
|
|
41
|
+
}
|
|
42
|
+
const LocationContext = React.createContext(null);
|
|
43
|
+
/**
|
|
44
|
+
* Hook to access Location context
|
|
45
|
+
* @throws Error if used outside of LocationProvider
|
|
46
|
+
*/
|
|
47
|
+
export function useLocationContext() {
|
|
48
|
+
const context = React.useContext(LocationContext);
|
|
49
|
+
if (!context) {
|
|
50
|
+
throw new Error('Location components must be used within LocationProvider');
|
|
51
|
+
}
|
|
52
|
+
return context;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Provider component used by LocationRepeater to provide context.
|
|
56
|
+
* Not used directly by consumers - only by TimeSlot.LocationRepeater.
|
|
57
|
+
*/
|
|
58
|
+
export function LocationProvider(props) {
|
|
59
|
+
const { children, location } = props;
|
|
60
|
+
const service = useTimeSlotListService();
|
|
61
|
+
const selectLocation = () => {
|
|
62
|
+
service.actions.selectLocation(location.id);
|
|
63
|
+
};
|
|
64
|
+
const contextValue = {
|
|
65
|
+
location,
|
|
66
|
+
selectLocation,
|
|
67
|
+
};
|
|
68
|
+
return (_jsx(LocationContext.Provider, { value: contextValue, children: children }));
|
|
69
|
+
}
|
|
70
|
+
const StaffMemberContext = React.createContext(null);
|
|
71
|
+
/**
|
|
72
|
+
* Hook to access StaffMember context
|
|
73
|
+
* @throws Error if used outside of StaffMemberProvider
|
|
74
|
+
*/
|
|
75
|
+
export function useStaffMemberContext() {
|
|
76
|
+
const context = React.useContext(StaffMemberContext);
|
|
77
|
+
if (!context) {
|
|
78
|
+
throw new Error('StaffMember components must be used within StaffMemberProvider');
|
|
79
|
+
}
|
|
80
|
+
return context;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Provider component used by StaffMemberRepeater to provide context.
|
|
84
|
+
* Not used directly by consumers - only by TimeSlot.StaffMemberRepeater.
|
|
85
|
+
*/
|
|
86
|
+
export function StaffMemberProvider(props) {
|
|
87
|
+
const { children, staffMember } = props;
|
|
88
|
+
const service = useTimeSlotListService();
|
|
89
|
+
const selectStaffMember = () => {
|
|
90
|
+
service.actions.selectStaffMember(staffMember.id);
|
|
91
|
+
};
|
|
92
|
+
const contextValue = {
|
|
93
|
+
staffMember,
|
|
94
|
+
selectStaffMember,
|
|
95
|
+
};
|
|
96
|
+
return (_jsx(StaffMemberContext.Provider, { value: contextValue, children: children }));
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Core component that provides access to time slot info via render props.
|
|
100
|
+
* Includes start/end dates, duration, bookable status, and selection state.
|
|
101
|
+
*
|
|
102
|
+
* @component
|
|
103
|
+
* @example
|
|
104
|
+
* ```tsx
|
|
105
|
+
* <TimeSlot.Info>
|
|
106
|
+
* {({ startDate, endDate, durationInMinutes, bookable, isSelected }) => (
|
|
107
|
+
* <div>
|
|
108
|
+
* <span>{startDate}</span>
|
|
109
|
+
* <span>{durationInMinutes} min</span>
|
|
110
|
+
* </div>
|
|
111
|
+
* )}
|
|
112
|
+
* </TimeSlot.Info>
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
export function Info(props) {
|
|
116
|
+
const { slot, isSelected } = useTimeSlotContext();
|
|
117
|
+
const startDate = slot.localStartDate ?? undefined;
|
|
118
|
+
const endDate = slot.localEndDate ?? undefined;
|
|
119
|
+
const bookable = slot.bookable ?? false;
|
|
120
|
+
// Calculate duration from start and end dates
|
|
121
|
+
let durationInMinutes = null;
|
|
122
|
+
if (startDate && endDate) {
|
|
123
|
+
const startTime = new Date(startDate).getTime();
|
|
124
|
+
const endTime = new Date(endDate).getTime();
|
|
125
|
+
durationInMinutes = Math.round((endTime - startTime) / (1000 * 60));
|
|
126
|
+
}
|
|
127
|
+
return props.children({
|
|
128
|
+
startDate,
|
|
129
|
+
endDate,
|
|
130
|
+
durationInMinutes,
|
|
131
|
+
bookable,
|
|
132
|
+
isSelected,
|
|
133
|
+
slot,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Core component that provides slot actions via render props.
|
|
138
|
+
*
|
|
139
|
+
* @component
|
|
140
|
+
* @example
|
|
141
|
+
* ```tsx
|
|
142
|
+
* <TimeSlot.Actions>
|
|
143
|
+
* {({ selectSlot, isSelected, bookable, clearPreferences, shouldShowClearPreferences }) => (
|
|
144
|
+
* <div>
|
|
145
|
+
* <button onClick={selectSlot} disabled={!bookable}>
|
|
146
|
+
* {isSelected ? 'Selected' : 'Select'}
|
|
147
|
+
* </button>
|
|
148
|
+
* {shouldShowClearPreferences && (
|
|
149
|
+
* <button onClick={clearPreferences}>Change</button>
|
|
150
|
+
* )}
|
|
151
|
+
* </div>
|
|
152
|
+
* )}
|
|
153
|
+
* </TimeSlot.Actions>
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
export function Actions(props) {
|
|
157
|
+
const { selectSlot, slot, isSelected } = useTimeSlotContext();
|
|
158
|
+
const service = useTimeSlotListService();
|
|
159
|
+
const selection = service.selection.get();
|
|
160
|
+
const bookable = slot.bookable ?? false;
|
|
161
|
+
// Check if at least one preference is selected
|
|
162
|
+
const hasPreferenceSelected = !!selection?.locationId || !!selection?.staffMemberId;
|
|
163
|
+
// Check if there are multiple options
|
|
164
|
+
const locationCount = slot.staffByLocation.length;
|
|
165
|
+
const staffCount = new Set(slot.staffByLocation.flatMap(({ staffMembers }) => staffMembers.map((s) => s.id))).size;
|
|
166
|
+
const hasMultipleOptions = locationCount > 1 || staffCount > 1;
|
|
167
|
+
const shouldShowClearPreferences = hasPreferenceSelected && hasMultipleOptions;
|
|
168
|
+
const clearPreferences = shouldShowClearPreferences
|
|
169
|
+
? service.actions.clearPreferences
|
|
170
|
+
: undefined;
|
|
171
|
+
return props.children({
|
|
172
|
+
selectSlot,
|
|
173
|
+
clearPreferences,
|
|
174
|
+
slot,
|
|
175
|
+
bookable,
|
|
176
|
+
isSelected,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Core component that provides access to time slot locations via render props.
|
|
181
|
+
* Extracts locations from slot.staffByLocation and enriches with name from originalSlots.
|
|
182
|
+
* Each location includes isSelected and isSelectable based on current selection state.
|
|
183
|
+
*
|
|
184
|
+
* @component
|
|
185
|
+
* @example
|
|
186
|
+
* ```tsx
|
|
187
|
+
* <CoreTimeSlot.Locations>
|
|
188
|
+
* {({ locations, locationsCount, selectLocation }) => (
|
|
189
|
+
* <GenericList.Root items={locations}>
|
|
190
|
+
* {children}
|
|
191
|
+
* </GenericList.Root>
|
|
192
|
+
* )}
|
|
193
|
+
* </CoreTimeSlot.Locations>
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
export function Locations(props) {
|
|
197
|
+
const { slot } = useTimeSlotContext();
|
|
198
|
+
const service = useTimeSlotListService();
|
|
199
|
+
const selection = service.selection.get();
|
|
200
|
+
const selectedLocationId = selection?.locationId ?? null;
|
|
201
|
+
const selectedStaffMemberId = selection?.staffMemberId ?? null;
|
|
202
|
+
// Build locations array from staffByLocation (names already included)
|
|
203
|
+
const locations = slot.staffByLocation.map(({ location, staffMembers }) => {
|
|
204
|
+
// Check if this location is selectable based on selected staff
|
|
205
|
+
// If no staff selected, all locations are selectable
|
|
206
|
+
// If staff selected, only locations where that staff works are selectable
|
|
207
|
+
const isSelectable = selectedStaffMemberId
|
|
208
|
+
? staffMembers.some((s) => s.id === selectedStaffMemberId)
|
|
209
|
+
: true;
|
|
210
|
+
return {
|
|
211
|
+
id: location.id,
|
|
212
|
+
name: location.name,
|
|
213
|
+
isSelected: selectedLocationId === location.id,
|
|
214
|
+
isSelectable,
|
|
215
|
+
};
|
|
216
|
+
});
|
|
217
|
+
return props.children({
|
|
218
|
+
locations,
|
|
219
|
+
selectLocation: service.actions.selectLocation,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Core component that provides access to location info via render props.
|
|
224
|
+
* Must be used within LocationProvider.
|
|
225
|
+
*
|
|
226
|
+
* @component
|
|
227
|
+
* @example
|
|
228
|
+
* ```tsx
|
|
229
|
+
* <LocationInfo>
|
|
230
|
+
* {({ name, isSelected, isSelectable }) => (
|
|
231
|
+
* <span>{name}</span>
|
|
232
|
+
* )}
|
|
233
|
+
* </LocationInfo>
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
export function LocationInfo(props) {
|
|
237
|
+
const { location } = useLocationContext();
|
|
238
|
+
return props.children({
|
|
239
|
+
name: location.name,
|
|
240
|
+
isSelected: location.isSelected,
|
|
241
|
+
isSelectable: location.isSelectable,
|
|
242
|
+
location,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Core component that provides location actions via render props.
|
|
247
|
+
* Must be used within LocationProvider.
|
|
248
|
+
*
|
|
249
|
+
* @component
|
|
250
|
+
* @example
|
|
251
|
+
* ```tsx
|
|
252
|
+
* <LocationActions>
|
|
253
|
+
* {({ selectLocation, isSelected, isSelectable }) => (
|
|
254
|
+
* <button onClick={selectLocation} disabled={!isSelectable}>
|
|
255
|
+
* {isSelected ? 'Selected' : 'Select'}
|
|
256
|
+
* </button>
|
|
257
|
+
* )}
|
|
258
|
+
* </LocationActions>
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
export function LocationActions(props) {
|
|
262
|
+
const { location, selectLocation } = useLocationContext();
|
|
263
|
+
return props.children({
|
|
264
|
+
selectLocation,
|
|
265
|
+
isSelected: location.isSelected,
|
|
266
|
+
isSelectable: location.isSelectable,
|
|
267
|
+
location,
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Core component that provides access to time slot staff members via render props.
|
|
272
|
+
* Extracts unique staff members from slot.staffByLocation (names already included).
|
|
273
|
+
* Each staff member includes isSelected and isSelectable based on current selection state.
|
|
274
|
+
*
|
|
275
|
+
* @component
|
|
276
|
+
* @example
|
|
277
|
+
* ```tsx
|
|
278
|
+
* <CoreTimeSlot.StaffMembers>
|
|
279
|
+
* {({ staffMembers, selectStaffMember }) => (
|
|
280
|
+
* <GenericList.Root items={staffMembers}>
|
|
281
|
+
* {children}
|
|
282
|
+
* </GenericList.Root>
|
|
283
|
+
* )}
|
|
284
|
+
* </CoreTimeSlot.StaffMembers>
|
|
285
|
+
* ```
|
|
286
|
+
*/
|
|
287
|
+
export function StaffMembers(props) {
|
|
288
|
+
const { slot } = useTimeSlotContext();
|
|
289
|
+
const service = useTimeSlotListService();
|
|
290
|
+
const selection = service.selection.get();
|
|
291
|
+
const selectedStaffMemberId = selection?.staffMemberId ?? null;
|
|
292
|
+
const selectedLocationId = selection?.locationId ?? null;
|
|
293
|
+
// Build unique staff members array from staffByLocation
|
|
294
|
+
// Flatten all staff members with their location IDs, then dedupe by ID
|
|
295
|
+
const allStaff = slot.staffByLocation.flatMap(({ location, staffMembers }) => staffMembers.map((s) => ({ ...s, locationId: location.id })));
|
|
296
|
+
// Group by staff ID to get all locations per staff member
|
|
297
|
+
const grouped = Object.groupBy(allStaff, (s) => s.id);
|
|
298
|
+
const staffMembers = Object.entries(grouped).map(([id, entries]) => ({
|
|
299
|
+
id,
|
|
300
|
+
name: entries[0].name,
|
|
301
|
+
isSelected: selectedStaffMemberId === id,
|
|
302
|
+
isSelectable: !selectedLocationId ||
|
|
303
|
+
entries.some((e) => e.locationId === selectedLocationId),
|
|
304
|
+
}));
|
|
305
|
+
return props.children({
|
|
306
|
+
staffMembers,
|
|
307
|
+
selectStaffMember: service.actions.selectStaffMember,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Core component that provides access to staff member info via render props.
|
|
312
|
+
* Must be used within StaffMemberProvider.
|
|
313
|
+
*
|
|
314
|
+
* @component
|
|
315
|
+
* @example
|
|
316
|
+
* ```tsx
|
|
317
|
+
* <StaffMemberInfo>
|
|
318
|
+
* {({ name, isSelected, isSelectable }) => (
|
|
319
|
+
* <span>{name}</span>
|
|
320
|
+
* )}
|
|
321
|
+
* </StaffMemberInfo>
|
|
322
|
+
* ```
|
|
323
|
+
*/
|
|
324
|
+
export function StaffMemberInfo(props) {
|
|
325
|
+
const { staffMember } = useStaffMemberContext();
|
|
326
|
+
return props.children({
|
|
327
|
+
name: staffMember.name,
|
|
328
|
+
isSelected: staffMember.isSelected,
|
|
329
|
+
isSelectable: staffMember.isSelectable,
|
|
330
|
+
staffMember,
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Core component that provides staff member actions via render props.
|
|
335
|
+
* Must be used within StaffMemberProvider.
|
|
336
|
+
*
|
|
337
|
+
* @component
|
|
338
|
+
* @example
|
|
339
|
+
* ```tsx
|
|
340
|
+
* <StaffMemberActions>
|
|
341
|
+
* {({ selectStaffMember, isSelected, isSelectable }) => (
|
|
342
|
+
* <button onClick={selectStaffMember} disabled={!isSelectable}>
|
|
343
|
+
* {isSelected ? 'Selected' : 'Select'}
|
|
344
|
+
* </button>
|
|
345
|
+
* )}
|
|
346
|
+
* </StaffMemberActions>
|
|
347
|
+
* ```
|
|
348
|
+
*/
|
|
349
|
+
export function StaffMemberActions(props) {
|
|
350
|
+
const { staffMember, selectStaffMember } = useStaffMemberContext();
|
|
351
|
+
return props.children({
|
|
352
|
+
selectStaffMember,
|
|
353
|
+
isSelected: staffMember.isSelected,
|
|
354
|
+
isSelectable: staffMember.isSelectable,
|
|
355
|
+
staffMember,
|
|
356
|
+
});
|
|
357
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core TimeSlotList Components
|
|
3
|
+
* Provides low-level access to TimeSlotListService via render props
|
|
4
|
+
*/
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { type TimeSlotListServiceAPI, type TimeSlotListServiceConfig, type TimeSlot } from '../../../services/time-slot-list/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* Hook to access TimeSlotListService from within TimeSlotList.Root
|
|
9
|
+
*/
|
|
10
|
+
export declare const useTimeSlotListService: () => TimeSlotListServiceAPI;
|
|
11
|
+
/**
|
|
12
|
+
* Props for Root component
|
|
13
|
+
*/
|
|
14
|
+
export interface RootProps {
|
|
15
|
+
children: React.ReactNode;
|
|
16
|
+
config?: TimeSlotListServiceConfig;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Root component that provides TimeSlotListService context to its children.
|
|
20
|
+
*
|
|
21
|
+
* @component
|
|
22
|
+
* @example
|
|
23
|
+
* ```tsx
|
|
24
|
+
* <Root config={{ services, timeSlots, timezone }}>
|
|
25
|
+
* {children}
|
|
26
|
+
* </Root>
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function Root(props: RootProps): React.ReactNode;
|
|
30
|
+
/**
|
|
31
|
+
* Props for Timezone render prop component
|
|
32
|
+
*/
|
|
33
|
+
export interface TimezoneProps {
|
|
34
|
+
children: (data: {
|
|
35
|
+
timezone: string | undefined;
|
|
36
|
+
}) => React.ReactNode;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Core component that provides access to the current timezone via render props.
|
|
40
|
+
*
|
|
41
|
+
* @component
|
|
42
|
+
* @example
|
|
43
|
+
* ```tsx
|
|
44
|
+
* <Timezone>
|
|
45
|
+
* {({ timezone }) => (
|
|
46
|
+
* <span>{timezone}</span>
|
|
47
|
+
* )}
|
|
48
|
+
* </Timezone>
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare function Timezone(props: TimezoneProps): React.ReactNode;
|
|
52
|
+
/**
|
|
53
|
+
* Render props for ListData component
|
|
54
|
+
*/
|
|
55
|
+
export interface ListDataRenderProps {
|
|
56
|
+
timeSlots: TimeSlot[];
|
|
57
|
+
hasMore: boolean;
|
|
58
|
+
isLoading: boolean;
|
|
59
|
+
error: string | null;
|
|
60
|
+
loadMore: () => Promise<void>;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Props for ListData render prop component
|
|
64
|
+
*/
|
|
65
|
+
export interface ListDataProps {
|
|
66
|
+
children: (data: ListDataRenderProps) => React.ReactNode;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Core component that provides access to time slots list data via render props.
|
|
70
|
+
* Use this to build list containers with GenericList.
|
|
71
|
+
*
|
|
72
|
+
* @component
|
|
73
|
+
* @example
|
|
74
|
+
* ```tsx
|
|
75
|
+
* <ListData>
|
|
76
|
+
* {({ timeSlots, hasMore, isLoading, loadMore }) => (
|
|
77
|
+
* <GenericList.Root items={timeSlots} hasMore={hasMore} isLoading={isLoading} loadMore={loadMore}>
|
|
78
|
+
* {children}
|
|
79
|
+
* </GenericList.Root>
|
|
80
|
+
* )}
|
|
81
|
+
* </ListData>
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export declare function ListData(props: ListDataProps): React.ReactNode;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useService, WixServices } from '@wix/services-manager-react';
|
|
3
|
+
import { createServicesMap } from '@wix/services-manager';
|
|
4
|
+
import { TimeSlotListServiceDefinition, TimeSlotListService, } from '../../../services/time-slot-list/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Hook to access TimeSlotListService from within TimeSlotList.Root
|
|
7
|
+
*/
|
|
8
|
+
export const useTimeSlotListService = () => {
|
|
9
|
+
return useService(TimeSlotListServiceDefinition);
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Root component that provides TimeSlotListService context to its children.
|
|
13
|
+
*
|
|
14
|
+
* @component
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* <Root config={{ services, timeSlots, timezone }}>
|
|
18
|
+
* {children}
|
|
19
|
+
* </Root>
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function Root(props) {
|
|
23
|
+
return (_jsx(WixServices, { servicesMap: createServicesMap().addService(TimeSlotListServiceDefinition, TimeSlotListService, props.config || {}), children: props.children }));
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Core component that provides access to the current timezone via render props.
|
|
27
|
+
*
|
|
28
|
+
* @component
|
|
29
|
+
* @example
|
|
30
|
+
* ```tsx
|
|
31
|
+
* <Timezone>
|
|
32
|
+
* {({ timezone }) => (
|
|
33
|
+
* <span>{timezone}</span>
|
|
34
|
+
* )}
|
|
35
|
+
* </Timezone>
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export function Timezone(props) {
|
|
39
|
+
const service = useTimeSlotListService();
|
|
40
|
+
const timezone = service.timezone.get();
|
|
41
|
+
return props.children({ timezone });
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Core component that provides access to time slots list data via render props.
|
|
45
|
+
* Use this to build list containers with GenericList.
|
|
46
|
+
*
|
|
47
|
+
* @component
|
|
48
|
+
* @example
|
|
49
|
+
* ```tsx
|
|
50
|
+
* <ListData>
|
|
51
|
+
* {({ timeSlots, hasMore, isLoading, loadMore }) => (
|
|
52
|
+
* <GenericList.Root items={timeSlots} hasMore={hasMore} isLoading={isLoading} loadMore={loadMore}>
|
|
53
|
+
* {children}
|
|
54
|
+
* </GenericList.Root>
|
|
55
|
+
* )}
|
|
56
|
+
* </ListData>
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export function ListData(props) {
|
|
60
|
+
const service = useTimeSlotListService();
|
|
61
|
+
return props.children({
|
|
62
|
+
timeSlots: service.timeSlots.get(),
|
|
63
|
+
hasMore: service.hasMore.get(),
|
|
64
|
+
isLoading: service.isLoading.get(),
|
|
65
|
+
error: service.error.get(),
|
|
66
|
+
loadMore: service.actions.loadMore,
|
|
67
|
+
});
|
|
68
|
+
}
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * as Booking from './booking/Booking.js';
|
|
2
2
|
export * as Service from './service/Service.js';
|
|
3
|
+
export * as TimeSlotList from './time-slot-list/TimeSlotList.js';
|
|
3
4
|
export * as ServiceList from './service-list/ServiceList.js';
|
|
4
5
|
export * as Location from './location/Location.js';
|
package/dist/react/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * as Booking from './booking/Booking.js';
|
|
2
2
|
export * as Service from './service/Service.js';
|
|
3
|
+
export * as TimeSlotList from './time-slot-list/TimeSlotList.js';
|
|
3
4
|
export * as ServiceList from './service-list/ServiceList.js';
|
|
4
5
|
export * as Location from './location/Location.js';
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
import * as CoreLocation from '../core/location/Location.js';
|
|
7
7
|
import { AsChildChildren } from '@wix/headless-utils/react';
|
|
8
|
-
import type
|
|
8
|
+
import { LocationType, type Service } from '@wix/auto_sdk_bookings_services';
|
|
9
9
|
/**
|
|
10
10
|
* Re-export AddressData type from core for convenience
|
|
11
11
|
*/
|
|
@@ -14,10 +14,10 @@ export type { AddressData } from '../core/location/Location.js';
|
|
|
14
14
|
* Props for Location.Root component
|
|
15
15
|
*/
|
|
16
16
|
export interface LocationRootProps {
|
|
17
|
-
location: NonNullable<
|
|
17
|
+
location: NonNullable<Service['locations']>[number];
|
|
18
18
|
asChild?: boolean;
|
|
19
19
|
children?: React.ReactNode | AsChildChildren<{
|
|
20
|
-
locationType:
|
|
20
|
+
locationType: LocationType;
|
|
21
21
|
address: CoreLocation.AddressData | null;
|
|
22
22
|
}>;
|
|
23
23
|
className?: string;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
import { AsChildChildren } from '@wix/headless-utils/react';
|
|
7
7
|
import { MoneyData } from '@wix/headless-components/react';
|
|
8
|
-
import {
|
|
8
|
+
import { type Service, type Payment } from '@wix/auto_sdk_bookings_services';
|
|
9
9
|
/**
|
|
10
10
|
* Props for Service.Root component
|
|
11
11
|
*/
|
|
@@ -14,7 +14,7 @@ export interface ServiceRootProps {
|
|
|
14
14
|
selected: boolean;
|
|
15
15
|
bookable: boolean;
|
|
16
16
|
}>;
|
|
17
|
-
service:
|
|
17
|
+
service: Service;
|
|
18
18
|
appId?: string;
|
|
19
19
|
asChild?: boolean;
|
|
20
20
|
className?: string;
|
|
@@ -106,8 +106,8 @@ export declare const Description: React.ForwardRefExoticComponent<DescriptionPro
|
|
|
106
106
|
export interface PriceProps {
|
|
107
107
|
asChild?: boolean;
|
|
108
108
|
children?: AsChildChildren<{
|
|
109
|
-
servicePayment:
|
|
110
|
-
rateType:
|
|
109
|
+
servicePayment: Payment | undefined;
|
|
110
|
+
rateType: Payment['rateType'] | undefined;
|
|
111
111
|
money: MoneyData | null;
|
|
112
112
|
minPrice: MoneyData | null;
|
|
113
113
|
maxPrice: MoneyData | null;
|
|
@@ -327,7 +327,7 @@ export declare const Category: React.ForwardRefExoticComponent<CategoryProps & R
|
|
|
327
327
|
/**
|
|
328
328
|
* Type for location
|
|
329
329
|
*/
|
|
330
|
-
type LocationType = NonNullable<
|
|
330
|
+
type LocationType = NonNullable<Service['locations']>[number] & {
|
|
331
331
|
id: string;
|
|
332
332
|
};
|
|
333
333
|
/**
|
|
@@ -717,7 +717,7 @@ export declare const MediaItems: React.ForwardRefExoticComponent<MediaItemsProps
|
|
|
717
717
|
export interface RawProps {
|
|
718
718
|
asChild?: boolean;
|
|
719
719
|
children?: AsChildChildren<{
|
|
720
|
-
service:
|
|
720
|
+
service: Service;
|
|
721
721
|
isLoading: boolean;
|
|
722
722
|
error: string | null;
|
|
723
723
|
}>;
|
|
@@ -755,7 +755,7 @@ export declare namespace Actions {
|
|
|
755
755
|
selected: boolean;
|
|
756
756
|
requiresAvailability: boolean;
|
|
757
757
|
onClick: () => void;
|
|
758
|
-
service:
|
|
758
|
+
service: Service;
|
|
759
759
|
}) => React.ReactNode);
|
|
760
760
|
className?: string;
|
|
761
761
|
label?: string;
|
|
@@ -795,7 +795,7 @@ export declare namespace Actions {
|
|
|
795
795
|
selected: boolean;
|
|
796
796
|
requiresAvailability: boolean;
|
|
797
797
|
onClick: () => void;
|
|
798
|
-
service:
|
|
798
|
+
service: Service;
|
|
799
799
|
}) => React.ReactNode);
|
|
800
800
|
className?: string;
|
|
801
801
|
label?: string;
|
|
@@ -835,7 +835,7 @@ export declare namespace Actions {
|
|
|
835
835
|
selected: boolean;
|
|
836
836
|
requiresAvailability: boolean;
|
|
837
837
|
onClick: () => void;
|
|
838
|
-
service:
|
|
838
|
+
service: Service;
|
|
839
839
|
}) => React.ReactNode);
|
|
840
840
|
className?: string;
|
|
841
841
|
label?: string;
|
|
@@ -9,7 +9,7 @@ import { AsChildSlot } from '@wix/headless-utils/react';
|
|
|
9
9
|
import { Money, GenericList } from '@wix/headless-components/react';
|
|
10
10
|
import { WixMediaImage } from '@wix/headless-media/react';
|
|
11
11
|
import { MediaGallery } from '@wix/headless-media/react';
|
|
12
|
-
import {
|
|
12
|
+
import { RateType, } from '@wix/auto_sdk_bookings_services';
|
|
13
13
|
import * as Location from '../location/Location.js';
|
|
14
14
|
var TestIds;
|
|
15
15
|
(function (TestIds) {
|
|
@@ -160,17 +160,17 @@ export const Price = React.forwardRef((props, ref) => {
|
|
|
160
160
|
// Default rendering based on rate type
|
|
161
161
|
const renderDefaultPrice = () => {
|
|
162
162
|
switch (rateType) {
|
|
163
|
-
case
|
|
163
|
+
case RateType.FIXED:
|
|
164
164
|
return money ? (_jsx(Money, { money: money, className: className })) : null;
|
|
165
|
-
case
|
|
165
|
+
case RateType.VARIED:
|
|
166
166
|
if (minPrice && maxPrice) {
|
|
167
167
|
return (_jsxs("span", { className: className, "data-testid": TestIds.servicePrice, children: [_jsx(Money, { money: minPrice }), " - ", _jsx(Money, { money: maxPrice })] }));
|
|
168
168
|
}
|
|
169
169
|
// Fallback to defaultPrice if min/max not available
|
|
170
170
|
return money ? (_jsx(Money, { money: money, className: className })) : null;
|
|
171
|
-
case
|
|
171
|
+
case RateType.CUSTOM:
|
|
172
172
|
return priceDescription ? (_jsx("span", { className: className, "data-testid": TestIds.servicePrice, children: priceDescription })) : null;
|
|
173
|
-
case
|
|
173
|
+
case RateType.NO_FEE:
|
|
174
174
|
return money ? (_jsx(Money, { money: money, className: className })) : null;
|
|
175
175
|
default:
|
|
176
176
|
// UNKNOWN_RATE_TYPE or undefined
|
|
@@ -6,7 +6,7 @@ import React from 'react';
|
|
|
6
6
|
import { ListVariant, GenericListLoadMoreRenderProps } from '@wix/headless-components/react';
|
|
7
7
|
import { AsChildChildren } from '@wix/headless-utils/react';
|
|
8
8
|
import type { ServiceListServiceConfig } from '../../services/service-list/service-list.js';
|
|
9
|
-
import type {
|
|
9
|
+
import type { Service as ServiceType } from '@wix/auto_sdk_bookings_services';
|
|
10
10
|
/**
|
|
11
11
|
* Props for the ServiceList root component
|
|
12
12
|
*/
|
|
@@ -79,7 +79,7 @@ export type ServiceRootChildren = AsChildChildren<{
|
|
|
79
79
|
* Supports both ReactNode and function children that receive { selected, bookable }
|
|
80
80
|
*/
|
|
81
81
|
export interface ServiceItemWrapperProps {
|
|
82
|
-
item:
|
|
82
|
+
item: ServiceType;
|
|
83
83
|
index?: number;
|
|
84
84
|
/** Children can be ReactNode or a function that receives { selected, bookable } from Service.Root */
|
|
85
85
|
children: React.ReactNode | ServiceRootChildren;
|
|
@@ -89,7 +89,7 @@ export interface ServiceItemWrapperProps {
|
|
|
89
89
|
* Provides items array and itemWrapper function for custom rendering
|
|
90
90
|
*/
|
|
91
91
|
export interface ServiceRepeaterRenderProps {
|
|
92
|
-
items:
|
|
92
|
+
items: ServiceType[];
|
|
93
93
|
variant?: ListVariant;
|
|
94
94
|
/** Wraps each item in Service.Root - children can be ReactNode or function receiving { selected, bookable } */
|
|
95
95
|
itemWrapper: (props: ServiceItemWrapperProps) => React.ReactNode;
|