@wix/headless-bookings 0.0.52 → 0.0.54
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 +5 -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 +51 -0
- package/cjs/dist/react/service/Service.d.ts +16 -44
- package/cjs/dist/react/service/Service.js +23 -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/book-action/buildBookingRequest.js +1 -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/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 +5 -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 +51 -0
- package/dist/react/service/Service.d.ts +16 -44
- package/dist/react/service/Service.js +23 -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/book-action/buildBookingRequest.js +1 -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/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
|
+
}
|
|
@@ -122,7 +122,11 @@ export async function queryServices({ appId, filters, pagingMetadata, sort, }) {
|
|
|
122
122
|
sort,
|
|
123
123
|
});
|
|
124
124
|
// Call queryServices with QueryServicesRequest and execute the query
|
|
125
|
-
|
|
125
|
+
// Include conditionalFields to fetch staff member details
|
|
126
|
+
const result = await queryServicesApi({
|
|
127
|
+
...queryRequest,
|
|
128
|
+
conditionalFields: ['STAFF_MEMBER_DETAILS'],
|
|
129
|
+
}).find();
|
|
126
130
|
// Construct PagingMetadata from result properties
|
|
127
131
|
// Includes count (number of items returned) and hasNext (whether more items are available)
|
|
128
132
|
const resultPagingMetadata = {
|
|
@@ -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
|
+
};
|
|
@@ -8,6 +8,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
8
8
|
import React from 'react';
|
|
9
9
|
import { GenericList, } from '@wix/headless-components/react';
|
|
10
10
|
import { AsChildSlot } from '@wix/headless-utils/react';
|
|
11
|
+
import { useService } from '@wix/services-manager-react';
|
|
12
|
+
import { BookingServiceDefinition } from '../../services/booking/booking.js';
|
|
11
13
|
import * as CoreLocationList from '../core/location-list/LocationList.js';
|
|
12
14
|
import * as Location from './Location.js';
|
|
13
15
|
// ============================================================================
|
|
@@ -18,6 +20,7 @@ var TestIds;
|
|
|
18
20
|
TestIds["locationListRoot"] = "location-list-root";
|
|
19
21
|
TestIds["locationListLocations"] = "location-list-locations";
|
|
20
22
|
TestIds["locationListLocation"] = "location-list-location";
|
|
23
|
+
TestIds["locationListActionClear"] = "location-list-action-clear";
|
|
21
24
|
})(TestIds || (TestIds = {}));
|
|
22
25
|
/**
|
|
23
26
|
* Root component that provides the LocationList service context for rendering locations lists.
|
|
@@ -118,3 +121,51 @@ export const Totals = React.forwardRef((props, ref) => {
|
|
|
118
121
|
} }));
|
|
119
122
|
});
|
|
120
123
|
Totals.displayName = 'LocationList.Totals';
|
|
124
|
+
/**
|
|
125
|
+
* Button to clear the location selection.
|
|
126
|
+
* Clears the location from the BookingService.
|
|
127
|
+
*
|
|
128
|
+
* @component
|
|
129
|
+
* @example
|
|
130
|
+
* ```tsx
|
|
131
|
+
* // Default button with "Clear" label
|
|
132
|
+
* <LocationList.Actions.Clear />
|
|
133
|
+
*
|
|
134
|
+
* // With custom label
|
|
135
|
+
* <LocationList.Actions.Clear label="Clear selection" />
|
|
136
|
+
*
|
|
137
|
+
* // With asChild
|
|
138
|
+
* <LocationList.Actions.Clear asChild>
|
|
139
|
+
* <button className="btn-secondary">Clear location</button>
|
|
140
|
+
* </LocationList.Actions.Clear>
|
|
141
|
+
*
|
|
142
|
+
* // Using render prop pattern
|
|
143
|
+
* <LocationList.Actions.Clear>
|
|
144
|
+
* {({ onClick }) => <button onClick={onClick}>Clear selection</button>}
|
|
145
|
+
* </LocationList.Actions.Clear>
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
const Clear = React.forwardRef((props, ref) => {
|
|
149
|
+
const { asChild, children, className, label = 'Clear', onClicked } = props;
|
|
150
|
+
let bookingService = null;
|
|
151
|
+
try {
|
|
152
|
+
bookingService = useService(BookingServiceDefinition);
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// BookingService not available - likely no ServiceManagerProvider
|
|
156
|
+
}
|
|
157
|
+
const handleClick = () => {
|
|
158
|
+
bookingService?.actions.clearLocation();
|
|
159
|
+
onClicked?.();
|
|
160
|
+
};
|
|
161
|
+
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.locationListActionClear, customElement: children, customElementProps: {
|
|
162
|
+
onClick: handleClick,
|
|
163
|
+
}, children: _jsx("button", { type: "button", onClick: handleClick, children: label }) }));
|
|
164
|
+
});
|
|
165
|
+
Clear.displayName = 'LocationList.Actions.Clear';
|
|
166
|
+
/**
|
|
167
|
+
* Actions namespace for location list-level actions
|
|
168
|
+
*/
|
|
169
|
+
export const Actions = {
|
|
170
|
+
Clear,
|
|
171
|
+
};
|