@wix/headless-bookings 0.0.31 → 0.0.33

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.
@@ -4,14 +4,6 @@
4
4
  import type { Resource } from '@wix/auto_sdk_bookings_availability-time-slots';
5
5
  import type { FormValues } from '@wix/form-public';
6
6
  import type { ServiceSelection, ServiceSelectionTimeSlot, Location, BookingServiceConfig } from '../services/booking/booking.js';
7
- /**
8
- * Mock time slot data
9
- */
10
- export declare const mockTimeSlot: ServiceSelectionTimeSlot;
11
- /**
12
- * Mock time slot for afternoon
13
- */
14
- export declare const mockTimeSlotAfternoon: ServiceSelectionTimeSlot;
15
7
  /**
16
8
  * Mock resource (staff member)
17
9
  */
@@ -24,6 +16,22 @@ export declare const mockResourceTwo: Resource;
24
16
  * Mock resource (room)
25
17
  */
26
18
  export declare const mockResourceRoom: Resource;
19
+ /**
20
+ * Mock location
21
+ */
22
+ export declare const mockLocation: Location;
23
+ /**
24
+ * Mock location (second)
25
+ */
26
+ export declare const mockLocationTwo: Location;
27
+ /**
28
+ * Mock time slot data
29
+ */
30
+ export declare const mockTimeSlot: ServiceSelectionTimeSlot;
31
+ /**
32
+ * Mock time slot for afternoon
33
+ */
34
+ export declare const mockTimeSlotAfternoon: ServiceSelectionTimeSlot;
27
35
  /**
28
36
  * Mock service selection with all data
29
37
  */
@@ -36,14 +44,6 @@ export declare const mockServiceSelectionWithoutTimeSlot: ServiceSelection;
36
44
  * Mock service selection for class
37
45
  */
38
46
  export declare const mockServiceSelectionClass: ServiceSelection;
39
- /**
40
- * Mock location
41
- */
42
- export declare const mockLocation: Location;
43
- /**
44
- * Mock location (second)
45
- */
46
- export declare const mockLocationTwo: Location;
47
47
  /**
48
48
  * Mock form submission (contact info)
49
49
  */
@@ -2,26 +2,6 @@
2
2
  * Shared mock data for booking service tests
3
3
  */
4
4
  import { mockService, mockServiceClass } from './services.js';
5
- /**
6
- * Mock time slot data
7
- */
8
- export const mockTimeSlot = {
9
- startDate: '2024-03-15T10:00:00Z',
10
- endDate: '2024-03-15T11:00:00Z',
11
- totalCapacity: 10,
12
- remainingCapacity: 5,
13
- scheduleId: 'schedule-123',
14
- };
15
- /**
16
- * Mock time slot for afternoon
17
- */
18
- export const mockTimeSlotAfternoon = {
19
- startDate: '2024-03-15T14:00:00Z',
20
- endDate: '2024-03-15T15:00:00Z',
21
- totalCapacity: 10,
22
- remainingCapacity: 8,
23
- scheduleId: 'schedule-456',
24
- };
25
5
  /**
26
6
  * Mock resource (staff member)
27
7
  */
@@ -48,6 +28,44 @@ export const mockResourceRoom = {
48
28
  name: 'Conference Room A',
49
29
  tag: 'RESOURCE',
50
30
  };
31
+ /**
32
+ * Mock location
33
+ */
34
+ export const mockLocation = {
35
+ id: 'location-1',
36
+ name: 'Main Office',
37
+ };
38
+ /**
39
+ * Mock location (second)
40
+ */
41
+ export const mockLocationTwo = {
42
+ id: 'location-2',
43
+ name: 'Downtown Branch',
44
+ };
45
+ /**
46
+ * Mock time slot data
47
+ */
48
+ export const mockTimeSlot = {
49
+ startDate: '2024-03-15T10:00:00Z',
50
+ endDate: '2024-03-15T11:00:00Z',
51
+ totalCapacity: 10,
52
+ remainingCapacity: 5,
53
+ scheduleId: 'schedule-123',
54
+ resources: [mockResource],
55
+ location: mockLocation,
56
+ };
57
+ /**
58
+ * Mock time slot for afternoon
59
+ */
60
+ export const mockTimeSlotAfternoon = {
61
+ startDate: '2024-03-15T14:00:00Z',
62
+ endDate: '2024-03-15T15:00:00Z',
63
+ totalCapacity: 10,
64
+ remainingCapacity: 8,
65
+ scheduleId: 'schedule-456',
66
+ resources: [mockResourceTwo],
67
+ location: mockLocationTwo,
68
+ };
51
69
  /**
52
70
  * Mock service selection with all data
53
71
  */
@@ -77,20 +95,6 @@ export const mockServiceSelectionClass = {
77
95
  timeSlot: mockTimeSlotAfternoon,
78
96
  totalParticipants: 3,
79
97
  };
80
- /**
81
- * Mock location
82
- */
83
- export const mockLocation = {
84
- id: 'location-1',
85
- name: 'Main Office',
86
- };
87
- /**
88
- * Mock location (second)
89
- */
90
- export const mockLocationTwo = {
91
- id: 'location-2',
92
- name: 'Downtown Branch',
93
- };
94
98
  /**
95
99
  * Mock form submission (contact info)
96
100
  */
@@ -43,7 +43,7 @@ function RootContent({ children, }) {
43
43
  * ```
44
44
  */
45
45
  export function Root(props) {
46
- const { children, paymentServiceConfig = {}, slotServices, numberOfParticipants } = props;
46
+ const { children, paymentServiceConfig = {}, slotServices, numberOfParticipants, } = props;
47
47
  // Merge public config with lazy loading props into internal config
48
48
  const internalConfig = {
49
49
  ...paymentServiceConfig,
@@ -21,13 +21,13 @@ export interface StartDateProps {
21
21
  className?: string;
22
22
  }
23
23
  /**
24
- * Displays the time slot start date/time as a Date.
25
- * Consumer is responsible for formatting.
24
+ * Displays the time slot start time.
25
+ * Default formatting shows time as "10:00 AM" (hour:minute with AM/PM).
26
26
  *
27
27
  * @component
28
28
  * @example
29
29
  * ```tsx
30
- * // Default usage - displays Date.toString()
30
+ * // Default usage - displays "10:00 AM"
31
31
  * <TimeSlot.StartDate className="text-foreground" />
32
32
  *
33
33
  * // With custom formatting
@@ -50,13 +50,13 @@ export interface EndDateProps {
50
50
  className?: string;
51
51
  }
52
52
  /**
53
- * Displays the time slot end date/time as a Date.
54
- * Consumer is responsible for formatting.
53
+ * Displays the time slot end time.
54
+ * Default formatting shows time as "11:00 AM" (hour:minute with AM/PM).
55
55
  *
56
56
  * @component
57
57
  * @example
58
58
  * ```tsx
59
- * // Default usage - displays Date.toString()
59
+ * // Default usage - displays "11:00 AM"
60
60
  * <TimeSlot.EndDate className="text-foreground" />
61
61
  *
62
62
  * // With custom formatting
@@ -112,12 +112,16 @@ export interface SelectProps {
112
112
  }
113
113
  /**
114
114
  * Button to select this time slot.
115
+ * Default label is "Select".
115
116
  *
116
117
  * @component
117
118
  * @example
118
119
  * ```tsx
119
- * // Default button
120
- * <TimeSlot.Actions.Select label="Select" />
120
+ * // Default button with "Select" label
121
+ * <TimeSlot.Actions.Select />
122
+ *
123
+ * // With custom label
124
+ * <TimeSlot.Actions.Select label="Book" />
121
125
  *
122
126
  * // With asChild
123
127
  * <TimeSlot.Actions.Select asChild>
@@ -149,11 +153,15 @@ export interface ClearStaffSelectionProps {
149
153
  /**
150
154
  * Button to clear staff selection while keeping the slot selected.
151
155
  * Only renders when a staff member is selected and there are multiple staff options.
156
+ * Default label is "Change".
152
157
  *
153
158
  * @component
154
159
  * @example
155
160
  * ```tsx
156
- * // Default button - only shows when there's something to clear
161
+ * // Default button with "Change" label
162
+ * <TimeSlot.Actions.ClearStaffSelection />
163
+ *
164
+ * // With custom label
157
165
  * <TimeSlot.Actions.ClearStaffSelection label="Change staff" />
158
166
  *
159
167
  * // With asChild
@@ -297,12 +305,16 @@ export interface SelectStaffMemberProps {
297
305
  }
298
306
  /**
299
307
  * Button to select this staff member.
308
+ * Default label is "Select".
300
309
  *
301
310
  * @component
302
311
  * @example
303
312
  * ```tsx
304
- * // Default button
305
- * <TimeSlot.StaffMember.Actions.Select label="Select" />
313
+ * // Default button with "Select" label
314
+ * <TimeSlot.StaffMember.Actions.Select />
315
+ *
316
+ * // With custom label
317
+ * <TimeSlot.StaffMember.Actions.Select label="Choose" />
306
318
  *
307
319
  * // With asChild
308
320
  * <TimeSlot.StaffMember.Actions.Select asChild>
@@ -31,13 +31,13 @@ var TestIds;
31
31
  TestIds["timeSlotStaffMemberActionSelect"] = "time-slot-staff-member-action-select";
32
32
  })(TestIds || (TestIds = {}));
33
33
  /**
34
- * Displays the time slot start date/time as a Date.
35
- * Consumer is responsible for formatting.
34
+ * Displays the time slot start time.
35
+ * Default formatting shows time as "10:00 AM" (hour:minute with AM/PM).
36
36
  *
37
37
  * @component
38
38
  * @example
39
39
  * ```tsx
40
- * // Default usage - displays Date.toString()
40
+ * // Default usage - displays "10:00 AM"
41
41
  * <TimeSlot.StartDate className="text-foreground" />
42
42
  *
43
43
  * // With custom formatting
@@ -50,17 +50,20 @@ var TestIds;
50
50
  */
51
51
  export const StartDate = React.forwardRef((props, ref) => {
52
52
  const { asChild, children, className } = props;
53
- return (_jsx(CoreTimeSlot.Info, { children: ({ startDate }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotStartDate, customElement: children, customElementProps: { startDate }, children: _jsx("span", { children: startDate.toString() }) })) }));
53
+ return (_jsx(CoreTimeSlot.Info, { children: ({ startDate }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotStartDate, customElement: children, customElementProps: { startDate }, children: _jsx("span", { children: startDate.toLocaleTimeString([], {
54
+ hour: '2-digit',
55
+ minute: '2-digit',
56
+ }) }) })) }));
54
57
  });
55
58
  StartDate.displayName = 'TimeSlot.StartDate';
56
59
  /**
57
- * Displays the time slot end date/time as a Date.
58
- * Consumer is responsible for formatting.
60
+ * Displays the time slot end time.
61
+ * Default formatting shows time as "11:00 AM" (hour:minute with AM/PM).
59
62
  *
60
63
  * @component
61
64
  * @example
62
65
  * ```tsx
63
- * // Default usage - displays Date.toString()
66
+ * // Default usage - displays "11:00 AM"
64
67
  * <TimeSlot.EndDate className="text-foreground" />
65
68
  *
66
69
  * // With custom formatting
@@ -73,7 +76,10 @@ StartDate.displayName = 'TimeSlot.StartDate';
73
76
  */
74
77
  export const EndDate = React.forwardRef((props, ref) => {
75
78
  const { asChild, children, className } = props;
76
- return (_jsx(CoreTimeSlot.Info, { children: ({ endDate }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotEndDate, customElement: children, customElementProps: { endDate }, children: _jsx("span", { children: endDate.toString() }) })) }));
79
+ return (_jsx(CoreTimeSlot.Info, { children: ({ endDate }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotEndDate, customElement: children, customElementProps: { endDate }, children: _jsx("span", { children: endDate.toLocaleTimeString([], {
80
+ hour: '2-digit',
81
+ minute: '2-digit',
82
+ }) }) })) }));
77
83
  });
78
84
  EndDate.displayName = 'TimeSlot.EndDate';
79
85
  /**
@@ -101,12 +107,16 @@ export const Duration = React.forwardRef((props, ref) => {
101
107
  Duration.displayName = 'TimeSlot.Duration';
102
108
  /**
103
109
  * Button to select this time slot.
110
+ * Default label is "Select".
104
111
  *
105
112
  * @component
106
113
  * @example
107
114
  * ```tsx
108
- * // Default button
109
- * <TimeSlot.Actions.Select label="Select" />
115
+ * // Default button with "Select" label
116
+ * <TimeSlot.Actions.Select />
117
+ *
118
+ * // With custom label
119
+ * <TimeSlot.Actions.Select label="Book" />
110
120
  *
111
121
  * // With asChild
112
122
  * <TimeSlot.Actions.Select asChild>
@@ -124,7 +134,7 @@ Duration.displayName = 'TimeSlot.Duration';
124
134
  * ```
125
135
  */
126
136
  export const Select = React.forwardRef((props, ref) => {
127
- const { asChild, children, className, label } = props;
137
+ const { asChild, children, className, label = 'Select' } = props;
128
138
  return (_jsx(CoreTimeSlot.Actions, { children: ({ selectTimeSlot, isSelected, bookable }) => {
129
139
  return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotActionSelect, "data-selected": isSelected, "data-bookable": bookable, customElement: children, customElementProps: {
130
140
  onClick: selectTimeSlot,
@@ -138,11 +148,15 @@ Select.displayName = 'TimeSlot.Actions.Select';
138
148
  /**
139
149
  * Button to clear staff selection while keeping the slot selected.
140
150
  * Only renders when a staff member is selected and there are multiple staff options.
151
+ * Default label is "Change".
141
152
  *
142
153
  * @component
143
154
  * @example
144
155
  * ```tsx
145
- * // Default button - only shows when there's something to clear
156
+ * // Default button with "Change" label
157
+ * <TimeSlot.Actions.ClearStaffSelection />
158
+ *
159
+ * // With custom label
146
160
  * <TimeSlot.Actions.ClearStaffSelection label="Change staff" />
147
161
  *
148
162
  * // With asChild
@@ -157,7 +171,7 @@ Select.displayName = 'TimeSlot.Actions.Select';
157
171
  * ```
158
172
  */
159
173
  export const ClearStaffSelection = React.forwardRef((props, ref) => {
160
- const { asChild, children, className, label } = props;
174
+ const { asChild, children, className, label = 'Change' } = props;
161
175
  return (_jsx(CoreTimeSlot.Actions, { children: ({ clearStaffSelection }) => {
162
176
  if (!clearStaffSelection) {
163
177
  return null;
@@ -278,12 +292,16 @@ export const StaffMemberName = React.forwardRef((props, ref) => {
278
292
  StaffMemberName.displayName = 'TimeSlot.StaffMember.Name';
279
293
  /**
280
294
  * Button to select this staff member.
295
+ * Default label is "Select".
281
296
  *
282
297
  * @component
283
298
  * @example
284
299
  * ```tsx
285
- * // Default button
286
- * <TimeSlot.StaffMember.Actions.Select label="Select" />
300
+ * // Default button with "Select" label
301
+ * <TimeSlot.StaffMember.Actions.Select />
302
+ *
303
+ * // With custom label
304
+ * <TimeSlot.StaffMember.Actions.Select label="Choose" />
287
305
  *
288
306
  * // With asChild
289
307
  * <TimeSlot.StaffMember.Actions.Select asChild>
@@ -301,7 +319,7 @@ StaffMemberName.displayName = 'TimeSlot.StaffMember.Name';
301
319
  * ```
302
320
  */
303
321
  export const SelectStaffMember = React.forwardRef((props, ref) => {
304
- const { asChild, children, className, label } = props;
322
+ const { asChild, children, className, label = 'Select' } = props;
305
323
  return (_jsx(CoreTimeSlot.StaffMemberActions, { children: ({ selectStaffMember, isSelected }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotStaffMemberActionSelect, "data-selected": isSelected, customElement: children, customElementProps: {
306
324
  onClick: selectStaffMember,
307
325
  isSelected,
@@ -190,9 +190,15 @@ export interface DateRangeInputProps {
190
190
  * Uses the core DateRange component to access service data.
191
191
  * Both dates are set together and trigger a single fetch.
192
192
  *
193
+ * Default rendering provides two native date inputs.
194
+ *
193
195
  * @component
194
196
  * @example
195
197
  * ```tsx
198
+ * // Default usage - renders two date inputs
199
+ * <TimeSlotList.DateRange.Input className="flex gap-2" />
200
+ *
201
+ * // With asChild for custom rendering
196
202
  * <TimeSlotList.DateRange.Input asChild>
197
203
  * {({ startDate, endDate, onChange }) => (
198
204
  * <MyDateRangePicker
@@ -9,6 +9,15 @@ import { AsChildSlot } from '@wix/headless-utils/react';
9
9
  import * as CoreTimeSlotList from '../core/time-slot-list/TimeSlotList.js';
10
10
  import { TimeSlotProvider, Info as CoreTimeSlotInfo, } from '../core/time-slot-list/TimeSlot.js';
11
11
  import { StartDate as TimeSlotStartDate, EndDate as TimeSlotEndDate, Duration, Actions as TimeSlotActions, Location, StaffMembers, StaffMemberRepeater, StaffMember, } from './TimeSlot.js';
12
+ // ============================================================================
13
+ // Utilities
14
+ // ============================================================================
15
+ /**
16
+ * Converts a Date to ISO date string format (YYYY-MM-DD) for input[type="date"]
17
+ */
18
+ function toISODateString(date) {
19
+ return date.toISOString().split('T')[0] ?? '';
20
+ }
12
21
  /**
13
22
  * TimeSlot with required id field for GenericList
14
23
  */
@@ -178,9 +187,15 @@ export const Actions = {
178
187
  * Uses the core DateRange component to access service data.
179
188
  * Both dates are set together and trigger a single fetch.
180
189
  *
190
+ * Default rendering provides two native date inputs.
191
+ *
181
192
  * @component
182
193
  * @example
183
194
  * ```tsx
195
+ * // Default usage - renders two date inputs
196
+ * <TimeSlotList.DateRange.Input className="flex gap-2" />
197
+ *
198
+ * // With asChild for custom rendering
184
199
  * <TimeSlotList.DateRange.Input asChild>
185
200
  * {({ startDate, endDate, onChange }) => (
186
201
  * <MyDateRangePicker
@@ -194,11 +209,14 @@ export const Actions = {
194
209
  */
195
210
  export const DateRangeInput = React.forwardRef((props, ref) => {
196
211
  const { asChild, children, className, ...otherProps } = props;
197
- return (_jsx(CoreTimeSlotList.DateRange, { children: ({ startDate, endDate, setDateRange }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotListDateRangeInput, customElement: children, customElementProps: {
198
- startDate,
199
- endDate,
200
- onChange: setDateRange,
201
- }, ...otherProps, children: _jsxs("div", { children: [startDate.toLocaleDateString(), " - ", endDate.toLocaleDateString()] }) })) }));
212
+ return (_jsx(CoreTimeSlotList.DateRange, { children: ({ startDate, endDate, setDateRange }) => {
213
+ const defaultContent = (_jsxs("div", { ref: ref, className: className, "data-testid": TestIds.timeSlotListDateRangeInput, children: [_jsx("input", { type: "date", value: toISODateString(startDate), onChange: (e) => setDateRange(new Date(e.target.value), endDate) }), _jsx("span", { children: "-" }), _jsx("input", { type: "date", value: toISODateString(endDate), onChange: (e) => setDateRange(startDate, new Date(e.target.value)) })] }));
214
+ return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotListDateRangeInput, customElement: children, customElementProps: {
215
+ startDate,
216
+ endDate,
217
+ onChange: setDateRange,
218
+ }, ...otherProps, children: defaultContent }));
219
+ } }));
202
220
  });
203
221
  DateRangeInput.displayName = 'TimeSlotList.DateRange.Input';
204
222
  /**
@@ -43,8 +43,9 @@ export async function executeBookAction(params) {
43
43
  throw new Error('Failed to create booking');
44
44
  }
45
45
  // Step 2: Create checkout
46
- // businessLocationId comes from location.id for multi-location support
47
- const businessLocationId = params.location?.id ?? undefined;
46
+ // businessLocationId: prefer timeSlot.location, fallback to global location
47
+ const firstSelection = params.serviceSelections[0];
48
+ const businessLocationId = firstSelection?.timeSlot?.location?.id ?? undefined;
48
49
  const checkoutRequest = buildCheckoutRequest({
49
50
  bookingId,
50
51
  contactDetails,
@@ -46,8 +46,10 @@ export function buildBookingRequest(params) {
46
46
  if (!item.timeSlot) {
47
47
  throw new Error('No time slot selected for service selection');
48
48
  }
49
- // Get resource from service selection
50
- const resource = item.resources?.[0];
49
+ // Get resource: prefer timeSlot.resources, fallback to item.resources
50
+ const resource = item.timeSlot.resources?.[0] ?? item.resources?.[0];
51
+ // Get location: prefer timeSlot.location, fallback to params.location
52
+ const slotLocation = item.timeSlot.location ?? location;
51
53
  return {
52
54
  booking: {
53
55
  // Payment option derived from service payment settings
@@ -66,8 +68,8 @@ export function buildBookingRequest(params) {
66
68
  resource: resource
67
69
  ? { _id: resource._id, name: resource.name }
68
70
  : undefined,
69
- location: location
70
- ? { _id: location.id, name: location.name }
71
+ location: slotLocation
72
+ ? { _id: slotLocation.id, name: slotLocation.name }
71
73
  : undefined,
72
74
  },
73
75
  },
@@ -19,6 +19,10 @@ export interface ServiceSelectionTimeSlot {
19
19
  remainingCapacity?: number;
20
20
  scheduleId?: string;
21
21
  eventInfo?: EventInfo;
22
+ /** Resources available in this time slot (populated when slot is selected) */
23
+ resources?: Resource[];
24
+ /** Location of this time slot (populated when slot is selected) */
25
+ location?: Location;
22
26
  }
23
27
  /**
24
28
  * ServiceSelection contains the service AND its related selections
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { type PaymentServiceConfig, type PaymentServiceInternalConfig, type SlotService } from './payment.def.js';
7
7
  export { PaymentServiceDefinition, type PaymentServiceConfig, type PaymentDetails, type LineItemAdditionalInfo, type SlotService, } from './payment.def.js';
8
- export type { PaymentServiceAPI, PaymentServiceInternalConfig } from './payment.def.js';
8
+ export type { PaymentServiceAPI, PaymentServiceInternalConfig, } from './payment.def.js';
9
9
  export declare const PaymentService: import("@wix/services-definitions").ServiceFactory<string & {
10
10
  __api: import("./payment.def.js").PaymentServiceAPI;
11
11
  __config: {};
@@ -86,6 +86,14 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
86
86
  * - Auto-selects staff only when there is exactly one staff option in this slot
87
87
  */
88
88
  const selectSlot = (slot) => {
89
+ const staffMembersFromSlot = slot.availableResources[0].resources.map((r) => ({
90
+ _id: r._id,
91
+ name: r.name,
92
+ }));
93
+ const slotLocation = {
94
+ id: slot.location?._id,
95
+ name: slot.location?.name ?? undefined,
96
+ };
89
97
  const timeSlot = {
90
98
  startDate: slot.localStartDate,
91
99
  endDate: slot.localEndDate,
@@ -93,15 +101,12 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
93
101
  remainingCapacity: slot.remainingCapacity ?? undefined,
94
102
  scheduleId: slot.scheduleId ?? undefined,
95
103
  eventInfo: slot.eventInfo ?? undefined,
104
+ resources: staffMembersFromSlot,
105
+ location: slotLocation,
96
106
  };
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
- }));
107
+ // Keep setting top-level location (for pre-slot selection use cases)
108
+ bookingService.actions.setLocation(slotLocation);
109
+ // Auto-select resources only when single staff
105
110
  const resources = staffMembersFromSlot.length === 1 ? staffMembersFromSlot : [];
106
111
  bookingService.actions.updateItem({
107
112
  timeSlot,
@@ -4,14 +4,6 @@
4
4
  import type { Resource } from '@wix/auto_sdk_bookings_availability-time-slots';
5
5
  import type { FormValues } from '@wix/form-public';
6
6
  import type { ServiceSelection, ServiceSelectionTimeSlot, Location, BookingServiceConfig } from '../services/booking/booking.js';
7
- /**
8
- * Mock time slot data
9
- */
10
- export declare const mockTimeSlot: ServiceSelectionTimeSlot;
11
- /**
12
- * Mock time slot for afternoon
13
- */
14
- export declare const mockTimeSlotAfternoon: ServiceSelectionTimeSlot;
15
7
  /**
16
8
  * Mock resource (staff member)
17
9
  */
@@ -24,6 +16,22 @@ export declare const mockResourceTwo: Resource;
24
16
  * Mock resource (room)
25
17
  */
26
18
  export declare const mockResourceRoom: Resource;
19
+ /**
20
+ * Mock location
21
+ */
22
+ export declare const mockLocation: Location;
23
+ /**
24
+ * Mock location (second)
25
+ */
26
+ export declare const mockLocationTwo: Location;
27
+ /**
28
+ * Mock time slot data
29
+ */
30
+ export declare const mockTimeSlot: ServiceSelectionTimeSlot;
31
+ /**
32
+ * Mock time slot for afternoon
33
+ */
34
+ export declare const mockTimeSlotAfternoon: ServiceSelectionTimeSlot;
27
35
  /**
28
36
  * Mock service selection with all data
29
37
  */
@@ -36,14 +44,6 @@ export declare const mockServiceSelectionWithoutTimeSlot: ServiceSelection;
36
44
  * Mock service selection for class
37
45
  */
38
46
  export declare const mockServiceSelectionClass: ServiceSelection;
39
- /**
40
- * Mock location
41
- */
42
- export declare const mockLocation: Location;
43
- /**
44
- * Mock location (second)
45
- */
46
- export declare const mockLocationTwo: Location;
47
47
  /**
48
48
  * Mock form submission (contact info)
49
49
  */
@@ -2,26 +2,6 @@
2
2
  * Shared mock data for booking service tests
3
3
  */
4
4
  import { mockService, mockServiceClass } from './services.js';
5
- /**
6
- * Mock time slot data
7
- */
8
- export const mockTimeSlot = {
9
- startDate: '2024-03-15T10:00:00Z',
10
- endDate: '2024-03-15T11:00:00Z',
11
- totalCapacity: 10,
12
- remainingCapacity: 5,
13
- scheduleId: 'schedule-123',
14
- };
15
- /**
16
- * Mock time slot for afternoon
17
- */
18
- export const mockTimeSlotAfternoon = {
19
- startDate: '2024-03-15T14:00:00Z',
20
- endDate: '2024-03-15T15:00:00Z',
21
- totalCapacity: 10,
22
- remainingCapacity: 8,
23
- scheduleId: 'schedule-456',
24
- };
25
5
  /**
26
6
  * Mock resource (staff member)
27
7
  */
@@ -48,6 +28,44 @@ export const mockResourceRoom = {
48
28
  name: 'Conference Room A',
49
29
  tag: 'RESOURCE',
50
30
  };
31
+ /**
32
+ * Mock location
33
+ */
34
+ export const mockLocation = {
35
+ id: 'location-1',
36
+ name: 'Main Office',
37
+ };
38
+ /**
39
+ * Mock location (second)
40
+ */
41
+ export const mockLocationTwo = {
42
+ id: 'location-2',
43
+ name: 'Downtown Branch',
44
+ };
45
+ /**
46
+ * Mock time slot data
47
+ */
48
+ export const mockTimeSlot = {
49
+ startDate: '2024-03-15T10:00:00Z',
50
+ endDate: '2024-03-15T11:00:00Z',
51
+ totalCapacity: 10,
52
+ remainingCapacity: 5,
53
+ scheduleId: 'schedule-123',
54
+ resources: [mockResource],
55
+ location: mockLocation,
56
+ };
57
+ /**
58
+ * Mock time slot for afternoon
59
+ */
60
+ export const mockTimeSlotAfternoon = {
61
+ startDate: '2024-03-15T14:00:00Z',
62
+ endDate: '2024-03-15T15:00:00Z',
63
+ totalCapacity: 10,
64
+ remainingCapacity: 8,
65
+ scheduleId: 'schedule-456',
66
+ resources: [mockResourceTwo],
67
+ location: mockLocationTwo,
68
+ };
51
69
  /**
52
70
  * Mock service selection with all data
53
71
  */
@@ -77,20 +95,6 @@ export const mockServiceSelectionClass = {
77
95
  timeSlot: mockTimeSlotAfternoon,
78
96
  totalParticipants: 3,
79
97
  };
80
- /**
81
- * Mock location
82
- */
83
- export const mockLocation = {
84
- id: 'location-1',
85
- name: 'Main Office',
86
- };
87
- /**
88
- * Mock location (second)
89
- */
90
- export const mockLocationTwo = {
91
- id: 'location-2',
92
- name: 'Downtown Branch',
93
- };
94
98
  /**
95
99
  * Mock form submission (contact info)
96
100
  */
@@ -43,7 +43,7 @@ function RootContent({ children, }) {
43
43
  * ```
44
44
  */
45
45
  export function Root(props) {
46
- const { children, paymentServiceConfig = {}, slotServices, numberOfParticipants } = props;
46
+ const { children, paymentServiceConfig = {}, slotServices, numberOfParticipants, } = props;
47
47
  // Merge public config with lazy loading props into internal config
48
48
  const internalConfig = {
49
49
  ...paymentServiceConfig,
@@ -21,13 +21,13 @@ export interface StartDateProps {
21
21
  className?: string;
22
22
  }
23
23
  /**
24
- * Displays the time slot start date/time as a Date.
25
- * Consumer is responsible for formatting.
24
+ * Displays the time slot start time.
25
+ * Default formatting shows time as "10:00 AM" (hour:minute with AM/PM).
26
26
  *
27
27
  * @component
28
28
  * @example
29
29
  * ```tsx
30
- * // Default usage - displays Date.toString()
30
+ * // Default usage - displays "10:00 AM"
31
31
  * <TimeSlot.StartDate className="text-foreground" />
32
32
  *
33
33
  * // With custom formatting
@@ -50,13 +50,13 @@ export interface EndDateProps {
50
50
  className?: string;
51
51
  }
52
52
  /**
53
- * Displays the time slot end date/time as a Date.
54
- * Consumer is responsible for formatting.
53
+ * Displays the time slot end time.
54
+ * Default formatting shows time as "11:00 AM" (hour:minute with AM/PM).
55
55
  *
56
56
  * @component
57
57
  * @example
58
58
  * ```tsx
59
- * // Default usage - displays Date.toString()
59
+ * // Default usage - displays "11:00 AM"
60
60
  * <TimeSlot.EndDate className="text-foreground" />
61
61
  *
62
62
  * // With custom formatting
@@ -112,12 +112,16 @@ export interface SelectProps {
112
112
  }
113
113
  /**
114
114
  * Button to select this time slot.
115
+ * Default label is "Select".
115
116
  *
116
117
  * @component
117
118
  * @example
118
119
  * ```tsx
119
- * // Default button
120
- * <TimeSlot.Actions.Select label="Select" />
120
+ * // Default button with "Select" label
121
+ * <TimeSlot.Actions.Select />
122
+ *
123
+ * // With custom label
124
+ * <TimeSlot.Actions.Select label="Book" />
121
125
  *
122
126
  * // With asChild
123
127
  * <TimeSlot.Actions.Select asChild>
@@ -149,11 +153,15 @@ export interface ClearStaffSelectionProps {
149
153
  /**
150
154
  * Button to clear staff selection while keeping the slot selected.
151
155
  * Only renders when a staff member is selected and there are multiple staff options.
156
+ * Default label is "Change".
152
157
  *
153
158
  * @component
154
159
  * @example
155
160
  * ```tsx
156
- * // Default button - only shows when there's something to clear
161
+ * // Default button with "Change" label
162
+ * <TimeSlot.Actions.ClearStaffSelection />
163
+ *
164
+ * // With custom label
157
165
  * <TimeSlot.Actions.ClearStaffSelection label="Change staff" />
158
166
  *
159
167
  * // With asChild
@@ -297,12 +305,16 @@ export interface SelectStaffMemberProps {
297
305
  }
298
306
  /**
299
307
  * Button to select this staff member.
308
+ * Default label is "Select".
300
309
  *
301
310
  * @component
302
311
  * @example
303
312
  * ```tsx
304
- * // Default button
305
- * <TimeSlot.StaffMember.Actions.Select label="Select" />
313
+ * // Default button with "Select" label
314
+ * <TimeSlot.StaffMember.Actions.Select />
315
+ *
316
+ * // With custom label
317
+ * <TimeSlot.StaffMember.Actions.Select label="Choose" />
306
318
  *
307
319
  * // With asChild
308
320
  * <TimeSlot.StaffMember.Actions.Select asChild>
@@ -31,13 +31,13 @@ var TestIds;
31
31
  TestIds["timeSlotStaffMemberActionSelect"] = "time-slot-staff-member-action-select";
32
32
  })(TestIds || (TestIds = {}));
33
33
  /**
34
- * Displays the time slot start date/time as a Date.
35
- * Consumer is responsible for formatting.
34
+ * Displays the time slot start time.
35
+ * Default formatting shows time as "10:00 AM" (hour:minute with AM/PM).
36
36
  *
37
37
  * @component
38
38
  * @example
39
39
  * ```tsx
40
- * // Default usage - displays Date.toString()
40
+ * // Default usage - displays "10:00 AM"
41
41
  * <TimeSlot.StartDate className="text-foreground" />
42
42
  *
43
43
  * // With custom formatting
@@ -50,17 +50,20 @@ var TestIds;
50
50
  */
51
51
  export const StartDate = React.forwardRef((props, ref) => {
52
52
  const { asChild, children, className } = props;
53
- return (_jsx(CoreTimeSlot.Info, { children: ({ startDate }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotStartDate, customElement: children, customElementProps: { startDate }, children: _jsx("span", { children: startDate.toString() }) })) }));
53
+ return (_jsx(CoreTimeSlot.Info, { children: ({ startDate }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotStartDate, customElement: children, customElementProps: { startDate }, children: _jsx("span", { children: startDate.toLocaleTimeString([], {
54
+ hour: '2-digit',
55
+ minute: '2-digit',
56
+ }) }) })) }));
54
57
  });
55
58
  StartDate.displayName = 'TimeSlot.StartDate';
56
59
  /**
57
- * Displays the time slot end date/time as a Date.
58
- * Consumer is responsible for formatting.
60
+ * Displays the time slot end time.
61
+ * Default formatting shows time as "11:00 AM" (hour:minute with AM/PM).
59
62
  *
60
63
  * @component
61
64
  * @example
62
65
  * ```tsx
63
- * // Default usage - displays Date.toString()
66
+ * // Default usage - displays "11:00 AM"
64
67
  * <TimeSlot.EndDate className="text-foreground" />
65
68
  *
66
69
  * // With custom formatting
@@ -73,7 +76,10 @@ StartDate.displayName = 'TimeSlot.StartDate';
73
76
  */
74
77
  export const EndDate = React.forwardRef((props, ref) => {
75
78
  const { asChild, children, className } = props;
76
- return (_jsx(CoreTimeSlot.Info, { children: ({ endDate }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotEndDate, customElement: children, customElementProps: { endDate }, children: _jsx("span", { children: endDate.toString() }) })) }));
79
+ return (_jsx(CoreTimeSlot.Info, { children: ({ endDate }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotEndDate, customElement: children, customElementProps: { endDate }, children: _jsx("span", { children: endDate.toLocaleTimeString([], {
80
+ hour: '2-digit',
81
+ minute: '2-digit',
82
+ }) }) })) }));
77
83
  });
78
84
  EndDate.displayName = 'TimeSlot.EndDate';
79
85
  /**
@@ -101,12 +107,16 @@ export const Duration = React.forwardRef((props, ref) => {
101
107
  Duration.displayName = 'TimeSlot.Duration';
102
108
  /**
103
109
  * Button to select this time slot.
110
+ * Default label is "Select".
104
111
  *
105
112
  * @component
106
113
  * @example
107
114
  * ```tsx
108
- * // Default button
109
- * <TimeSlot.Actions.Select label="Select" />
115
+ * // Default button with "Select" label
116
+ * <TimeSlot.Actions.Select />
117
+ *
118
+ * // With custom label
119
+ * <TimeSlot.Actions.Select label="Book" />
110
120
  *
111
121
  * // With asChild
112
122
  * <TimeSlot.Actions.Select asChild>
@@ -124,7 +134,7 @@ Duration.displayName = 'TimeSlot.Duration';
124
134
  * ```
125
135
  */
126
136
  export const Select = React.forwardRef((props, ref) => {
127
- const { asChild, children, className, label } = props;
137
+ const { asChild, children, className, label = 'Select' } = props;
128
138
  return (_jsx(CoreTimeSlot.Actions, { children: ({ selectTimeSlot, isSelected, bookable }) => {
129
139
  return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotActionSelect, "data-selected": isSelected, "data-bookable": bookable, customElement: children, customElementProps: {
130
140
  onClick: selectTimeSlot,
@@ -138,11 +148,15 @@ Select.displayName = 'TimeSlot.Actions.Select';
138
148
  /**
139
149
  * Button to clear staff selection while keeping the slot selected.
140
150
  * Only renders when a staff member is selected and there are multiple staff options.
151
+ * Default label is "Change".
141
152
  *
142
153
  * @component
143
154
  * @example
144
155
  * ```tsx
145
- * // Default button - only shows when there's something to clear
156
+ * // Default button with "Change" label
157
+ * <TimeSlot.Actions.ClearStaffSelection />
158
+ *
159
+ * // With custom label
146
160
  * <TimeSlot.Actions.ClearStaffSelection label="Change staff" />
147
161
  *
148
162
  * // With asChild
@@ -157,7 +171,7 @@ Select.displayName = 'TimeSlot.Actions.Select';
157
171
  * ```
158
172
  */
159
173
  export const ClearStaffSelection = React.forwardRef((props, ref) => {
160
- const { asChild, children, className, label } = props;
174
+ const { asChild, children, className, label = 'Change' } = props;
161
175
  return (_jsx(CoreTimeSlot.Actions, { children: ({ clearStaffSelection }) => {
162
176
  if (!clearStaffSelection) {
163
177
  return null;
@@ -278,12 +292,16 @@ export const StaffMemberName = React.forwardRef((props, ref) => {
278
292
  StaffMemberName.displayName = 'TimeSlot.StaffMember.Name';
279
293
  /**
280
294
  * Button to select this staff member.
295
+ * Default label is "Select".
281
296
  *
282
297
  * @component
283
298
  * @example
284
299
  * ```tsx
285
- * // Default button
286
- * <TimeSlot.StaffMember.Actions.Select label="Select" />
300
+ * // Default button with "Select" label
301
+ * <TimeSlot.StaffMember.Actions.Select />
302
+ *
303
+ * // With custom label
304
+ * <TimeSlot.StaffMember.Actions.Select label="Choose" />
287
305
  *
288
306
  * // With asChild
289
307
  * <TimeSlot.StaffMember.Actions.Select asChild>
@@ -301,7 +319,7 @@ StaffMemberName.displayName = 'TimeSlot.StaffMember.Name';
301
319
  * ```
302
320
  */
303
321
  export const SelectStaffMember = React.forwardRef((props, ref) => {
304
- const { asChild, children, className, label } = props;
322
+ const { asChild, children, className, label = 'Select' } = props;
305
323
  return (_jsx(CoreTimeSlot.StaffMemberActions, { children: ({ selectStaffMember, isSelected }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotStaffMemberActionSelect, "data-selected": isSelected, customElement: children, customElementProps: {
306
324
  onClick: selectStaffMember,
307
325
  isSelected,
@@ -190,9 +190,15 @@ export interface DateRangeInputProps {
190
190
  * Uses the core DateRange component to access service data.
191
191
  * Both dates are set together and trigger a single fetch.
192
192
  *
193
+ * Default rendering provides two native date inputs.
194
+ *
193
195
  * @component
194
196
  * @example
195
197
  * ```tsx
198
+ * // Default usage - renders two date inputs
199
+ * <TimeSlotList.DateRange.Input className="flex gap-2" />
200
+ *
201
+ * // With asChild for custom rendering
196
202
  * <TimeSlotList.DateRange.Input asChild>
197
203
  * {({ startDate, endDate, onChange }) => (
198
204
  * <MyDateRangePicker
@@ -9,6 +9,15 @@ import { AsChildSlot } from '@wix/headless-utils/react';
9
9
  import * as CoreTimeSlotList from '../core/time-slot-list/TimeSlotList.js';
10
10
  import { TimeSlotProvider, Info as CoreTimeSlotInfo, } from '../core/time-slot-list/TimeSlot.js';
11
11
  import { StartDate as TimeSlotStartDate, EndDate as TimeSlotEndDate, Duration, Actions as TimeSlotActions, Location, StaffMembers, StaffMemberRepeater, StaffMember, } from './TimeSlot.js';
12
+ // ============================================================================
13
+ // Utilities
14
+ // ============================================================================
15
+ /**
16
+ * Converts a Date to ISO date string format (YYYY-MM-DD) for input[type="date"]
17
+ */
18
+ function toISODateString(date) {
19
+ return date.toISOString().split('T')[0] ?? '';
20
+ }
12
21
  /**
13
22
  * TimeSlot with required id field for GenericList
14
23
  */
@@ -178,9 +187,15 @@ export const Actions = {
178
187
  * Uses the core DateRange component to access service data.
179
188
  * Both dates are set together and trigger a single fetch.
180
189
  *
190
+ * Default rendering provides two native date inputs.
191
+ *
181
192
  * @component
182
193
  * @example
183
194
  * ```tsx
195
+ * // Default usage - renders two date inputs
196
+ * <TimeSlotList.DateRange.Input className="flex gap-2" />
197
+ *
198
+ * // With asChild for custom rendering
184
199
  * <TimeSlotList.DateRange.Input asChild>
185
200
  * {({ startDate, endDate, onChange }) => (
186
201
  * <MyDateRangePicker
@@ -194,11 +209,14 @@ export const Actions = {
194
209
  */
195
210
  export const DateRangeInput = React.forwardRef((props, ref) => {
196
211
  const { asChild, children, className, ...otherProps } = props;
197
- return (_jsx(CoreTimeSlotList.DateRange, { children: ({ startDate, endDate, setDateRange }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotListDateRangeInput, customElement: children, customElementProps: {
198
- startDate,
199
- endDate,
200
- onChange: setDateRange,
201
- }, ...otherProps, children: _jsxs("div", { children: [startDate.toLocaleDateString(), " - ", endDate.toLocaleDateString()] }) })) }));
212
+ return (_jsx(CoreTimeSlotList.DateRange, { children: ({ startDate, endDate, setDateRange }) => {
213
+ const defaultContent = (_jsxs("div", { ref: ref, className: className, "data-testid": TestIds.timeSlotListDateRangeInput, children: [_jsx("input", { type: "date", value: toISODateString(startDate), onChange: (e) => setDateRange(new Date(e.target.value), endDate) }), _jsx("span", { children: "-" }), _jsx("input", { type: "date", value: toISODateString(endDate), onChange: (e) => setDateRange(startDate, new Date(e.target.value)) })] }));
214
+ return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotListDateRangeInput, customElement: children, customElementProps: {
215
+ startDate,
216
+ endDate,
217
+ onChange: setDateRange,
218
+ }, ...otherProps, children: defaultContent }));
219
+ } }));
202
220
  });
203
221
  DateRangeInput.displayName = 'TimeSlotList.DateRange.Input';
204
222
  /**
@@ -43,8 +43,9 @@ export async function executeBookAction(params) {
43
43
  throw new Error('Failed to create booking');
44
44
  }
45
45
  // Step 2: Create checkout
46
- // businessLocationId comes from location.id for multi-location support
47
- const businessLocationId = params.location?.id ?? undefined;
46
+ // businessLocationId: prefer timeSlot.location, fallback to global location
47
+ const firstSelection = params.serviceSelections[0];
48
+ const businessLocationId = firstSelection?.timeSlot?.location?.id ?? undefined;
48
49
  const checkoutRequest = buildCheckoutRequest({
49
50
  bookingId,
50
51
  contactDetails,
@@ -46,8 +46,10 @@ export function buildBookingRequest(params) {
46
46
  if (!item.timeSlot) {
47
47
  throw new Error('No time slot selected for service selection');
48
48
  }
49
- // Get resource from service selection
50
- const resource = item.resources?.[0];
49
+ // Get resource: prefer timeSlot.resources, fallback to item.resources
50
+ const resource = item.timeSlot.resources?.[0] ?? item.resources?.[0];
51
+ // Get location: prefer timeSlot.location, fallback to params.location
52
+ const slotLocation = item.timeSlot.location ?? location;
51
53
  return {
52
54
  booking: {
53
55
  // Payment option derived from service payment settings
@@ -66,8 +68,8 @@ export function buildBookingRequest(params) {
66
68
  resource: resource
67
69
  ? { _id: resource._id, name: resource.name }
68
70
  : undefined,
69
- location: location
70
- ? { _id: location.id, name: location.name }
71
+ location: slotLocation
72
+ ? { _id: slotLocation.id, name: slotLocation.name }
71
73
  : undefined,
72
74
  },
73
75
  },
@@ -19,6 +19,10 @@ export interface ServiceSelectionTimeSlot {
19
19
  remainingCapacity?: number;
20
20
  scheduleId?: string;
21
21
  eventInfo?: EventInfo;
22
+ /** Resources available in this time slot (populated when slot is selected) */
23
+ resources?: Resource[];
24
+ /** Location of this time slot (populated when slot is selected) */
25
+ location?: Location;
22
26
  }
23
27
  /**
24
28
  * ServiceSelection contains the service AND its related selections
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { type PaymentServiceConfig, type PaymentServiceInternalConfig, type SlotService } from './payment.def.js';
7
7
  export { PaymentServiceDefinition, type PaymentServiceConfig, type PaymentDetails, type LineItemAdditionalInfo, type SlotService, } from './payment.def.js';
8
- export type { PaymentServiceAPI, PaymentServiceInternalConfig } from './payment.def.js';
8
+ export type { PaymentServiceAPI, PaymentServiceInternalConfig, } from './payment.def.js';
9
9
  export declare const PaymentService: import("@wix/services-definitions").ServiceFactory<string & {
10
10
  __api: import("./payment.def.js").PaymentServiceAPI;
11
11
  __config: {};
@@ -86,6 +86,14 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
86
86
  * - Auto-selects staff only when there is exactly one staff option in this slot
87
87
  */
88
88
  const selectSlot = (slot) => {
89
+ const staffMembersFromSlot = slot.availableResources[0].resources.map((r) => ({
90
+ _id: r._id,
91
+ name: r.name,
92
+ }));
93
+ const slotLocation = {
94
+ id: slot.location?._id,
95
+ name: slot.location?.name ?? undefined,
96
+ };
89
97
  const timeSlot = {
90
98
  startDate: slot.localStartDate,
91
99
  endDate: slot.localEndDate,
@@ -93,15 +101,12 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
93
101
  remainingCapacity: slot.remainingCapacity ?? undefined,
94
102
  scheduleId: slot.scheduleId ?? undefined,
95
103
  eventInfo: slot.eventInfo ?? undefined,
104
+ resources: staffMembersFromSlot,
105
+ location: slotLocation,
96
106
  };
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
- }));
107
+ // Keep setting top-level location (for pre-slot selection use cases)
108
+ bookingService.actions.setLocation(slotLocation);
109
+ // Auto-select resources only when single staff
105
110
  const resources = staffMembersFromSlot.length === 1 ? staffMembersFromSlot : [];
106
111
  bookingService.actions.updateItem({
107
112
  timeSlot,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/headless-bookings",
3
- "version": "0.0.31",
3
+ "version": "0.0.33",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -72,5 +72,5 @@
72
72
  "groupId": "com.wixpress.headless-components"
73
73
  }
74
74
  },
75
- "falconPackageHash": "7f0622f4f250d712f40cd5c74b49c920e2e55e5b19b7e1a86f572158"
75
+ "falconPackageHash": "b5f66fe6afde6dde21cff958f2df9ecaa8bb6890eed0ee093057887e"
76
76
  }