@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.
- package/cjs/dist/__mocks__/booking.d.ts +4 -5
- package/cjs/dist/__mocks__/booking.js +6 -3
- package/cjs/dist/react/core/service/Service.d.ts +2 -5
- package/cjs/dist/react/core/service/Service.js +1 -4
- package/cjs/dist/react/core/staff-member/StaffMember.js +2 -1
- package/cjs/dist/react/staff-member/StaffMemberList.d.ts +1 -9
- package/cjs/dist/react/staff-member/StaffMemberList.js +5 -6
- package/cjs/dist/services/booking/booking.d.ts +15 -8
- package/cjs/dist/services/booking/booking.js +8 -16
- package/cjs/dist/services/time-slot-list/time-slot-list.js +1 -1
- package/dist/__mocks__/booking.d.ts +4 -5
- package/dist/__mocks__/booking.js +6 -3
- package/dist/react/core/service/Service.d.ts +2 -5
- package/dist/react/core/service/Service.js +1 -4
- package/dist/react/core/staff-member/StaffMember.js +2 -1
- package/dist/react/staff-member/StaffMemberList.d.ts +1 -9
- package/dist/react/staff-member/StaffMemberList.js +5 -6
- package/dist/services/booking/booking.d.ts +15 -8
- package/dist/services/booking/booking.js +8 -16
- package/dist/services/time-slot-list/time-slot-list.js +1 -1
- package/package.json +2 -2
|
@@ -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:
|
|
14
|
+
export declare const mockResource: ExtendedResource;
|
|
16
15
|
/**
|
|
17
16
|
* Mock resource (another staff member)
|
|
18
17
|
*/
|
|
19
|
-
export declare const mockResourceTwo:
|
|
18
|
+
export declare const mockResourceTwo: ExtendedResource;
|
|
20
19
|
/**
|
|
21
20
|
* Mock resource (room)
|
|
22
21
|
*/
|
|
23
|
-
export declare const mockResourceRoom:
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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?:
|
|
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
|
|
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.
|
|
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<
|
|
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
|
-
|
|
63
|
-
const itemsWithId = staffMembers.map((staffMember, index) => ({
|
|
62
|
+
const itemsWithId = staffMembers.map((staffMember) => ({
|
|
64
63
|
...staffMember,
|
|
65
|
-
id: staffMember.staffMemberId
|
|
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:
|
|
94
|
-
return (_jsx(StaffMember.Root, { staffMember:
|
|
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.
|
|
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:
|
|
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
|
|
57
|
-
|
|
58
|
-
/** Gets a resource by
|
|
59
|
-
|
|
60
|
-
/** Clears a resource by
|
|
61
|
-
|
|
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
|
-
|
|
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
|
-
|
|
129
|
-
|
|
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
|
-
|
|
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.
|
|
142
|
+
return targetItem.resources.find((r) => r.type === resourceType);
|
|
151
143
|
},
|
|
152
|
-
|
|
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
|
|
162
|
-
const newResources = item.resources.filter((r) => r.
|
|
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.
|
|
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:
|
|
14
|
+
export declare const mockResource: ExtendedResource;
|
|
16
15
|
/**
|
|
17
16
|
* Mock resource (another staff member)
|
|
18
17
|
*/
|
|
19
|
-
export declare const mockResourceTwo:
|
|
18
|
+
export declare const mockResourceTwo: ExtendedResource;
|
|
20
19
|
/**
|
|
21
20
|
* Mock resource (room)
|
|
22
21
|
*/
|
|
23
|
-
export declare const mockResourceRoom:
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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?:
|
|
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
|
|
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.
|
|
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<
|
|
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
|
-
|
|
63
|
-
const itemsWithId = staffMembers.map((staffMember, index) => ({
|
|
62
|
+
const itemsWithId = staffMembers.map((staffMember) => ({
|
|
64
63
|
...staffMember,
|
|
65
|
-
id: staffMember.staffMemberId
|
|
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:
|
|
94
|
-
return (_jsx(StaffMember.Root, { staffMember:
|
|
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.
|
|
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:
|
|
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
|
|
57
|
-
|
|
58
|
-
/** Gets a resource by
|
|
59
|
-
|
|
60
|
-
/** Clears a resource by
|
|
61
|
-
|
|
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
|
-
|
|
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
|
-
|
|
129
|
-
|
|
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
|
-
|
|
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.
|
|
142
|
+
return targetItem.resources.find((r) => r.type === resourceType);
|
|
151
143
|
},
|
|
152
|
-
|
|
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
|
|
162
|
-
const newResources = item.resources.filter((r) => r.
|
|
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.
|
|
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.
|
|
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": "
|
|
75
|
+
"falconPackageHash": "42dc732173b7489bf0966f3c1db262dcc4ca3ee26f306b3ae0c74c8d"
|
|
76
76
|
}
|