@wix/headless-bookings 0.0.15 → 0.0.16
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/react/core/booking/Booking.d.ts +17 -9
- package/cjs/dist/react/core/booking/Booking.js +13 -7
- package/cjs/dist/services/booking/booking.d.ts +48 -30
- package/cjs/dist/services/booking/booking.js +74 -44
- package/cjs/dist/services/index.d.ts +1 -1
- package/cjs/dist/services/service/service.js +10 -7
- package/cjs/dist/services/time-slot-list/time-slot-list.js +109 -56
- package/dist/react/core/booking/Booking.d.ts +17 -9
- package/dist/react/core/booking/Booking.js +13 -7
- package/dist/services/booking/booking.d.ts +48 -30
- package/dist/services/booking/booking.js +74 -44
- package/dist/services/index.d.ts +1 -1
- package/dist/services/service/service.js +10 -7
- package/dist/services/time-slot-list/time-slot-list.js +109 -56
- package/package.json +2 -2
|
@@ -81,8 +81,8 @@ export const ServiceService = implementService.withConfig()(ServiceServiceDefini
|
|
|
81
81
|
const currentService = serviceSignal.get();
|
|
82
82
|
if (!currentService._id)
|
|
83
83
|
return false;
|
|
84
|
-
const
|
|
85
|
-
return
|
|
84
|
+
const bookingItems = bookingService.bookingItems.get();
|
|
85
|
+
return bookingItems.some(({ service }) => service._id === currentService._id);
|
|
86
86
|
});
|
|
87
87
|
// requiresAvailability signal - true for APPOINTMENT and CLASS types
|
|
88
88
|
const requiresAvailabilitySignal = signalsService.computed(() => {
|
|
@@ -185,25 +185,28 @@ export const ServiceService = implementService.withConfig()(ServiceServiceDefini
|
|
|
185
185
|
if (!bookableSignal.get() || !bookingService)
|
|
186
186
|
return;
|
|
187
187
|
const currentService = serviceSignal.get();
|
|
188
|
-
bookingService.actions.
|
|
188
|
+
bookingService.actions.updateItem({ service: currentService });
|
|
189
189
|
},
|
|
190
190
|
add: () => {
|
|
191
191
|
if (!bookableSignal.get() || !bookingService)
|
|
192
192
|
return;
|
|
193
193
|
const currentService = serviceSignal.get();
|
|
194
|
-
bookingService.actions.
|
|
194
|
+
bookingService.actions.addItem({
|
|
195
|
+
service: currentService,
|
|
196
|
+
resources: [],
|
|
197
|
+
});
|
|
195
198
|
},
|
|
196
199
|
remove: () => {
|
|
197
200
|
if (!bookableSignal.get() || !bookingService)
|
|
198
201
|
return;
|
|
199
202
|
const currentService = serviceSignal.get();
|
|
200
203
|
// Remove all instances of this service (by serviceId)
|
|
201
|
-
const
|
|
202
|
-
const instancesToRemove =
|
|
204
|
+
const bookingItems = bookingService.bookingItems.get();
|
|
205
|
+
const instancesToRemove = bookingItems
|
|
203
206
|
.filter((s) => s.service._id === currentService._id)
|
|
204
207
|
.map((s) => s.instanceId);
|
|
205
208
|
instancesToRemove.forEach((instanceId) => {
|
|
206
|
-
bookingService.actions.
|
|
209
|
+
bookingService.actions.removeItem(instanceId);
|
|
207
210
|
});
|
|
208
211
|
},
|
|
209
212
|
};
|
|
@@ -6,7 +6,7 @@ import { implementService } from '@wix/services-definitions';
|
|
|
6
6
|
import { SignalsServiceDefinition } from '@wix/services-definitions/core-services/signals';
|
|
7
7
|
import { TimeSlotListServiceDefinition, ViewMode, } from './time-slot-list.def.js';
|
|
8
8
|
import { fetchAvailability } from '../../api/time-slot-list/index.js';
|
|
9
|
-
import { BookingServiceDefinition } from '../booking/booking.js';
|
|
9
|
+
import { BookingServiceDefinition, } from '../booking/booking.js';
|
|
10
10
|
// ============================================================================
|
|
11
11
|
// Helpers
|
|
12
12
|
// ============================================================================
|
|
@@ -79,7 +79,7 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
|
|
|
79
79
|
const getServices = () => {
|
|
80
80
|
if (config.services?.length)
|
|
81
81
|
return config.services;
|
|
82
|
-
return bookingService.
|
|
82
|
+
return bookingService.bookingItems.get().map((s) => s.service);
|
|
83
83
|
};
|
|
84
84
|
/**
|
|
85
85
|
* Fetch time slots from API
|
|
@@ -115,82 +115,139 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
|
|
|
115
115
|
};
|
|
116
116
|
/**
|
|
117
117
|
* Action: Select a time slot
|
|
118
|
-
*
|
|
119
|
-
*
|
|
118
|
+
* Auto-selects location/staff based on availability:
|
|
119
|
+
* - One location + one staff → auto-select both
|
|
120
|
+
* - One location + many staff → auto-select location only
|
|
121
|
+
* - Many locations + one staff → auto-select staff only
|
|
122
|
+
* - Many locations + many staff → don't auto-select anything
|
|
120
123
|
*/
|
|
121
124
|
const selectSlot = (slot) => {
|
|
122
125
|
const currentSelection = selectionSignal.get();
|
|
123
126
|
if (currentSelection?.slot?.id === slot.id)
|
|
124
127
|
return;
|
|
128
|
+
const timeSlot = {
|
|
129
|
+
startDate: slot.localStartDate,
|
|
130
|
+
endDate: slot.localEndDate,
|
|
131
|
+
totalCapacity: slot.totalCapacity ?? undefined,
|
|
132
|
+
remainingCapacity: slot.remainingCapacity ?? undefined,
|
|
133
|
+
scheduleId: slot.scheduleId ?? undefined,
|
|
134
|
+
eventInfo: slot.eventInfo ?? undefined,
|
|
135
|
+
};
|
|
125
136
|
const hasOneLocation = slot.staffByLocation.length === 1;
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
bookingService.actions.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
137
|
+
// Collect all unique staff members across all locations
|
|
138
|
+
const allStaffMembers = slot.staffByLocation.flatMap((loc) => loc.staffMembers);
|
|
139
|
+
const uniqueStaffIds = new Set(allStaffMembers.map((s) => s.id));
|
|
140
|
+
const hasOneStaff = uniqueStaffIds.size === 1;
|
|
141
|
+
// Determine what to auto-select
|
|
142
|
+
let locationId = null;
|
|
143
|
+
let staffMemberId = null;
|
|
144
|
+
if (hasOneLocation) {
|
|
145
|
+
const { location } = slot.staffByLocation[0];
|
|
146
|
+
locationId = location.id;
|
|
147
|
+
bookingService.actions.setLocation(location);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
bookingService.actions.clearLocation();
|
|
151
|
+
}
|
|
152
|
+
if (hasOneStaff) {
|
|
153
|
+
const staffMember = allStaffMembers[0];
|
|
154
|
+
staffMemberId = staffMember.id;
|
|
155
|
+
bookingService.actions.updateItem({
|
|
156
|
+
timeSlot,
|
|
157
|
+
resources: [
|
|
158
|
+
{
|
|
159
|
+
_id: staffMemberId,
|
|
160
|
+
name: staffMember.name,
|
|
161
|
+
},
|
|
162
|
+
],
|
|
146
163
|
});
|
|
147
164
|
}
|
|
148
165
|
else {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
staffMemberId: null,
|
|
166
|
+
bookingService.actions.updateItem({
|
|
167
|
+
timeSlot,
|
|
168
|
+
resources: [],
|
|
153
169
|
});
|
|
154
170
|
}
|
|
171
|
+
selectionSignal.set({
|
|
172
|
+
slot,
|
|
173
|
+
locationId,
|
|
174
|
+
staffMemberId,
|
|
175
|
+
});
|
|
155
176
|
};
|
|
156
177
|
/**
|
|
157
178
|
* Action: Select a location for the current slot
|
|
158
|
-
* Updates the booking service with the
|
|
179
|
+
* Updates the booking service with the location
|
|
180
|
+
* If the location has only one staff member, auto-selects that staff member too
|
|
159
181
|
*/
|
|
160
182
|
const selectLocation = (locationId) => {
|
|
161
183
|
const currentSelections = selectionSignal.get();
|
|
162
184
|
if (!currentSelections?.slot)
|
|
163
185
|
return;
|
|
164
|
-
|
|
165
|
-
const
|
|
166
|
-
if (
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
186
|
+
const slot = currentSelections.slot;
|
|
187
|
+
const locationEntry = slot.staffByLocation.find((loc) => loc.location.id === locationId);
|
|
188
|
+
if (!locationEntry)
|
|
189
|
+
return;
|
|
190
|
+
const { location, staffMembers } = locationEntry;
|
|
191
|
+
bookingService.actions.setLocation(location);
|
|
192
|
+
// If this location has only one staff member, auto-select them
|
|
193
|
+
const hasOneStaff = staffMembers.length === 1;
|
|
194
|
+
if (hasOneStaff) {
|
|
195
|
+
const staffMember = staffMembers[0];
|
|
196
|
+
selectionSignal.set({
|
|
197
|
+
...currentSelections,
|
|
198
|
+
locationId,
|
|
199
|
+
staffMemberId: staffMember.id,
|
|
170
200
|
});
|
|
201
|
+
bookingService.actions.updateItem({
|
|
202
|
+
resources: [
|
|
203
|
+
{
|
|
204
|
+
_id: staffMember.id,
|
|
205
|
+
name: staffMember.name,
|
|
206
|
+
},
|
|
207
|
+
],
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
selectionSignal.set({ ...currentSelections, locationId });
|
|
171
212
|
}
|
|
172
213
|
};
|
|
173
214
|
/**
|
|
174
215
|
* Action: Select a staff member for the current slot
|
|
175
|
-
* Updates the booking service with the selected resource
|
|
216
|
+
* Updates the booking service with the selected resource
|
|
217
|
+
* If the staff member is only available at one location, auto-selects that location too
|
|
176
218
|
*/
|
|
177
219
|
const selectStaffMember = (staffMemberId) => {
|
|
178
220
|
const currentSelections = selectionSignal.get();
|
|
179
221
|
if (!currentSelections?.slot)
|
|
180
222
|
return;
|
|
181
|
-
selectionSignal.set({ ...currentSelections, staffMemberId });
|
|
182
223
|
const slot = currentSelections.slot;
|
|
183
|
-
// Find
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
224
|
+
// Find all locations that have this staff member
|
|
225
|
+
const locationsWithThisStaff = slot.staffByLocation.filter((loc) => loc.staffMembers.some((s) => s.id === staffMemberId));
|
|
226
|
+
// Find the staff member info
|
|
227
|
+
const staffMember = locationsWithThisStaff[0]?.staffMembers.find((s) => s.id === staffMemberId);
|
|
228
|
+
if (!staffMember)
|
|
229
|
+
return;
|
|
230
|
+
bookingService.actions.updateItem({
|
|
231
|
+
resources: [
|
|
232
|
+
{
|
|
233
|
+
_id: staffMember.id,
|
|
234
|
+
name: staffMember.name,
|
|
235
|
+
},
|
|
236
|
+
],
|
|
237
|
+
});
|
|
238
|
+
// If this staff member is only at one location, auto-select that location
|
|
239
|
+
const hasOneLocation = locationsWithThisStaff.length === 1;
|
|
240
|
+
if (hasOneLocation) {
|
|
241
|
+
const location = locationsWithThisStaff[0].location;
|
|
242
|
+
selectionSignal.set({
|
|
243
|
+
...currentSelections,
|
|
244
|
+
staffMemberId,
|
|
245
|
+
locationId: location.id,
|
|
246
|
+
});
|
|
247
|
+
bookingService.actions.setLocation(location);
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
selectionSignal.set({ ...currentSelections, staffMemberId });
|
|
194
251
|
}
|
|
195
252
|
};
|
|
196
253
|
/**
|
|
@@ -206,15 +263,11 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
|
|
|
206
263
|
locationId: null,
|
|
207
264
|
staffMemberId: null,
|
|
208
265
|
});
|
|
209
|
-
// Clear
|
|
266
|
+
// Clear selections in booking service
|
|
210
267
|
bookingService.actions.clearLocation();
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
bookingService.actions.updateBookingSelection({
|
|
215
|
-
staff: undefined,
|
|
216
|
-
});
|
|
217
|
-
}
|
|
268
|
+
bookingService.actions.updateItem({
|
|
269
|
+
resources: [],
|
|
270
|
+
});
|
|
218
271
|
};
|
|
219
272
|
/**
|
|
220
273
|
* Action: Load more slots (pagination)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/headless-bookings",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.16",
|
|
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": "9e70aba1e4a39f28a7d02fca86dcf92c71014635fbfc9208bf1569f4"
|
|
72
72
|
}
|