@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.
Files changed (55) hide show
  1. package/cjs/dist/__mocks__/booking.js +1 -0
  2. package/cjs/dist/__mocks__/services.d.ts +38 -1
  3. package/cjs/dist/__mocks__/services.js +82 -0
  4. package/cjs/dist/api/query-services/index.js +5 -1
  5. package/cjs/dist/react/core/staff-member/StaffMember.d.ts +104 -0
  6. package/cjs/dist/react/core/staff-member/StaffMember.js +143 -0
  7. package/cjs/dist/react/core/staff-member-list/StaffMemberList.d.ts +96 -0
  8. package/cjs/dist/react/core/staff-member-list/StaffMemberList.js +66 -0
  9. package/cjs/dist/react/index.d.ts +2 -0
  10. package/cjs/dist/react/index.js +2 -0
  11. package/cjs/dist/react/location/LocationList.d.ts +19 -0
  12. package/cjs/dist/react/location/LocationList.js +51 -0
  13. package/cjs/dist/react/service/Service.d.ts +16 -44
  14. package/cjs/dist/react/service/Service.js +23 -37
  15. package/cjs/dist/react/staff-member/StaffMember.d.ts +119 -0
  16. package/cjs/dist/react/staff-member/StaffMember.js +147 -0
  17. package/cjs/dist/react/staff-member/StaffMemberList.d.ts +123 -0
  18. package/cjs/dist/react/staff-member/StaffMemberList.js +168 -0
  19. package/cjs/dist/services/booking/book-action/buildBookingRequest.js +1 -0
  20. package/cjs/dist/services/booking/booking.d.ts +2 -0
  21. package/cjs/dist/services/booking/booking.js +15 -0
  22. package/cjs/dist/services/index.d.ts +1 -0
  23. package/cjs/dist/services/index.js +1 -0
  24. package/cjs/dist/services/staff-member-list/staff-member-list.d.ts +85 -0
  25. package/cjs/dist/services/staff-member-list/staff-member-list.def.d.ts +46 -0
  26. package/cjs/dist/services/staff-member-list/staff-member-list.def.js +14 -0
  27. package/cjs/dist/services/staff-member-list/staff-member-list.js +105 -0
  28. package/dist/__mocks__/booking.js +1 -0
  29. package/dist/__mocks__/services.d.ts +38 -1
  30. package/dist/__mocks__/services.js +82 -0
  31. package/dist/api/query-services/index.js +5 -1
  32. package/dist/react/core/staff-member/StaffMember.d.ts +104 -0
  33. package/dist/react/core/staff-member/StaffMember.js +143 -0
  34. package/dist/react/core/staff-member-list/StaffMemberList.d.ts +96 -0
  35. package/dist/react/core/staff-member-list/StaffMemberList.js +66 -0
  36. package/dist/react/index.d.ts +2 -0
  37. package/dist/react/index.js +2 -0
  38. package/dist/react/location/LocationList.d.ts +19 -0
  39. package/dist/react/location/LocationList.js +51 -0
  40. package/dist/react/service/Service.d.ts +16 -44
  41. package/dist/react/service/Service.js +23 -37
  42. package/dist/react/staff-member/StaffMember.d.ts +119 -0
  43. package/dist/react/staff-member/StaffMember.js +147 -0
  44. package/dist/react/staff-member/StaffMemberList.d.ts +123 -0
  45. package/dist/react/staff-member/StaffMemberList.js +168 -0
  46. package/dist/services/booking/book-action/buildBookingRequest.js +1 -0
  47. package/dist/services/booking/booking.d.ts +2 -0
  48. package/dist/services/booking/booking.js +15 -0
  49. package/dist/services/index.d.ts +1 -0
  50. package/dist/services/index.js +1 -0
  51. package/dist/services/staff-member-list/staff-member-list.d.ts +85 -0
  52. package/dist/services/staff-member-list/staff-member-list.def.d.ts +46 -0
  53. package/dist/services/staff-member-list/staff-member-list.def.js +14 -0
  54. package/dist/services/staff-member-list/staff-member-list.js +105 -0
  55. package/package.json +2 -2
@@ -0,0 +1,168 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * StaffMemberList - High-level component for displaying staff member lists
4
+ * Follows the pattern from LocationList.tsx
5
+ *
6
+ * @module React/StaffMemberList
7
+ */
8
+ import React from 'react';
9
+ import { GenericList, } from '@wix/headless-components/react';
10
+ import { AsChildSlot } from '@wix/headless-utils/react';
11
+ import { useService } from '@wix/services-manager-react';
12
+ import { BookingServiceDefinition } from '../../services/booking/booking.js';
13
+ import * as CoreStaffMemberList from '../core/staff-member-list/StaffMemberList.js';
14
+ import * as StaffMember from './StaffMember.js';
15
+ /** Resource type ID for staff members */
16
+ const STAFF_MEMBER_RESOURCE_TYPE_ID = '1cd44cf8-756f-41c3-bd90-3e2ffcaf1155';
17
+ // ============================================================================
18
+ // TestIds
19
+ // ============================================================================
20
+ var TestIds;
21
+ (function (TestIds) {
22
+ TestIds["staffMemberListRoot"] = "staff-member-list-root";
23
+ TestIds["staffMemberListStaffMembers"] = "staff-member-list-staff-members";
24
+ TestIds["staffMemberListStaffMember"] = "staff-member-list-staff-member";
25
+ TestIds["staffMemberListActionClear"] = "staff-member-list-action-clear";
26
+ })(TestIds || (TestIds = {}));
27
+ /**
28
+ * Root component that provides the StaffMemberList service context for rendering staff member lists.
29
+ *
30
+ * @component
31
+ * @example
32
+ * ```tsx
33
+ * import { StaffMemberList, StaffMember } from '@wix/bookings/react';
34
+ *
35
+ * function StaffMembersPage({ staffMemberListConfig }) {
36
+ * return (
37
+ * <StaffMemberList.Root staffMemberListConfig={staffMemberListConfig}>
38
+ * <StaffMemberList.StaffMembers emptyState={<div>No staff members available</div>}>
39
+ * <StaffMemberList.StaffMemberRepeater>
40
+ * <StaffMember.Name />
41
+ * </StaffMemberList.StaffMemberRepeater>
42
+ * </StaffMemberList.StaffMembers>
43
+ * </StaffMemberList.Root>
44
+ * );
45
+ * }
46
+ * ```
47
+ */
48
+ export const Root = React.forwardRef((props, ref) => {
49
+ const { children, staffMemberListConfig, className, variant } = props;
50
+ const config = staffMemberListConfig || {
51
+ staffMembers: [],
52
+ };
53
+ return (_jsx(CoreStaffMemberList.Root, { staffMemberListServiceConfig: config, children: _jsx(RootContent, { className: className, ref: ref, variant: variant, children: children }) }));
54
+ });
55
+ Root.displayName = 'StaffMemberList.Root';
56
+ /**
57
+ * Internal component to handle the Root content with service access
58
+ */
59
+ const RootContent = React.forwardRef((props, ref) => {
60
+ const { children, className, variant } = props;
61
+ return (_jsx(CoreStaffMemberList.StaffMembers, { children: ({ staffMembers, isLoading }) => {
62
+ // Add id to each staff member for GenericList (staffMemberId equals resource id)
63
+ const itemsWithId = staffMembers.map((staffMember, index) => ({
64
+ ...staffMember,
65
+ id: staffMember.staffMemberId || String(index),
66
+ }));
67
+ return (_jsx(GenericList.Root, { items: itemsWithId, hasMore: false, isLoading: isLoading, className: className, ref: ref, "data-testid": TestIds.staffMemberListRoot, variant: variant, children: children }));
68
+ } }));
69
+ });
70
+ RootContent.displayName = 'StaffMemberList.RootContent';
71
+ /**
72
+ * Container for the staff members list with empty state support.
73
+ * Wraps GenericList.Items internally (no separate Items export).
74
+ *
75
+ * @component
76
+ * @example
77
+ * ```tsx
78
+ * <StaffMemberList.StaffMembers emptyState={<div>No staff members available</div>}>
79
+ * <StaffMemberList.StaffMemberRepeater>
80
+ * <StaffMember.Name />
81
+ * </StaffMemberList.StaffMemberRepeater>
82
+ * </StaffMemberList.StaffMembers>
83
+ * ```
84
+ */
85
+ export const StaffMembers = React.forwardRef((props, ref) => {
86
+ const { children, ...otherProps } = props;
87
+ return (_jsx(GenericList.Items, { ref: ref, "data-testid": TestIds.staffMemberListStaffMembers, ...otherProps, children: children }));
88
+ });
89
+ StaffMembers.displayName = 'StaffMemberList.StaffMembers';
90
+ export const StaffMemberRepeater = React.forwardRef((props, ref) => {
91
+ const { children } = props;
92
+ // Custom itemWrapper that wraps each item in StaffMember.Root
93
+ const staffMemberItemWrapper = ({ item: staffMemberWithId, children: itemChildren, }) => {
94
+ return (_jsx(StaffMember.Root, { staffMember: staffMemberWithId, "data-testid": TestIds.staffMemberListStaffMember, "data-staff-member-id": staffMemberWithId.id, "data-item-id": staffMemberWithId.id, children: itemChildren }, staffMemberWithId.id));
95
+ };
96
+ return (_jsx(GenericList.Repeater, { ref: ref, itemWrapper: staffMemberItemWrapper, children: children }));
97
+ });
98
+ StaffMemberRepeater.displayName = 'StaffMemberList.StaffMemberRepeater';
99
+ /**
100
+ * Displays the total count of staff members.
101
+ *
102
+ * @component
103
+ * @example
104
+ * ```tsx
105
+ * <StaffMemberList.Totals />
106
+ *
107
+ * // With asChild
108
+ * <StaffMemberList.Totals asChild>
109
+ * {({ count }) => <span>{count} staff members available</span>}
110
+ * </StaffMemberList.Totals>
111
+ * ```
112
+ */
113
+ export const Totals = React.forwardRef((props, ref) => {
114
+ const { asChild, children, className, ...attrs } = props;
115
+ return (_jsx(CoreStaffMemberList.StaffMembers, { children: ({ staffMembers, hasStaffMembers }) => {
116
+ const count = staffMembers.length;
117
+ return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, customElement: children, customElementProps: { count, hasStaffMembers }, ...attrs, children: _jsx("span", { children: count }) }));
118
+ } }));
119
+ });
120
+ Totals.displayName = 'StaffMemberList.Totals';
121
+ /**
122
+ * Button to clear the staff member selection.
123
+ * Clears the staff member resource from the BookingService.
124
+ *
125
+ * @component
126
+ * @example
127
+ * ```tsx
128
+ * // Default button with "Clear" label
129
+ * <StaffMemberList.Actions.Clear />
130
+ *
131
+ * // With custom label
132
+ * <StaffMemberList.Actions.Clear label="Clear selection" />
133
+ *
134
+ * // With asChild
135
+ * <StaffMemberList.Actions.Clear asChild>
136
+ * <button className="btn-secondary">Clear staff</button>
137
+ * </StaffMemberList.Actions.Clear>
138
+ *
139
+ * // Using render prop pattern
140
+ * <StaffMemberList.Actions.Clear>
141
+ * {({ onClick }) => <button onClick={onClick}>Clear selection</button>}
142
+ * </StaffMemberList.Actions.Clear>
143
+ * ```
144
+ */
145
+ const Clear = React.forwardRef((props, ref) => {
146
+ const { asChild, children, className, label = 'Clear', onClicked } = props;
147
+ let bookingService = null;
148
+ try {
149
+ bookingService = useService(BookingServiceDefinition);
150
+ }
151
+ catch {
152
+ // BookingService not available - likely no ServiceManagerProvider
153
+ }
154
+ const handleClick = () => {
155
+ bookingService?.actions.clearResourceById(STAFF_MEMBER_RESOURCE_TYPE_ID);
156
+ onClicked?.();
157
+ };
158
+ return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.staffMemberListActionClear, customElement: children, customElementProps: {
159
+ onClick: handleClick,
160
+ }, children: _jsx("button", { type: "button", onClick: handleClick, children: label }) }));
161
+ });
162
+ Clear.displayName = 'StaffMemberList.Actions.Clear';
163
+ /**
164
+ * Actions namespace for staff member list-level actions
165
+ */
166
+ export const Actions = {
167
+ Clear,
168
+ };
@@ -81,6 +81,7 @@ export function buildBookingRequest(params) {
81
81
  },
82
82
  },
83
83
  participantNotification: {
84
+ metadata: { channels: 'EMAIL,SMS' },
84
85
  notifyParticipants: true,
85
86
  },
86
87
  sendSmsReminder: true,
@@ -57,6 +57,8 @@ export interface BookingServiceActions {
57
57
  setResourceById(resourceId: string, resource: Resource, instanceId?: string): void;
58
58
  /** Gets a resource by ID from a service selection. If no instanceId provided, uses the first item. */
59
59
  getResourceById(resourceId: string, instanceId?: string): Resource | undefined;
60
+ /** Clears a resource by ID from a service selection. If no instanceId provided, uses the first item. */
61
+ clearResourceById(resourceId: string, instanceId?: string): void;
60
62
  setLocation(location: ServiceLocationType | null): void;
61
63
  clearLocation(): void;
62
64
  setTimezone(timezone: string): void;
@@ -149,6 +149,21 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
149
149
  return undefined;
150
150
  return targetItem.resources.find((r) => r._id === resourceId);
151
151
  },
152
+ clearResourceById(resourceId, instanceId) {
153
+ const current = serviceSelectionsSignal.get();
154
+ // If no instanceId provided, use the first item
155
+ const targetId = instanceId ?? current[0]?.instanceId;
156
+ if (!targetId)
157
+ return;
158
+ const updated = current.map((item) => {
159
+ if (item.instanceId !== targetId)
160
+ return item;
161
+ // Filter out the resource with matching ID
162
+ const newResources = item.resources.filter((r) => r._id !== resourceId);
163
+ return { ...item, resources: newResources };
164
+ });
165
+ serviceSelectionsSignal.set(updated);
166
+ },
152
167
  // Location actions
153
168
  setLocation(location) {
154
169
  locationSignal.set(location);
@@ -10,3 +10,4 @@ export { executeBookAction, canBook, buildBookingRequest, buildCheckoutRequest,
10
10
  export { BookingFormService, BookingFormServiceDefinition, type BookingFormServiceAPI, type BookingFormServiceConfig, type BookingFormServiceInternalAPI, type ValidationResult, } from './booking-form/booking-form.js';
11
11
  export { PaymentService, PaymentServiceDefinition, type PaymentServiceAPI, type PaymentServiceConfig, type PaymentDetails, type SlotService, type LineItemAdditionalInfo, loadPaymentConfig, type SuccessPaymentConfigResult, type ErrorPaymentConfigResult, } from './payment/payment.js';
12
12
  export { LocationListService, LocationListServiceDefinition, LocationType, loadLocationListServiceInitialData, locationListServiceBinding, type LocationListServiceAPI, type LocationListServiceConfig, type LocationListActions, type LocationData, type DisplayLocation, type LoadLocationListServiceResult, } from './location-list/location-list.js';
13
+ export { StaffMemberListService, StaffMemberListServiceDefinition, loadStaffMemberListServiceInitialData, staffMemberListServiceBinding, type StaffMemberListServiceAPI, type StaffMemberListServiceConfig, type StaffMemberListActions, type StaffMemberData, type LoadStaffMemberListServiceResult, } from './staff-member-list/staff-member-list.js';
@@ -10,3 +10,4 @@ export { executeBookAction, canBook, buildBookingRequest, buildCheckoutRequest,
10
10
  export { BookingFormService, BookingFormServiceDefinition, } from './booking-form/booking-form.js';
11
11
  export { PaymentService, PaymentServiceDefinition, loadPaymentConfig, } from './payment/payment.js';
12
12
  export { LocationListService, LocationListServiceDefinition, LocationType, loadLocationListServiceInitialData, locationListServiceBinding, } from './location-list/location-list.js';
13
+ export { StaffMemberListService, StaffMemberListServiceDefinition, loadStaffMemberListServiceInitialData, staffMemberListServiceBinding, } from './staff-member-list/staff-member-list.js';
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Staff Member List Service Implementation
3
+ * Manages staff member state and BookingService integration
4
+ *
5
+ * @module Services/StaffMemberList
6
+ */
7
+ import type { ServiceFactoryConfig } from '@wix/services-definitions';
8
+ import { type StaffMemberData } from './staff-member-list.def.js';
9
+ /**
10
+ * Configuration interface for StaffMemberListService
11
+ */
12
+ export interface StaffMemberListServiceConfig {
13
+ /** Staff members array */
14
+ staffMembers?: StaffMemberData[];
15
+ }
16
+ /**
17
+ * Implementation of the StaffMemberList service
18
+ * Manages staff member state for display purposes
19
+ */
20
+ export declare const StaffMemberListService: import("@wix/services-definitions").ServiceFactory<string & {
21
+ __api: import("./staff-member-list.def.js").StaffMemberListServiceAPI;
22
+ __config: {};
23
+ isServiceDefinition?: boolean;
24
+ } & import("./staff-member-list.def.js").StaffMemberListServiceAPI, StaffMemberListServiceConfig>;
25
+ /**
26
+ * Result type for SSR loader
27
+ */
28
+ export type LoadStaffMemberListServiceResult = {
29
+ type: 'success';
30
+ config: StaffMemberListServiceConfig;
31
+ } | {
32
+ type: 'error';
33
+ error: string;
34
+ };
35
+ /**
36
+ * SSR Loader: Creates configuration for server-side rendering.
37
+ *
38
+ * @param options - Optional configuration
39
+ * @returns Configuration result for StaffMemberListService
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * // Pass staff members directly (e.g., from service.staffMemberDetails.staffMembers)
44
+ * const result = await loadStaffMemberListServiceInitialData({
45
+ * staffMembers: service.staffMemberDetails?.staffMembers,
46
+ * });
47
+ *
48
+ * if (result.type === 'error') {
49
+ * return Astro.redirect('/500');
50
+ * }
51
+ *
52
+ * const staffMemberListConfig = result.config;
53
+ * ```
54
+ */
55
+ export declare function loadStaffMemberListServiceInitialData(options?: {
56
+ /** Pass staff members directly */
57
+ staffMembers?: StaffMemberData[];
58
+ }): Promise<LoadStaffMemberListServiceResult>;
59
+ /**
60
+ * Service binding helper for StaffMemberListService.
61
+ * Bundles definition, implementation, and config for ServicesManager.
62
+ *
63
+ * @param servicesConfigs - Object containing StaffMemberListServiceDefinition config
64
+ * @returns Tuple of [Definition, Implementation, Config] for addService()
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * const servicesManager = createServicesManager(
69
+ * createServicesMap()
70
+ * .addService(...staffMemberListServiceBinding(configs))
71
+ * );
72
+ * ```
73
+ */
74
+ export declare const staffMemberListServiceBinding: <T extends {
75
+ [key: string]: StaffMemberListServiceConfig;
76
+ }>(servicesConfigs: T) => readonly [string & {
77
+ __api: import("./staff-member-list.def.js").StaffMemberListServiceAPI;
78
+ __config: {};
79
+ isServiceDefinition?: boolean;
80
+ } & import("./staff-member-list.def.js").StaffMemberListServiceAPI, import("@wix/services-definitions").ServiceFactory<string & {
81
+ __api: import("./staff-member-list.def.js").StaffMemberListServiceAPI;
82
+ __config: {};
83
+ isServiceDefinition?: boolean;
84
+ } & import("./staff-member-list.def.js").StaffMemberListServiceAPI, StaffMemberListServiceConfig>, StaffMemberListServiceConfig];
85
+ export { StaffMemberListServiceDefinition, type StaffMemberData, type StaffMemberListActions, type StaffMemberListServiceAPI, } from './staff-member-list.def.js';
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Staff Member List Service Definition
3
+ * Defines types and service interface for managing staff member lists
4
+ *
5
+ * @module Services/StaffMemberList/Definition
6
+ */
7
+ import type { Signal, ReadOnlySignal } from '@wix/services-definitions/core-services/signals';
8
+ import type { StaffMember } from '@wix/auto_sdk_bookings_services';
9
+ /**
10
+ * StaffMemberData type - from Service['staffMemberDetails']['staffMembers'][number]
11
+ * Contains staffMemberId (which equals resource id), name, and mainMedia
12
+ */
13
+ export type StaffMemberData = StaffMember;
14
+ /**
15
+ * Actions interface for staff member list management
16
+ */
17
+ export interface StaffMemberListActions {
18
+ /** Select a staff member */
19
+ select: (staffMember: StaffMemberData) => void;
20
+ }
21
+ /**
22
+ * API interface for the StaffMemberList service
23
+ */
24
+ export interface StaffMemberListServiceAPI {
25
+ /** Reactive signal containing the staff members array */
26
+ staffMembers: Signal<StaffMemberData[]>;
27
+ /** Whether there are any staff members */
28
+ hasStaffMembers: ReadOnlySignal<boolean>;
29
+ /** Reactive signal indicating if staff members are loading */
30
+ isLoading: Signal<boolean>;
31
+ /** Reactive signal containing any error message */
32
+ error: Signal<string | null>;
33
+ /** Computed signal for selected staff member */
34
+ selectedStaffMember: ReadOnlySignal<StaffMemberData | null>;
35
+ /** Actions for staff member management */
36
+ actions: StaffMemberListActions;
37
+ }
38
+ /**
39
+ * Service definition for StaffMemberList
40
+ */
41
+ export declare const StaffMemberListServiceDefinition: string & {
42
+ __api: StaffMemberListServiceAPI;
43
+ __config: {};
44
+ isServiceDefinition?: boolean;
45
+ } & StaffMemberListServiceAPI;
46
+ export type { StaffMember };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Staff Member List Service Definition
3
+ * Defines types and service interface for managing staff member lists
4
+ *
5
+ * @module Services/StaffMemberList/Definition
6
+ */
7
+ import { defineService } from '@wix/services-definitions';
8
+ // ============================================================================
9
+ // Service Definition
10
+ // ============================================================================
11
+ /**
12
+ * Service definition for StaffMemberList
13
+ */
14
+ export const StaffMemberListServiceDefinition = defineService('staff-member-list');
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Staff Member List Service Implementation
3
+ * Manages staff member state and BookingService integration
4
+ *
5
+ * @module Services/StaffMemberList
6
+ */
7
+ import { implementService } from '@wix/services-definitions';
8
+ import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
9
+ import { StaffMemberListServiceDefinition, } from './staff-member-list.def.js';
10
+ // ============================================================================
11
+ // Service Implementation
12
+ // ============================================================================
13
+ /**
14
+ * Implementation of the StaffMemberList service
15
+ * Manages staff member state for display purposes
16
+ */
17
+ export const StaffMemberListService = implementService.withConfig()(StaffMemberListServiceDefinition, ({ getService, config }) => {
18
+ const signalsService = getService(SignalsServiceDefinition);
19
+ // Initialize staff members signal
20
+ const staffMembersSignal = signalsService.signal(config.staffMembers || []);
21
+ // Has staff members signal
22
+ const hasStaffMembersSignal = signalsService.computed(() => staffMembersSignal.get().length > 0);
23
+ const isLoadingSignal = signalsService.signal(false);
24
+ const errorSignal = signalsService.signal(null);
25
+ // Selected staff member - managed locally
26
+ const selectedStaffMemberSignal = signalsService.signal(null);
27
+ // Actions
28
+ const actions = {
29
+ select: (staffMember) => {
30
+ selectedStaffMemberSignal.set(staffMember);
31
+ },
32
+ };
33
+ return {
34
+ staffMembers: staffMembersSignal,
35
+ hasStaffMembers: hasStaffMembersSignal,
36
+ isLoading: isLoadingSignal,
37
+ error: errorSignal,
38
+ selectedStaffMember: selectedStaffMemberSignal,
39
+ actions,
40
+ };
41
+ });
42
+ /**
43
+ * SSR Loader: Creates configuration for server-side rendering.
44
+ *
45
+ * @param options - Optional configuration
46
+ * @returns Configuration result for StaffMemberListService
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * // Pass staff members directly (e.g., from service.staffMemberDetails.staffMembers)
51
+ * const result = await loadStaffMemberListServiceInitialData({
52
+ * staffMembers: service.staffMemberDetails?.staffMembers,
53
+ * });
54
+ *
55
+ * if (result.type === 'error') {
56
+ * return Astro.redirect('/500');
57
+ * }
58
+ *
59
+ * const staffMemberListConfig = result.config;
60
+ * ```
61
+ */
62
+ export async function loadStaffMemberListServiceInitialData(options) {
63
+ try {
64
+ return {
65
+ type: 'success',
66
+ config: {
67
+ staffMembers: options?.staffMembers || [],
68
+ },
69
+ };
70
+ }
71
+ catch (error) {
72
+ const message = error instanceof Error ? error.message : 'Failed to load staff members';
73
+ console.error('loadStaffMemberListServiceInitialData error:', error);
74
+ return { type: 'error', error: message };
75
+ }
76
+ }
77
+ // ============================================================================
78
+ // Service Binding Helper
79
+ // ============================================================================
80
+ /**
81
+ * Service binding helper for StaffMemberListService.
82
+ * Bundles definition, implementation, and config for ServicesManager.
83
+ *
84
+ * @param servicesConfigs - Object containing StaffMemberListServiceDefinition config
85
+ * @returns Tuple of [Definition, Implementation, Config] for addService()
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * const servicesManager = createServicesManager(
90
+ * createServicesMap()
91
+ * .addService(...staffMemberListServiceBinding(configs))
92
+ * );
93
+ * ```
94
+ */
95
+ export const staffMemberListServiceBinding = (servicesConfigs) => {
96
+ return [
97
+ StaffMemberListServiceDefinition,
98
+ StaffMemberListService,
99
+ servicesConfigs['staff-member-list'],
100
+ ];
101
+ };
102
+ // ============================================================================
103
+ // Re-exports
104
+ // ============================================================================
105
+ export { StaffMemberListServiceDefinition, } from './staff-member-list.def.js';
@@ -37,6 +37,7 @@ export function createMockBookingService(initialSelections = []) {
37
37
  clearItems: vi.fn(),
38
38
  setResourceById: vi.fn(),
39
39
  getResourceById: vi.fn(),
40
+ clearResourceById: vi.fn(),
40
41
  setLocation: vi.fn(),
41
42
  clearLocation: vi.fn(),
42
43
  setTimezone: vi.fn(),
@@ -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
- const result = await queryServicesApi(queryRequest).find();
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 = {