@wix/headless-bookings 0.0.72 → 0.0.73

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.
@@ -13,7 +13,12 @@ export function mockSignal(initialValue) {
13
13
  export function createMockSignalsService() {
14
14
  return {
15
15
  signal: mockSignal,
16
- computed: (fn) => mockSignal(fn()),
16
+ // Re-evaluate the computed function on every get/peek (like real computed signals)
17
+ computed: (fn) => ({
18
+ get: () => fn(),
19
+ peek: () => fn(),
20
+ set: () => { }, // no-op for computed
21
+ }),
17
22
  effect: vi.fn((fn) => {
18
23
  fn();
19
24
  }),
@@ -52,7 +52,7 @@ function buildDisplayLocations(locations, hasCustomLocations, hasCustomerLocatio
52
52
  else if (hasCustomLocations) {
53
53
  // Synthetic custom location (only from explicit flag, not array)
54
54
  displayLocations.push({
55
- location: null,
55
+ location: { _id: SYNTHETIC_CUSTOM_ID, type: LocationType.CUSTOM },
56
56
  type: LocationType.CUSTOM,
57
57
  isSynthetic: true,
58
58
  id: SYNTHETIC_CUSTOM_ID,
@@ -60,10 +60,13 @@ function buildDisplayLocations(locations, hasCustomLocations, hasCustomerLocatio
60
60
  }
61
61
  // 3. Add CUSTOMER location (always synthetic display, real or flag-based)
62
62
  if (customerFromArray || hasCustomerLocations) {
63
+ const isSynthetic = !customerFromArray;
63
64
  displayLocations.push({
64
- location: customerFromArray || null,
65
+ location: isSynthetic
66
+ ? { _id: SYNTHETIC_CUSTOMER_ID, type: LocationType.CUSTOMER }
67
+ : customerFromArray,
65
68
  type: LocationType.CUSTOMER,
66
- isSynthetic: !customerFromArray,
69
+ isSynthetic,
67
70
  id: SYNTHETIC_CUSTOMER_ID,
68
71
  });
69
72
  }
@@ -149,7 +149,7 @@ export const ServiceListService = implementService.withConfig()(ServiceListServi
149
149
  // Helper to get effective filters including location from BookingService
150
150
  const getEffectiveFilters = (baseFilters) => {
151
151
  const selectedLocation = bookingService.location.get();
152
- const locationId = selectedLocation?.business?._id;
152
+ const locationId = selectedLocation?._id;
153
153
  if (!baseFilters && !locationId) {
154
154
  return undefined;
155
155
  }
@@ -10,7 +10,7 @@ import type { Service } from '@wix/auto_sdk_bookings_services';
10
10
  * Require a stable `id` + `locationType` pair (no optional fields).
11
11
  */
12
12
  export interface Location {
13
- id: string;
13
+ id?: string;
14
14
  locationType: LocationTypeWithLiterals;
15
15
  }
16
16
  export declare enum ViewMode {
@@ -3,18 +3,26 @@
3
3
  * Manages time slot fetching, selection, and state
4
4
  */
5
5
  import { implementService } from '@wix/services-definitions';
6
- import { SignalsServiceDefinition } from '@wix/services-definitions/core-services/signals';
6
+ import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
7
7
  import { TimeSlotListServiceDefinition, ViewMode, } from './time-slot-list.def.js';
8
+ import { LocationType, } from '@wix/auto_sdk_bookings_event-time-slots';
8
9
  import { fetchAvailability } from '../../api/fetch-availability/index.js';
9
10
  import { BookingServiceDefinition, ANY_STAFF_MEMBER_ID, } from '../booking/booking.js';
10
11
  // ============================================================================
11
12
  // Helpers
12
13
  // ============================================================================
13
- function getClientTimezone() {
14
+ const getClientTimezone = () => {
14
15
  return typeof Intl !== 'undefined'
15
16
  ? Intl.DateTimeFormat().resolvedOptions().timeZone
16
17
  : undefined;
17
- }
18
+ };
19
+ const getStaffName = (staffMemberId, slots) => {
20
+ if (staffMemberId === ANY_STAFF_MEMBER_ID)
21
+ return 'Any staff member';
22
+ return (slots
23
+ .flatMap((slot) => slot.availableResources[0].resources)
24
+ .find((r) => r._id === staffMemberId)?.name ?? undefined);
25
+ };
18
26
  // ============================================================================
19
27
  // Service Implementation
20
28
  // ============================================================================
@@ -31,6 +39,12 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
31
39
  end: config.endDate,
32
40
  });
33
41
  const cursorSignal = signalsService.signal(undefined);
42
+ const preSelectedStaffMemberIdSignal = signalsService.computed(() => {
43
+ const serviceSelections = bookingService.serviceSelections.get();
44
+ return serviceSelections.length
45
+ ? (serviceSelections[0]?.resources?.[0]?._id ?? undefined)
46
+ : undefined;
47
+ });
34
48
  const getServices = () => {
35
49
  const serviceSelections = bookingService.serviceSelections.peek();
36
50
  return serviceSelections.length
@@ -40,12 +54,16 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
40
54
  const getFilters = () => {
41
55
  const baseFilters = config.filters ?? {};
42
56
  const selectedLocation = bookingService.location.peek();
57
+ const isCustomOrCustomerLocation = selectedLocation?.type === LocationType.CUSTOM ||
58
+ selectedLocation?.type === LocationType.CUSTOMER;
43
59
  const location = selectedLocation
44
- ? { id: selectedLocation._id, locationType: selectedLocation.type }
60
+ ? {
61
+ id: isCustomOrCustomerLocation ? undefined : selectedLocation._id,
62
+ locationType: selectedLocation.type,
63
+ }
45
64
  : baseFilters.location;
46
- const selectedResources = bookingService.serviceSelections.peek()[0]?.resources ?? [];
47
- const staffMemberIds = selectedResources.length
48
- ? selectedResources.map((r) => r._id)
65
+ const staffMemberIds = preSelectedStaffMemberIdSignal.peek()
66
+ ? [preSelectedStaffMemberIdSignal.peek()]
49
67
  : baseFilters.staffMemberIds;
50
68
  return { ...baseFilters, location, staffMemberIds };
51
69
  };
@@ -85,11 +103,14 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
85
103
  * - Auto-selects staff only when there is exactly one staff option in this slot
86
104
  */
87
105
  const selectSlot = (slot) => {
88
- const staffMembersFromSlot = slot.availableResources[0].resources.map((r) => ({
89
- _id: r._id,
90
- name: r.name,
91
- }));
92
- const resources = staffMembersFromSlot.length === 1 ? staffMembersFromSlot : [];
106
+ const resources = preSelectedStaffMemberIdSignal.peek()
107
+ ? [
108
+ {
109
+ _id: preSelectedStaffMemberIdSignal.peek(),
110
+ name: getStaffName(preSelectedStaffMemberIdSignal.peek(), timeSlotsSignal.peek()),
111
+ },
112
+ ]
113
+ : [];
93
114
  const timeSlot = {
94
115
  startDate: slot.localStartDate,
95
116
  endDate: slot.localEndDate,
@@ -112,18 +133,10 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
112
133
  const selectedTimeSlot = bookingService.serviceSelections.peek()[0]?.timeSlot;
113
134
  if (!selectedTimeSlot)
114
135
  return;
115
- const getStaffName = (id) => {
116
- if (id === ANY_STAFF_MEMBER_ID)
117
- return 'Any staff member';
118
- const slots = timeSlotsSignal.peek();
119
- return (slots
120
- .flatMap((slot) => slot.availableResources[0].resources)
121
- .find((r) => r._id === id)?.name ?? undefined);
122
- };
123
136
  const resources = [
124
137
  {
125
138
  _id: staffMemberId,
126
- name: getStaffName(staffMemberId),
139
+ name: getStaffName(staffMemberId, timeSlotsSignal.peek()),
127
140
  },
128
141
  ];
129
142
  bookingService.actions.updateItem({
@@ -191,18 +204,12 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
191
204
  }
192
205
  dateRangeSignal.set({ start: newStartDate, end: newEndDate });
193
206
  };
194
- const preSelectedStaffMemberId = signalsService.computed(() => {
195
- const serviceSelections = bookingService.serviceSelections.get();
196
- return serviceSelections.length
197
- ? (serviceSelections[0]?.resources?.[0]?._id ?? undefined)
198
- : undefined;
199
- });
200
207
  let isFirstRun = true;
201
208
  const dispose = signalsService.effect(() => {
202
209
  dateRangeSignal.get();
203
210
  bookingService.timezone.get();
204
211
  bookingService.location.get();
205
- preSelectedStaffMemberId.get();
212
+ preSelectedStaffMemberIdSignal.get();
206
213
  if (isFirstRun) {
207
214
  isFirstRun = false;
208
215
  if (config.timeSlots) {
@@ -13,7 +13,12 @@ export function mockSignal(initialValue) {
13
13
  export function createMockSignalsService() {
14
14
  return {
15
15
  signal: mockSignal,
16
- computed: (fn) => mockSignal(fn()),
16
+ // Re-evaluate the computed function on every get/peek (like real computed signals)
17
+ computed: (fn) => ({
18
+ get: () => fn(),
19
+ peek: () => fn(),
20
+ set: () => { }, // no-op for computed
21
+ }),
17
22
  effect: vi.fn((fn) => {
18
23
  fn();
19
24
  }),
@@ -52,7 +52,7 @@ function buildDisplayLocations(locations, hasCustomLocations, hasCustomerLocatio
52
52
  else if (hasCustomLocations) {
53
53
  // Synthetic custom location (only from explicit flag, not array)
54
54
  displayLocations.push({
55
- location: null,
55
+ location: { _id: SYNTHETIC_CUSTOM_ID, type: LocationType.CUSTOM },
56
56
  type: LocationType.CUSTOM,
57
57
  isSynthetic: true,
58
58
  id: SYNTHETIC_CUSTOM_ID,
@@ -60,10 +60,13 @@ function buildDisplayLocations(locations, hasCustomLocations, hasCustomerLocatio
60
60
  }
61
61
  // 3. Add CUSTOMER location (always synthetic display, real or flag-based)
62
62
  if (customerFromArray || hasCustomerLocations) {
63
+ const isSynthetic = !customerFromArray;
63
64
  displayLocations.push({
64
- location: customerFromArray || null,
65
+ location: isSynthetic
66
+ ? { _id: SYNTHETIC_CUSTOMER_ID, type: LocationType.CUSTOMER }
67
+ : customerFromArray,
65
68
  type: LocationType.CUSTOMER,
66
- isSynthetic: !customerFromArray,
69
+ isSynthetic,
67
70
  id: SYNTHETIC_CUSTOMER_ID,
68
71
  });
69
72
  }
@@ -149,7 +149,7 @@ export const ServiceListService = implementService.withConfig()(ServiceListServi
149
149
  // Helper to get effective filters including location from BookingService
150
150
  const getEffectiveFilters = (baseFilters) => {
151
151
  const selectedLocation = bookingService.location.get();
152
- const locationId = selectedLocation?.business?._id;
152
+ const locationId = selectedLocation?._id;
153
153
  if (!baseFilters && !locationId) {
154
154
  return undefined;
155
155
  }
@@ -10,7 +10,7 @@ import type { Service } from '@wix/auto_sdk_bookings_services';
10
10
  * Require a stable `id` + `locationType` pair (no optional fields).
11
11
  */
12
12
  export interface Location {
13
- id: string;
13
+ id?: string;
14
14
  locationType: LocationTypeWithLiterals;
15
15
  }
16
16
  export declare enum ViewMode {
@@ -3,18 +3,26 @@
3
3
  * Manages time slot fetching, selection, and state
4
4
  */
5
5
  import { implementService } from '@wix/services-definitions';
6
- import { SignalsServiceDefinition } from '@wix/services-definitions/core-services/signals';
6
+ import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
7
7
  import { TimeSlotListServiceDefinition, ViewMode, } from './time-slot-list.def.js';
8
+ import { LocationType, } from '@wix/auto_sdk_bookings_event-time-slots';
8
9
  import { fetchAvailability } from '../../api/fetch-availability/index.js';
9
10
  import { BookingServiceDefinition, ANY_STAFF_MEMBER_ID, } from '../booking/booking.js';
10
11
  // ============================================================================
11
12
  // Helpers
12
13
  // ============================================================================
13
- function getClientTimezone() {
14
+ const getClientTimezone = () => {
14
15
  return typeof Intl !== 'undefined'
15
16
  ? Intl.DateTimeFormat().resolvedOptions().timeZone
16
17
  : undefined;
17
- }
18
+ };
19
+ const getStaffName = (staffMemberId, slots) => {
20
+ if (staffMemberId === ANY_STAFF_MEMBER_ID)
21
+ return 'Any staff member';
22
+ return (slots
23
+ .flatMap((slot) => slot.availableResources[0].resources)
24
+ .find((r) => r._id === staffMemberId)?.name ?? undefined);
25
+ };
18
26
  // ============================================================================
19
27
  // Service Implementation
20
28
  // ============================================================================
@@ -31,6 +39,12 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
31
39
  end: config.endDate,
32
40
  });
33
41
  const cursorSignal = signalsService.signal(undefined);
42
+ const preSelectedStaffMemberIdSignal = signalsService.computed(() => {
43
+ const serviceSelections = bookingService.serviceSelections.get();
44
+ return serviceSelections.length
45
+ ? (serviceSelections[0]?.resources?.[0]?._id ?? undefined)
46
+ : undefined;
47
+ });
34
48
  const getServices = () => {
35
49
  const serviceSelections = bookingService.serviceSelections.peek();
36
50
  return serviceSelections.length
@@ -40,12 +54,16 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
40
54
  const getFilters = () => {
41
55
  const baseFilters = config.filters ?? {};
42
56
  const selectedLocation = bookingService.location.peek();
57
+ const isCustomOrCustomerLocation = selectedLocation?.type === LocationType.CUSTOM ||
58
+ selectedLocation?.type === LocationType.CUSTOMER;
43
59
  const location = selectedLocation
44
- ? { id: selectedLocation._id, locationType: selectedLocation.type }
60
+ ? {
61
+ id: isCustomOrCustomerLocation ? undefined : selectedLocation._id,
62
+ locationType: selectedLocation.type,
63
+ }
45
64
  : baseFilters.location;
46
- const selectedResources = bookingService.serviceSelections.peek()[0]?.resources ?? [];
47
- const staffMemberIds = selectedResources.length
48
- ? selectedResources.map((r) => r._id)
65
+ const staffMemberIds = preSelectedStaffMemberIdSignal.peek()
66
+ ? [preSelectedStaffMemberIdSignal.peek()]
49
67
  : baseFilters.staffMemberIds;
50
68
  return { ...baseFilters, location, staffMemberIds };
51
69
  };
@@ -85,11 +103,14 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
85
103
  * - Auto-selects staff only when there is exactly one staff option in this slot
86
104
  */
87
105
  const selectSlot = (slot) => {
88
- const staffMembersFromSlot = slot.availableResources[0].resources.map((r) => ({
89
- _id: r._id,
90
- name: r.name,
91
- }));
92
- const resources = staffMembersFromSlot.length === 1 ? staffMembersFromSlot : [];
106
+ const resources = preSelectedStaffMemberIdSignal.peek()
107
+ ? [
108
+ {
109
+ _id: preSelectedStaffMemberIdSignal.peek(),
110
+ name: getStaffName(preSelectedStaffMemberIdSignal.peek(), timeSlotsSignal.peek()),
111
+ },
112
+ ]
113
+ : [];
93
114
  const timeSlot = {
94
115
  startDate: slot.localStartDate,
95
116
  endDate: slot.localEndDate,
@@ -112,18 +133,10 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
112
133
  const selectedTimeSlot = bookingService.serviceSelections.peek()[0]?.timeSlot;
113
134
  if (!selectedTimeSlot)
114
135
  return;
115
- const getStaffName = (id) => {
116
- if (id === ANY_STAFF_MEMBER_ID)
117
- return 'Any staff member';
118
- const slots = timeSlotsSignal.peek();
119
- return (slots
120
- .flatMap((slot) => slot.availableResources[0].resources)
121
- .find((r) => r._id === id)?.name ?? undefined);
122
- };
123
136
  const resources = [
124
137
  {
125
138
  _id: staffMemberId,
126
- name: getStaffName(staffMemberId),
139
+ name: getStaffName(staffMemberId, timeSlotsSignal.peek()),
127
140
  },
128
141
  ];
129
142
  bookingService.actions.updateItem({
@@ -191,18 +204,12 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
191
204
  }
192
205
  dateRangeSignal.set({ start: newStartDate, end: newEndDate });
193
206
  };
194
- const preSelectedStaffMemberId = signalsService.computed(() => {
195
- const serviceSelections = bookingService.serviceSelections.get();
196
- return serviceSelections.length
197
- ? (serviceSelections[0]?.resources?.[0]?._id ?? undefined)
198
- : undefined;
199
- });
200
207
  let isFirstRun = true;
201
208
  const dispose = signalsService.effect(() => {
202
209
  dateRangeSignal.get();
203
210
  bookingService.timezone.get();
204
211
  bookingService.location.get();
205
- preSelectedStaffMemberId.get();
212
+ preSelectedStaffMemberIdSignal.get();
206
213
  if (isFirstRun) {
207
214
  isFirstRun = false;
208
215
  if (config.timeSlots) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/headless-bookings",
3
- "version": "0.0.72",
3
+ "version": "0.0.73",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "scripts": {
@@ -72,5 +72,5 @@
72
72
  "groupId": "com.wixpress.headless-components"
73
73
  }
74
74
  },
75
- "falconPackageHash": "fba67207f62950f205edc9cf8dd4f0cd00a1aba8aba35b2ba034c3f2"
75
+ "falconPackageHash": "34417118571f5f9e720d6fd388d06f0244497d6ec0184bca137822c9"
76
76
  }