@wix/headless-bookings 0.0.20 → 0.0.21

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.
@@ -5,6 +5,7 @@
5
5
  import { listAvailabilityTimeSlots, } from '@wix/auto_sdk_bookings_availability-time-slots';
6
6
  import { listEventTimeSlots } from '@wix/auto_sdk_bookings_event-time-slots';
7
7
  import { ServiceType } from '@wix/auto_sdk_bookings_services';
8
+ import { ANY_STAFF_MEMBER_ID } from '../../services/booking/booking.js';
8
9
  import { ViewMode, } from '../../services/time-slot-list/time-slot-list.def.js';
9
10
  // ============================================================================
10
11
  // Internal Types
@@ -107,7 +108,8 @@ export async function fetchAvailability({ services: selectedServices, viewMode =
107
108
  const flow = detectFlow(selectedServices, viewMode);
108
109
  const serviceIds = selectedServices.map((s) => s._id);
109
110
  if (flow === FlowType.SINGLE_SERVICE) {
110
- const resourceTypes = staffMemberIds?.length
111
+ const isAnyStaffMemberSelected = staffMemberIds?.length === 1 && staffMemberIds[0] === ANY_STAFF_MEMBER_ID;
112
+ const resourceTypes = staffMemberIds?.length && !isAnyStaffMemberSelected
111
113
  ? [
112
114
  {
113
115
  resourceTypeId: STAFF_RESOURCE_TYPE_ID,
@@ -128,7 +130,9 @@ export async function fetchAvailability({ services: selectedServices, viewMode =
128
130
  resourceTypes,
129
131
  bookable,
130
132
  bookingPolicyViolations,
131
- includeResourceTypeIds: [STAFF_RESOURCE_TYPE_ID],
133
+ includeResourceTypeIds: isAnyStaffMemberSelected
134
+ ? undefined
135
+ : [STAFF_RESOURCE_TYPE_ID],
132
136
  });
133
137
  return {
134
138
  timeSlots: groupTimeSlotsByTime(response.timeSlots || []),
@@ -5,7 +5,7 @@
5
5
  * @module API
6
6
  */
7
7
  export { getServiceById, getServiceBySlug, queryServices, type PagingMetadata, type ServiceListFilters, type QueryServicesRequest, } from './query-services/index.js';
8
- export { fetchAvailability } from './time-slot-list/index.js';
8
+ export { fetchAvailability } from './fetch-availability/index.js';
9
9
  /**
10
10
  * PagingMetadata includes:
11
11
  * - limit: Number of items per page
@@ -5,7 +5,7 @@
5
5
  * @module API
6
6
  */
7
7
  export { getServiceById, getServiceBySlug, queryServices, } from './query-services/index.js';
8
- export { fetchAvailability } from './time-slot-list/index.js';
8
+ export { fetchAvailability } from './fetch-availability/index.js';
9
9
  /**
10
10
  * PagingMetadata includes:
11
11
  * - limit: Number of items per page
@@ -9,6 +9,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
9
9
  import React from 'react';
10
10
  import { useService } from '@wix/services-manager-react';
11
11
  import { TimeSlotListServiceDefinition, } from '../../../services/time-slot-list/time-slot-list.def.js';
12
+ import { ANY_STAFF_MEMBER_ID } from '../../../services/booking/booking.js';
12
13
  const TimeSlotContext = React.createContext(null);
13
14
  /**
14
15
  * Hook to access TimeSlot context
@@ -202,12 +203,13 @@ export function Locations(props) {
202
203
  const selection = service.selection.get();
203
204
  const selectedLocationId = selection?.locationId ?? null;
204
205
  const selectedStaffMemberId = selection?.staffMemberId ?? null;
206
+ const isAnyStaffMemberSelected = selectedStaffMemberId === ANY_STAFF_MEMBER_ID;
205
207
  // Build locations array from staffByLocation (names already included)
206
208
  const locations = timeSlot.staffByLocation.map(({ location, staffMembers }) => {
207
209
  // Check if this location is selectable based on selected staff
208
210
  // If no staff selected, all locations are selectable
209
211
  // If staff selected, only locations where that staff works are selectable
210
- const isSelectable = selectedStaffMemberId
212
+ const isSelectable = !isAnyStaffMemberSelected && selectedStaffMemberId
211
213
  ? staffMembers.some((s) => s.id === selectedStaffMemberId)
212
214
  : true;
213
215
  return {
@@ -311,12 +313,18 @@ export function StaffMembers(props) {
311
313
  isSelectable: !selectedLocationId ||
312
314
  entries.some((e) => e.locationId === selectedLocationId),
313
315
  }));
316
+ const anyStaffOption = {
317
+ id: ANY_STAFF_MEMBER_ID,
318
+ name: 'Any staff member',
319
+ isSelected: selectedStaffMemberId === ANY_STAFF_MEMBER_ID,
320
+ isSelectable: true,
321
+ };
314
322
  // Return null if only 1 staff member - nothing to choose from
315
323
  if (staffMembers.length <= 1) {
316
324
  return null;
317
325
  }
318
326
  return props.children({
319
- staffMembers,
327
+ staffMembers: [anyStaffOption, ...staffMembers],
320
328
  selectStaffMember: service.actions.selectStaffMember,
321
329
  });
322
330
  }
@@ -7,6 +7,7 @@ import { type Signal } from '@wix/services-definitions/core-services/signals';
7
7
  import type { Service } from '@wix/auto_sdk_bookings_services';
8
8
  import type { Resource, EventInfo } from '@wix/auto_sdk_bookings_availability-time-slots';
9
9
  import type { FormValues } from '@wix/form-public';
10
+ export declare const ANY_STAFF_MEMBER_ID = "__any_staff_member__";
10
11
  /**
11
12
  * Minimal time slot data for service selections
12
13
  */
@@ -6,6 +6,10 @@
6
6
  import { defineService, implementService } from '@wix/services-definitions';
7
7
  import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
8
8
  // ============================================================================
9
+ // Constants
10
+ // ============================================================================
11
+ export const ANY_STAFF_MEMBER_ID = '__any_staff_member__';
12
+ // ============================================================================
9
13
  // Types
10
14
  // ============================================================================
11
15
  /**
@@ -6,8 +6,8 @@ import { implementService } from '@wix/services-definitions';
6
6
  import { SignalsServiceDefinition } from '@wix/services-definitions/core-services/signals';
7
7
  import { format } from 'date-fns';
8
8
  import { TimeSlotListServiceDefinition, ViewMode, } from './time-slot-list.def.js';
9
- import { fetchAvailability } from '../../api/time-slot-list/index.js';
10
- import { BookingServiceDefinition, } from '../booking/booking.js';
9
+ import { fetchAvailability } from '../../api/fetch-availability/index.js';
10
+ import { BookingServiceDefinition, ANY_STAFF_MEMBER_ID, } from '../booking/booking.js';
11
11
  // ============================================================================
12
12
  // Helpers
13
13
  // ============================================================================
@@ -84,8 +84,8 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
84
84
  const getFilters = () => {
85
85
  // Get BookingService selections (these take priority)
86
86
  const location = bookingService.location.get();
87
- const selections = bookingService.serviceSelections.get();
88
- const selectedStaffMemberIds = selections
87
+ const serviceSelections = bookingService.serviceSelections.get();
88
+ const selectedStaffMemberIds = serviceSelections
89
89
  .map(({ resources }) => resources.map((r) => r._id))
90
90
  .flat();
91
91
  const selectedLocation = location ? { _id: location.id } : null;
@@ -243,6 +243,18 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
243
243
  const currentSelections = selectionSignal.get();
244
244
  if (!currentSelections?.slot)
245
245
  return;
246
+ if (staffMemberId === ANY_STAFF_MEMBER_ID) {
247
+ bookingService.actions.updateItem({
248
+ resources: [
249
+ {
250
+ _id: ANY_STAFF_MEMBER_ID,
251
+ name: 'Any staff member',
252
+ },
253
+ ],
254
+ });
255
+ selectionSignal.set({ ...currentSelections, staffMemberId });
256
+ return;
257
+ }
246
258
  const slot = currentSelections.slot;
247
259
  // Find all locations that have this staff member
248
260
  const locationsWithThisStaff = slot.staffByLocation.filter((loc) => loc.staffMembers.some((s) => s.id === staffMemberId));
@@ -5,6 +5,7 @@
5
5
  import { listAvailabilityTimeSlots, } from '@wix/auto_sdk_bookings_availability-time-slots';
6
6
  import { listEventTimeSlots } from '@wix/auto_sdk_bookings_event-time-slots';
7
7
  import { ServiceType } from '@wix/auto_sdk_bookings_services';
8
+ import { ANY_STAFF_MEMBER_ID } from '../../services/booking/booking.js';
8
9
  import { ViewMode, } from '../../services/time-slot-list/time-slot-list.def.js';
9
10
  // ============================================================================
10
11
  // Internal Types
@@ -107,7 +108,8 @@ export async function fetchAvailability({ services: selectedServices, viewMode =
107
108
  const flow = detectFlow(selectedServices, viewMode);
108
109
  const serviceIds = selectedServices.map((s) => s._id);
109
110
  if (flow === FlowType.SINGLE_SERVICE) {
110
- const resourceTypes = staffMemberIds?.length
111
+ const isAnyStaffMemberSelected = staffMemberIds?.length === 1 && staffMemberIds[0] === ANY_STAFF_MEMBER_ID;
112
+ const resourceTypes = staffMemberIds?.length && !isAnyStaffMemberSelected
111
113
  ? [
112
114
  {
113
115
  resourceTypeId: STAFF_RESOURCE_TYPE_ID,
@@ -128,7 +130,9 @@ export async function fetchAvailability({ services: selectedServices, viewMode =
128
130
  resourceTypes,
129
131
  bookable,
130
132
  bookingPolicyViolations,
131
- includeResourceTypeIds: [STAFF_RESOURCE_TYPE_ID],
133
+ includeResourceTypeIds: isAnyStaffMemberSelected
134
+ ? undefined
135
+ : [STAFF_RESOURCE_TYPE_ID],
132
136
  });
133
137
  return {
134
138
  timeSlots: groupTimeSlotsByTime(response.timeSlots || []),
@@ -5,7 +5,7 @@
5
5
  * @module API
6
6
  */
7
7
  export { getServiceById, getServiceBySlug, queryServices, type PagingMetadata, type ServiceListFilters, type QueryServicesRequest, } from './query-services/index.js';
8
- export { fetchAvailability } from './time-slot-list/index.js';
8
+ export { fetchAvailability } from './fetch-availability/index.js';
9
9
  /**
10
10
  * PagingMetadata includes:
11
11
  * - limit: Number of items per page
package/dist/api/index.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * @module API
6
6
  */
7
7
  export { getServiceById, getServiceBySlug, queryServices, } from './query-services/index.js';
8
- export { fetchAvailability } from './time-slot-list/index.js';
8
+ export { fetchAvailability } from './fetch-availability/index.js';
9
9
  /**
10
10
  * PagingMetadata includes:
11
11
  * - limit: Number of items per page
@@ -9,6 +9,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
9
9
  import React from 'react';
10
10
  import { useService } from '@wix/services-manager-react';
11
11
  import { TimeSlotListServiceDefinition, } from '../../../services/time-slot-list/time-slot-list.def.js';
12
+ import { ANY_STAFF_MEMBER_ID } from '../../../services/booking/booking.js';
12
13
  const TimeSlotContext = React.createContext(null);
13
14
  /**
14
15
  * Hook to access TimeSlot context
@@ -202,12 +203,13 @@ export function Locations(props) {
202
203
  const selection = service.selection.get();
203
204
  const selectedLocationId = selection?.locationId ?? null;
204
205
  const selectedStaffMemberId = selection?.staffMemberId ?? null;
206
+ const isAnyStaffMemberSelected = selectedStaffMemberId === ANY_STAFF_MEMBER_ID;
205
207
  // Build locations array from staffByLocation (names already included)
206
208
  const locations = timeSlot.staffByLocation.map(({ location, staffMembers }) => {
207
209
  // Check if this location is selectable based on selected staff
208
210
  // If no staff selected, all locations are selectable
209
211
  // If staff selected, only locations where that staff works are selectable
210
- const isSelectable = selectedStaffMemberId
212
+ const isSelectable = !isAnyStaffMemberSelected && selectedStaffMemberId
211
213
  ? staffMembers.some((s) => s.id === selectedStaffMemberId)
212
214
  : true;
213
215
  return {
@@ -311,12 +313,18 @@ export function StaffMembers(props) {
311
313
  isSelectable: !selectedLocationId ||
312
314
  entries.some((e) => e.locationId === selectedLocationId),
313
315
  }));
316
+ const anyStaffOption = {
317
+ id: ANY_STAFF_MEMBER_ID,
318
+ name: 'Any staff member',
319
+ isSelected: selectedStaffMemberId === ANY_STAFF_MEMBER_ID,
320
+ isSelectable: true,
321
+ };
314
322
  // Return null if only 1 staff member - nothing to choose from
315
323
  if (staffMembers.length <= 1) {
316
324
  return null;
317
325
  }
318
326
  return props.children({
319
- staffMembers,
327
+ staffMembers: [anyStaffOption, ...staffMembers],
320
328
  selectStaffMember: service.actions.selectStaffMember,
321
329
  });
322
330
  }
@@ -7,6 +7,7 @@ import { type Signal } from '@wix/services-definitions/core-services/signals';
7
7
  import type { Service } from '@wix/auto_sdk_bookings_services';
8
8
  import type { Resource, EventInfo } from '@wix/auto_sdk_bookings_availability-time-slots';
9
9
  import type { FormValues } from '@wix/form-public';
10
+ export declare const ANY_STAFF_MEMBER_ID = "__any_staff_member__";
10
11
  /**
11
12
  * Minimal time slot data for service selections
12
13
  */
@@ -6,6 +6,10 @@
6
6
  import { defineService, implementService } from '@wix/services-definitions';
7
7
  import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
8
8
  // ============================================================================
9
+ // Constants
10
+ // ============================================================================
11
+ export const ANY_STAFF_MEMBER_ID = '__any_staff_member__';
12
+ // ============================================================================
9
13
  // Types
10
14
  // ============================================================================
11
15
  /**
@@ -6,8 +6,8 @@ import { implementService } from '@wix/services-definitions';
6
6
  import { SignalsServiceDefinition } from '@wix/services-definitions/core-services/signals';
7
7
  import { format } from 'date-fns';
8
8
  import { TimeSlotListServiceDefinition, ViewMode, } from './time-slot-list.def.js';
9
- import { fetchAvailability } from '../../api/time-slot-list/index.js';
10
- import { BookingServiceDefinition, } from '../booking/booking.js';
9
+ import { fetchAvailability } from '../../api/fetch-availability/index.js';
10
+ import { BookingServiceDefinition, ANY_STAFF_MEMBER_ID, } from '../booking/booking.js';
11
11
  // ============================================================================
12
12
  // Helpers
13
13
  // ============================================================================
@@ -84,8 +84,8 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
84
84
  const getFilters = () => {
85
85
  // Get BookingService selections (these take priority)
86
86
  const location = bookingService.location.get();
87
- const selections = bookingService.serviceSelections.get();
88
- const selectedStaffMemberIds = selections
87
+ const serviceSelections = bookingService.serviceSelections.get();
88
+ const selectedStaffMemberIds = serviceSelections
89
89
  .map(({ resources }) => resources.map((r) => r._id))
90
90
  .flat();
91
91
  const selectedLocation = location ? { _id: location.id } : null;
@@ -243,6 +243,18 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
243
243
  const currentSelections = selectionSignal.get();
244
244
  if (!currentSelections?.slot)
245
245
  return;
246
+ if (staffMemberId === ANY_STAFF_MEMBER_ID) {
247
+ bookingService.actions.updateItem({
248
+ resources: [
249
+ {
250
+ _id: ANY_STAFF_MEMBER_ID,
251
+ name: 'Any staff member',
252
+ },
253
+ ],
254
+ });
255
+ selectionSignal.set({ ...currentSelections, staffMemberId });
256
+ return;
257
+ }
246
258
  const slot = currentSelections.slot;
247
259
  // Find all locations that have this staff member
248
260
  const locationsWithThisStaff = slot.staffByLocation.filter((loc) => loc.staffMembers.some((s) => s.id === staffMemberId));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/headless-bookings",
3
- "version": "0.0.20",
3
+ "version": "0.0.21",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -70,5 +70,5 @@
70
70
  "groupId": "com.wixpress.headless-components"
71
71
  }
72
72
  },
73
- "falconPackageHash": "25ba2b137a6e9ae4a9d267c7eeede1474665fe843f2999d663f593e4"
73
+ "falconPackageHash": "d2842c53f889bbbdfd049c74e533eef301d158412ec519b08c80c87c"
74
74
  }