@wix/headless-bookings 0.0.58 → 0.0.60

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.
@@ -1,6 +1,5 @@
1
- import type { Resource } from '@wix/auto_sdk_bookings_availability-time-slots';
2
1
  import type { FormValues } from '@wix/form-public';
3
- import type { ServiceSelection, ServiceSelectionTimeSlot, BookingServiceConfig, BookingService } from '../services/booking/booking.js';
2
+ import type { ServiceSelection, ServiceSelectionTimeSlot, BookingServiceConfig, BookingService, ExtendedResource } from '../services/booking/booking.js';
4
3
  import type { Signal } from '@wix/services-definitions/core-services/signals';
5
4
  export declare function mockSignal<T>(initialValue: T): Signal<T>;
6
5
  export declare function createMockSignalsService(): {
@@ -12,15 +11,15 @@ export declare function createMockBookingService(initialSelections?: ServiceSele
12
11
  /**
13
12
  * Mock resource (staff member)
14
13
  */
15
- export declare const mockResource: Resource;
14
+ export declare const mockResource: ExtendedResource;
16
15
  /**
17
16
  * Mock resource (another staff member)
18
17
  */
19
- export declare const mockResourceTwo: Resource;
18
+ export declare const mockResourceTwo: ExtendedResource;
20
19
  /**
21
20
  * Mock resource (room)
22
21
  */
23
- export declare const mockResourceRoom: Resource;
22
+ export declare const mockResourceRoom: ExtendedResource;
24
23
  /**
25
24
  * Mock location
26
25
  */
@@ -35,9 +35,9 @@ export function createMockBookingService(initialSelections = []) {
35
35
  addItem: vi.fn(),
36
36
  removeItem: vi.fn(),
37
37
  clearItems: vi.fn(),
38
- setResourceById: vi.fn(),
39
- getResourceById: vi.fn(),
40
- clearResourceById: vi.fn(),
38
+ setResource: vi.fn(),
39
+ getResourceByType: vi.fn(),
40
+ clearResourceByType: vi.fn(),
41
41
  setLocation: vi.fn(),
42
42
  clearLocation: vi.fn(),
43
43
  setTimezone: vi.fn(),
@@ -56,6 +56,7 @@ export const mockResource = {
56
56
  name: 'John Doe',
57
57
  email: 'john.doe@example.com',
58
58
  tag: 'STAFF',
59
+ type: 'staff',
59
60
  };
60
61
  /**
61
62
  * Mock resource (another staff member)
@@ -65,6 +66,7 @@ export const mockResourceTwo = {
65
66
  name: 'Jane Smith',
66
67
  email: 'jane.smith@example.com',
67
68
  tag: 'STAFF',
69
+ type: 'staff',
68
70
  };
69
71
  /**
70
72
  * Mock resource (room)
@@ -73,6 +75,7 @@ export const mockResourceRoom = {
73
75
  _id: 'resource-room-1',
74
76
  name: 'Conference Room A',
75
77
  tag: 'RESOURCE',
78
+ type: 'room',
76
79
  };
77
80
  /**
78
81
  * Mock location
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import React from 'react';
6
6
  import { type ServiceServiceConfig } from '../../../services/service/service.js';
7
- import type { Service, Payment, BookingPolicy, Schedule } from '@wix/auto_sdk_bookings_services';
7
+ import type { Service, Payment, BookingPolicy, Schedule, StaffMember } from '@wix/auto_sdk_bookings_services';
8
8
  import type { MoneyData } from '@wix/headless-components/react';
9
9
  /**
10
10
  * Props for Service.Root component
@@ -56,10 +56,7 @@ export interface InfoProps {
56
56
  _id?: string;
57
57
  };
58
58
  locations?: Array<NonNullable<Service['locations']>[number]>;
59
- staff?: Array<{
60
- name?: string;
61
- _id?: string;
62
- }>;
59
+ staff?: StaffMember[];
63
60
  media?: Array<{
64
61
  url?: string;
65
62
  _id?: string;
@@ -92,10 +92,7 @@ export function Info(props) {
92
92
  const duration = service.schedule?.availabilityConstraints?.sessionDurations?.[0];
93
93
  // Get staff members from staffMemberDetails.staffMembers
94
94
  // (available when using conditionalFields: ['STAFF_MEMBER_DETAILS'] in queryServices)
95
- const staff = service.staffMembers?.map((member) => ({
96
- _id: member.staffMemberId,
97
- name: member.name || undefined,
98
- })) || [];
95
+ const staff = service.staffMembers || [];
99
96
  // Convert mainMedia to WixMediaImage format
100
97
  // Handle both snake_case (main_media) and camelCase (mainMedia) from API
101
98
  // Handle both string and object formats for image
@@ -130,7 +130,8 @@ export function Actions(props) {
130
130
  if (!rawStaffMember?.staffMemberId || !bookingService)
131
131
  return;
132
132
  // Use resource type ID as the lookup key, staff member ID as the actual resource ID
133
- bookingService.actions.setResourceById(STAFF_MEMBER_RESOURCE_TYPE_ID, {
133
+ bookingService.actions.setResource({
134
+ type: STAFF_MEMBER_RESOURCE_TYPE_ID,
134
135
  _id: rawStaffMember.staffMemberId,
135
136
  name: rawStaffMember.name,
136
137
  });
@@ -9,13 +9,6 @@ import { GenericListRepeaterProps, type ListVariant } from '@wix/headless-compon
9
9
  import { type AsChildChildren } from '@wix/headless-utils/react';
10
10
  import type { StaffMemberListServiceConfig } from '../../services/staff-member-list/staff-member-list.js';
11
11
  import type { StaffMemberData } from '../../services/staff-member-list/staff-member-list.def.js';
12
- /**
13
- * Staff member with id for list rendering
14
- * Uses staffMemberId as the id (which equals resource id)
15
- */
16
- interface StaffMemberWithId extends StaffMemberData {
17
- id: string;
18
- }
19
12
  /**
20
13
  * Props for the StaffMemberList root component
21
14
  */
@@ -73,7 +66,7 @@ export declare const StaffMembers: React.ForwardRefExoticComponent<StaffMembersP
73
66
  /**
74
67
  * Props for StaffMemberList.StaffMemberRepeater component
75
68
  */
76
- export type StaffMemberRepeaterProps = GenericListRepeaterProps<StaffMemberWithId>;
69
+ export type StaffMemberRepeaterProps = GenericListRepeaterProps<StaffMemberData>;
77
70
  export declare const StaffMemberRepeater: React.ForwardRefExoticComponent<StaffMemberRepeaterProps & React.RefAttributes<HTMLElement>>;
78
71
  /**
79
72
  * Props for StaffMemberList.Totals component
@@ -120,4 +113,3 @@ export interface ClearProps {
120
113
  export declare const Actions: {
121
114
  Clear: React.ForwardRefExoticComponent<ClearProps & React.RefAttributes<HTMLButtonElement>>;
122
115
  };
123
- export {};
@@ -59,10 +59,9 @@ Root.displayName = 'StaffMemberList.Root';
59
59
  const RootContent = React.forwardRef((props, ref) => {
60
60
  const { children, className, variant } = props;
61
61
  return (_jsx(CoreStaffMemberList.StaffMembers, { children: ({ staffMembers, isLoading }) => {
62
- // Add id to each staff member for GenericList (staffMemberId equals resource id)
63
- const itemsWithId = staffMembers.map((staffMember, index) => ({
62
+ const itemsWithId = staffMembers.map((staffMember) => ({
64
63
  ...staffMember,
65
- id: staffMember.staffMemberId || String(index),
64
+ id: staffMember.staffMemberId,
66
65
  }));
67
66
  return (_jsx(GenericList.Root, { items: itemsWithId, hasMore: false, isLoading: isLoading, className: className, ref: ref, "data-testid": TestIds.staffMemberListRoot, variant: variant, children: children }));
68
67
  } }));
@@ -90,8 +89,8 @@ StaffMembers.displayName = 'StaffMemberList.StaffMembers';
90
89
  export const StaffMemberRepeater = React.forwardRef((props, ref) => {
91
90
  const { children } = props;
92
91
  // Custom itemWrapper that wraps each item in StaffMember.Root
93
- const staffMemberItemWrapper = ({ item: staffMemberWithId, children: itemChildren, }) => {
94
- return (_jsx(StaffMember.Root, { staffMember: staffMemberWithId, "data-testid": TestIds.staffMemberListStaffMember, "data-staff-member-id": staffMemberWithId.id, "data-item-id": staffMemberWithId.id, children: itemChildren }, staffMemberWithId.id));
92
+ const staffMemberItemWrapper = ({ item: staffMember, children: itemChildren, }) => {
93
+ return (_jsx(StaffMember.Root, { staffMember: staffMember, "data-testid": TestIds.staffMemberListStaffMember, "data-staff-member-id": staffMember.staffMemberId, "data-item-id": staffMember.staffMemberId, children: itemChildren }, staffMember.staffMemberId));
95
94
  };
96
95
  return (_jsx(GenericList.Repeater, { ref: ref, itemWrapper: staffMemberItemWrapper, children: children }));
97
96
  });
@@ -152,7 +151,7 @@ const Clear = React.forwardRef((props, ref) => {
152
151
  // BookingService not available - likely no ServiceManagerProvider
153
152
  }
154
153
  const handleClick = () => {
155
- bookingService?.actions.clearResourceById(STAFF_MEMBER_RESOURCE_TYPE_ID);
154
+ bookingService?.actions.clearResourceByType(STAFF_MEMBER_RESOURCE_TYPE_ID);
156
155
  onClicked?.();
157
156
  };
158
157
  return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.staffMemberListActionClear, customElement: children, customElementProps: {
@@ -9,6 +9,13 @@ import type { Resource, EventInfo, Location as TimeSlotLocationType } from '@wix
9
9
  import type { FormValues } from '@wix/form-public';
10
10
  import type { BookResult } from './book-action/types.js';
11
11
  export declare const ANY_STAFF_MEMBER_ID = "__any_staff_member__";
12
+ /**
13
+ * Extended Resource type with a type field for categorization
14
+ */
15
+ export interface ExtendedResource extends Resource {
16
+ /** Resource type identifier (e.g., 'staff', 'room', 'equipment') */
17
+ type: string;
18
+ }
12
19
  /**
13
20
  * Minimal time slot data for service selections
14
21
  */
@@ -32,8 +39,8 @@ export interface ServiceSelection {
32
39
  instanceId: string;
33
40
  /** The selected service */
34
41
  service: Service;
35
- /** Selected resources (staff members, rooms, etc.) */
36
- resources: Resource[];
42
+ /** Selected resources (staff members, rooms, etc.) with type information */
43
+ resources: ExtendedResource[];
37
44
  /** Per-item time slot data */
38
45
  timeSlot?: ServiceSelectionTimeSlot;
39
46
  /** Number of participants for this service selection */
@@ -53,12 +60,12 @@ export interface BookingServiceActions {
53
60
  removeItem(instanceId?: string): void;
54
61
  /** Clears all service selections */
55
62
  clearItems(): void;
56
- /** Sets a resource by ID within a service selection. If no instanceId provided, uses the first item. */
57
- setResourceById(resourceId: string, resource: Resource, instanceId?: string): void;
58
- /** Gets a resource by ID from a service selection. If no instanceId provided, uses the first item. */
59
- getResourceById(resourceId: string, instanceId?: string): Resource | undefined;
60
- /** Clears a resource by ID from a service selection. If no instanceId provided, uses the first item. */
61
- clearResourceById(resourceId: string, instanceId?: string): void;
63
+ /** Sets a resource by type within a service selection. If no instanceId provided, uses the first item. Only one resource per type is allowed. The resourceType parameter specifies which type to set. */
64
+ setResource(resource: ExtendedResource, instanceId?: string): void;
65
+ /** Gets a resource by type from a service selection. If no instanceId provided, uses the first item. */
66
+ getResourceByType(resourceType: string, instanceId?: string): Resource | undefined;
67
+ /** Clears a resource by type from a service selection. If no instanceId provided, uses the first item. */
68
+ clearResourceByType(resourceType: string, instanceId?: string): void;
62
69
  setLocation(location: ServiceLocationType | null): void;
63
70
  clearLocation(): void;
64
71
  setTimezone(timezone: string): void;
@@ -115,8 +115,7 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
115
115
  clearItems() {
116
116
  serviceSelectionsSignal.set([]);
117
117
  },
118
- // Resource helpers
119
- setResourceById(resourceId, resource, instanceId) {
118
+ setResource(resource, instanceId) {
120
119
  const current = serviceSelectionsSignal.get();
121
120
  // If no instanceId provided, use the first item
122
121
  const targetId = instanceId ?? current[0]?.instanceId;
@@ -125,20 +124,13 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
125
124
  const updated = current.map((item) => {
126
125
  if (item.instanceId !== targetId)
127
126
  return item;
128
- // Find and replace resource by ID, or add if not found
129
- const existingIndex = item.resources.findIndex((r) => r._id === resourceId);
130
- const newResources = [...item.resources];
131
- if (existingIndex >= 0) {
132
- newResources[existingIndex] = resource;
133
- }
134
- else {
135
- newResources.push(resource);
136
- }
127
+ const newResources = item.resources.filter((r) => r.type !== resource.type);
128
+ newResources.push(resource);
137
129
  return { ...item, resources: newResources };
138
130
  });
139
131
  serviceSelectionsSignal.set(updated);
140
132
  },
141
- getResourceById(resourceId, instanceId) {
133
+ getResourceByType(resourceType, instanceId) {
142
134
  const current = serviceSelectionsSignal.get();
143
135
  // If no instanceId provided, use the first item
144
136
  const targetId = instanceId ?? current[0]?.instanceId;
@@ -147,9 +139,9 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
147
139
  const targetItem = current.find((item) => item.instanceId === targetId);
148
140
  if (!targetItem)
149
141
  return undefined;
150
- return targetItem.resources.find((r) => r._id === resourceId);
142
+ return targetItem.resources.find((r) => r.type === resourceType);
151
143
  },
152
- clearResourceById(resourceId, instanceId) {
144
+ clearResourceByType(resourceType, instanceId) {
153
145
  const current = serviceSelectionsSignal.get();
154
146
  // If no instanceId provided, use the first item
155
147
  const targetId = instanceId ?? current[0]?.instanceId;
@@ -158,8 +150,8 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
158
150
  const updated = current.map((item) => {
159
151
  if (item.instanceId !== targetId)
160
152
  return item;
161
- // Filter out the resource with matching ID
162
- const newResources = item.resources.filter((r) => r._id !== resourceId);
153
+ // Filter out the resource with matching type
154
+ const newResources = item.resources.filter((r) => r.type !== resourceType);
163
155
  return { ...item, resources: newResources };
164
156
  });
165
157
  serviceSelectionsSignal.set(updated);
@@ -195,7 +195,7 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
195
195
  dateRangeSignal.set({ start: newStartDate, end: newEndDate });
196
196
  };
197
197
  const preSelectedStaffMemberId = signalsService.computed(() => {
198
- const serviceSelections = bookingService.serviceSelections.peek();
198
+ const serviceSelections = bookingService.serviceSelections.get();
199
199
  return serviceSelections.length
200
200
  ? (serviceSelections[0]?.resources?.[0]?._id ?? undefined)
201
201
  : undefined;
@@ -1,6 +1,5 @@
1
- import type { Resource } from '@wix/auto_sdk_bookings_availability-time-slots';
2
1
  import type { FormValues } from '@wix/form-public';
3
- import type { ServiceSelection, ServiceSelectionTimeSlot, BookingServiceConfig, BookingService } from '../services/booking/booking.js';
2
+ import type { ServiceSelection, ServiceSelectionTimeSlot, BookingServiceConfig, BookingService, ExtendedResource } from '../services/booking/booking.js';
4
3
  import type { Signal } from '@wix/services-definitions/core-services/signals';
5
4
  export declare function mockSignal<T>(initialValue: T): Signal<T>;
6
5
  export declare function createMockSignalsService(): {
@@ -12,15 +11,15 @@ export declare function createMockBookingService(initialSelections?: ServiceSele
12
11
  /**
13
12
  * Mock resource (staff member)
14
13
  */
15
- export declare const mockResource: Resource;
14
+ export declare const mockResource: ExtendedResource;
16
15
  /**
17
16
  * Mock resource (another staff member)
18
17
  */
19
- export declare const mockResourceTwo: Resource;
18
+ export declare const mockResourceTwo: ExtendedResource;
20
19
  /**
21
20
  * Mock resource (room)
22
21
  */
23
- export declare const mockResourceRoom: Resource;
22
+ export declare const mockResourceRoom: ExtendedResource;
24
23
  /**
25
24
  * Mock location
26
25
  */
@@ -35,9 +35,9 @@ export function createMockBookingService(initialSelections = []) {
35
35
  addItem: vi.fn(),
36
36
  removeItem: vi.fn(),
37
37
  clearItems: vi.fn(),
38
- setResourceById: vi.fn(),
39
- getResourceById: vi.fn(),
40
- clearResourceById: vi.fn(),
38
+ setResource: vi.fn(),
39
+ getResourceByType: vi.fn(),
40
+ clearResourceByType: vi.fn(),
41
41
  setLocation: vi.fn(),
42
42
  clearLocation: vi.fn(),
43
43
  setTimezone: vi.fn(),
@@ -56,6 +56,7 @@ export const mockResource = {
56
56
  name: 'John Doe',
57
57
  email: 'john.doe@example.com',
58
58
  tag: 'STAFF',
59
+ type: 'staff',
59
60
  };
60
61
  /**
61
62
  * Mock resource (another staff member)
@@ -65,6 +66,7 @@ export const mockResourceTwo = {
65
66
  name: 'Jane Smith',
66
67
  email: 'jane.smith@example.com',
67
68
  tag: 'STAFF',
69
+ type: 'staff',
68
70
  };
69
71
  /**
70
72
  * Mock resource (room)
@@ -73,6 +75,7 @@ export const mockResourceRoom = {
73
75
  _id: 'resource-room-1',
74
76
  name: 'Conference Room A',
75
77
  tag: 'RESOURCE',
78
+ type: 'room',
76
79
  };
77
80
  /**
78
81
  * Mock location
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import React from 'react';
6
6
  import { type ServiceServiceConfig } from '../../../services/service/service.js';
7
- import type { Service, Payment, BookingPolicy, Schedule } from '@wix/auto_sdk_bookings_services';
7
+ import type { Service, Payment, BookingPolicy, Schedule, StaffMember } from '@wix/auto_sdk_bookings_services';
8
8
  import type { MoneyData } from '@wix/headless-components/react';
9
9
  /**
10
10
  * Props for Service.Root component
@@ -56,10 +56,7 @@ export interface InfoProps {
56
56
  _id?: string;
57
57
  };
58
58
  locations?: Array<NonNullable<Service['locations']>[number]>;
59
- staff?: Array<{
60
- name?: string;
61
- _id?: string;
62
- }>;
59
+ staff?: StaffMember[];
63
60
  media?: Array<{
64
61
  url?: string;
65
62
  _id?: string;
@@ -92,10 +92,7 @@ export function Info(props) {
92
92
  const duration = service.schedule?.availabilityConstraints?.sessionDurations?.[0];
93
93
  // Get staff members from staffMemberDetails.staffMembers
94
94
  // (available when using conditionalFields: ['STAFF_MEMBER_DETAILS'] in queryServices)
95
- const staff = service.staffMembers?.map((member) => ({
96
- _id: member.staffMemberId,
97
- name: member.name || undefined,
98
- })) || [];
95
+ const staff = service.staffMembers || [];
99
96
  // Convert mainMedia to WixMediaImage format
100
97
  // Handle both snake_case (main_media) and camelCase (mainMedia) from API
101
98
  // Handle both string and object formats for image
@@ -130,7 +130,8 @@ export function Actions(props) {
130
130
  if (!rawStaffMember?.staffMemberId || !bookingService)
131
131
  return;
132
132
  // Use resource type ID as the lookup key, staff member ID as the actual resource ID
133
- bookingService.actions.setResourceById(STAFF_MEMBER_RESOURCE_TYPE_ID, {
133
+ bookingService.actions.setResource({
134
+ type: STAFF_MEMBER_RESOURCE_TYPE_ID,
134
135
  _id: rawStaffMember.staffMemberId,
135
136
  name: rawStaffMember.name,
136
137
  });
@@ -9,13 +9,6 @@ import { GenericListRepeaterProps, type ListVariant } from '@wix/headless-compon
9
9
  import { type AsChildChildren } from '@wix/headless-utils/react';
10
10
  import type { StaffMemberListServiceConfig } from '../../services/staff-member-list/staff-member-list.js';
11
11
  import type { StaffMemberData } from '../../services/staff-member-list/staff-member-list.def.js';
12
- /**
13
- * Staff member with id for list rendering
14
- * Uses staffMemberId as the id (which equals resource id)
15
- */
16
- interface StaffMemberWithId extends StaffMemberData {
17
- id: string;
18
- }
19
12
  /**
20
13
  * Props for the StaffMemberList root component
21
14
  */
@@ -73,7 +66,7 @@ export declare const StaffMembers: React.ForwardRefExoticComponent<StaffMembersP
73
66
  /**
74
67
  * Props for StaffMemberList.StaffMemberRepeater component
75
68
  */
76
- export type StaffMemberRepeaterProps = GenericListRepeaterProps<StaffMemberWithId>;
69
+ export type StaffMemberRepeaterProps = GenericListRepeaterProps<StaffMemberData>;
77
70
  export declare const StaffMemberRepeater: React.ForwardRefExoticComponent<StaffMemberRepeaterProps & React.RefAttributes<HTMLElement>>;
78
71
  /**
79
72
  * Props for StaffMemberList.Totals component
@@ -120,4 +113,3 @@ export interface ClearProps {
120
113
  export declare const Actions: {
121
114
  Clear: React.ForwardRefExoticComponent<ClearProps & React.RefAttributes<HTMLButtonElement>>;
122
115
  };
123
- export {};
@@ -59,10 +59,9 @@ Root.displayName = 'StaffMemberList.Root';
59
59
  const RootContent = React.forwardRef((props, ref) => {
60
60
  const { children, className, variant } = props;
61
61
  return (_jsx(CoreStaffMemberList.StaffMembers, { children: ({ staffMembers, isLoading }) => {
62
- // Add id to each staff member for GenericList (staffMemberId equals resource id)
63
- const itemsWithId = staffMembers.map((staffMember, index) => ({
62
+ const itemsWithId = staffMembers.map((staffMember) => ({
64
63
  ...staffMember,
65
- id: staffMember.staffMemberId || String(index),
64
+ id: staffMember.staffMemberId,
66
65
  }));
67
66
  return (_jsx(GenericList.Root, { items: itemsWithId, hasMore: false, isLoading: isLoading, className: className, ref: ref, "data-testid": TestIds.staffMemberListRoot, variant: variant, children: children }));
68
67
  } }));
@@ -90,8 +89,8 @@ StaffMembers.displayName = 'StaffMemberList.StaffMembers';
90
89
  export const StaffMemberRepeater = React.forwardRef((props, ref) => {
91
90
  const { children } = props;
92
91
  // Custom itemWrapper that wraps each item in StaffMember.Root
93
- const staffMemberItemWrapper = ({ item: staffMemberWithId, children: itemChildren, }) => {
94
- return (_jsx(StaffMember.Root, { staffMember: staffMemberWithId, "data-testid": TestIds.staffMemberListStaffMember, "data-staff-member-id": staffMemberWithId.id, "data-item-id": staffMemberWithId.id, children: itemChildren }, staffMemberWithId.id));
92
+ const staffMemberItemWrapper = ({ item: staffMember, children: itemChildren, }) => {
93
+ return (_jsx(StaffMember.Root, { staffMember: staffMember, "data-testid": TestIds.staffMemberListStaffMember, "data-staff-member-id": staffMember.staffMemberId, "data-item-id": staffMember.staffMemberId, children: itemChildren }, staffMember.staffMemberId));
95
94
  };
96
95
  return (_jsx(GenericList.Repeater, { ref: ref, itemWrapper: staffMemberItemWrapper, children: children }));
97
96
  });
@@ -152,7 +151,7 @@ const Clear = React.forwardRef((props, ref) => {
152
151
  // BookingService not available - likely no ServiceManagerProvider
153
152
  }
154
153
  const handleClick = () => {
155
- bookingService?.actions.clearResourceById(STAFF_MEMBER_RESOURCE_TYPE_ID);
154
+ bookingService?.actions.clearResourceByType(STAFF_MEMBER_RESOURCE_TYPE_ID);
156
155
  onClicked?.();
157
156
  };
158
157
  return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.staffMemberListActionClear, customElement: children, customElementProps: {
@@ -9,6 +9,13 @@ import type { Resource, EventInfo, Location as TimeSlotLocationType } from '@wix
9
9
  import type { FormValues } from '@wix/form-public';
10
10
  import type { BookResult } from './book-action/types.js';
11
11
  export declare const ANY_STAFF_MEMBER_ID = "__any_staff_member__";
12
+ /**
13
+ * Extended Resource type with a type field for categorization
14
+ */
15
+ export interface ExtendedResource extends Resource {
16
+ /** Resource type identifier (e.g., 'staff', 'room', 'equipment') */
17
+ type: string;
18
+ }
12
19
  /**
13
20
  * Minimal time slot data for service selections
14
21
  */
@@ -32,8 +39,8 @@ export interface ServiceSelection {
32
39
  instanceId: string;
33
40
  /** The selected service */
34
41
  service: Service;
35
- /** Selected resources (staff members, rooms, etc.) */
36
- resources: Resource[];
42
+ /** Selected resources (staff members, rooms, etc.) with type information */
43
+ resources: ExtendedResource[];
37
44
  /** Per-item time slot data */
38
45
  timeSlot?: ServiceSelectionTimeSlot;
39
46
  /** Number of participants for this service selection */
@@ -53,12 +60,12 @@ export interface BookingServiceActions {
53
60
  removeItem(instanceId?: string): void;
54
61
  /** Clears all service selections */
55
62
  clearItems(): void;
56
- /** Sets a resource by ID within a service selection. If no instanceId provided, uses the first item. */
57
- setResourceById(resourceId: string, resource: Resource, instanceId?: string): void;
58
- /** Gets a resource by ID from a service selection. If no instanceId provided, uses the first item. */
59
- getResourceById(resourceId: string, instanceId?: string): Resource | undefined;
60
- /** Clears a resource by ID from a service selection. If no instanceId provided, uses the first item. */
61
- clearResourceById(resourceId: string, instanceId?: string): void;
63
+ /** Sets a resource by type within a service selection. If no instanceId provided, uses the first item. Only one resource per type is allowed. The resourceType parameter specifies which type to set. */
64
+ setResource(resource: ExtendedResource, instanceId?: string): void;
65
+ /** Gets a resource by type from a service selection. If no instanceId provided, uses the first item. */
66
+ getResourceByType(resourceType: string, instanceId?: string): Resource | undefined;
67
+ /** Clears a resource by type from a service selection. If no instanceId provided, uses the first item. */
68
+ clearResourceByType(resourceType: string, instanceId?: string): void;
62
69
  setLocation(location: ServiceLocationType | null): void;
63
70
  clearLocation(): void;
64
71
  setTimezone(timezone: string): void;
@@ -115,8 +115,7 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
115
115
  clearItems() {
116
116
  serviceSelectionsSignal.set([]);
117
117
  },
118
- // Resource helpers
119
- setResourceById(resourceId, resource, instanceId) {
118
+ setResource(resource, instanceId) {
120
119
  const current = serviceSelectionsSignal.get();
121
120
  // If no instanceId provided, use the first item
122
121
  const targetId = instanceId ?? current[0]?.instanceId;
@@ -125,20 +124,13 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
125
124
  const updated = current.map((item) => {
126
125
  if (item.instanceId !== targetId)
127
126
  return item;
128
- // Find and replace resource by ID, or add if not found
129
- const existingIndex = item.resources.findIndex((r) => r._id === resourceId);
130
- const newResources = [...item.resources];
131
- if (existingIndex >= 0) {
132
- newResources[existingIndex] = resource;
133
- }
134
- else {
135
- newResources.push(resource);
136
- }
127
+ const newResources = item.resources.filter((r) => r.type !== resource.type);
128
+ newResources.push(resource);
137
129
  return { ...item, resources: newResources };
138
130
  });
139
131
  serviceSelectionsSignal.set(updated);
140
132
  },
141
- getResourceById(resourceId, instanceId) {
133
+ getResourceByType(resourceType, instanceId) {
142
134
  const current = serviceSelectionsSignal.get();
143
135
  // If no instanceId provided, use the first item
144
136
  const targetId = instanceId ?? current[0]?.instanceId;
@@ -147,9 +139,9 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
147
139
  const targetItem = current.find((item) => item.instanceId === targetId);
148
140
  if (!targetItem)
149
141
  return undefined;
150
- return targetItem.resources.find((r) => r._id === resourceId);
142
+ return targetItem.resources.find((r) => r.type === resourceType);
151
143
  },
152
- clearResourceById(resourceId, instanceId) {
144
+ clearResourceByType(resourceType, instanceId) {
153
145
  const current = serviceSelectionsSignal.get();
154
146
  // If no instanceId provided, use the first item
155
147
  const targetId = instanceId ?? current[0]?.instanceId;
@@ -158,8 +150,8 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
158
150
  const updated = current.map((item) => {
159
151
  if (item.instanceId !== targetId)
160
152
  return item;
161
- // Filter out the resource with matching ID
162
- const newResources = item.resources.filter((r) => r._id !== resourceId);
153
+ // Filter out the resource with matching type
154
+ const newResources = item.resources.filter((r) => r.type !== resourceType);
163
155
  return { ...item, resources: newResources };
164
156
  });
165
157
  serviceSelectionsSignal.set(updated);
@@ -195,7 +195,7 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
195
195
  dateRangeSignal.set({ start: newStartDate, end: newEndDate });
196
196
  };
197
197
  const preSelectedStaffMemberId = signalsService.computed(() => {
198
- const serviceSelections = bookingService.serviceSelections.peek();
198
+ const serviceSelections = bookingService.serviceSelections.get();
199
199
  return serviceSelections.length
200
200
  ? (serviceSelections[0]?.resources?.[0]?._id ?? undefined)
201
201
  : undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/headless-bookings",
3
- "version": "0.0.58",
3
+ "version": "0.0.60",
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": "ccd30f51c7b5e50deedb808077fe5dfaebe97ef4f66da71d4f246455"
75
+ "falconPackageHash": "42dc732173b7489bf0966f3c1db262dcc4ca3ee26f306b3ae0c74c8d"
76
76
  }