@wix/headless-bookings 0.0.26 → 0.0.28

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/api/create-booking/index.d.ts +42 -0
  2. package/cjs/dist/api/create-booking/index.js +35 -0
  3. package/cjs/dist/api/create-checkout/index.d.ts +40 -0
  4. package/cjs/dist/api/create-checkout/index.js +37 -0
  5. package/cjs/dist/api/fetch-availability/index.d.ts +4 -4
  6. package/cjs/dist/api/fetch-availability/index.js +3 -47
  7. package/cjs/dist/api/index.d.ts +2 -0
  8. package/cjs/dist/api/index.js +2 -0
  9. package/cjs/dist/react/core/time-slot-list/TimeSlot.d.ts +9 -143
  10. package/cjs/dist/react/core/time-slot-list/TimeSlot.js +32 -167
  11. package/cjs/dist/react/core/time-slot-list/TimeSlotList.d.ts +3 -2
  12. package/cjs/dist/react/core/time-slot-list/TimeSlotList.js +1 -1
  13. package/cjs/dist/react/time-slot-list/TimeSlot.d.ts +15 -113
  14. package/cjs/dist/react/time-slot-list/TimeSlot.js +26 -125
  15. package/cjs/dist/react/time-slot-list/TimeSlotList.d.ts +5 -34
  16. package/cjs/dist/react/time-slot-list/TimeSlotList.js +12 -5
  17. package/cjs/dist/services/booking/book-action/bookAction.d.ts +2 -2
  18. package/cjs/dist/services/booking/book-action/bookAction.js +7 -7
  19. package/cjs/dist/services/booking/book-action/buildBookingRequest.d.ts +1 -1
  20. package/cjs/dist/services/booking/book-action/buildCheckoutRequest.d.ts +2 -2
  21. package/cjs/dist/services/booking/book-action/buildCheckoutRequest.js +1 -1
  22. package/cjs/dist/services/index.d.ts +1 -1
  23. package/cjs/dist/services/time-slot-list/index.d.ts +1 -1
  24. package/cjs/dist/services/time-slot-list/time-slot-list.d.ts +4 -4
  25. package/cjs/dist/services/time-slot-list/time-slot-list.def.d.ts +5 -40
  26. package/cjs/dist/services/time-slot-list/time-slot-list.js +38 -167
  27. package/dist/api/create-booking/index.d.ts +42 -0
  28. package/dist/api/create-booking/index.js +35 -0
  29. package/dist/api/create-checkout/index.d.ts +40 -0
  30. package/dist/api/create-checkout/index.js +37 -0
  31. package/dist/api/fetch-availability/index.d.ts +4 -4
  32. package/dist/api/fetch-availability/index.js +3 -47
  33. package/dist/api/index.d.ts +2 -0
  34. package/dist/api/index.js +2 -0
  35. package/dist/react/core/time-slot-list/TimeSlot.d.ts +9 -143
  36. package/dist/react/core/time-slot-list/TimeSlot.js +32 -167
  37. package/dist/react/core/time-slot-list/TimeSlotList.d.ts +3 -2
  38. package/dist/react/core/time-slot-list/TimeSlotList.js +1 -1
  39. package/dist/react/time-slot-list/TimeSlot.d.ts +15 -113
  40. package/dist/react/time-slot-list/TimeSlot.js +26 -125
  41. package/dist/react/time-slot-list/TimeSlotList.d.ts +5 -34
  42. package/dist/react/time-slot-list/TimeSlotList.js +12 -5
  43. package/dist/services/booking/book-action/bookAction.d.ts +2 -2
  44. package/dist/services/booking/book-action/bookAction.js +7 -7
  45. package/dist/services/booking/book-action/buildBookingRequest.d.ts +1 -1
  46. package/dist/services/booking/book-action/buildCheckoutRequest.d.ts +2 -2
  47. package/dist/services/booking/book-action/buildCheckoutRequest.js +1 -1
  48. package/dist/services/index.d.ts +1 -1
  49. package/dist/services/time-slot-list/index.d.ts +1 -1
  50. package/dist/services/time-slot-list/time-slot-list.d.ts +4 -4
  51. package/dist/services/time-slot-list/time-slot-list.def.d.ts +5 -40
  52. package/dist/services/time-slot-list/time-slot-list.js +38 -167
  53. package/package.json +2 -2
@@ -10,37 +10,11 @@ import { BookingServiceDefinition, ANY_STAFF_MEMBER_ID, } from '../booking/booki
10
10
  // ============================================================================
11
11
  // Helpers
12
12
  // ============================================================================
13
- function getDefaultEndDate() {
14
- return new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
15
- }
16
13
  function getClientTimezone() {
17
14
  return typeof Intl !== 'undefined'
18
15
  ? Intl.DateTimeFormat().resolvedOptions().timeZone
19
16
  : undefined;
20
17
  }
21
- /**
22
- * Merges new grouped slots with existing ones
23
- * Slots with the same start time are merged
24
- */
25
- function mergeGroupedSlots(existing, newSlots) {
26
- const mergedMap = new Map();
27
- for (const slot of existing) {
28
- mergedMap.set(slot.localStartDate, slot);
29
- }
30
- for (const newSlot of newSlots) {
31
- const key = newSlot.localStartDate;
32
- const existingSlot = mergedMap.get(key);
33
- if (existingSlot) {
34
- // Merge staffByLocation and originalSlots
35
- existingSlot.staffByLocation.push(...newSlot.staffByLocation);
36
- existingSlot.originalSlots.push(...newSlot.originalSlots);
37
- }
38
- else {
39
- mergedMap.set(key, newSlot);
40
- }
41
- }
42
- return Array.from(mergedMap.values());
43
- }
44
18
  // ============================================================================
45
19
  // Service Implementation
46
20
  // ============================================================================
@@ -48,18 +22,15 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
48
22
  // Get dependent services
49
23
  const signalsService = getService(SignalsServiceDefinition);
50
24
  const bookingService = getService(BookingServiceDefinition);
51
- // Initialize default values
52
- const currentDate = new Date();
53
25
  // Initialize Signals
54
26
  const timeSlotsSignal = signalsService.signal(config.timeSlots || []);
55
- const selectionSignal = signalsService.signal(null);
56
27
  const isLoadingSignal = signalsService.signal(false);
57
28
  const errorSignal = signalsService.signal(null);
58
29
  const hasMoreSignal = signalsService.signal(false);
59
30
  // Internal only - viewMode is auto-detected based on service types
60
31
  const viewModeSignal = signalsService.signal(ViewMode.CLASSIC);
61
- const startDateSignal = signalsService.signal(config.startDate || currentDate);
62
- const endDateSignal = signalsService.signal(config.endDate || getDefaultEndDate());
32
+ const startDateSignal = signalsService.signal(config.startDate);
33
+ const endDateSignal = signalsService.signal(config.endDate);
63
34
  const cursorSignal = signalsService.signal(undefined);
64
35
  /**
65
36
  * Helper: Get services from config or BookingService
@@ -110,16 +81,11 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
110
81
  };
111
82
  /**
112
83
  * Action: Select a time slot
113
- * Auto-selects location/staff based on availability:
114
- * - One location + one staff → auto-select both
115
- * - One location + many staff → auto-select location only
116
- * - Many locations + one staff → auto-select staff only
117
- * - Many locations + many staff → don't auto-select anything
84
+ * Writes selection directly into BookingService (TimeSlotList does not track selection state)
85
+ * - Always sets booking location from slot.location (one location per slot)
86
+ * - Auto-selects staff only when there is exactly one staff option in this slot
118
87
  */
119
88
  const selectSlot = (slot) => {
120
- const currentSelection = selectionSignal.get();
121
- if (currentSelection?.slot?.id === slot.id)
122
- return;
123
89
  const timeSlot = {
124
90
  startDate: slot.localStartDate,
125
91
  endDate: slot.localEndDate,
@@ -128,93 +94,34 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
128
94
  scheduleId: slot.scheduleId ?? undefined,
129
95
  eventInfo: slot.eventInfo ?? undefined,
130
96
  };
131
- const hasOneLocation = slot.staffByLocation.length === 1;
132
- // Collect all unique staff members across all locations
133
- const allStaffMembers = slot.staffByLocation.flatMap((loc) => loc.staffMembers);
134
- const uniqueStaffIds = new Set(allStaffMembers.map((s) => s.id));
135
- const hasOneStaff = uniqueStaffIds.size === 1;
136
- // Determine what to auto-select
137
- let locationId = null;
138
- let staffMemberId = null;
139
- if (hasOneLocation) {
140
- const { location } = slot.staffByLocation[0];
141
- locationId = location.id;
142
- bookingService.actions.setLocation(location);
143
- }
144
- else {
145
- bookingService.actions.clearLocation();
146
- }
147
- if (hasOneStaff) {
148
- const staffMember = allStaffMembers[0];
149
- staffMemberId = staffMember.id;
150
- bookingService.actions.updateItem({
151
- timeSlot,
152
- resources: [
153
- {
154
- _id: staffMemberId,
155
- name: staffMember.name,
156
- },
157
- ],
158
- });
159
- }
160
- else {
161
- bookingService.actions.updateItem({
162
- timeSlot,
163
- resources: [],
164
- });
165
- }
166
- selectionSignal.set({
167
- slot,
168
- locationId,
169
- staffMemberId,
97
+ bookingService.actions.setLocation({
98
+ id: slot.location?._id,
99
+ name: slot.location?.name ?? undefined,
100
+ });
101
+ const staffMembersFromSlot = slot.availableResources[0].resources.map((r) => ({
102
+ id: r._id,
103
+ name: r.name,
104
+ }));
105
+ const resources = staffMembersFromSlot.length === 1 ? staffMembersFromSlot : [];
106
+ bookingService.actions.updateItem({
107
+ timeSlot,
108
+ resources,
170
109
  });
171
- };
172
- /**
173
- * Action: Select a location for the current slot
174
- * Updates the booking service with the location
175
- * If the location has only one staff member, auto-selects that staff member too
176
- */
177
- const selectLocation = (locationId) => {
178
- const currentSelections = selectionSignal.get();
179
- if (!currentSelections?.slot)
180
- return;
181
- const slot = currentSelections.slot;
182
- const locationEntry = slot.staffByLocation.find((loc) => loc.location.id === locationId);
183
- if (!locationEntry)
184
- return;
185
- const { location, staffMembers } = locationEntry;
186
- bookingService.actions.setLocation(location);
187
- // If this location has only one staff member, auto-select them
188
- const hasOneStaff = staffMembers.length === 1;
189
- if (hasOneStaff) {
190
- const staffMember = staffMembers[0];
191
- selectionSignal.set({
192
- ...currentSelections,
193
- locationId,
194
- staffMemberId: staffMember.id,
195
- });
196
- bookingService.actions.updateItem({
197
- resources: [
198
- {
199
- _id: staffMember.id,
200
- name: staffMember.name,
201
- },
202
- ],
203
- });
204
- }
205
- else {
206
- selectionSignal.set({ ...currentSelections, locationId });
207
- }
208
110
  };
209
111
  /**
210
112
  * Action: Select a staff member for the current slot
211
113
  * Updates the booking service with the selected resource
212
- * If the staff member is only available at one location, auto-selects that location too
213
114
  */
214
115
  const selectStaffMember = (staffMemberId) => {
215
- const currentSelections = selectionSignal.get();
216
- if (!currentSelections?.slot)
116
+ const selectedBookingTimeSlot = bookingService.serviceSelections.get()[0]?.timeSlot;
117
+ if (!selectedBookingTimeSlot)
217
118
  return;
119
+ const findStaffName = (id) => {
120
+ const slots = timeSlotsSignal.get();
121
+ return (slots
122
+ .flatMap((slot) => slot.availableResources[0].resources)
123
+ .find((r) => r._id === id)?.name ?? undefined);
124
+ };
218
125
  if (staffMemberId === ANY_STAFF_MEMBER_ID) {
219
126
  bookingService.actions.updateItem({
220
127
  resources: [
@@ -224,54 +131,24 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
224
131
  },
225
132
  ],
226
133
  });
227
- selectionSignal.set({ ...currentSelections, staffMemberId });
228
134
  return;
229
135
  }
230
- const slot = currentSelections.slot;
231
- // Find all locations that have this staff member
232
- const locationsWithThisStaff = slot.staffByLocation.filter((loc) => loc.staffMembers.some((s) => s.id === staffMemberId));
233
- // Find the staff member info
234
- const staffMember = locationsWithThisStaff[0]?.staffMembers.find((s) => s.id === staffMemberId);
235
- if (!staffMember)
236
- return;
237
136
  bookingService.actions.updateItem({
238
137
  resources: [
239
138
  {
240
- _id: staffMember.id,
241
- name: staffMember.name,
139
+ _id: staffMemberId,
140
+ name: findStaffName(staffMemberId),
242
141
  },
243
142
  ],
244
143
  });
245
- // If this staff member is only at one location, auto-select that location
246
- const hasOneLocation = locationsWithThisStaff.length === 1;
247
- if (hasOneLocation) {
248
- const location = locationsWithThisStaff[0].location;
249
- selectionSignal.set({
250
- ...currentSelections,
251
- staffMemberId,
252
- locationId: location.id,
253
- });
254
- bookingService.actions.setLocation(location);
255
- }
256
- else {
257
- selectionSignal.set({ ...currentSelections, staffMemberId });
258
- }
259
144
  };
260
145
  /**
261
- * Action: Clear preferences (location and staff) while keeping the slot selected
146
+ * Action: Clear staff selection while keeping the selected time slot
262
147
  */
263
- const clearPreferences = () => {
264
- const currentSelection = selectionSignal.get();
265
- if (!currentSelection?.slot)
148
+ const clearStaffSelection = () => {
149
+ const selectedBookingTimeSlot = bookingService.serviceSelections.get()[0]?.timeSlot;
150
+ if (!selectedBookingTimeSlot)
266
151
  return;
267
- // Keep the slot, but clear location and staff selections
268
- selectionSignal.set({
269
- slot: currentSelection.slot,
270
- locationId: null,
271
- staffMemberId: null,
272
- });
273
- // Clear selections in booking service
274
- bookingService.actions.clearLocation();
275
152
  bookingService.actions.updateItem({
276
153
  resources: [],
277
154
  });
@@ -295,9 +172,10 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
295
172
  viewMode: viewModeSignal.get(),
296
173
  ...config.filters,
297
174
  });
298
- // API returns grouped slots, merge with existing
299
- const existing = timeSlotsSignal.get();
300
- timeSlotsSignal.set(mergeGroupedSlots(existing, response.timeSlots));
175
+ timeSlotsSignal.set([
176
+ ...timeSlotsSignal.get(),
177
+ ...response.timeSlots,
178
+ ]);
301
179
  const nextCursor = response.cursorPagingMetadata?.cursors?.next ?? undefined;
302
180
  cursorSignal.set(nextCursor);
303
181
  hasMoreSignal.set(!!nextCursor);
@@ -345,7 +223,6 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
345
223
  return {
346
224
  // State Signals
347
225
  timeSlots: timeSlotsSignal,
348
- selection: selectionSignal,
349
226
  isLoading: isLoadingSignal,
350
227
  error: errorSignal,
351
228
  hasMore: hasMoreSignal,
@@ -355,9 +232,8 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
355
232
  // Actions
356
233
  actions: {
357
234
  selectSlot,
358
- selectLocation,
359
235
  selectStaffMember,
360
- clearPreferences,
236
+ clearStaffSelection,
361
237
  loadMore,
362
238
  setDateRange,
363
239
  },
@@ -385,22 +261,17 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
385
261
  * ```
386
262
  */
387
263
  export async function loadTimeSlotListConfig(options) {
388
- const now = new Date();
389
- const startDate = options.startDate || now;
390
- const endDate = options.endDate || getDefaultEndDate();
391
264
  try {
392
265
  const response = await fetchAvailability({
393
266
  services: options.services || [],
394
- fromLocalDate: startDate,
395
- toLocalDate: endDate,
267
+ fromLocalDate: options.startDate,
268
+ toLocalDate: options.endDate,
396
269
  timeZone: options.timezone ?? getClientTimezone(),
397
270
  ...options.filters,
398
271
  });
399
272
  const config = {
400
273
  ...options,
401
274
  timeSlots: response.timeSlots || [],
402
- startDate,
403
- endDate,
404
275
  };
405
276
  return { type: 'success', config };
406
277
  }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Create Booking API
3
+ * Wrapper for the Wix Bookings createBooking SDK function
4
+ */
5
+ import { type Booking, type CreateBookingResponse, type ParticipantNotification } from '@wix/auto_sdk_bookings_bookings';
6
+ import type { FormValues } from '@wix/form-public';
7
+ /**
8
+ * Options for creating a booking
9
+ */
10
+ export interface CreateBookingOptions {
11
+ /** Notification settings for participants */
12
+ participantNotification?: ParticipantNotification;
13
+ /** Whether to send SMS reminder */
14
+ sendSmsReminder?: boolean;
15
+ /** Form submission data */
16
+ formSubmission?: FormValues;
17
+ }
18
+ /**
19
+ * Creates a booking with the specified booking data and options
20
+ *
21
+ * @param booking - The booking data
22
+ * @param options - Optional settings for notifications and form submission
23
+ * @returns Promise resolving to the created booking response
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * const response = await createBooking(
28
+ * {
29
+ * selectedPaymentOption: 'ONLINE',
30
+ * totalParticipants: 1,
31
+ * bookedEntity: { slot: { ... } }
32
+ * },
33
+ * {
34
+ * participantNotification: { notifyParticipants: true },
35
+ * sendSmsReminder: true,
36
+ * formSubmission: formValues
37
+ * }
38
+ * );
39
+ * ```
40
+ */
41
+ export declare function createBooking(booking: Booking, options?: CreateBookingOptions): Promise<CreateBookingResponse>;
42
+ export type { Booking, CreateBookingRequest, CreateBookingResponse, ParticipantNotification, ContactDetails, } from '@wix/auto_sdk_bookings_bookings';
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Create Booking API
3
+ * Wrapper for the Wix Bookings createBooking SDK function
4
+ */
5
+ import { createBooking as createBookingSdk, } from '@wix/auto_sdk_bookings_bookings';
6
+ /**
7
+ * Creates a booking with the specified booking data and options
8
+ *
9
+ * @param booking - The booking data
10
+ * @param options - Optional settings for notifications and form submission
11
+ * @returns Promise resolving to the created booking response
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const response = await createBooking(
16
+ * {
17
+ * selectedPaymentOption: 'ONLINE',
18
+ * totalParticipants: 1,
19
+ * bookedEntity: { slot: { ... } }
20
+ * },
21
+ * {
22
+ * participantNotification: { notifyParticipants: true },
23
+ * sendSmsReminder: true,
24
+ * formSubmission: formValues
25
+ * }
26
+ * );
27
+ * ```
28
+ */
29
+ export async function createBooking(booking, options) {
30
+ return createBookingSdk(booking, {
31
+ participantNotification: options?.participantNotification,
32
+ sendSmsReminder: options?.sendSmsReminder,
33
+ formSubmission: options?.formSubmission,
34
+ });
35
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Create Checkout API
3
+ * Wrapper for the Wix eCommerce createCheckout SDK function
4
+ */
5
+ import { type CreateCheckoutRequest, type Checkout } from '@wix/auto_sdk_ecom_checkout';
6
+ /**
7
+ * Response from createCheckout API
8
+ */
9
+ export interface CreateCheckoutResponse {
10
+ /** The created checkout */
11
+ checkout?: Checkout;
12
+ }
13
+ /**
14
+ * Creates a checkout session with the specified request data
15
+ *
16
+ * @param request - The checkout request data including line items and checkout info
17
+ * @returns Promise resolving to the created checkout response
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const response = await createCheckout({
22
+ * channelType: ChannelType.WEB,
23
+ * lineItems: [
24
+ * {
25
+ * quantity: 1,
26
+ * catalogReference: {
27
+ * catalogItemId: bookingId,
28
+ * appId: BOOKINGS_APP_DEF_ID,
29
+ * },
30
+ * },
31
+ * ],
32
+ * checkoutInfo: {
33
+ * businessLocationId,
34
+ * billingInfo: { ... },
35
+ * },
36
+ * });
37
+ * ```
38
+ */
39
+ export declare function createCheckout(request: CreateCheckoutRequest): Promise<CreateCheckoutResponse>;
40
+ export { ChannelType, type CreateCheckoutRequest, } from '@wix/auto_sdk_ecom_checkout';
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Create Checkout API
3
+ * Wrapper for the Wix eCommerce createCheckout SDK function
4
+ */
5
+ import { createCheckout as createCheckoutSdk, } from '@wix/auto_sdk_ecom_checkout';
6
+ /**
7
+ * Creates a checkout session with the specified request data
8
+ *
9
+ * @param request - The checkout request data including line items and checkout info
10
+ * @returns Promise resolving to the created checkout response
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const response = await createCheckout({
15
+ * channelType: ChannelType.WEB,
16
+ * lineItems: [
17
+ * {
18
+ * quantity: 1,
19
+ * catalogReference: {
20
+ * catalogItemId: bookingId,
21
+ * appId: BOOKINGS_APP_DEF_ID,
22
+ * },
23
+ * },
24
+ * ],
25
+ * checkoutInfo: {
26
+ * businessLocationId,
27
+ * billingInfo: { ... },
28
+ * },
29
+ * });
30
+ * ```
31
+ */
32
+ export async function createCheckout(request) {
33
+ const checkout = await createCheckoutSdk(request);
34
+ return { checkout };
35
+ }
36
+ // Re-export types and constants that consumers may need
37
+ export { ChannelType, } from '@wix/auto_sdk_ecom_checkout';
@@ -2,9 +2,9 @@
2
2
  * Time Slot List API
3
3
  * Fetches available time slots for booking services from Wix Bookings
4
4
  */
5
- import { type CursorPaging, type CursorPagingMetadata } from '@wix/auto_sdk_bookings_availability-time-slots';
5
+ import { type TimeSlot, type CursorPaging, type CursorPagingMetadata } from '@wix/auto_sdk_bookings_availability-time-slots';
6
6
  import { type Service } from '@wix/auto_sdk_bookings_services';
7
- import { ViewMode, type TimeSlot, type Location } from '../../services/time-slot-list/time-slot-list.def.js';
7
+ import { ViewMode, type Location } from '../../services/time-slot-list/time-slot-list.def.js';
8
8
  export interface FetchAvailabilityOptions {
9
9
  services: Service[];
10
10
  fromLocalDate?: string | null;
@@ -28,14 +28,14 @@ export interface FetchAvailabilityOptions {
28
28
  * Response from fetchAvailability with grouped time slots
29
29
  */
30
30
  export interface FetchAvailabilityResponse {
31
- /** Grouped time slots (one per unique time) */
31
+ /** time slots */
32
32
  timeSlots: TimeSlot[];
33
33
  /** Cursor pagination metadata for loading more results */
34
34
  cursorPagingMetadata?: CursorPagingMetadata;
35
35
  }
36
36
  /**
37
37
  * Main entry point for fetching availability
38
- * Detects flow type, calls appropriate API, and groups slots by time
38
+ * Detects flow type and calls appropriate API
39
39
  *
40
40
  * @param options - Fetch options including services, date range, timezone, and view mode
41
41
  * @returns Promise with grouped time slots
@@ -29,50 +29,6 @@ function toLocalDateString(date) {
29
29
  return format(date, pattern);
30
30
  }
31
31
  // ============================================================================
32
- // Grouping Functions
33
- // ============================================================================
34
- /**
35
- * Groups API time slots by their start time
36
- * Multiple slots for the same time (different locations) are merged into one
37
- */
38
- function groupTimeSlotsByTime(apiSlots) {
39
- const groupedMap = new Map();
40
- for (const apiSlot of apiSlots) {
41
- const key = apiSlot.localStartDate;
42
- if (!groupedMap.has(key)) {
43
- // Create new grouped slot - omit location and availableResources
44
- const { location: _location, availableResources: _availableResources, ...rest } = apiSlot;
45
- groupedMap.set(key, {
46
- ...rest,
47
- staffByLocation: [],
48
- originalSlots: [],
49
- id: apiSlot.localStartDate,
50
- });
51
- }
52
- const groupedSlot = groupedMap.get(key);
53
- // Extract staff members with IDs and names from availableResources
54
- const staffMembers = (apiSlot.availableResources || [])
55
- .flatMap((resourceGroup) => resourceGroup.resources || [])
56
- .filter((resource) => resource._id && resource.name)
57
- .map((resource) => ({
58
- id: resource._id,
59
- name: resource.name,
60
- }));
61
- // Add this slot's location/staff info
62
- const staffByLocation = {
63
- location: {
64
- id: apiSlot.location?._id,
65
- name: apiSlot.location?.name,
66
- },
67
- staffMembers,
68
- };
69
- groupedSlot.staffByLocation.push(staffByLocation);
70
- // Store original slot for booking service
71
- groupedSlot.originalSlots.push(apiSlot);
72
- }
73
- return Array.from(groupedMap.values());
74
- }
75
- // ============================================================================
76
32
  // Internal Flow Detection
77
33
  // ============================================================================
78
34
  /**
@@ -98,7 +54,7 @@ function detectFlow(bookingServices, viewMode) {
98
54
  }
99
55
  /**
100
56
  * Main entry point for fetching availability
101
- * Detects flow type, calls appropriate API, and groups slots by time
57
+ * Detects flow type and calls appropriate API
102
58
  *
103
59
  * @param options - Fetch options including services, date range, timezone, and view mode
104
60
  * @returns Promise with grouped time slots
@@ -158,7 +114,7 @@ export async function fetchAvailability({ services: selectedServices, viewMode =
158
114
  timeSlotsPerDay,
159
115
  });
160
116
  return {
161
- timeSlots: groupTimeSlotsByTime(response.timeSlots || []),
117
+ timeSlots: response.timeSlots || [],
162
118
  cursorPagingMetadata: response.cursorPagingMetadata,
163
119
  };
164
120
  }
@@ -188,7 +144,7 @@ export async function fetchAvailability({ services: selectedServices, viewMode =
188
144
  maxSlotsPerDay: timeSlotsPerDay,
189
145
  });
190
146
  return {
191
- timeSlots: groupTimeSlotsByTime(response.timeSlots || []),
147
+ timeSlots: response.timeSlots || [],
192
148
  cursorPagingMetadata: response.pagingMetadata,
193
149
  };
194
150
  }
@@ -6,6 +6,8 @@
6
6
  */
7
7
  export { getServiceById, getServiceBySlug, queryServices, type PagingMetadata, type ServiceListFilters, type QueryServicesRequest, } from './query-services/index.js';
8
8
  export { fetchAvailability } from './fetch-availability/index.js';
9
+ export { createBooking, type CreateBookingOptions, type Booking, type CreateBookingRequest, type CreateBookingResponse, type ParticipantNotification, type ContactDetails, } from './create-booking/index.js';
10
+ export { createCheckout, ChannelType, type CreateCheckoutRequest, type CreateCheckoutResponse, } from './create-checkout/index.js';
9
11
  /**
10
12
  * PagingMetadata includes:
11
13
  * - limit: Number of items per page
package/dist/api/index.js CHANGED
@@ -6,6 +6,8 @@
6
6
  */
7
7
  export { getServiceById, getServiceBySlug, queryServices, } from './query-services/index.js';
8
8
  export { fetchAvailability } from './fetch-availability/index.js';
9
+ export { createBooking, } from './create-booking/index.js';
10
+ export { createCheckout, ChannelType, } from './create-checkout/index.js';
9
11
  /**
10
12
  * PagingMetadata includes:
11
13
  * - limit: Number of items per page