@wix/headless-bookings 0.0.43 → 0.0.44
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/api/index.d.ts +1 -0
- package/cjs/dist/api/index.js +1 -0
- package/cjs/dist/api/query-locations/index.d.ts +38 -0
- package/cjs/dist/api/query-locations/index.js +30 -0
- package/cjs/dist/react/core/location/Location.d.ts +113 -14
- package/cjs/dist/react/core/location/Location.js +189 -30
- package/cjs/dist/react/core/location-list/LocationList.d.ts +102 -0
- package/cjs/dist/react/core/location-list/LocationList.js +71 -0
- package/cjs/dist/react/index.d.ts +1 -0
- package/cjs/dist/react/index.js +1 -0
- package/cjs/dist/react/location/Location.d.ts +211 -41
- package/cjs/dist/react/location/Location.js +219 -46
- package/cjs/dist/react/location/LocationList.d.ts +98 -0
- package/cjs/dist/react/location/LocationList.js +120 -0
- package/cjs/dist/react/service/Service.d.ts +17 -24
- package/cjs/dist/react/service/Service.js +24 -36
- package/cjs/dist/services/index.d.ts +1 -0
- package/cjs/dist/services/index.js +1 -0
- package/cjs/dist/services/location-list/location-list.d.ts +100 -0
- package/cjs/dist/services/location-list/location-list.def.d.ts +62 -0
- package/cjs/dist/services/location-list/location-list.def.js +17 -0
- package/cjs/dist/services/location-list/location-list.js +212 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +1 -0
- package/dist/api/query-locations/index.d.ts +38 -0
- package/dist/api/query-locations/index.js +30 -0
- package/dist/react/core/location/Location.d.ts +113 -14
- package/dist/react/core/location/Location.js +189 -30
- package/dist/react/core/location-list/LocationList.d.ts +102 -0
- package/dist/react/core/location-list/LocationList.js +71 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +1 -0
- package/dist/react/location/Location.d.ts +211 -41
- package/dist/react/location/Location.js +219 -46
- package/dist/react/location/LocationList.d.ts +98 -0
- package/dist/react/location/LocationList.js +120 -0
- package/dist/react/service/Service.d.ts +17 -24
- package/dist/react/service/Service.js +24 -36
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/services/location-list/location-list.d.ts +100 -0
- package/dist/services/location-list/location-list.def.d.ts +62 -0
- package/dist/services/location-list/location-list.def.js +17 -0
- package/dist/services/location-list/location-list.js +212 -0
- package/package.json +2 -2
package/cjs/dist/api/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export { getServiceById, getServiceBySlug, queryServices, type PagingMetadata, t
|
|
|
8
8
|
export { fetchAvailability } from './fetch-availability/index.js';
|
|
9
9
|
export { createBooking, type CreateBookingOptions, type Booking, type CreateBookingRequest, type CreateBookingResponse, type ParticipantNotification, type ContactDetails, } from './create-booking/index.js';
|
|
10
10
|
export { createCheckout, ChannelType, type CreateCheckoutRequest, type CreateCheckoutResponse, } from './create-checkout/index.js';
|
|
11
|
+
export { queryLocations, type QueryLocationsResult, type LocationData, } from './query-locations/index.js';
|
|
11
12
|
/**
|
|
12
13
|
* PagingMetadata includes:
|
|
13
14
|
* - limit: Number of items per page
|
package/cjs/dist/api/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export { getServiceById, getServiceBySlug, queryServices, } from './query-servic
|
|
|
8
8
|
export { fetchAvailability } from './fetch-availability/index.js';
|
|
9
9
|
export { createBooking, } from './create-booking/index.js';
|
|
10
10
|
export { createCheckout, ChannelType, } from './create-checkout/index.js';
|
|
11
|
+
export { queryLocations, } from './query-locations/index.js';
|
|
11
12
|
/**
|
|
12
13
|
* PagingMetadata includes:
|
|
13
14
|
* - limit: Number of items per page
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query Locations API
|
|
3
|
+
* Fetches business locations from Wix Bookings Services
|
|
4
|
+
*
|
|
5
|
+
* @module API/QueryLocations
|
|
6
|
+
*/
|
|
7
|
+
import type { Service } from '@wix/auto_sdk_bookings_services';
|
|
8
|
+
/**
|
|
9
|
+
* LocationData type - from Service['locations'][number]
|
|
10
|
+
*/
|
|
11
|
+
export type LocationData = NonNullable<Service['locations']>[number];
|
|
12
|
+
/**
|
|
13
|
+
* Result from querying locations
|
|
14
|
+
*/
|
|
15
|
+
export interface QueryLocationsResult {
|
|
16
|
+
/** Business locations array */
|
|
17
|
+
locations: LocationData[];
|
|
18
|
+
/** Whether custom locations exist for any service */
|
|
19
|
+
hasCustomLocations: boolean;
|
|
20
|
+
/** Whether customer locations (at customer's place) exist for any service */
|
|
21
|
+
hasCustomerLocations: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Query all locations connected to services.
|
|
25
|
+
* Returns business locations array and existence flags for custom/customer locations.
|
|
26
|
+
*
|
|
27
|
+
* @returns Promise resolving to locations and existence flags
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* const { locations, hasCustomLocations, hasCustomerLocations } = await queryLocations();
|
|
32
|
+
*
|
|
33
|
+
* // locations contains all business locations
|
|
34
|
+
* // hasCustomLocations indicates if any service uses custom locations
|
|
35
|
+
* // hasCustomerLocations indicates if any service is at customer's place
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function queryLocations(): Promise<QueryLocationsResult>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query Locations API
|
|
3
|
+
* Fetches business locations from Wix Bookings Services
|
|
4
|
+
*
|
|
5
|
+
* @module API/QueryLocations
|
|
6
|
+
*/
|
|
7
|
+
import { queryLocations as queryLocationsApi, } from '@wix/auto_sdk_bookings_services';
|
|
8
|
+
/**
|
|
9
|
+
* Query all locations connected to services.
|
|
10
|
+
* Returns business locations array and existence flags for custom/customer locations.
|
|
11
|
+
*
|
|
12
|
+
* @returns Promise resolving to locations and existence flags
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const { locations, hasCustomLocations, hasCustomerLocations } = await queryLocations();
|
|
17
|
+
*
|
|
18
|
+
* // locations contains all business locations
|
|
19
|
+
* // hasCustomLocations indicates if any service uses custom locations
|
|
20
|
+
* // hasCustomerLocations indicates if any service is at customer's place
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export async function queryLocations() {
|
|
24
|
+
const response = await queryLocationsApi();
|
|
25
|
+
return {
|
|
26
|
+
locations: (response.businessLocations?.locations || []),
|
|
27
|
+
hasCustomLocations: response.customLocations?.exists || false,
|
|
28
|
+
hasCustomerLocations: response.customerLocations?.exists || false,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* Core Location Component - Parses service location data
|
|
3
3
|
* Handles business, custom, and customer location types
|
|
4
4
|
* Converts location data to Address component format
|
|
5
|
+
*
|
|
6
|
+
* @module Core/Location
|
|
5
7
|
*/
|
|
6
8
|
import React from 'react';
|
|
7
9
|
import { LocationType, type Service } from '@wix/auto_sdk_bookings_services';
|
|
@@ -10,35 +12,132 @@ import type { AddressData as AddressDataType } from '@wix/headless-components/re
|
|
|
10
12
|
* Re-export AddressData type from Address component for convenience
|
|
11
13
|
*/
|
|
12
14
|
export type AddressData = AddressDataType;
|
|
15
|
+
/**
|
|
16
|
+
* Service location type - from Service['locations'][number]
|
|
17
|
+
*/
|
|
18
|
+
export type ServiceLocation = NonNullable<Service['locations']>[number];
|
|
19
|
+
/**
|
|
20
|
+
* Synthetic location - represents a location type without real data
|
|
21
|
+
* Used for CUSTOMER or CUSTOM locations when no real location data exists
|
|
22
|
+
*/
|
|
23
|
+
export interface SyntheticLocation {
|
|
24
|
+
/** Location type */
|
|
25
|
+
locationType: LocationType.CUSTOMER | LocationType.CUSTOM;
|
|
26
|
+
/** Marker to identify synthetic locations */
|
|
27
|
+
synthetic: true;
|
|
28
|
+
/** Optional ID for tracking */
|
|
29
|
+
id?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Union type - location prop accepts Service or Synthetic location
|
|
33
|
+
*/
|
|
34
|
+
export type LocationInput = ServiceLocation | SyntheticLocation;
|
|
13
35
|
/**
|
|
14
36
|
* Location render props passed to children
|
|
15
37
|
*/
|
|
16
38
|
export interface LocationRenderProps {
|
|
39
|
+
/** Location type */
|
|
17
40
|
locationType: LocationType;
|
|
41
|
+
/** Parsed address data compatible with Address.Root, null if not available */
|
|
18
42
|
address: AddressData | null;
|
|
43
|
+
/** Location name (business.name or custom name) */
|
|
44
|
+
name: string | undefined;
|
|
45
|
+
/** Location ID */
|
|
46
|
+
locationId: string | undefined;
|
|
47
|
+
/** Whether this is a customer location */
|
|
48
|
+
isCustomerLocation: boolean;
|
|
49
|
+
/** Whether this is a custom location */
|
|
50
|
+
isCustomLocation: boolean;
|
|
51
|
+
/** Whether this is a synthetic entry (not from array) */
|
|
52
|
+
isSynthetic: boolean;
|
|
53
|
+
/** Phone number (only for BUSINESS ServiceLocations) */
|
|
54
|
+
phone: string | undefined;
|
|
55
|
+
/** Email address (only for BUSINESS ServiceLocations) */
|
|
56
|
+
email: string | undefined;
|
|
57
|
+
/** Raw location object (Service or Synthetic location) */
|
|
58
|
+
rawLocation: LocationInput | null;
|
|
19
59
|
}
|
|
20
60
|
/**
|
|
21
|
-
* Props for the
|
|
61
|
+
* Props for the Core Location Root component
|
|
22
62
|
*/
|
|
23
|
-
export interface
|
|
24
|
-
location
|
|
63
|
+
export interface RootProps {
|
|
64
|
+
/** Raw location data - accepts Service or Synthetic location */
|
|
65
|
+
location?: LocationInput;
|
|
66
|
+
/** Children */
|
|
67
|
+
children: React.ReactNode;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Props for the Core Location Data component
|
|
71
|
+
*/
|
|
72
|
+
export interface DataProps {
|
|
73
|
+
/** Children render prop that receives location data */
|
|
25
74
|
children: (props: LocationRenderProps) => React.ReactNode;
|
|
26
75
|
}
|
|
27
76
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
77
|
+
* Hook to access location context from CoreLocation.Root
|
|
78
|
+
* @throws Error if used outside of CoreLocation.Root
|
|
79
|
+
*/
|
|
80
|
+
export declare function useLocationContext(): LocationRenderProps;
|
|
81
|
+
/**
|
|
82
|
+
* Core Location Root component that provides location context.
|
|
83
|
+
* Parses location data and makes it available to all child components via context.
|
|
84
|
+
*
|
|
85
|
+
* @component
|
|
86
|
+
* @example
|
|
87
|
+
* ```tsx
|
|
88
|
+
* <CoreLocation.Root location={serviceLocation}>
|
|
89
|
+
* <Location.Name />
|
|
90
|
+
* <Location.Address />
|
|
91
|
+
* </CoreLocation.Root>
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export declare function Root(props: RootProps): React.ReactNode;
|
|
95
|
+
/**
|
|
96
|
+
* Core Location Data component that exposes location data via render props.
|
|
97
|
+
* Must be used within a CoreLocation.Root component.
|
|
98
|
+
*
|
|
99
|
+
* @component
|
|
100
|
+
* @example
|
|
101
|
+
* ```tsx
|
|
102
|
+
* <CoreLocation.Root location={serviceLocation}>
|
|
103
|
+
* <CoreLocation.Data>
|
|
104
|
+
* {({ displayName, address }) => (
|
|
105
|
+
* <div>
|
|
106
|
+
* <span>{displayName}</span>
|
|
107
|
+
* {address && <Address.Formatted address={address} />}
|
|
108
|
+
* </div>
|
|
109
|
+
* )}
|
|
110
|
+
* </CoreLocation.Data>
|
|
111
|
+
* </CoreLocation.Root>
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export declare function Data(props: DataProps): React.ReactNode;
|
|
115
|
+
/**
|
|
116
|
+
* Props for Actions render prop component
|
|
117
|
+
*/
|
|
118
|
+
export interface ActionsProps {
|
|
119
|
+
children: (actions: {
|
|
120
|
+
select: () => void;
|
|
121
|
+
rawLocation: LocationInput | null;
|
|
122
|
+
selected: boolean;
|
|
123
|
+
}) => React.ReactNode;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Core component that provides location selection actions via render props.
|
|
127
|
+
* Sets the location in BookingService when select is called.
|
|
30
128
|
*
|
|
31
129
|
* @component
|
|
32
130
|
* @example
|
|
33
131
|
* ```tsx
|
|
34
|
-
* <CoreLocation location={serviceLocation}>
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* <
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
132
|
+
* <CoreLocation.Root location={serviceLocation}>
|
|
133
|
+
* <CoreLocation.Actions>
|
|
134
|
+
* {({ select, selected, rawLocation }) => (
|
|
135
|
+
* <button onClick={select}>
|
|
136
|
+
* {selected ? 'Selected' : 'Select'}
|
|
137
|
+
* </button>
|
|
138
|
+
* )}
|
|
139
|
+
* </CoreLocation.Actions>
|
|
140
|
+
* </CoreLocation.Root>
|
|
42
141
|
* ```
|
|
43
142
|
*/
|
|
44
|
-
export declare function
|
|
143
|
+
export declare function Actions(props: ActionsProps): React.ReactNode;
|
|
@@ -1,26 +1,50 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
2
|
/**
|
|
2
3
|
* Core Location Component - Parses service location data
|
|
3
4
|
* Handles business, custom, and customer location types
|
|
4
5
|
* Converts location data to Address component format
|
|
6
|
+
*
|
|
7
|
+
* @module Core/Location
|
|
8
|
+
*/
|
|
9
|
+
import React, { createContext, useContext } from 'react';
|
|
10
|
+
import { useService } from '@wix/services-manager-react';
|
|
11
|
+
import { LocationType, } from '@wix/auto_sdk_bookings_services';
|
|
12
|
+
import { BookingServiceDefinition } from '../../../services/booking/booking.js';
|
|
13
|
+
// ==========================================
|
|
14
|
+
// Context
|
|
15
|
+
// ==========================================
|
|
16
|
+
/**
|
|
17
|
+
* Location context value - same as LocationRenderProps
|
|
18
|
+
*/
|
|
19
|
+
const LocationContext = createContext(null);
|
|
20
|
+
/**
|
|
21
|
+
* Hook to access location context from CoreLocation.Root
|
|
22
|
+
* @throws Error if used outside of CoreLocation.Root
|
|
5
23
|
*/
|
|
6
|
-
|
|
24
|
+
export function useLocationContext() {
|
|
25
|
+
const context = useContext(LocationContext);
|
|
26
|
+
if (!context) {
|
|
27
|
+
throw new Error('useLocationContext must be used within a CoreLocation.Root component');
|
|
28
|
+
}
|
|
29
|
+
return context;
|
|
30
|
+
}
|
|
31
|
+
// ==========================================
|
|
32
|
+
// Helper Functions
|
|
33
|
+
// ==========================================
|
|
34
|
+
/**
|
|
35
|
+
* Type guard to check if location is a Synthetic location.
|
|
36
|
+
* Synthetic locations have a `synthetic: true` marker.
|
|
37
|
+
*/
|
|
38
|
+
function isSyntheticLocation(location) {
|
|
39
|
+
return 'synthetic' in location && location.synthetic === true;
|
|
40
|
+
}
|
|
7
41
|
/**
|
|
8
|
-
* Parses
|
|
42
|
+
* Parses ServiceLocation data into Address component format
|
|
9
43
|
*/
|
|
10
44
|
function parseLocationAddress(location, locationType) {
|
|
11
|
-
// Handle customer location
|
|
45
|
+
// Handle customer location - return null, let consumer handle
|
|
12
46
|
if (locationType === LocationType.CUSTOMER) {
|
|
13
|
-
|
|
14
|
-
return {
|
|
15
|
-
address: {
|
|
16
|
-
addressLine: "Customer's Place",
|
|
17
|
-
formattedAddress: "Customer's Place",
|
|
18
|
-
city: '',
|
|
19
|
-
subdivision: '',
|
|
20
|
-
postalCode: '',
|
|
21
|
-
country: '',
|
|
22
|
-
},
|
|
23
|
-
};
|
|
47
|
+
return null;
|
|
24
48
|
}
|
|
25
49
|
// Get the common address from the appropriate location type
|
|
26
50
|
const commonAddress = location.calculatedAddress ||
|
|
@@ -29,7 +53,7 @@ function parseLocationAddress(location, locationType) {
|
|
|
29
53
|
if (!commonAddress) {
|
|
30
54
|
return null;
|
|
31
55
|
}
|
|
32
|
-
// Convert CommonAddress to AddressData format
|
|
56
|
+
// Convert CommonAddress to AddressData format
|
|
33
57
|
return {
|
|
34
58
|
address: {
|
|
35
59
|
addressLine: commonAddress.streetAddress?.name ||
|
|
@@ -50,29 +74,164 @@ function parseLocationAddress(location, locationType) {
|
|
|
50
74
|
},
|
|
51
75
|
};
|
|
52
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Get location type from ServiceLocation data
|
|
79
|
+
*/
|
|
80
|
+
function getLocationType(location) {
|
|
81
|
+
return location.type || LocationType.BUSINESS;
|
|
82
|
+
}
|
|
83
|
+
// ==========================================
|
|
84
|
+
// Helper function for computing render props
|
|
85
|
+
// ==========================================
|
|
86
|
+
/**
|
|
87
|
+
* Computes LocationRenderProps from location input
|
|
88
|
+
*/
|
|
89
|
+
function computeLocationRenderProps(rawLocation) {
|
|
90
|
+
// Handle no location
|
|
91
|
+
if (!rawLocation) {
|
|
92
|
+
return {
|
|
93
|
+
locationType: LocationType.BUSINESS,
|
|
94
|
+
address: null,
|
|
95
|
+
name: undefined,
|
|
96
|
+
locationId: undefined,
|
|
97
|
+
isCustomerLocation: false,
|
|
98
|
+
isCustomLocation: false,
|
|
99
|
+
isSynthetic: false,
|
|
100
|
+
phone: undefined,
|
|
101
|
+
email: undefined,
|
|
102
|
+
rawLocation: null,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
// Handle synthetic location
|
|
106
|
+
if (isSyntheticLocation(rawLocation)) {
|
|
107
|
+
const syntheticLoc = rawLocation;
|
|
108
|
+
const locationType = syntheticLoc.locationType;
|
|
109
|
+
return {
|
|
110
|
+
locationType,
|
|
111
|
+
address: null,
|
|
112
|
+
name: undefined,
|
|
113
|
+
locationId: syntheticLoc.id,
|
|
114
|
+
isCustomerLocation: locationType === LocationType.CUSTOMER,
|
|
115
|
+
isCustomLocation: locationType === LocationType.CUSTOM,
|
|
116
|
+
isSynthetic: true,
|
|
117
|
+
phone: undefined,
|
|
118
|
+
email: undefined,
|
|
119
|
+
rawLocation: syntheticLoc,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
// Handle Service location
|
|
123
|
+
const serviceLoc = rawLocation;
|
|
124
|
+
const locationType = getLocationType(serviceLoc);
|
|
125
|
+
return {
|
|
126
|
+
locationType,
|
|
127
|
+
address: parseLocationAddress(serviceLoc, locationType),
|
|
128
|
+
name: serviceLoc.business?.name ||
|
|
129
|
+
serviceLoc.custom?.address?.addressLine ||
|
|
130
|
+
'',
|
|
131
|
+
locationId: serviceLoc.business?._id || serviceLoc.custom?._id,
|
|
132
|
+
isCustomerLocation: locationType === LocationType.CUSTOMER,
|
|
133
|
+
isCustomLocation: locationType === LocationType.CUSTOM,
|
|
134
|
+
isSynthetic: false,
|
|
135
|
+
phone: serviceLoc.business?.phone ?? undefined,
|
|
136
|
+
email: serviceLoc.business?.email ?? undefined,
|
|
137
|
+
rawLocation,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
53
140
|
// ==========================================
|
|
54
|
-
// Component
|
|
141
|
+
// Root Component (Context Provider)
|
|
55
142
|
// ==========================================
|
|
56
143
|
/**
|
|
57
|
-
* Core Location component that
|
|
58
|
-
*
|
|
144
|
+
* Core Location Root component that provides location context.
|
|
145
|
+
* Parses location data and makes it available to all child components via context.
|
|
59
146
|
*
|
|
60
147
|
* @component
|
|
61
148
|
* @example
|
|
62
149
|
* ```tsx
|
|
63
|
-
* <CoreLocation location={serviceLocation}>
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
* {address && <Address.Root address={address}><Address.Formatted /></Address.Root>}
|
|
68
|
-
* </div>
|
|
69
|
-
* )}
|
|
70
|
-
* </CoreLocation>
|
|
150
|
+
* <CoreLocation.Root location={serviceLocation}>
|
|
151
|
+
* <Location.Name />
|
|
152
|
+
* <Location.Address />
|
|
153
|
+
* </CoreLocation.Root>
|
|
71
154
|
* ```
|
|
72
155
|
*/
|
|
73
|
-
export function
|
|
156
|
+
export function Root(props) {
|
|
74
157
|
const { location, children } = props;
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
158
|
+
const renderProps = computeLocationRenderProps(location);
|
|
159
|
+
return (_jsx(LocationContext.Provider, { value: renderProps, children: children }));
|
|
160
|
+
}
|
|
161
|
+
// ==========================================
|
|
162
|
+
// Data Component (Render Props)
|
|
163
|
+
// ==========================================
|
|
164
|
+
/**
|
|
165
|
+
* Core Location Data component that exposes location data via render props.
|
|
166
|
+
* Must be used within a CoreLocation.Root component.
|
|
167
|
+
*
|
|
168
|
+
* @component
|
|
169
|
+
* @example
|
|
170
|
+
* ```tsx
|
|
171
|
+
* <CoreLocation.Root location={serviceLocation}>
|
|
172
|
+
* <CoreLocation.Data>
|
|
173
|
+
* {({ displayName, address }) => (
|
|
174
|
+
* <div>
|
|
175
|
+
* <span>{displayName}</span>
|
|
176
|
+
* {address && <Address.Formatted address={address} />}
|
|
177
|
+
* </div>
|
|
178
|
+
* )}
|
|
179
|
+
* </CoreLocation.Data>
|
|
180
|
+
* </CoreLocation.Root>
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export function Data(props) {
|
|
184
|
+
const context = useLocationContext();
|
|
185
|
+
return props.children(context);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Core component that provides location selection actions via render props.
|
|
189
|
+
* Sets the location in BookingService when select is called.
|
|
190
|
+
*
|
|
191
|
+
* @component
|
|
192
|
+
* @example
|
|
193
|
+
* ```tsx
|
|
194
|
+
* <CoreLocation.Root location={serviceLocation}>
|
|
195
|
+
* <CoreLocation.Actions>
|
|
196
|
+
* {({ select, selected, rawLocation }) => (
|
|
197
|
+
* <button onClick={select}>
|
|
198
|
+
* {selected ? 'Selected' : 'Select'}
|
|
199
|
+
* </button>
|
|
200
|
+
* )}
|
|
201
|
+
* </CoreLocation.Actions>
|
|
202
|
+
* </CoreLocation.Root>
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
205
|
+
export function Actions(props) {
|
|
206
|
+
const { rawLocation } = useLocationContext();
|
|
207
|
+
// Try to get BookingService for setting location
|
|
208
|
+
let bookingService = null;
|
|
209
|
+
try {
|
|
210
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
211
|
+
bookingService = useService(BookingServiceDefinition);
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
bookingService = null;
|
|
215
|
+
}
|
|
216
|
+
// Compute selected state from BookingService
|
|
217
|
+
const selected = React.useMemo(() => {
|
|
218
|
+
if (!bookingService || !rawLocation)
|
|
219
|
+
return false;
|
|
220
|
+
const currentLocation = bookingService.location.get();
|
|
221
|
+
if (!currentLocation || !rawLocation)
|
|
222
|
+
return false;
|
|
223
|
+
// Compare by _id if available
|
|
224
|
+
return currentLocation._id === rawLocation._id;
|
|
225
|
+
}, [bookingService, rawLocation]);
|
|
226
|
+
const select = () => {
|
|
227
|
+
// Set location in BookingService
|
|
228
|
+
if (bookingService && rawLocation) {
|
|
229
|
+
bookingService.actions.setLocation(rawLocation);
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
return props.children({
|
|
233
|
+
select,
|
|
234
|
+
rawLocation,
|
|
235
|
+
selected,
|
|
236
|
+
});
|
|
78
237
|
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core LocationList Component
|
|
3
|
+
* Bridge between LocationListService and headless components using render props
|
|
4
|
+
*
|
|
5
|
+
* @module Core/LocationList
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { type LocationListServiceConfig } from '../../../services/location-list/location-list.js';
|
|
9
|
+
import type { LocationData, DisplayLocation } from '../../../services/location-list/location-list.def.js';
|
|
10
|
+
/**
|
|
11
|
+
* Props for LocationList.Root component
|
|
12
|
+
*/
|
|
13
|
+
export interface RootProps {
|
|
14
|
+
children: React.ReactNode;
|
|
15
|
+
locationListServiceConfig: LocationListServiceConfig;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Root component that provides LocationList service context
|
|
19
|
+
*
|
|
20
|
+
* @component
|
|
21
|
+
* @example
|
|
22
|
+
* ```tsx
|
|
23
|
+
* <CoreLocationList.Root locationListServiceConfig={config}>
|
|
24
|
+
* <CoreLocationList.Locations>
|
|
25
|
+
* {({ displayLocations }) => (
|
|
26
|
+
* // render locations
|
|
27
|
+
* )}
|
|
28
|
+
* </CoreLocationList.Locations>
|
|
29
|
+
* </CoreLocationList.Root>
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare function Root(props: RootProps): React.ReactNode;
|
|
33
|
+
/**
|
|
34
|
+
* Render props for Locations component
|
|
35
|
+
*/
|
|
36
|
+
export interface LocationsRenderProps {
|
|
37
|
+
/** Raw locations array from the service */
|
|
38
|
+
locations: LocationData[];
|
|
39
|
+
/** Processed display locations for UI */
|
|
40
|
+
displayLocations: DisplayLocation[];
|
|
41
|
+
/** Whether there are any locations */
|
|
42
|
+
hasLocations: boolean;
|
|
43
|
+
/** Whether custom locations exist */
|
|
44
|
+
hasCustomLocations: boolean;
|
|
45
|
+
/** Whether customer locations exist */
|
|
46
|
+
hasCustomerLocations: boolean;
|
|
47
|
+
/** Whether locations are currently loading */
|
|
48
|
+
isLoading: boolean;
|
|
49
|
+
/** Error message if any */
|
|
50
|
+
error: string | null;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Props for Locations render prop component
|
|
54
|
+
*/
|
|
55
|
+
export interface LocationsProps {
|
|
56
|
+
children: (data: LocationsRenderProps) => React.ReactNode;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Core component that provides access to locations list via render props
|
|
60
|
+
*
|
|
61
|
+
* @component
|
|
62
|
+
* @example
|
|
63
|
+
* ```tsx
|
|
64
|
+
* <CoreLocationList.Locations>
|
|
65
|
+
* {({ displayLocations, hasLocations, isLoading }) => (
|
|
66
|
+
* isLoading ? <Spinner /> : displayLocations.map(...)
|
|
67
|
+
* )}
|
|
68
|
+
* </CoreLocationList.Locations>
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export declare function Locations(props: LocationsProps): React.ReactNode;
|
|
72
|
+
/**
|
|
73
|
+
* Render props for Actions component
|
|
74
|
+
*/
|
|
75
|
+
export interface ActionsRenderProps {
|
|
76
|
+
/** Select a display location */
|
|
77
|
+
select: (displayLocation: DisplayLocation) => void;
|
|
78
|
+
/** Currently selected location (from BookingService) */
|
|
79
|
+
selectedLocation: LocationData | null;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Props for Actions render prop component
|
|
83
|
+
*/
|
|
84
|
+
export interface ActionsProps {
|
|
85
|
+
children: (actions: ActionsRenderProps) => React.ReactNode;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Core component that provides location actions via render props
|
|
89
|
+
*
|
|
90
|
+
* @component
|
|
91
|
+
* @example
|
|
92
|
+
* ```tsx
|
|
93
|
+
* <CoreLocationList.Actions>
|
|
94
|
+
* {({ select, selectedLocation }) => (
|
|
95
|
+
* <button onClick={() => select(displayLoc)}>
|
|
96
|
+
* {selectedLocation?.business?.name || 'Select'}
|
|
97
|
+
* </button>
|
|
98
|
+
* )}
|
|
99
|
+
* </CoreLocationList.Actions>
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export declare function Actions(props: ActionsProps): React.ReactNode;
|
|
@@ -0,0 +1,71 @@
|
|
|
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 { LocationListServiceDefinition, LocationListService, } from '../../../services/location-list/location-list.js';
|
|
5
|
+
/**
|
|
6
|
+
* Root component that provides LocationList service context
|
|
7
|
+
*
|
|
8
|
+
* @component
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* <CoreLocationList.Root locationListServiceConfig={config}>
|
|
12
|
+
* <CoreLocationList.Locations>
|
|
13
|
+
* {({ displayLocations }) => (
|
|
14
|
+
* // render locations
|
|
15
|
+
* )}
|
|
16
|
+
* </CoreLocationList.Locations>
|
|
17
|
+
* </CoreLocationList.Root>
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export function Root(props) {
|
|
21
|
+
return (_jsx(WixServices, { servicesMap: createServicesMap().addService(LocationListServiceDefinition, LocationListService, props.locationListServiceConfig), children: props.children }));
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Core component that provides access to locations list via render props
|
|
25
|
+
*
|
|
26
|
+
* @component
|
|
27
|
+
* @example
|
|
28
|
+
* ```tsx
|
|
29
|
+
* <CoreLocationList.Locations>
|
|
30
|
+
* {({ displayLocations, hasLocations, isLoading }) => (
|
|
31
|
+
* isLoading ? <Spinner /> : displayLocations.map(...)
|
|
32
|
+
* )}
|
|
33
|
+
* </CoreLocationList.Locations>
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export function Locations(props) {
|
|
37
|
+
const service = useService(LocationListServiceDefinition);
|
|
38
|
+
const locations = service.locations.get();
|
|
39
|
+
const displayLocations = service.displayLocations.get();
|
|
40
|
+
return props.children({
|
|
41
|
+
locations,
|
|
42
|
+
displayLocations,
|
|
43
|
+
hasLocations: displayLocations.length > 0,
|
|
44
|
+
hasCustomLocations: service.hasCustomLocations.get(),
|
|
45
|
+
hasCustomerLocations: service.hasCustomerLocations.get(),
|
|
46
|
+
isLoading: service.isLoading.get(),
|
|
47
|
+
error: service.error.get(),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Core component that provides location actions via render props
|
|
52
|
+
*
|
|
53
|
+
* @component
|
|
54
|
+
* @example
|
|
55
|
+
* ```tsx
|
|
56
|
+
* <CoreLocationList.Actions>
|
|
57
|
+
* {({ select, selectedLocation }) => (
|
|
58
|
+
* <button onClick={() => select(displayLoc)}>
|
|
59
|
+
* {selectedLocation?.business?.name || 'Select'}
|
|
60
|
+
* </button>
|
|
61
|
+
* )}
|
|
62
|
+
* </CoreLocationList.Actions>
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export function Actions(props) {
|
|
66
|
+
const service = useService(LocationListServiceDefinition);
|
|
67
|
+
return props.children({
|
|
68
|
+
select: service.actions.select,
|
|
69
|
+
selectedLocation: service.selectedLocation.get(),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
@@ -5,4 +5,5 @@ export * as ServiceMedia from './service/ServiceMedia.js';
|
|
|
5
5
|
export * as TimeSlotList from './time-slot-list/TimeSlotList.js';
|
|
6
6
|
export * as ServiceList from './service-list/ServiceList.js';
|
|
7
7
|
export * as Location from './location/Location.js';
|
|
8
|
+
export * as LocationList from './location/LocationList.js';
|
|
8
9
|
export * as Payment from './payment/Payment.js';
|
package/cjs/dist/react/index.js
CHANGED
|
@@ -5,4 +5,5 @@ export * as ServiceMedia from './service/ServiceMedia.js';
|
|
|
5
5
|
export * as TimeSlotList from './time-slot-list/TimeSlotList.js';
|
|
6
6
|
export * as ServiceList from './service-list/ServiceList.js';
|
|
7
7
|
export * as Location from './location/Location.js';
|
|
8
|
+
export * as LocationList from './location/LocationList.js';
|
|
8
9
|
export * as Payment from './payment/Payment.js';
|