@wix/headless-bookings 0.0.0

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 (44) hide show
  1. package/cjs/dist/react/ServiceList.d.ts +50 -0
  2. package/cjs/dist/react/ServiceList.js +100 -0
  3. package/cjs/dist/react/ServiceListSort.d.ts +37 -0
  4. package/cjs/dist/react/ServiceListSort.js +35 -0
  5. package/cjs/dist/react/core/Service.d.ts +91 -0
  6. package/cjs/dist/react/core/Service.js +73 -0
  7. package/cjs/dist/react/core/ServiceList.d.ts +218 -0
  8. package/cjs/dist/react/core/ServiceList.js +199 -0
  9. package/cjs/dist/react/index.d.ts +4 -0
  10. package/cjs/dist/react/index.js +5 -0
  11. package/cjs/dist/react/test-ids.d.ts +18 -0
  12. package/cjs/dist/react/test-ids.js +24 -0
  13. package/cjs/dist/react/types.d.ts +52 -0
  14. package/cjs/dist/react/types.js +1 -0
  15. package/cjs/dist/services/index.d.ts +1 -0
  16. package/cjs/dist/services/index.js +1 -0
  17. package/cjs/dist/services/service-service.d.ts +136 -0
  18. package/cjs/dist/services/service-service.js +140 -0
  19. package/cjs/dist/services/services-list-service.d.ts +184 -0
  20. package/cjs/dist/services/services-list-service.js +168 -0
  21. package/cjs/package.json +3 -0
  22. package/dist/react/ServiceList.d.ts +50 -0
  23. package/dist/react/ServiceList.js +100 -0
  24. package/dist/react/ServiceListSort.d.ts +37 -0
  25. package/dist/react/ServiceListSort.js +35 -0
  26. package/dist/react/core/Service.d.ts +91 -0
  27. package/dist/react/core/Service.js +73 -0
  28. package/dist/react/core/ServiceList.d.ts +218 -0
  29. package/dist/react/core/ServiceList.js +199 -0
  30. package/dist/react/index.d.ts +4 -0
  31. package/dist/react/index.js +5 -0
  32. package/dist/react/test-ids.d.ts +18 -0
  33. package/dist/react/test-ids.js +24 -0
  34. package/dist/react/types.d.ts +52 -0
  35. package/dist/react/types.js +1 -0
  36. package/dist/services/index.d.ts +1 -0
  37. package/dist/services/index.js +1 -0
  38. package/dist/services/service-service.d.ts +136 -0
  39. package/dist/services/service-service.js +140 -0
  40. package/dist/services/services-list-service.d.ts +184 -0
  41. package/dist/services/services-list-service.js +168 -0
  42. package/package.json +70 -0
  43. package/react/package.json +4 -0
  44. package/services/package.json +4 -0
@@ -0,0 +1,199 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useService, WixServices } from '@wix/services-manager-react';
3
+ import { createServicesMap } from '@wix/services-manager';
4
+ import { ServicesListService, ServicesListServiceDefinition, } from '../../services/services-list-service.js';
5
+ /**
6
+ * Root component that provides ServiceList service context to its children.
7
+ * This component sets up the necessary services for managing services list state,
8
+ * including filtering, sorting, and pagination functionality.
9
+ *
10
+ * @order 1
11
+ * @component
12
+ * @example
13
+ * ```tsx
14
+ * import { ServiceList, Service } from '@wix/headless-services/react';
15
+ *
16
+ * function ServiceListPage() {
17
+ * return (
18
+ * <ServiceList.Root
19
+ * servicesListConfig={{
20
+ * services: myServices,
21
+ * searchOptions: {
22
+ * cursorPaging: { limit: 10 },
23
+ * sort: [{ fieldName: 'name', order: 'ASC' }]
24
+ * },
25
+ * pagingMetadata: { count: 10, hasNext: true }
26
+ * }}
27
+ * >
28
+ * <ServiceList.Options>
29
+ * <ServiceList.ServiceRepeater>
30
+ * <Service.Name>
31
+ * {({ name }) => <h3>{name}</h3>}
32
+ * </Service.Name>
33
+ * <Service.Price>
34
+ * {({ price }) => price && <div>{price.value} {price.currency}</div>}
35
+ * </Service.Price>
36
+ * </ServiceList.ServiceRepeater>
37
+ * </ServiceList.Options>
38
+ * </ServiceList.Root>
39
+ * );
40
+ * }
41
+ * ```
42
+ */
43
+ export function Root(props) {
44
+ return (_jsx(WixServices, { servicesMap: createServicesMap().addService(ServicesListServiceDefinition, ServicesListService, props.servicesListConfig), children: props.children }));
45
+ }
46
+ /**
47
+ * Component that renders content when the services list is empty.
48
+ * Only displays its children when there are no services, no loading state, and no errors.
49
+ *
50
+ * @component
51
+ * @example
52
+ * ```tsx
53
+ * import { ServiceList } from '@wix/headless-services/react';
54
+ *
55
+ * function EmptyServicesMessage() {
56
+ * return (
57
+ * <ServiceList.EmptyState>
58
+ * {() => (
59
+ * <div className="empty-state">
60
+ * <h3>No services found</h3>
61
+ * <p>Try adjusting your search or filter criteria</p>
62
+ * <button>Clear Filters</button>
63
+ * </div>
64
+ * )}
65
+ * </ServiceList.EmptyState>
66
+ * );
67
+ * }
68
+ * ```
69
+ */
70
+ export function EmptyState(props) {
71
+ const { isLoading, error, services: servicesList, } = useService(ServicesListServiceDefinition);
72
+ const isLoadingValue = isLoading.get();
73
+ const errorValue = error.get();
74
+ const servicesValue = servicesList.get();
75
+ if (!isLoadingValue && !errorValue && servicesValue.length === 0) {
76
+ return typeof props.children === 'function'
77
+ ? props.children({})
78
+ : props.children;
79
+ }
80
+ return null;
81
+ }
82
+ /**
83
+ * Component that renders content during loading state.
84
+ * Only displays its children when the services list is currently loading.
85
+ *
86
+ * @component
87
+ * @example
88
+ * ```tsx
89
+ * import { ServiceList } from '@wix/headless-services/react';
90
+ *
91
+ * function ServicesLoading() {
92
+ * return (
93
+ * <ServiceList.Loading>
94
+ * {() => (
95
+ * <div className="loading-spinner">
96
+ * <div>Loading services...</div>
97
+ * <div className="spinner"></div>
98
+ * </div>
99
+ * )}
100
+ * </ServiceList.Loading>
101
+ * );
102
+ * }
103
+ * ```
104
+ */
105
+ export function Loading(props) {
106
+ const { isLoading } = useService(ServicesListServiceDefinition);
107
+ const isLoadingValue = isLoading.get();
108
+ if (isLoadingValue) {
109
+ return typeof props.children === 'function'
110
+ ? props.children({})
111
+ : props.children;
112
+ }
113
+ return null;
114
+ }
115
+ /**
116
+ * Component that renders content when there's an error loading services.
117
+ * Only displays its children when an error has occurred.
118
+ *
119
+ * @component
120
+ * @example
121
+ * ```tsx
122
+ * import { ServiceList } from '@wix/headless-services/react';
123
+ *
124
+ * function ServicesError() {
125
+ * return (
126
+ * <ServiceList.Error>
127
+ * {({ error }) => (
128
+ * <div className="error-state">
129
+ * <h3>Error loading services</h3>
130
+ * <p>{error}</p>
131
+ * <button onClick={() => window.location.reload()}>
132
+ * Try Again
133
+ * </button>
134
+ * </div>
135
+ * )}
136
+ * </ServiceList.Error>
137
+ * );
138
+ * }
139
+ * ```
140
+ */
141
+ export function Error(props) {
142
+ const { error } = useService(ServicesListServiceDefinition);
143
+ const errorValue = error.get();
144
+ if (errorValue) {
145
+ return typeof props.children === 'function'
146
+ ? props.children({ error: errorValue })
147
+ : props.children;
148
+ }
149
+ return null;
150
+ }
151
+ /**
152
+ * Component that renders content for each service in the list.
153
+ * Maps over all services and provides each service through a service context.
154
+ * Only renders when services are successfully loaded (not loading, no error, and has services).
155
+ *
156
+ * @component
157
+ * @example
158
+ * ```tsx
159
+ * import { ServiceList, Service } from '@wix/headless-services/react';
160
+ *
161
+ * function ServicesGrid() {
162
+ * return (
163
+ * <ServiceList.ItemContent>
164
+ * {({ service }) => (
165
+ * <div className="service-card">
166
+ * <Service.Image>
167
+ * {({ image, alt }) => <img src={image} alt={alt} />}
168
+ * </Service.Image>
169
+ * <Service.Name>
170
+ * {({ name }) => <h3>{name}</h3>}
171
+ * </Service.Name>
172
+ * <Service.Price>
173
+ * {({ price }) => price && <p>{price.value} {price.currency}</p>}
174
+ * </Service.Price>
175
+ * <button>Book Now</button>
176
+ * </div>
177
+ * )}
178
+ * </ServiceList.ItemContent>
179
+ * );
180
+ * }
181
+ * ```
182
+ */
183
+ export function ItemContent(props) {
184
+ const { services: servicesList, isLoading, error, } = useService(ServicesListServiceDefinition);
185
+ const servicesValue = servicesList.get();
186
+ if (isLoading.get() || error.get() || servicesValue.length === 0) {
187
+ return null;
188
+ }
189
+ return servicesValue.map((service) => (_jsx(WixServices, { servicesMap: createServicesMap(), children: typeof props.children === 'function'
190
+ ? props.children({ service })
191
+ : props.children }, service._id)));
192
+ }
193
+ export function Items(props) {
194
+ const { services: servicesList } = useService(ServicesListServiceDefinition);
195
+ const servicesValue = servicesList.get();
196
+ return typeof props.children === 'function'
197
+ ? props.children({ services: servicesValue })
198
+ : props.children;
199
+ }
@@ -0,0 +1,4 @@
1
+ export * as ServiceList from './ServiceList.js';
2
+ export * as Service from './core/Service.js';
3
+ export * as ServicesSort from './ServiceListSort.js';
4
+ export * from './test-ids.js';
@@ -0,0 +1,5 @@
1
+ // Components
2
+ export * as ServiceList from './ServiceList.js';
3
+ export * as Service from './core/Service.js';
4
+ export * as ServicesSort from './ServiceListSort.js';
5
+ export * from './test-ids.js';
@@ -0,0 +1,18 @@
1
+ export declare enum TestIds {
2
+ servicesList = "services-list",
3
+ servicesOptions = "services-options",
4
+ serviceRepeater = "service-repeater",
5
+ serviceRoot = "service-root",
6
+ serviceName = "service-name",
7
+ serviceDescription = "service-description",
8
+ servicePrice = "service-price",
9
+ serviceDuration = "service-duration",
10
+ serviceImage = "service-image",
11
+ serviceCategory = "service-category",
12
+ serviceError = "service-error",
13
+ serviceLoadMore = "service-load-more",
14
+ serviceTotalsDisplayed = "service-totals-displayed",
15
+ serviceSort = "service-sort",
16
+ serviceFilter = "service-filter",
17
+ serviceFilterResetTrigger = "service-filter-reset-trigger"
18
+ }
@@ -0,0 +1,24 @@
1
+ export var TestIds;
2
+ (function (TestIds) {
3
+ // Container Level
4
+ TestIds["servicesList"] = "services-list";
5
+ // List Container Level
6
+ TestIds["servicesOptions"] = "services-options";
7
+ // Repeater Level
8
+ TestIds["serviceRepeater"] = "service-repeater";
9
+ // Entity Root and Components
10
+ TestIds["serviceRoot"] = "service-root";
11
+ TestIds["serviceName"] = "service-name";
12
+ TestIds["serviceDescription"] = "service-description";
13
+ TestIds["servicePrice"] = "service-price";
14
+ TestIds["serviceDuration"] = "service-duration";
15
+ TestIds["serviceImage"] = "service-image";
16
+ TestIds["serviceCategory"] = "service-category";
17
+ // Additional Components
18
+ TestIds["serviceError"] = "service-error";
19
+ TestIds["serviceLoadMore"] = "service-load-more";
20
+ TestIds["serviceTotalsDisplayed"] = "service-totals-displayed";
21
+ TestIds["serviceSort"] = "service-sort";
22
+ TestIds["serviceFilter"] = "service-filter";
23
+ TestIds["serviceFilterResetTrigger"] = "service-filter-reset-trigger";
24
+ })(TestIds || (TestIds = {}));
@@ -0,0 +1,52 @@
1
+ import { services } from '@wix/bookings';
2
+ export interface ServiceListConfig {
3
+ services: services.Service[];
4
+ searchOptions: {
5
+ cursorPaging: {
6
+ limit: number;
7
+ };
8
+ };
9
+ pagingMetadata: {
10
+ count: number;
11
+ };
12
+ aggregations: {
13
+ results: any[];
14
+ };
15
+ customizations: any[];
16
+ }
17
+ export interface ServiceContextValue {
18
+ service: services.Service;
19
+ }
20
+ export interface ServiceListRenderProps {
21
+ services: services.Service[];
22
+ }
23
+ export interface ServiceRenderProps {
24
+ service: services.Service;
25
+ }
26
+ export interface ErrorRenderProps {
27
+ error: string | null;
28
+ }
29
+ export interface ServiceListState {
30
+ services: services.Service[];
31
+ pagingMetadata: {
32
+ count: number;
33
+ };
34
+ filters: Record<string, any>;
35
+ error: string | null;
36
+ }
37
+ export interface ServiceListServiceValue {
38
+ services: {
39
+ get: () => services.Service[];
40
+ };
41
+ pagingMetadata: {
42
+ get: () => {
43
+ count: number;
44
+ };
45
+ };
46
+ filters: {
47
+ get: () => Record<string, any>;
48
+ };
49
+ error: {
50
+ get: () => string | null;
51
+ };
52
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export * from './services-list-service.js';
@@ -0,0 +1 @@
1
+ export * from './services-list-service.js';
@@ -0,0 +1,136 @@
1
+ import { type Signal } from '@wix/services-definitions/core-services/signals';
2
+ import { services } from '@wix/bookings';
3
+ /**
4
+ * API interface for the Service service, providing reactive service data management.
5
+ * This service handles loading and managing a single service's data, loading state, and errors.
6
+ *
7
+ * @interface ServiceServiceAPI
8
+ */
9
+ export interface ServiceServiceAPI {
10
+ /** Reactive signal containing the current service data */
11
+ service: Signal<services.Service>;
12
+ /** Reactive signal indicating if a service is currently being loaded */
13
+ isLoading: Signal<boolean>;
14
+ /** Reactive signal containing any error message, or null if no error */
15
+ error: Signal<string | null>;
16
+ /** Function to load a service by its id */
17
+ loadService: (id: string) => Promise<void>;
18
+ }
19
+ /**
20
+ * Service definition for the Service service.
21
+ * This defines the contract that the ServiceService must implement.
22
+ *
23
+ * @constant
24
+ */
25
+ export declare const ServiceServiceDefinition: string & {
26
+ __api: ServiceServiceAPI;
27
+ __config: {};
28
+ isServiceDefinition?: boolean;
29
+ } & ServiceServiceAPI;
30
+ /**
31
+ * Configuration interface required to initialize the ServiceService.
32
+ * Contains the initial service data that will be loaded into the service.
33
+ *
34
+ * @interface ServiceServiceConfig
35
+ */
36
+ export interface ServiceServiceConfig {
37
+ /** The initial service data to configure the service with */
38
+ service?: services.Service;
39
+ /** The service ID to load if no initial service is provided */
40
+ serviceId?: string;
41
+ }
42
+ /**
43
+ * Implementation of the Service service that manages reactive service data.
44
+ * This service provides signals for service data, loading state, and error handling,
45
+ * along with methods to dynamically load services.
46
+ *
47
+ * @example
48
+ * ```tsx
49
+ * import { ServiceService, ServiceServiceDefinition } from '@wix/services/services';
50
+ * import { useService } from '@wix/services-manager-react';
51
+ *
52
+ * function ServiceComponent({ serviceConfig }) {
53
+ * return (
54
+ * <ServiceProvider services={createServicesMap([
55
+ * [ServiceServiceDefinition, ServiceService.withConfig(serviceConfig)]
56
+ * ])}>
57
+ * <ServiceDisplay />
58
+ * </ServiceProvider>
59
+ * );
60
+ * }
61
+ *
62
+ * function ServiceDisplay() {
63
+ * const serviceService = useService(ServiceServiceDefinition);
64
+ * const service = serviceService.service.get();
65
+ * const isLoading = serviceService.isLoading.get();
66
+ * const error = serviceService.error.get();
67
+ *
68
+ * if (isLoading) return <div>Loading...</div>;
69
+ * if (error) return <div>Error: {error}</div>;
70
+ *
71
+ * return <h1>{service.name}</h1>;
72
+ * }
73
+ * ```
74
+ */
75
+ export declare const ServiceService: import("@wix/services-definitions").ServiceFactory<string & {
76
+ __api: ServiceServiceAPI;
77
+ __config: {};
78
+ isServiceDefinition?: boolean;
79
+ } & ServiceServiceAPI, ServiceServiceConfig>;
80
+ /**
81
+ * Success result interface for service service configuration loading.
82
+ * Returned when a service is successfully found and loaded.
83
+ *
84
+ * @interface SuccessServiceServiceConfigResult
85
+ */
86
+ export interface SuccessServiceServiceConfigResult {
87
+ /** Type "success" means that the service was found and the config is valid */
88
+ type: 'success';
89
+ /** The service config containing the loaded service data */
90
+ config: ServiceServiceConfig;
91
+ }
92
+ /**
93
+ * Not found result interface for service service configuration loading.
94
+ * Returned when a service with the given id cannot be found.
95
+ *
96
+ * @interface NotFoundServiceServiceConfigResult
97
+ */
98
+ export interface NotFoundServiceServiceConfigResult {
99
+ /** Type "notFound" means that the service was not found */
100
+ type: 'notFound';
101
+ }
102
+ /**
103
+ * Loads service service configuration from the Wix Services API for SSR initialization.
104
+ * This function is designed to be used during Server-Side Rendering (SSR) to preload
105
+ * a specific service by id that will be used to configure the ServiceService.
106
+ *
107
+ * @param serviceId The service id to load
108
+ * @returns Promise that resolves to ServiceServiceConfigResult (success with config or notFound)
109
+ *
110
+ * @example
111
+ * ```astro
112
+ * ---
113
+ * // Astro page example - pages/service/[id].astro
114
+ * import { loadServiceServiceConfig } from '@wix/services/services';
115
+ * import { Service } from '@wix/services/components';
116
+ *
117
+ * // Get service id from URL params
118
+ * const { id } = Astro.params;
119
+ *
120
+ * // Load service data during SSR
121
+ * const serviceResult = await loadServiceServiceConfig(id);
122
+ *
123
+ * // Handle not found case
124
+ * if (serviceResult.type === 'notFound') {
125
+ * return Astro.redirect('/404');
126
+ * }
127
+ * ---
128
+ *
129
+ * <Service.Root serviceConfig={serviceResult.config}>
130
+ * <Service.Name>
131
+ * {({ name }) => <h1>{name}</h1>}
132
+ * </Service.Name>
133
+ * </Service.Root>
134
+ * ```
135
+ */
136
+ export declare function loadServiceServiceConfig(serviceId: string): Promise<SuccessServiceServiceConfigResult | NotFoundServiceServiceConfigResult>;
@@ -0,0 +1,140 @@
1
+ import { defineService, implementService } from '@wix/services-definitions';
2
+ import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
3
+ import { services } from '@wix/bookings';
4
+ /**
5
+ * Service definition for the Service service.
6
+ * This defines the contract that the ServiceService must implement.
7
+ *
8
+ * @constant
9
+ */
10
+ export const ServiceServiceDefinition = defineService('service');
11
+ /**
12
+ * Implementation of the Service service that manages reactive service data.
13
+ * This service provides signals for service data, loading state, and error handling,
14
+ * along with methods to dynamically load services.
15
+ *
16
+ * @example
17
+ * ```tsx
18
+ * import { ServiceService, ServiceServiceDefinition } from '@wix/services/services';
19
+ * import { useService } from '@wix/services-manager-react';
20
+ *
21
+ * function ServiceComponent({ serviceConfig }) {
22
+ * return (
23
+ * <ServiceProvider services={createServicesMap([
24
+ * [ServiceServiceDefinition, ServiceService.withConfig(serviceConfig)]
25
+ * ])}>
26
+ * <ServiceDisplay />
27
+ * </ServiceProvider>
28
+ * );
29
+ * }
30
+ *
31
+ * function ServiceDisplay() {
32
+ * const serviceService = useService(ServiceServiceDefinition);
33
+ * const service = serviceService.service.get();
34
+ * const isLoading = serviceService.isLoading.get();
35
+ * const error = serviceService.error.get();
36
+ *
37
+ * if (isLoading) return <div>Loading...</div>;
38
+ * if (error) return <div>Error: {error}</div>;
39
+ *
40
+ * return <h1>{service.name}</h1>;
41
+ * }
42
+ * ```
43
+ */
44
+ export const ServiceService = implementService.withConfig()(ServiceServiceDefinition, ({ getService, config }) => {
45
+ const signalsService = getService(SignalsServiceDefinition);
46
+ const service = signalsService.signal(config.service);
47
+ const isLoading = signalsService.signal(!!config.serviceId);
48
+ const error = signalsService.signal(null);
49
+ const loadService = async (id) => {
50
+ isLoading.set(true);
51
+ const serviceResponse = await loadServiceById(id);
52
+ if (!serviceResponse.service) {
53
+ error.set('Service not found');
54
+ }
55
+ else {
56
+ service.set(serviceResponse.service);
57
+ error.set(null);
58
+ }
59
+ isLoading.set(false);
60
+ };
61
+ if (config.serviceId) {
62
+ loadService(config.serviceId);
63
+ }
64
+ return {
65
+ service,
66
+ isLoading,
67
+ error,
68
+ loadService,
69
+ };
70
+ });
71
+ /**
72
+ * Internal helper function to load a service by its ID from the Wix Services API.
73
+ * Fetches comprehensive service data including description, categories, media, etc.
74
+ *
75
+ * @private
76
+ * @param {string} id - The service ID to load
77
+ * @returns {Promise} Service response from the API
78
+ */
79
+ const loadServiceById = async (id) => {
80
+ try {
81
+ const service = await services.getService(id);
82
+ return { service };
83
+ }
84
+ catch (error) {
85
+ console.error(`Failed to load service for id "${id}":`, error);
86
+ return { service: null };
87
+ }
88
+ };
89
+ /**
90
+ * Loads service service configuration from the Wix Services API for SSR initialization.
91
+ * This function is designed to be used during Server-Side Rendering (SSR) to preload
92
+ * a specific service by id that will be used to configure the ServiceService.
93
+ *
94
+ * @param serviceId The service id to load
95
+ * @returns Promise that resolves to ServiceServiceConfigResult (success with config or notFound)
96
+ *
97
+ * @example
98
+ * ```astro
99
+ * ---
100
+ * // Astro page example - pages/service/[id].astro
101
+ * import { loadServiceServiceConfig } from '@wix/services/services';
102
+ * import { Service } from '@wix/services/components';
103
+ *
104
+ * // Get service id from URL params
105
+ * const { id } = Astro.params;
106
+ *
107
+ * // Load service data during SSR
108
+ * const serviceResult = await loadServiceServiceConfig(id);
109
+ *
110
+ * // Handle not found case
111
+ * if (serviceResult.type === 'notFound') {
112
+ * return Astro.redirect('/404');
113
+ * }
114
+ * ---
115
+ *
116
+ * <Service.Root serviceConfig={serviceResult.config}>
117
+ * <Service.Name>
118
+ * {({ name }) => <h1>{name}</h1>}
119
+ * </Service.Name>
120
+ * </Service.Root>
121
+ * ```
122
+ */
123
+ export async function loadServiceServiceConfig(serviceId) {
124
+ try {
125
+ const serviceResponse = await loadServiceById(serviceId);
126
+ if (!serviceResponse.service) {
127
+ return { type: 'notFound' };
128
+ }
129
+ return {
130
+ type: 'success',
131
+ config: {
132
+ service: serviceResponse.service,
133
+ },
134
+ };
135
+ }
136
+ catch (error) {
137
+ console.error(`Failed to load service for id "${serviceId}":`, error);
138
+ return { type: 'notFound' };
139
+ }
140
+ }