@wix/headless-bookings 0.0.9 → 0.0.11
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 +10 -1
- package/cjs/dist/api/index.js +10 -1
- package/cjs/dist/api/query-services/index.d.ts +78 -0
- package/cjs/dist/api/query-services/index.js +137 -0
- package/cjs/dist/react/core/booking/Booking.d.ts +4 -4
- package/cjs/dist/react/core/booking/Booking.js +3 -3
- package/cjs/dist/react/core/location/Location.d.ts +44 -0
- package/cjs/dist/react/core/location/Location.js +78 -0
- package/cjs/dist/react/core/service/Service.d.ts +160 -17
- package/cjs/dist/react/core/service/Service.js +211 -13
- package/cjs/dist/react/core/service-list/ServiceList.d.ts +75 -0
- package/cjs/dist/react/core/service-list/ServiceList.js +58 -0
- package/cjs/dist/react/index.d.ts +2 -0
- package/cjs/dist/react/index.js +2 -0
- package/cjs/dist/react/location/Location.d.ts +77 -0
- package/cjs/dist/react/location/Location.js +89 -0
- package/cjs/dist/react/service/Service.d.ts +1036 -31
- package/cjs/dist/react/service/Service.js +1060 -47
- package/cjs/dist/react/service-list/ServiceList.d.ts +185 -0
- package/cjs/dist/react/service-list/ServiceList.js +184 -0
- package/cjs/dist/services/booking/booking.d.ts +50 -33
- package/cjs/dist/services/booking/booking.js +72 -38
- package/cjs/dist/services/index.d.ts +3 -2
- package/cjs/dist/services/index.js +3 -2
- package/cjs/dist/services/service/service.d.ts +71 -18
- package/cjs/dist/services/service/service.js +187 -52
- package/cjs/dist/services/service-list/service-list.d.ts +157 -0
- package/cjs/dist/services/service-list/service-list.js +274 -0
- package/cjs/dist/utils/dateAndTime.d.ts +2 -0
- package/cjs/dist/utils/dateAndTime.js +18 -0
- package/cjs/dist/utils/money.d.ts +21 -0
- package/cjs/dist/utils/money.js +34 -0
- package/dist/api/index.d.ts +10 -1
- package/dist/api/index.js +10 -1
- package/dist/api/query-services/index.d.ts +78 -0
- package/dist/api/query-services/index.js +137 -0
- package/dist/react/core/booking/Booking.d.ts +4 -4
- package/dist/react/core/booking/Booking.js +3 -3
- package/dist/react/core/location/Location.d.ts +44 -0
- package/dist/react/core/location/Location.js +78 -0
- package/dist/react/core/service/Service.d.ts +160 -17
- package/dist/react/core/service/Service.js +211 -13
- package/dist/react/core/service-list/ServiceList.d.ts +75 -0
- package/dist/react/core/service-list/ServiceList.js +58 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +2 -0
- package/dist/react/location/Location.d.ts +77 -0
- package/dist/react/location/Location.js +89 -0
- package/dist/react/service/Service.d.ts +1036 -31
- package/dist/react/service/Service.js +1060 -47
- package/dist/react/service-list/ServiceList.d.ts +185 -0
- package/dist/react/service-list/ServiceList.js +184 -0
- package/dist/services/booking/booking.d.ts +50 -33
- package/dist/services/booking/booking.js +72 -38
- package/dist/services/index.d.ts +3 -2
- package/dist/services/index.js +3 -2
- package/dist/services/service/service.d.ts +71 -18
- package/dist/services/service/service.js +187 -52
- package/dist/services/service-list/service-list.d.ts +157 -0
- package/dist/services/service-list/service-list.js +274 -0
- package/dist/utils/dateAndTime.d.ts +2 -0
- package/dist/utils/dateAndTime.js +18 -0
- package/dist/utils/money.d.ts +21 -0
- package/dist/utils/money.js +34 -0
- package/package.json +3 -2
- package/cjs/dist/api/query-service/index.d.ts +0 -23
- package/cjs/dist/api/query-service/index.js +0 -41
- package/dist/api/query-service/index.d.ts +0 -23
- package/dist/api/query-service/index.js +0 -41
package/cjs/dist/api/index.d.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* API Layer
|
|
3
3
|
* Exports all Wix Bookings API functions
|
|
4
|
+
*
|
|
5
|
+
* @module API
|
|
6
|
+
*/
|
|
7
|
+
export { getServiceById, getServiceBySlug, queryServices, type PagingMetadata, type ServiceListFilters, type QueryServicesRequest, } from './query-services/index.js';
|
|
8
|
+
/**
|
|
9
|
+
* PagingMetadata includes:
|
|
10
|
+
* - limit: Number of items per page
|
|
11
|
+
* - offset: Number of items to skip
|
|
12
|
+
* - count: Number of items returned in the current page
|
|
13
|
+
* - hasNext: Whether there are more services available to load
|
|
4
14
|
*/
|
|
5
|
-
export { getServiceById, getServiceBySlug } from './query-service/index.js';
|
package/cjs/dist/api/index.js
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* API Layer
|
|
3
3
|
* Exports all Wix Bookings API functions
|
|
4
|
+
*
|
|
5
|
+
* @module API
|
|
6
|
+
*/
|
|
7
|
+
export { getServiceById, getServiceBySlug, queryServices, } from './query-services/index.js';
|
|
8
|
+
/**
|
|
9
|
+
* PagingMetadata includes:
|
|
10
|
+
* - limit: Number of items per page
|
|
11
|
+
* - offset: Number of items to skip
|
|
12
|
+
* - count: Number of items returned in the current page
|
|
13
|
+
* - hasNext: Whether there are more services available to load
|
|
4
14
|
*/
|
|
5
|
-
export { getServiceById, getServiceBySlug } from './query-service/index.js';
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query Services API
|
|
3
|
+
* Fetches single or multiple services with pagination and sorting
|
|
4
|
+
*/
|
|
5
|
+
import { services } from '@wix/bookings';
|
|
6
|
+
import type { services as servicesTypes } from '@wix/bookings';
|
|
7
|
+
/**
|
|
8
|
+
* Paging metadata from query services response.
|
|
9
|
+
* Extends the SDK's Paging type with hasNext flag to indicate if more services are available.
|
|
10
|
+
*/
|
|
11
|
+
export type PagingMetadata = services.Paging & {
|
|
12
|
+
/** Number of items returned in the current page */
|
|
13
|
+
count?: number;
|
|
14
|
+
/** Whether there are more services available to load */
|
|
15
|
+
hasNext?: boolean;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Service list filters
|
|
19
|
+
*/
|
|
20
|
+
export interface ServiceListFilters {
|
|
21
|
+
serviceIds?: string[];
|
|
22
|
+
categoryIds?: string[];
|
|
23
|
+
locationIds?: string[];
|
|
24
|
+
staffMemberIds?: string[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Query services request options
|
|
28
|
+
* Used internally by ServiceListService to track query state
|
|
29
|
+
*/
|
|
30
|
+
export interface QueryServicesRequest {
|
|
31
|
+
appId: string;
|
|
32
|
+
filters?: ServiceListFilters;
|
|
33
|
+
pagingMetadata?: PagingMetadata;
|
|
34
|
+
sort?: services.Sorting[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Fetches a service by its ID
|
|
38
|
+
* @param id - The service ID
|
|
39
|
+
* @param appId - Optional app ID, defaults to booking app ID
|
|
40
|
+
* @returns Object containing the service or null if not found
|
|
41
|
+
*/
|
|
42
|
+
export declare const getServiceById: (id: string, appId?: string) => Promise<{
|
|
43
|
+
service: servicesTypes.Service | null;
|
|
44
|
+
}>;
|
|
45
|
+
/**
|
|
46
|
+
* Fetches a service by its slug
|
|
47
|
+
* @param slug - The service slug
|
|
48
|
+
* @param appId - Optional app ID, defaults to booking app ID
|
|
49
|
+
* @returns Object containing the service or null if not found
|
|
50
|
+
*/
|
|
51
|
+
export declare const getServiceBySlug: (slug: string, appId?: string) => Promise<{
|
|
52
|
+
service: servicesTypes.Service | null;
|
|
53
|
+
}>;
|
|
54
|
+
/**
|
|
55
|
+
* Query services with pagination and sorting.
|
|
56
|
+
* Returns services array and paging metadata including hasNext flag.
|
|
57
|
+
*
|
|
58
|
+
* @param params - Query parameters including appId, filters, paging metadata, and sort options
|
|
59
|
+
* @returns Promise that resolves to services array and paging metadata with hasNext flag
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* const { services, pagingMetadata } = await queryServices({
|
|
64
|
+
* appId: '13d21c63-b5ec-5912-8397-c3a5ddb27a97',
|
|
65
|
+
* filters: { serviceIds: ['service1', 'service2'] },
|
|
66
|
+
* pagingMetadata: { limit: 20, offset: 0 },
|
|
67
|
+
* sort: [{ fieldName: 'name', order: 'ASC' }]
|
|
68
|
+
* });
|
|
69
|
+
*
|
|
70
|
+
* if (pagingMetadata.hasNext) {
|
|
71
|
+
* // Load more services
|
|
72
|
+
* }
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export declare function queryServices({ appId, filters, pagingMetadata, sort, }: QueryServicesRequest): Promise<{
|
|
76
|
+
services: servicesTypes.Service[];
|
|
77
|
+
pagingMetadata: PagingMetadata;
|
|
78
|
+
}>;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query Services API
|
|
3
|
+
* Fetches single or multiple services with pagination and sorting
|
|
4
|
+
*/
|
|
5
|
+
import { services } from '@wix/bookings';
|
|
6
|
+
/**
|
|
7
|
+
* Booking app ID constant
|
|
8
|
+
*/
|
|
9
|
+
const BOOKING_APP_ID = '13d21c63-b5ec-5912-8397-c3a5ddb27a97';
|
|
10
|
+
/**
|
|
11
|
+
* Fetches a service by its ID
|
|
12
|
+
* @param id - The service ID
|
|
13
|
+
* @param appId - Optional app ID, defaults to booking app ID
|
|
14
|
+
* @returns Object containing the service or null if not found
|
|
15
|
+
*/
|
|
16
|
+
export const getServiceById = async (id, appId) => {
|
|
17
|
+
try {
|
|
18
|
+
const finalAppId = appId ?? BOOKING_APP_ID;
|
|
19
|
+
// Query services where _id equals the provided id and appId matches
|
|
20
|
+
const query = services.queryServices({
|
|
21
|
+
conditionalFields: ['STAFF_MEMBER_DETAILS'],
|
|
22
|
+
});
|
|
23
|
+
const result = await query
|
|
24
|
+
.eq('_id', id)
|
|
25
|
+
// @ts-ignore
|
|
26
|
+
.eq('appId', finalAppId)
|
|
27
|
+
.limit(1)
|
|
28
|
+
.find();
|
|
29
|
+
const service = result.items?.[0] || null;
|
|
30
|
+
return { service };
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
console.error(`Failed to load service for id "${id}":`, error);
|
|
34
|
+
return { service: null };
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Fetches a service by its slug
|
|
39
|
+
* @param slug - The service slug
|
|
40
|
+
* @param appId - Optional app ID, defaults to booking app ID
|
|
41
|
+
* @returns Object containing the service or null if not found
|
|
42
|
+
*/
|
|
43
|
+
export const getServiceBySlug = async (slug, appId) => {
|
|
44
|
+
try {
|
|
45
|
+
const finalAppId = appId ?? BOOKING_APP_ID;
|
|
46
|
+
// Query services where mainSlug.name equals the provided slug and appId matches
|
|
47
|
+
const query = services.queryServices({
|
|
48
|
+
conditionalFields: ['STAFF_MEMBER_DETAILS'],
|
|
49
|
+
});
|
|
50
|
+
const result = await query
|
|
51
|
+
.eq('mainSlug.name', slug)
|
|
52
|
+
// @ts-ignore
|
|
53
|
+
.eq('appId', finalAppId)
|
|
54
|
+
.limit(1)
|
|
55
|
+
.find();
|
|
56
|
+
const service = result.items?.[0] || null;
|
|
57
|
+
return { service };
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
console.error(`Failed to load service for slug "${slug}":`, error);
|
|
61
|
+
return { service: null };
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Builds a QueryServicesRequest from appId, filters, paging, and sort
|
|
66
|
+
* @param params - Parameters including appId, filters, paging, and sort
|
|
67
|
+
* @returns QueryServicesRequest object
|
|
68
|
+
*/
|
|
69
|
+
const buildServicesQueryRequest = ({ appId, filters, paging, sort, }) => {
|
|
70
|
+
const filter = {
|
|
71
|
+
appId,
|
|
72
|
+
};
|
|
73
|
+
// Add serviceIds filter if provided
|
|
74
|
+
if (filters?.serviceIds && filters.serviceIds.length > 0) {
|
|
75
|
+
filter['_id'] = { $in: filters.serviceIds };
|
|
76
|
+
}
|
|
77
|
+
// Add other filters as they are implemented in future phases
|
|
78
|
+
// categoryIds, locationIds, staffMemberIds to be added later
|
|
79
|
+
const query = {
|
|
80
|
+
filter: Object.keys(filter).length > 0 ? filter : undefined,
|
|
81
|
+
paging: paging || {
|
|
82
|
+
limit: 100, // Default limit
|
|
83
|
+
},
|
|
84
|
+
sort,
|
|
85
|
+
};
|
|
86
|
+
return { query };
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Query services with pagination and sorting.
|
|
90
|
+
* Returns services array and paging metadata including hasNext flag.
|
|
91
|
+
*
|
|
92
|
+
* @param params - Query parameters including appId, filters, paging metadata, and sort options
|
|
93
|
+
* @returns Promise that resolves to services array and paging metadata with hasNext flag
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* const { services, pagingMetadata } = await queryServices({
|
|
98
|
+
* appId: '13d21c63-b5ec-5912-8397-c3a5ddb27a97',
|
|
99
|
+
* filters: { serviceIds: ['service1', 'service2'] },
|
|
100
|
+
* pagingMetadata: { limit: 20, offset: 0 },
|
|
101
|
+
* sort: [{ fieldName: 'name', order: 'ASC' }]
|
|
102
|
+
* });
|
|
103
|
+
*
|
|
104
|
+
* if (pagingMetadata.hasNext) {
|
|
105
|
+
* // Load more services
|
|
106
|
+
* }
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
export async function queryServices({ appId, filters, pagingMetadata, sort, }) {
|
|
110
|
+
try {
|
|
111
|
+
const queryRequest = buildServicesQueryRequest({
|
|
112
|
+
appId,
|
|
113
|
+
filters,
|
|
114
|
+
paging: pagingMetadata,
|
|
115
|
+
sort,
|
|
116
|
+
});
|
|
117
|
+
// Call queryServices with QueryServicesRequest and execute the query
|
|
118
|
+
const result = await services.queryServices(queryRequest).find();
|
|
119
|
+
// Construct PagingMetadata from result properties
|
|
120
|
+
// Includes count (number of items returned) and hasNext (whether more items are available)
|
|
121
|
+
const resultPagingMetadata = {
|
|
122
|
+
limit: pagingMetadata?.limit,
|
|
123
|
+
offset: pagingMetadata?.offset,
|
|
124
|
+
count: result.items.length,
|
|
125
|
+
hasNext: (result?.totalCount || 0) >
|
|
126
|
+
result.items.length + (pagingMetadata?.offset || 0),
|
|
127
|
+
};
|
|
128
|
+
return {
|
|
129
|
+
services: result.items || [],
|
|
130
|
+
pagingMetadata: resultPagingMetadata,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
console.error('Failed to query services:', error);
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Provides low-level access to BookingService via render props and service setup
|
|
4
4
|
*/
|
|
5
5
|
import React from 'react';
|
|
6
|
-
import { type BookingServiceConfig } from '../../../services/booking/booking.js';
|
|
7
|
-
import type {
|
|
6
|
+
import { type BookingServiceConfig, type ServiceSelection } from '../../../services/booking/booking.js';
|
|
7
|
+
import type { availabilityTimeSlots } from '@wix/bookings';
|
|
8
8
|
/**
|
|
9
9
|
* Props for Booking.Root component
|
|
10
10
|
*/
|
|
@@ -33,7 +33,7 @@ export declare function Root(props: RootProps): React.ReactNode;
|
|
|
33
33
|
*/
|
|
34
34
|
export interface DataProps {
|
|
35
35
|
children: (data: {
|
|
36
|
-
selectedServices:
|
|
36
|
+
selectedServices: ServiceSelection[];
|
|
37
37
|
selectedTimeSlot: availabilityTimeSlots.TimeSlot | null;
|
|
38
38
|
}) => React.ReactNode;
|
|
39
39
|
}
|
|
@@ -47,7 +47,7 @@ export interface DataProps {
|
|
|
47
47
|
* <Booking.Data>
|
|
48
48
|
* {({ selectedServices }) => (
|
|
49
49
|
* selectedServices.length > 0 ? (
|
|
50
|
-
* <div>{selectedServices.map(s => s.name).join(', ')}</div>
|
|
50
|
+
* <div>{selectedServices.map(s => s.service.name).join(', ')}</div>
|
|
51
51
|
* ) : (
|
|
52
52
|
* <div>No services selected</div>
|
|
53
53
|
* )
|
|
@@ -30,7 +30,7 @@ export function Root(props) {
|
|
|
30
30
|
* <Booking.Data>
|
|
31
31
|
* {({ selectedServices }) => (
|
|
32
32
|
* selectedServices.length > 0 ? (
|
|
33
|
-
* <div>{selectedServices.map(s => s.name).join(', ')}</div>
|
|
33
|
+
* <div>{selectedServices.map(s => s.service.name).join(', ')}</div>
|
|
34
34
|
* ) : (
|
|
35
35
|
* <div>No services selected</div>
|
|
36
36
|
* )
|
|
@@ -41,8 +41,8 @@ export function Root(props) {
|
|
|
41
41
|
export function Data(props) {
|
|
42
42
|
const { children } = props;
|
|
43
43
|
const bookingService = useService(BookingServiceDefinition);
|
|
44
|
-
const selectedServices = bookingService.
|
|
45
|
-
const selectedTimeSlot = bookingService.
|
|
44
|
+
const selectedServices = bookingService.services.get();
|
|
45
|
+
const selectedTimeSlot = bookingService.timeSlot.get();
|
|
46
46
|
return children({
|
|
47
47
|
selectedServices,
|
|
48
48
|
selectedTimeSlot,
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core Location Component - Parses service location data
|
|
3
|
+
* Handles business, custom, and customer location types
|
|
4
|
+
* Converts location data to Address component format
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { services } from '@wix/bookings';
|
|
8
|
+
import type { AddressData as AddressDataType } from '@wix/headless-components/react';
|
|
9
|
+
/**
|
|
10
|
+
* Re-export AddressData type from Address component for convenience
|
|
11
|
+
*/
|
|
12
|
+
export type AddressData = AddressDataType;
|
|
13
|
+
/**
|
|
14
|
+
* Location render props passed to children
|
|
15
|
+
*/
|
|
16
|
+
export interface LocationRenderProps {
|
|
17
|
+
locationType: services.LocationType;
|
|
18
|
+
address: AddressData | null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Props for the core Location component
|
|
22
|
+
*/
|
|
23
|
+
export interface LocationProps {
|
|
24
|
+
location: NonNullable<services.Service['locations']>[number];
|
|
25
|
+
children: (props: LocationRenderProps) => React.ReactNode;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Core Location component that parses service location data
|
|
29
|
+
* and provides location type and address data to children
|
|
30
|
+
*
|
|
31
|
+
* @component
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* <CoreLocation location={serviceLocation}>
|
|
35
|
+
* {({ locationType, address }) => (
|
|
36
|
+
* <div>
|
|
37
|
+
* <span>Type: {locationType}</span>
|
|
38
|
+
* {address && <Address.Root address={address}><Address.Formatted /></Address.Root>}
|
|
39
|
+
* </div>
|
|
40
|
+
* )}
|
|
41
|
+
* </CoreLocation>
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare function Location(props: LocationProps): React.ReactNode;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core Location Component - Parses service location data
|
|
3
|
+
* Handles business, custom, and customer location types
|
|
4
|
+
* Converts location data to Address component format
|
|
5
|
+
*/
|
|
6
|
+
import { services } from '@wix/bookings';
|
|
7
|
+
/**
|
|
8
|
+
* Parses location data into Address component format
|
|
9
|
+
*/
|
|
10
|
+
function parseLocationAddress(location, locationType) {
|
|
11
|
+
// Handle customer location specially
|
|
12
|
+
if (locationType === services.LocationType.CUSTOMER) {
|
|
13
|
+
// For customer location, return an AddressData object with Customer's Place
|
|
14
|
+
return {
|
|
15
|
+
address: {
|
|
16
|
+
addressLine: "Customer's Place",
|
|
17
|
+
formattedAddress: "Customer's Place",
|
|
18
|
+
city: '',
|
|
19
|
+
subdivision: '',
|
|
20
|
+
postalCode: '',
|
|
21
|
+
country: '',
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
// Get the common address from the appropriate location type
|
|
26
|
+
const commonAddress = location.calculatedAddress ||
|
|
27
|
+
location.business?.address ||
|
|
28
|
+
location.custom?.address;
|
|
29
|
+
if (!commonAddress) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
// Convert CommonAddress to AddressData format (compatible with Address.Root from @wix/headless-components)
|
|
33
|
+
return {
|
|
34
|
+
address: {
|
|
35
|
+
addressLine: commonAddress.streetAddress?.name ||
|
|
36
|
+
commonAddress.addressLine ||
|
|
37
|
+
commonAddress.addressLine1 ||
|
|
38
|
+
'',
|
|
39
|
+
city: commonAddress.city || '',
|
|
40
|
+
subdivision: commonAddress.subdivision || '',
|
|
41
|
+
postalCode: commonAddress.postalCode || '',
|
|
42
|
+
country: commonAddress.country || '',
|
|
43
|
+
streetAddress: commonAddress.streetAddress
|
|
44
|
+
? {
|
|
45
|
+
number: commonAddress.streetAddress.number,
|
|
46
|
+
name: commonAddress.streetAddress.name,
|
|
47
|
+
apt: commonAddress.streetAddress.apt,
|
|
48
|
+
}
|
|
49
|
+
: undefined,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
// ==========================================
|
|
54
|
+
// Component
|
|
55
|
+
// ==========================================
|
|
56
|
+
/**
|
|
57
|
+
* Core Location component that parses service location data
|
|
58
|
+
* and provides location type and address data to children
|
|
59
|
+
*
|
|
60
|
+
* @component
|
|
61
|
+
* @example
|
|
62
|
+
* ```tsx
|
|
63
|
+
* <CoreLocation location={serviceLocation}>
|
|
64
|
+
* {({ locationType, address }) => (
|
|
65
|
+
* <div>
|
|
66
|
+
* <span>Type: {locationType}</span>
|
|
67
|
+
* {address && <Address.Root address={address}><Address.Formatted /></Address.Root>}
|
|
68
|
+
* </div>
|
|
69
|
+
* )}
|
|
70
|
+
* </CoreLocation>
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export function Location(props) {
|
|
74
|
+
const { location, children } = props;
|
|
75
|
+
const locationType = location.type;
|
|
76
|
+
const address = parseLocationAddress(location, locationType);
|
|
77
|
+
return children({ locationType, address });
|
|
78
|
+
}
|
|
@@ -4,25 +4,18 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import React from 'react';
|
|
6
6
|
import { type ServiceServiceConfig } from '../../../services/service/service.js';
|
|
7
|
-
import
|
|
7
|
+
import { services } from '@wix/bookings';
|
|
8
|
+
import type { MoneyData } from '@wix/headless-components/react';
|
|
8
9
|
/**
|
|
9
10
|
* Props for Service.Root component
|
|
10
11
|
*/
|
|
11
12
|
export interface RootProps {
|
|
12
|
-
children: React.ReactNode
|
|
13
|
+
children: React.ReactNode | ((props: {
|
|
14
|
+
selected: boolean;
|
|
15
|
+
bookable: boolean;
|
|
16
|
+
}) => React.ReactNode);
|
|
13
17
|
serviceServiceConfig: ServiceServiceConfig;
|
|
14
18
|
}
|
|
15
|
-
/**
|
|
16
|
-
* Root component that provides service context.
|
|
17
|
-
*
|
|
18
|
-
* @component
|
|
19
|
-
* @example
|
|
20
|
-
* ```tsx
|
|
21
|
-
* <Service.Root serviceServiceConfig={{ service }}>
|
|
22
|
-
* {children}
|
|
23
|
-
* </Service.Root>
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
19
|
export declare function Root(props: RootProps): React.ReactNode;
|
|
27
20
|
/**
|
|
28
21
|
* Props for Service render prop component
|
|
@@ -55,26 +48,101 @@ export interface InfoProps {
|
|
|
55
48
|
children: (data: {
|
|
56
49
|
name: string;
|
|
57
50
|
description: string;
|
|
51
|
+
tagline?: string;
|
|
52
|
+
duration?: number;
|
|
53
|
+
type?: string;
|
|
54
|
+
category?: {
|
|
55
|
+
name?: string;
|
|
56
|
+
_id?: string;
|
|
57
|
+
};
|
|
58
|
+
locations?: Array<NonNullable<services.Service['locations']>[number]>;
|
|
59
|
+
staff?: Array<{
|
|
60
|
+
name?: string;
|
|
61
|
+
_id?: string;
|
|
62
|
+
}>;
|
|
63
|
+
media?: Array<{
|
|
64
|
+
url?: string;
|
|
65
|
+
_id?: string;
|
|
66
|
+
}>;
|
|
67
|
+
mainMedia?: {
|
|
68
|
+
image?: string;
|
|
69
|
+
};
|
|
70
|
+
coverMedia?: {
|
|
71
|
+
image?: string;
|
|
72
|
+
};
|
|
73
|
+
mediaItems?: Array<{
|
|
74
|
+
image?: string | null;
|
|
75
|
+
altText?: string | null;
|
|
76
|
+
}>;
|
|
77
|
+
price?: {
|
|
78
|
+
amount?: string;
|
|
79
|
+
formattedAmount?: string;
|
|
80
|
+
currency?: string;
|
|
81
|
+
};
|
|
82
|
+
defaultCapacity?: number;
|
|
83
|
+
selected: boolean;
|
|
58
84
|
}) => React.ReactNode;
|
|
59
85
|
}
|
|
60
86
|
/**
|
|
61
87
|
* Core component that provides access to service catalog info via render props.
|
|
62
|
-
* Includes name
|
|
88
|
+
* Includes name, description, tagline, duration, type, category, locations, staff, media, and price.
|
|
63
89
|
*
|
|
64
90
|
* @component
|
|
65
91
|
* @example
|
|
66
92
|
* ```tsx
|
|
67
93
|
* <Service.Info>
|
|
68
|
-
* {({ name, description }) => (
|
|
94
|
+
* {({ name, description, tagline, duration, type, category, locations, staff, media, price }) => (
|
|
69
95
|
* <div>
|
|
70
96
|
* <h1>{name}</h1>
|
|
71
97
|
* <p>{description}</p>
|
|
98
|
+
* {tagline && <p>{tagline}</p>}
|
|
99
|
+
* {duration && <p>Duration: {duration} minutes</p>}
|
|
100
|
+
* {type && <p>Type: {type}</p>}
|
|
101
|
+
* {category && <p>Category: {category.name}</p>}
|
|
72
102
|
* </div>
|
|
73
103
|
* )}
|
|
74
104
|
* </Service.Info>
|
|
75
105
|
* ```
|
|
76
106
|
*/
|
|
77
107
|
export declare function Info(props: InfoProps): React.ReactNode;
|
|
108
|
+
/**
|
|
109
|
+
* Props for Price render prop component
|
|
110
|
+
*/
|
|
111
|
+
export interface PriceProps {
|
|
112
|
+
children: (data: {
|
|
113
|
+
servicePayment: services.Payment | undefined;
|
|
114
|
+
rateType: services.Payment['rateType'] | undefined;
|
|
115
|
+
money: MoneyData | null;
|
|
116
|
+
minPrice: MoneyData | null;
|
|
117
|
+
maxPrice: MoneyData | null;
|
|
118
|
+
priceDescription: string | null;
|
|
119
|
+
hasAddOns: boolean;
|
|
120
|
+
hasPricingPlans: boolean;
|
|
121
|
+
}) => React.ReactNode;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Core component that provides access to service price via render props.
|
|
125
|
+
* Returns comprehensive pricing data including money, rate type, and service capabilities.
|
|
126
|
+
*
|
|
127
|
+
* @component
|
|
128
|
+
* @example
|
|
129
|
+
* ```tsx
|
|
130
|
+
* <Service.Price>
|
|
131
|
+
* {({ money, rateType, minPrice, maxPrice, priceDescription, hasAddOns, hasPricingPlans }) => (
|
|
132
|
+
* rateType === 'FIXED' && money ? (
|
|
133
|
+
* <Money money={money} />
|
|
134
|
+
* ) : rateType === 'VARIED' && minPrice && maxPrice ? (
|
|
135
|
+
* <span><Money money={minPrice} /> - <Money money={maxPrice} /></span>
|
|
136
|
+
* ) : rateType === 'CUSTOM' && priceDescription ? (
|
|
137
|
+
* <span>{priceDescription}</span>
|
|
138
|
+
* ) : rateType === 'NO_FEE' ? (
|
|
139
|
+
* <span>Free</span>
|
|
140
|
+
* ) : null
|
|
141
|
+
* )}
|
|
142
|
+
* </Service.Price>
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
export declare function Price(props: PriceProps): React.ReactNode;
|
|
78
146
|
/**
|
|
79
147
|
* Props for Actions render prop component
|
|
80
148
|
*/
|
|
@@ -83,7 +151,10 @@ export interface ActionsProps {
|
|
|
83
151
|
select: () => void;
|
|
84
152
|
add: () => void;
|
|
85
153
|
remove: () => void;
|
|
86
|
-
|
|
154
|
+
rawService: services.Service;
|
|
155
|
+
bookable: boolean;
|
|
156
|
+
selected: boolean;
|
|
157
|
+
requiresAvailability: boolean;
|
|
87
158
|
}) => React.ReactNode;
|
|
88
159
|
}
|
|
89
160
|
/**
|
|
@@ -93,7 +164,7 @@ export interface ActionsProps {
|
|
|
93
164
|
* @example
|
|
94
165
|
* ```tsx
|
|
95
166
|
* <Service.Actions>
|
|
96
|
-
* {({ select, add, remove,
|
|
167
|
+
* {({ select, add, remove, rawService, requiresAvailability }) => (
|
|
97
168
|
* <div>
|
|
98
169
|
* <button onClick={select}>Select</button>
|
|
99
170
|
* <button onClick={add}>Add</button>
|
|
@@ -104,3 +175,75 @@ export interface ActionsProps {
|
|
|
104
175
|
* ```
|
|
105
176
|
*/
|
|
106
177
|
export declare function Actions(props: ActionsProps): React.ReactNode;
|
|
178
|
+
/**
|
|
179
|
+
* Props for Policy render prop component
|
|
180
|
+
*/
|
|
181
|
+
export interface PolicyProps {
|
|
182
|
+
children: (data: {
|
|
183
|
+
bookingPolicy: services.BookingPolicy | null;
|
|
184
|
+
cancellationPolicyEnabled: boolean;
|
|
185
|
+
limitLatestCancellationEnabled: boolean;
|
|
186
|
+
latestCancellationInMinutes: number | undefined;
|
|
187
|
+
latestBookingPolicyEnabled: boolean;
|
|
188
|
+
latestBookingInMinutes: number | undefined;
|
|
189
|
+
earliestBookingPolicyEnabled: boolean;
|
|
190
|
+
earliestBookingInMinutes: number | undefined;
|
|
191
|
+
reschedulePolicyEnabled: boolean;
|
|
192
|
+
limitLatestRescheduleEnabled: boolean;
|
|
193
|
+
latestRescheduleInMinutes: number | undefined;
|
|
194
|
+
waitlistPolicyEnabled: boolean;
|
|
195
|
+
waitlistCapacity: number | undefined;
|
|
196
|
+
bookAfterStartEnabled: boolean;
|
|
197
|
+
maxParticipantsPerBooking: number | undefined;
|
|
198
|
+
}) => React.ReactNode;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Core component that provides access to service booking policy via render props.
|
|
202
|
+
* Computes all enabled flags and values from the booking policy.
|
|
203
|
+
*
|
|
204
|
+
* @component
|
|
205
|
+
* @example
|
|
206
|
+
* ```tsx
|
|
207
|
+
* <Service.Policy>
|
|
208
|
+
* {({ bookingPolicy, cancellationPolicyEnabled, latestCancellationInMinutes }) => (
|
|
209
|
+
* cancellationPolicyEnabled ? (
|
|
210
|
+
* <div>Cancel up to {latestCancellationInMinutes} minutes before</div>
|
|
211
|
+
* ) : null
|
|
212
|
+
* )}
|
|
213
|
+
* </Service.Policy>
|
|
214
|
+
* ```
|
|
215
|
+
*/
|
|
216
|
+
export declare function Policy(props: PolicyProps): React.ReactNode;
|
|
217
|
+
/**
|
|
218
|
+
* Props for Schedule render prop component
|
|
219
|
+
*/
|
|
220
|
+
export interface ScheduleProps {
|
|
221
|
+
children: (data: {
|
|
222
|
+
schedule: services.Schedule | null;
|
|
223
|
+
isClassOrCourse: boolean;
|
|
224
|
+
}) => React.ReactNode;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Core component that provides access to service schedule via render props.
|
|
228
|
+
* Uses the SDK's Schedule type directly. Only renders for CLASS or COURSE service types.
|
|
229
|
+
*
|
|
230
|
+
* @component
|
|
231
|
+
* @example
|
|
232
|
+
* ```tsx
|
|
233
|
+
* <Service.Schedule>
|
|
234
|
+
* {({ schedule, isClassOrCourse }) => (
|
|
235
|
+
* schedule && isClassOrCourse ? (
|
|
236
|
+
* <div>
|
|
237
|
+
* {schedule.firstSessionStart && (
|
|
238
|
+
* <span>Starts: {new Date(schedule.firstSessionStart).toLocaleDateString()}</span>
|
|
239
|
+
* )}
|
|
240
|
+
* {schedule.lastSessionEnd && (
|
|
241
|
+
* <span>Ends: {new Date(schedule.lastSessionEnd).toLocaleDateString()}</span>
|
|
242
|
+
* )}
|
|
243
|
+
* </div>
|
|
244
|
+
* ) : null
|
|
245
|
+
* )}
|
|
246
|
+
* </Service.Schedule>
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
export declare function Schedule(props: ScheduleProps): React.ReactNode;
|