@wix/headless-bookings 0.0.53 → 0.0.55
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.js +1 -0
- package/cjs/dist/__mocks__/services.d.ts +38 -1
- package/cjs/dist/__mocks__/services.js +82 -0
- package/cjs/dist/api/query-services/index.js +33 -3
- package/cjs/dist/react/core/location/Location.d.ts +2 -2
- package/cjs/dist/react/core/location/Location.js +1 -1
- package/cjs/dist/react/core/staff-member/StaffMember.d.ts +104 -0
- package/cjs/dist/react/core/staff-member/StaffMember.js +143 -0
- package/cjs/dist/react/core/staff-member-list/StaffMemberList.d.ts +96 -0
- package/cjs/dist/react/core/staff-member-list/StaffMemberList.js +66 -0
- package/cjs/dist/react/index.d.ts +2 -0
- package/cjs/dist/react/index.js +2 -0
- package/cjs/dist/react/location/LocationList.d.ts +19 -0
- package/cjs/dist/react/location/LocationList.js +52 -1
- package/cjs/dist/react/service/Service.d.ts +51 -44
- package/cjs/dist/react/service/Service.js +56 -37
- package/cjs/dist/react/staff-member/StaffMember.d.ts +119 -0
- package/cjs/dist/react/staff-member/StaffMember.js +147 -0
- package/cjs/dist/react/staff-member/StaffMemberList.d.ts +123 -0
- package/cjs/dist/react/staff-member/StaffMemberList.js +168 -0
- package/cjs/dist/services/booking/booking.d.ts +2 -0
- package/cjs/dist/services/booking/booking.js +15 -0
- package/cjs/dist/services/index.d.ts +1 -0
- package/cjs/dist/services/index.js +1 -0
- package/cjs/dist/services/service-list/service-list.js +41 -9
- package/cjs/dist/services/staff-member-list/staff-member-list.d.ts +85 -0
- package/cjs/dist/services/staff-member-list/staff-member-list.def.d.ts +46 -0
- package/cjs/dist/services/staff-member-list/staff-member-list.def.js +14 -0
- package/cjs/dist/services/staff-member-list/staff-member-list.js +105 -0
- package/dist/__mocks__/booking.js +1 -0
- package/dist/__mocks__/services.d.ts +38 -1
- package/dist/__mocks__/services.js +82 -0
- package/dist/api/query-services/index.js +33 -3
- package/dist/react/core/location/Location.d.ts +2 -2
- package/dist/react/core/location/Location.js +1 -1
- package/dist/react/core/staff-member/StaffMember.d.ts +104 -0
- package/dist/react/core/staff-member/StaffMember.js +143 -0
- package/dist/react/core/staff-member-list/StaffMemberList.d.ts +96 -0
- package/dist/react/core/staff-member-list/StaffMemberList.js +66 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +2 -0
- package/dist/react/location/LocationList.d.ts +19 -0
- package/dist/react/location/LocationList.js +52 -1
- package/dist/react/service/Service.d.ts +51 -44
- package/dist/react/service/Service.js +56 -37
- package/dist/react/staff-member/StaffMember.d.ts +119 -0
- package/dist/react/staff-member/StaffMember.js +147 -0
- package/dist/react/staff-member/StaffMemberList.d.ts +123 -0
- package/dist/react/staff-member/StaffMemberList.js +168 -0
- package/dist/services/booking/booking.d.ts +2 -0
- package/dist/services/booking/booking.js +15 -0
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/services/service-list/service-list.js +41 -9
- package/dist/services/staff-member-list/staff-member-list.d.ts +85 -0
- package/dist/services/staff-member-list/staff-member-list.def.d.ts +46 -0
- package/dist/services/staff-member-list/staff-member-list.def.js +14 -0
- package/dist/services/staff-member-list/staff-member-list.js +105 -0
- package/package.json +2 -2
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared mock data for booking service tests
|
|
3
3
|
*/
|
|
4
|
-
import type { Service } from '@wix/auto_sdk_bookings_services';
|
|
4
|
+
import type { Service, StaffMember } from '@wix/auto_sdk_bookings_services';
|
|
5
5
|
import type { ServiceServiceConfig } from '../services/service/service.js';
|
|
6
6
|
import type { ServiceListServiceConfig } from '../services/service-list/service-list.js';
|
|
7
|
+
import type { StaffMemberListServiceConfig } from '../services/staff-member-list/staff-member-list.js';
|
|
7
8
|
import type { PagingMetadata } from '../api/query-services/index.js';
|
|
8
9
|
import type { Category } from '../api/query-categories/index.js';
|
|
9
10
|
/**
|
|
@@ -94,3 +95,39 @@ export declare const mockServiceListConfigWithCategoriesAndMore: ServiceListServ
|
|
|
94
95
|
* Empty service list config with categories
|
|
95
96
|
*/
|
|
96
97
|
export declare const mockEmptyServiceListConfigWithCategories: ServiceListServiceConfig;
|
|
98
|
+
/**
|
|
99
|
+
* Base mock staff member with all fields
|
|
100
|
+
*/
|
|
101
|
+
export declare const mockStaffMember: StaffMember;
|
|
102
|
+
/**
|
|
103
|
+
* Second mock staff member
|
|
104
|
+
*/
|
|
105
|
+
export declare const mockStaffMember2: StaffMember;
|
|
106
|
+
/**
|
|
107
|
+
* Staff member without optional fields (minimal)
|
|
108
|
+
*/
|
|
109
|
+
export declare const mockStaffMemberMinimal: StaffMember;
|
|
110
|
+
/**
|
|
111
|
+
* Staff member with no name
|
|
112
|
+
*/
|
|
113
|
+
export declare const mockStaffMemberNoName: StaffMember;
|
|
114
|
+
/**
|
|
115
|
+
* Array of mock staff members for list tests
|
|
116
|
+
*/
|
|
117
|
+
export declare const mockStaffMembers: StaffMember[];
|
|
118
|
+
/**
|
|
119
|
+
* Staff member list config with staff members
|
|
120
|
+
*/
|
|
121
|
+
export declare const mockStaffMemberListConfig: StaffMemberListServiceConfig;
|
|
122
|
+
/**
|
|
123
|
+
* Empty staff member list config
|
|
124
|
+
*/
|
|
125
|
+
export declare const mockEmptyStaffMemberListConfig: StaffMemberListServiceConfig;
|
|
126
|
+
/**
|
|
127
|
+
* Single staff member list config
|
|
128
|
+
*/
|
|
129
|
+
export declare const mockSingleStaffMemberListConfig: StaffMemberListServiceConfig;
|
|
130
|
+
/**
|
|
131
|
+
* Helper to create a large list of staff members for tests
|
|
132
|
+
*/
|
|
133
|
+
export declare function createLargeStaffMemberList(count: number): StaffMember[];
|
|
@@ -360,3 +360,85 @@ export const mockEmptyServiceListConfigWithCategories = {
|
|
|
360
360
|
pagingMetadata: mockPagingMetadataEmpty,
|
|
361
361
|
},
|
|
362
362
|
};
|
|
363
|
+
// ============================================================================
|
|
364
|
+
// Staff Member Mocks
|
|
365
|
+
// ============================================================================
|
|
366
|
+
/**
|
|
367
|
+
* Base mock staff member with all fields
|
|
368
|
+
*/
|
|
369
|
+
export const mockStaffMember = {
|
|
370
|
+
staffMemberId: 'staff-member-1',
|
|
371
|
+
name: 'John Doe',
|
|
372
|
+
mainMedia: {
|
|
373
|
+
image: 'wix:image://v1/staff-member-1.jpg',
|
|
374
|
+
},
|
|
375
|
+
};
|
|
376
|
+
/**
|
|
377
|
+
* Second mock staff member
|
|
378
|
+
*/
|
|
379
|
+
export const mockStaffMember2 = {
|
|
380
|
+
staffMemberId: 'staff-member-2',
|
|
381
|
+
name: 'Jane Smith',
|
|
382
|
+
mainMedia: {
|
|
383
|
+
image: 'wix:image://v1/staff-member-2.jpg',
|
|
384
|
+
},
|
|
385
|
+
};
|
|
386
|
+
/**
|
|
387
|
+
* Staff member without optional fields (minimal)
|
|
388
|
+
*/
|
|
389
|
+
export const mockStaffMemberMinimal = {
|
|
390
|
+
staffMemberId: 'staff-member-minimal',
|
|
391
|
+
};
|
|
392
|
+
/**
|
|
393
|
+
* Staff member with no name
|
|
394
|
+
*/
|
|
395
|
+
export const mockStaffMemberNoName = {
|
|
396
|
+
staffMemberId: 'staff-member-no-name',
|
|
397
|
+
mainMedia: {
|
|
398
|
+
image: 'wix:image://v1/staff-no-name.jpg',
|
|
399
|
+
},
|
|
400
|
+
};
|
|
401
|
+
/**
|
|
402
|
+
* Array of mock staff members for list tests
|
|
403
|
+
*/
|
|
404
|
+
export const mockStaffMembers = [
|
|
405
|
+
mockStaffMember,
|
|
406
|
+
mockStaffMember2,
|
|
407
|
+
{
|
|
408
|
+
staffMemberId: 'staff-member-3',
|
|
409
|
+
name: 'Bob Johnson',
|
|
410
|
+
mainMedia: {
|
|
411
|
+
image: 'wix:image://v1/staff-member-3.jpg',
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
];
|
|
415
|
+
/**
|
|
416
|
+
* Staff member list config with staff members
|
|
417
|
+
*/
|
|
418
|
+
export const mockStaffMemberListConfig = {
|
|
419
|
+
staffMembers: mockStaffMembers,
|
|
420
|
+
};
|
|
421
|
+
/**
|
|
422
|
+
* Empty staff member list config
|
|
423
|
+
*/
|
|
424
|
+
export const mockEmptyStaffMemberListConfig = {
|
|
425
|
+
staffMembers: [],
|
|
426
|
+
};
|
|
427
|
+
/**
|
|
428
|
+
* Single staff member list config
|
|
429
|
+
*/
|
|
430
|
+
export const mockSingleStaffMemberListConfig = {
|
|
431
|
+
staffMembers: [mockStaffMember],
|
|
432
|
+
};
|
|
433
|
+
/**
|
|
434
|
+
* Helper to create a large list of staff members for tests
|
|
435
|
+
*/
|
|
436
|
+
export function createLargeStaffMemberList(count) {
|
|
437
|
+
return Array.from({ length: count }, (_, i) => ({
|
|
438
|
+
staffMemberId: `staff-member-${i}`,
|
|
439
|
+
name: `Staff Member ${i}`,
|
|
440
|
+
mainMedia: {
|
|
441
|
+
image: `wix:image://v1/staff-member-${i}.jpg`,
|
|
442
|
+
},
|
|
443
|
+
}));
|
|
444
|
+
}
|
|
@@ -2,11 +2,16 @@
|
|
|
2
2
|
* Query Services API
|
|
3
3
|
* Fetches single or multiple services with pagination and sorting
|
|
4
4
|
*/
|
|
5
|
-
import { queryServices as queryServicesApi, } from '@wix/auto_sdk_bookings_services';
|
|
5
|
+
import { queryServices as queryServicesApi, LocationType, } from '@wix/auto_sdk_bookings_services';
|
|
6
6
|
/**
|
|
7
7
|
* Booking app ID constant
|
|
8
8
|
*/
|
|
9
9
|
const BOOKING_APP_ID = '13d21c63-b5ec-5912-8397-c3a5ddb27a97';
|
|
10
|
+
/**
|
|
11
|
+
* Synthetic location ID constants for non-business locations
|
|
12
|
+
*/
|
|
13
|
+
const SYNTHETIC_CUSTOM_ID = '__synthetic_custom__';
|
|
14
|
+
const SYNTHETIC_CUSTOMER_ID = '__synthetic_customer__';
|
|
10
15
|
/**
|
|
11
16
|
* Fetches a service by its ID
|
|
12
17
|
* @param id - The service ID
|
|
@@ -80,7 +85,28 @@ const buildServicesQueryRequest = ({ appId, filters, paging, sort, }) => {
|
|
|
80
85
|
}
|
|
81
86
|
// Add locationIds filter if provided
|
|
82
87
|
if (filters?.locationIds && filters.locationIds.length > 0) {
|
|
83
|
-
|
|
88
|
+
// Separate synthetic IDs from business location IDs
|
|
89
|
+
const syntheticTypes = [];
|
|
90
|
+
const businessLocationIds = [];
|
|
91
|
+
for (const id of filters.locationIds) {
|
|
92
|
+
if (id === SYNTHETIC_CUSTOM_ID) {
|
|
93
|
+
syntheticTypes.push(LocationType.CUSTOM);
|
|
94
|
+
}
|
|
95
|
+
else if (id === SYNTHETIC_CUSTOMER_ID) {
|
|
96
|
+
syntheticTypes.push(LocationType.CUSTOMER);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
businessLocationIds.push(id);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Filter by location type for synthetic locations
|
|
103
|
+
if (syntheticTypes.length > 0) {
|
|
104
|
+
filter['locations.type'] = { $hasSome: syntheticTypes };
|
|
105
|
+
}
|
|
106
|
+
// Filter by business ID for business locations
|
|
107
|
+
if (businessLocationIds.length > 0) {
|
|
108
|
+
filter['locations.business.id'] = { $hasSome: businessLocationIds };
|
|
109
|
+
}
|
|
84
110
|
}
|
|
85
111
|
// staffMemberIds to be added later
|
|
86
112
|
const query = {
|
|
@@ -122,7 +148,11 @@ export async function queryServices({ appId, filters, pagingMetadata, sort, }) {
|
|
|
122
148
|
sort,
|
|
123
149
|
});
|
|
124
150
|
// Call queryServices with QueryServicesRequest and execute the query
|
|
125
|
-
|
|
151
|
+
// Include conditionalFields to fetch staff member details
|
|
152
|
+
const result = await queryServicesApi({
|
|
153
|
+
...queryRequest,
|
|
154
|
+
conditionalFields: ['STAFF_MEMBER_DETAILS'],
|
|
155
|
+
}).find();
|
|
126
156
|
// Construct PagingMetadata from result properties
|
|
127
157
|
// Includes count (number of items returned) and hasNext (whether more items are available)
|
|
128
158
|
const resultPagingMetadata = {
|
|
@@ -25,8 +25,8 @@ export interface SyntheticLocation {
|
|
|
25
25
|
locationType: LocationType.CUSTOMER | LocationType.CUSTOM;
|
|
26
26
|
/** Marker to identify synthetic locations */
|
|
27
27
|
synthetic: true;
|
|
28
|
-
/** Optional ID for tracking */
|
|
29
|
-
|
|
28
|
+
/** Optional ID for tracking (matches ServiceLocation._id) */
|
|
29
|
+
_id?: string;
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
32
|
* Union type - location prop accepts Service or Synthetic location
|
|
@@ -110,7 +110,7 @@ function computeLocationRenderProps(rawLocation) {
|
|
|
110
110
|
locationType,
|
|
111
111
|
address: null,
|
|
112
112
|
name: undefined,
|
|
113
|
-
locationId: syntheticLoc.
|
|
113
|
+
locationId: syntheticLoc._id,
|
|
114
114
|
isCustomerLocation: locationType === LocationType.CUSTOMER,
|
|
115
115
|
isCustomLocation: locationType === LocationType.CUSTOM,
|
|
116
116
|
isSynthetic: true,
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core StaffMember Component - Parses staff member data
|
|
3
|
+
* Handles staff member display with name
|
|
4
|
+
*
|
|
5
|
+
* @module Core/StaffMember
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import type { StaffMember as StaffMemberType } from '@wix/auto_sdk_bookings_services';
|
|
9
|
+
/**
|
|
10
|
+
* StaffMember type from SDK
|
|
11
|
+
* Contains staffMemberId (which equals resource id), name, and mainMedia
|
|
12
|
+
*/
|
|
13
|
+
export type StaffMemberData = StaffMemberType;
|
|
14
|
+
/**
|
|
15
|
+
* Staff member render props passed to children
|
|
16
|
+
*/
|
|
17
|
+
export interface StaffMemberRenderProps {
|
|
18
|
+
/** Staff member name */
|
|
19
|
+
name: string | undefined;
|
|
20
|
+
/** Raw staff member object */
|
|
21
|
+
rawStaffMember: StaffMemberData | null;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Props for the Core StaffMember Root component
|
|
25
|
+
*/
|
|
26
|
+
export interface RootProps {
|
|
27
|
+
/** Raw staff member data */
|
|
28
|
+
staffMember?: StaffMemberData;
|
|
29
|
+
/** Children */
|
|
30
|
+
children: React.ReactNode;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Props for the Core StaffMember Data component
|
|
34
|
+
*/
|
|
35
|
+
export interface DataProps {
|
|
36
|
+
/** Children render prop that receives staff member data */
|
|
37
|
+
children: (props: StaffMemberRenderProps) => React.ReactNode;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Hook to access staff member context from CoreStaffMember.Root
|
|
41
|
+
* @throws Error if used outside of CoreStaffMember.Root
|
|
42
|
+
*/
|
|
43
|
+
export declare function useStaffMemberContext(): StaffMemberRenderProps;
|
|
44
|
+
/**
|
|
45
|
+
* Core StaffMember Root component that provides staff member context.
|
|
46
|
+
* Parses staff member data and makes it available to all child components via context.
|
|
47
|
+
*
|
|
48
|
+
* @component
|
|
49
|
+
* @example
|
|
50
|
+
* ```tsx
|
|
51
|
+
* <CoreStaffMember.Root staffMember={staffMemberData}>
|
|
52
|
+
* <StaffMember.Name />
|
|
53
|
+
* </CoreStaffMember.Root>
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare function Root(props: RootProps): React.ReactNode;
|
|
57
|
+
/**
|
|
58
|
+
* Core StaffMember Data component that exposes staff member data via render props.
|
|
59
|
+
* Must be used within a CoreStaffMember.Root component.
|
|
60
|
+
*
|
|
61
|
+
* @component
|
|
62
|
+
* @example
|
|
63
|
+
* ```tsx
|
|
64
|
+
* <CoreStaffMember.Root staffMember={staffMemberData}>
|
|
65
|
+
* <CoreStaffMember.Data>
|
|
66
|
+
* {({ name, rawStaffMember }) => (
|
|
67
|
+
* <div>
|
|
68
|
+
* <span>{name}</span>
|
|
69
|
+
* </div>
|
|
70
|
+
* )}
|
|
71
|
+
* </CoreStaffMember.Data>
|
|
72
|
+
* </CoreStaffMember.Root>
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export declare function Data(props: DataProps): React.ReactNode;
|
|
76
|
+
/**
|
|
77
|
+
* Props for Actions render prop component
|
|
78
|
+
*/
|
|
79
|
+
export interface ActionsProps {
|
|
80
|
+
children: (actions: {
|
|
81
|
+
select: () => void;
|
|
82
|
+
rawStaffMember: StaffMemberData | null;
|
|
83
|
+
selected: boolean;
|
|
84
|
+
}) => React.ReactNode;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Core component that provides staff member selection actions via render props.
|
|
88
|
+
* Integrates with BookingService to persist selection state.
|
|
89
|
+
*
|
|
90
|
+
* @component
|
|
91
|
+
* @example
|
|
92
|
+
* ```tsx
|
|
93
|
+
* <CoreStaffMember.Root staffMember={staffMemberData}>
|
|
94
|
+
* <CoreStaffMember.Actions>
|
|
95
|
+
* {({ select, selected, rawStaffMember }) => (
|
|
96
|
+
* <button onClick={select}>
|
|
97
|
+
* {selected ? 'Selected' : 'Select'}
|
|
98
|
+
* </button>
|
|
99
|
+
* )}
|
|
100
|
+
* </CoreStaffMember.Actions>
|
|
101
|
+
* </CoreStaffMember.Root>
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export declare function Actions(props: ActionsProps): React.ReactNode;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Core StaffMember Component - Parses staff member data
|
|
4
|
+
* Handles staff member display with name
|
|
5
|
+
*
|
|
6
|
+
* @module Core/StaffMember
|
|
7
|
+
*/
|
|
8
|
+
import { createContext, useContext } from 'react';
|
|
9
|
+
import { useService } from '@wix/services-manager-react';
|
|
10
|
+
import { BookingServiceDefinition } from '../../../services/booking/booking.js';
|
|
11
|
+
/** Resource type ID for staff members */
|
|
12
|
+
const STAFF_MEMBER_RESOURCE_TYPE_ID = '1cd44cf8-756f-41c3-bd90-3e2ffcaf1155';
|
|
13
|
+
// ==========================================
|
|
14
|
+
// Context
|
|
15
|
+
// ==========================================
|
|
16
|
+
/**
|
|
17
|
+
* Staff member context value - same as StaffMemberRenderProps
|
|
18
|
+
*/
|
|
19
|
+
const StaffMemberContext = createContext(null);
|
|
20
|
+
/**
|
|
21
|
+
* Hook to access staff member context from CoreStaffMember.Root
|
|
22
|
+
* @throws Error if used outside of CoreStaffMember.Root
|
|
23
|
+
*/
|
|
24
|
+
export function useStaffMemberContext() {
|
|
25
|
+
const context = useContext(StaffMemberContext);
|
|
26
|
+
if (!context) {
|
|
27
|
+
throw new Error('useStaffMemberContext must be used within a CoreStaffMember.Root component');
|
|
28
|
+
}
|
|
29
|
+
return context;
|
|
30
|
+
}
|
|
31
|
+
// ==========================================
|
|
32
|
+
// Helper function for computing render props
|
|
33
|
+
// ==========================================
|
|
34
|
+
/**
|
|
35
|
+
* Computes StaffMemberRenderProps from staff member input
|
|
36
|
+
*/
|
|
37
|
+
function computeStaffMemberRenderProps(rawStaffMember) {
|
|
38
|
+
// Handle no staff member
|
|
39
|
+
if (!rawStaffMember) {
|
|
40
|
+
return {
|
|
41
|
+
name: undefined,
|
|
42
|
+
rawStaffMember: null,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
name: rawStaffMember.name ?? undefined,
|
|
47
|
+
rawStaffMember,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
// ==========================================
|
|
51
|
+
// Root Component (Context Provider)
|
|
52
|
+
// ==========================================
|
|
53
|
+
/**
|
|
54
|
+
* Core StaffMember Root component that provides staff member context.
|
|
55
|
+
* Parses staff member data and makes it available to all child components via context.
|
|
56
|
+
*
|
|
57
|
+
* @component
|
|
58
|
+
* @example
|
|
59
|
+
* ```tsx
|
|
60
|
+
* <CoreStaffMember.Root staffMember={staffMemberData}>
|
|
61
|
+
* <StaffMember.Name />
|
|
62
|
+
* </CoreStaffMember.Root>
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export function Root(props) {
|
|
66
|
+
const { staffMember, children } = props;
|
|
67
|
+
const renderProps = computeStaffMemberRenderProps(staffMember);
|
|
68
|
+
return (_jsx(StaffMemberContext.Provider, { value: renderProps, children: children }));
|
|
69
|
+
}
|
|
70
|
+
// ==========================================
|
|
71
|
+
// Data Component (Render Props)
|
|
72
|
+
// ==========================================
|
|
73
|
+
/**
|
|
74
|
+
* Core StaffMember Data component that exposes staff member data via render props.
|
|
75
|
+
* Must be used within a CoreStaffMember.Root component.
|
|
76
|
+
*
|
|
77
|
+
* @component
|
|
78
|
+
* @example
|
|
79
|
+
* ```tsx
|
|
80
|
+
* <CoreStaffMember.Root staffMember={staffMemberData}>
|
|
81
|
+
* <CoreStaffMember.Data>
|
|
82
|
+
* {({ name, rawStaffMember }) => (
|
|
83
|
+
* <div>
|
|
84
|
+
* <span>{name}</span>
|
|
85
|
+
* </div>
|
|
86
|
+
* )}
|
|
87
|
+
* </CoreStaffMember.Data>
|
|
88
|
+
* </CoreStaffMember.Root>
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export function Data(props) {
|
|
92
|
+
const context = useStaffMemberContext();
|
|
93
|
+
return props.children(context);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Core component that provides staff member selection actions via render props.
|
|
97
|
+
* Integrates with BookingService to persist selection state.
|
|
98
|
+
*
|
|
99
|
+
* @component
|
|
100
|
+
* @example
|
|
101
|
+
* ```tsx
|
|
102
|
+
* <CoreStaffMember.Root staffMember={staffMemberData}>
|
|
103
|
+
* <CoreStaffMember.Actions>
|
|
104
|
+
* {({ select, selected, rawStaffMember }) => (
|
|
105
|
+
* <button onClick={select}>
|
|
106
|
+
* {selected ? 'Selected' : 'Select'}
|
|
107
|
+
* </button>
|
|
108
|
+
* )}
|
|
109
|
+
* </CoreStaffMember.Actions>
|
|
110
|
+
* </CoreStaffMember.Root>
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export function Actions(props) {
|
|
114
|
+
const { rawStaffMember } = useStaffMemberContext();
|
|
115
|
+
let bookingService = null;
|
|
116
|
+
try {
|
|
117
|
+
bookingService = useService(BookingServiceDefinition);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// BookingService not available - likely no ServiceManagerProvider
|
|
121
|
+
}
|
|
122
|
+
const serviceSelections = bookingService?.serviceSelections.get() ?? [];
|
|
123
|
+
// Derive selected state - check if THIS staff member is currently selected
|
|
124
|
+
const staffMemberId = rawStaffMember?.staffMemberId;
|
|
125
|
+
const selected = staffMemberId
|
|
126
|
+
? (serviceSelections[0]?.resources?.some((r) => r._id === staffMemberId) ??
|
|
127
|
+
false)
|
|
128
|
+
: false;
|
|
129
|
+
const select = () => {
|
|
130
|
+
if (!rawStaffMember?.staffMemberId || !bookingService)
|
|
131
|
+
return;
|
|
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, {
|
|
134
|
+
_id: rawStaffMember.staffMemberId,
|
|
135
|
+
name: rawStaffMember.name,
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
return props.children({
|
|
139
|
+
select,
|
|
140
|
+
rawStaffMember,
|
|
141
|
+
selected,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core StaffMemberList Component
|
|
3
|
+
* Bridge between StaffMemberListService and headless components using render props
|
|
4
|
+
*
|
|
5
|
+
* @module Core/StaffMemberList
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { type StaffMemberListServiceConfig } from '../../../services/staff-member-list/staff-member-list.js';
|
|
9
|
+
import type { StaffMemberData } from '../../../services/staff-member-list/staff-member-list.def.js';
|
|
10
|
+
/**
|
|
11
|
+
* Props for StaffMemberList.Root component
|
|
12
|
+
*/
|
|
13
|
+
export interface RootProps {
|
|
14
|
+
children: React.ReactNode;
|
|
15
|
+
staffMemberListServiceConfig: StaffMemberListServiceConfig;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Root component that provides StaffMemberList service context
|
|
19
|
+
*
|
|
20
|
+
* @component
|
|
21
|
+
* @example
|
|
22
|
+
* ```tsx
|
|
23
|
+
* <CoreStaffMemberList.Root staffMemberListServiceConfig={config}>
|
|
24
|
+
* <CoreStaffMemberList.StaffMembers>
|
|
25
|
+
* {({ staffMembers }) => (
|
|
26
|
+
* // render staff members
|
|
27
|
+
* )}
|
|
28
|
+
* </CoreStaffMemberList.StaffMembers>
|
|
29
|
+
* </CoreStaffMemberList.Root>
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare function Root(props: RootProps): React.ReactNode;
|
|
33
|
+
/**
|
|
34
|
+
* Render props for StaffMembers component
|
|
35
|
+
*/
|
|
36
|
+
export interface StaffMembersRenderProps {
|
|
37
|
+
/** Staff members array from the service */
|
|
38
|
+
staffMembers: StaffMemberData[];
|
|
39
|
+
/** Whether there are any staff members */
|
|
40
|
+
hasStaffMembers: boolean;
|
|
41
|
+
/** Whether staff members are currently loading */
|
|
42
|
+
isLoading: boolean;
|
|
43
|
+
/** Error message if any */
|
|
44
|
+
error: string | null;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Props for StaffMembers render prop component
|
|
48
|
+
*/
|
|
49
|
+
export interface StaffMembersProps {
|
|
50
|
+
children: (data: StaffMembersRenderProps) => React.ReactNode;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Core component that provides access to staff members list via render props
|
|
54
|
+
*
|
|
55
|
+
* @component
|
|
56
|
+
* @example
|
|
57
|
+
* ```tsx
|
|
58
|
+
* <CoreStaffMemberList.StaffMembers>
|
|
59
|
+
* {({ staffMembers, hasStaffMembers, isLoading }) => (
|
|
60
|
+
* isLoading ? <Spinner /> : staffMembers.map(...)
|
|
61
|
+
* )}
|
|
62
|
+
* </CoreStaffMemberList.StaffMembers>
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export declare function StaffMembers(props: StaffMembersProps): React.ReactNode;
|
|
66
|
+
/**
|
|
67
|
+
* Render props for Actions component
|
|
68
|
+
*/
|
|
69
|
+
export interface ActionsRenderProps {
|
|
70
|
+
/** Select a staff member */
|
|
71
|
+
select: (staffMember: StaffMemberData) => void;
|
|
72
|
+
/** Currently selected staff member */
|
|
73
|
+
selectedStaffMember: StaffMemberData | null;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Props for Actions render prop component
|
|
77
|
+
*/
|
|
78
|
+
export interface ActionsProps {
|
|
79
|
+
children: (actions: ActionsRenderProps) => React.ReactNode;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Core component that provides staff member actions via render props
|
|
83
|
+
*
|
|
84
|
+
* @component
|
|
85
|
+
* @example
|
|
86
|
+
* ```tsx
|
|
87
|
+
* <CoreStaffMemberList.Actions>
|
|
88
|
+
* {({ select, selectedStaffMember }) => (
|
|
89
|
+
* <button onClick={() => select(staffMember)}>
|
|
90
|
+
* {selectedStaffMember?.name || 'Select'}
|
|
91
|
+
* </button>
|
|
92
|
+
* )}
|
|
93
|
+
* </CoreStaffMemberList.Actions>
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export declare function Actions(props: ActionsProps): React.ReactNode;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { WixServices, useService } from '@wix/services-manager-react';
|
|
3
|
+
import { createServicesMap } from '@wix/services-manager';
|
|
4
|
+
import { StaffMemberListServiceDefinition, StaffMemberListService, } from '../../../services/staff-member-list/staff-member-list.js';
|
|
5
|
+
/**
|
|
6
|
+
* Root component that provides StaffMemberList service context
|
|
7
|
+
*
|
|
8
|
+
* @component
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* <CoreStaffMemberList.Root staffMemberListServiceConfig={config}>
|
|
12
|
+
* <CoreStaffMemberList.StaffMembers>
|
|
13
|
+
* {({ staffMembers }) => (
|
|
14
|
+
* // render staff members
|
|
15
|
+
* )}
|
|
16
|
+
* </CoreStaffMemberList.StaffMembers>
|
|
17
|
+
* </CoreStaffMemberList.Root>
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export function Root(props) {
|
|
21
|
+
return (_jsx(WixServices, { servicesMap: createServicesMap().addService(StaffMemberListServiceDefinition, StaffMemberListService, props.staffMemberListServiceConfig), children: props.children }));
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Core component that provides access to staff members list via render props
|
|
25
|
+
*
|
|
26
|
+
* @component
|
|
27
|
+
* @example
|
|
28
|
+
* ```tsx
|
|
29
|
+
* <CoreStaffMemberList.StaffMembers>
|
|
30
|
+
* {({ staffMembers, hasStaffMembers, isLoading }) => (
|
|
31
|
+
* isLoading ? <Spinner /> : staffMembers.map(...)
|
|
32
|
+
* )}
|
|
33
|
+
* </CoreStaffMemberList.StaffMembers>
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export function StaffMembers(props) {
|
|
37
|
+
const service = useService(StaffMemberListServiceDefinition);
|
|
38
|
+
return props.children({
|
|
39
|
+
staffMembers: service.staffMembers.get(),
|
|
40
|
+
hasStaffMembers: service.hasStaffMembers.get(),
|
|
41
|
+
isLoading: service.isLoading.get(),
|
|
42
|
+
error: service.error.get(),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Core component that provides staff member actions via render props
|
|
47
|
+
*
|
|
48
|
+
* @component
|
|
49
|
+
* @example
|
|
50
|
+
* ```tsx
|
|
51
|
+
* <CoreStaffMemberList.Actions>
|
|
52
|
+
* {({ select, selectedStaffMember }) => (
|
|
53
|
+
* <button onClick={() => select(staffMember)}>
|
|
54
|
+
* {selectedStaffMember?.name || 'Select'}
|
|
55
|
+
* </button>
|
|
56
|
+
* )}
|
|
57
|
+
* </CoreStaffMemberList.Actions>
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export function Actions(props) {
|
|
61
|
+
const service = useService(StaffMemberListServiceDefinition);
|
|
62
|
+
return props.children({
|
|
63
|
+
select: service.actions.select,
|
|
64
|
+
selectedStaffMember: service.selectedStaffMember.get(),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
@@ -7,4 +7,6 @@ export * as TimeSlot from './time-slot-list/TimeSlot.js';
|
|
|
7
7
|
export * as ServiceList from './service-list/ServiceList.js';
|
|
8
8
|
export * as Location from './location/Location.js';
|
|
9
9
|
export * as LocationList from './location/LocationList.js';
|
|
10
|
+
export * as StaffMember from './staff-member/StaffMember.js';
|
|
11
|
+
export * as StaffMemberList from './staff-member/StaffMemberList.js';
|
|
10
12
|
export * as Payment from './payment/Payment.js';
|
package/cjs/dist/react/index.js
CHANGED
|
@@ -7,4 +7,6 @@ export * as TimeSlot from './time-slot-list/TimeSlot.js';
|
|
|
7
7
|
export * as ServiceList from './service-list/ServiceList.js';
|
|
8
8
|
export * as Location from './location/Location.js';
|
|
9
9
|
export * as LocationList from './location/LocationList.js';
|
|
10
|
+
export * as StaffMember from './staff-member/StaffMember.js';
|
|
11
|
+
export * as StaffMemberList from './staff-member/StaffMemberList.js';
|
|
10
12
|
export * as Payment from './payment/Payment.js';
|
|
@@ -96,3 +96,22 @@ export interface TotalsProps {
|
|
|
96
96
|
* ```
|
|
97
97
|
*/
|
|
98
98
|
export declare const Totals: React.ForwardRefExoticComponent<TotalsProps & React.RefAttributes<HTMLElement>>;
|
|
99
|
+
/**
|
|
100
|
+
* Props for LocationList.Actions.Clear component
|
|
101
|
+
*/
|
|
102
|
+
export interface ClearProps {
|
|
103
|
+
asChild?: boolean;
|
|
104
|
+
children?: React.ReactNode | ((props: {
|
|
105
|
+
onClick: () => void;
|
|
106
|
+
}) => React.ReactNode);
|
|
107
|
+
className?: string;
|
|
108
|
+
label?: string;
|
|
109
|
+
/** Callback fired when the clear button is clicked */
|
|
110
|
+
onClicked?: () => void;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Actions namespace for location list-level actions
|
|
114
|
+
*/
|
|
115
|
+
export declare const Actions: {
|
|
116
|
+
Clear: React.ForwardRefExoticComponent<ClearProps & React.RefAttributes<HTMLButtonElement>>;
|
|
117
|
+
};
|