@wix/headless-restaurants-olo 0.0.1
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/react/ItemDetails.d.ts +119 -0
- package/cjs/dist/react/ItemDetails.js +51 -0
- package/cjs/dist/react/core/ItemDetails.d.ts +50 -0
- package/cjs/dist/react/core/ItemDetails.js +73 -0
- package/cjs/dist/react/core/index.d.ts +1 -0
- package/cjs/dist/react/core/index.js +1 -0
- package/cjs/dist/react/index.d.ts +1 -0
- package/cjs/dist/react/index.js +1 -0
- package/cjs/dist/services/common-types.d.ts +3 -0
- package/cjs/dist/services/common-types.js +1 -0
- package/cjs/dist/services/index.d.ts +2 -0
- package/cjs/dist/services/index.js +2 -0
- package/cjs/dist/services/item-details-service.d.ts +154 -0
- package/cjs/dist/services/item-details-service.js +196 -0
- package/cjs/dist/services/olo-settings-service.d.ts +35 -0
- package/cjs/dist/services/olo-settings-service.js +43 -0
- package/dist/react/ItemDetails.d.ts +119 -0
- package/dist/react/ItemDetails.js +51 -0
- package/dist/react/core/ItemDetails.d.ts +50 -0
- package/dist/react/core/ItemDetails.js +73 -0
- package/dist/react/core/index.d.ts +1 -0
- package/dist/react/core/index.js +1 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +1 -0
- package/dist/services/common-types.d.ts +3 -0
- package/dist/services/common-types.js +1 -0
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.js +2 -0
- package/dist/services/item-details-service.d.ts +154 -0
- package/dist/services/item-details-service.js +196 -0
- package/dist/services/olo-settings-service.d.ts +35 -0
- package/dist/services/olo-settings-service.js +43 -0
- package/package.json +64 -0
- package/react/package.json +4 -0
- package/services/package.json +4 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { defineService, implementService } from '@wix/services-definitions';
|
|
2
|
+
import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
|
|
3
|
+
/**
|
|
4
|
+
* Service definition for the Item service.
|
|
5
|
+
* This defines the contract that the ItemService must implement.
|
|
6
|
+
*
|
|
7
|
+
* @constant
|
|
8
|
+
*/
|
|
9
|
+
export const ItemServiceDefinition = defineService('item');
|
|
10
|
+
/**
|
|
11
|
+
* Implementation of the Item service that manages reactive item data.
|
|
12
|
+
* This service provides signals for item data, loading state, and error handling,
|
|
13
|
+
* along with methods to dynamically load items.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* import { ItemService, ItemServiceDefinition } from '@wix/stores/services';
|
|
18
|
+
* import { useService } from '@wix/services-manager-react';
|
|
19
|
+
*
|
|
20
|
+
* function ItemComponent({ itemConfig }) {
|
|
21
|
+
* return (
|
|
22
|
+
* <ServiceProvider services={createServicesMap([
|
|
23
|
+
* [ItemServiceDefinition, ItemService.withConfig(itemConfig)]
|
|
24
|
+
* ])}>
|
|
25
|
+
* <ItemDisplay />
|
|
26
|
+
* </ServiceProvider>
|
|
27
|
+
* );
|
|
28
|
+
* }
|
|
29
|
+
*
|
|
30
|
+
* function ItemDisplay() {
|
|
31
|
+
* const itemService = useService(ItemServiceDefinition);
|
|
32
|
+
* const item = itemService.item.get();
|
|
33
|
+
* const isLoading = itemService.isLoading.get();
|
|
34
|
+
* const error = itemService.error.get();
|
|
35
|
+
*
|
|
36
|
+
* if (isLoading) return <div>Loading...</div>;
|
|
37
|
+
* if (error) return <div>Error: {error}</div>;
|
|
38
|
+
*
|
|
39
|
+
* return <h1>{item.name}</h1>;
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
const APP_ID = '9a5d83fd-8570-482e-81ab-cfa88942ee60';
|
|
44
|
+
export const ItemService = implementService.withConfig()(ItemServiceDefinition, ({ getService, config }) => {
|
|
45
|
+
const signalsService = getService(SignalsServiceDefinition);
|
|
46
|
+
const item = signalsService.signal(config.item);
|
|
47
|
+
const isLoading = signalsService.signal(!!config.item);
|
|
48
|
+
const error = signalsService.signal(config.item ? null : 'Item not found');
|
|
49
|
+
const quantity = signalsService.signal(1);
|
|
50
|
+
const specialRequest = signalsService.signal('');
|
|
51
|
+
const lineItem = signalsService.signal({});
|
|
52
|
+
if (config.item) {
|
|
53
|
+
console.log('config.item', config.item);
|
|
54
|
+
lineItem.set({
|
|
55
|
+
quantity: quantity.get(),
|
|
56
|
+
catalogReference: {
|
|
57
|
+
// @ts-expect-error - item is not typed
|
|
58
|
+
catalogItemId: config.item._id,
|
|
59
|
+
appId: APP_ID,
|
|
60
|
+
options: {
|
|
61
|
+
operationId: config.operationId,
|
|
62
|
+
// @ts-expect-error - item is not typed
|
|
63
|
+
menuId: config.item.menuId,
|
|
64
|
+
// @ts-expect-error - item is not typed
|
|
65
|
+
sectionId: config.item.sectionId,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
const updateQuantity = (_quantity) => {
|
|
71
|
+
quantity.set(_quantity);
|
|
72
|
+
const _lineItem = lineItem.get();
|
|
73
|
+
lineItem.set({
|
|
74
|
+
..._lineItem,
|
|
75
|
+
quantity: _quantity,
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
const updateSpecialRequest = (_specialRequest) => {
|
|
79
|
+
specialRequest.set(_specialRequest);
|
|
80
|
+
const _lineItem = lineItem.get();
|
|
81
|
+
lineItem.set({
|
|
82
|
+
..._lineItem,
|
|
83
|
+
catalogReference: {
|
|
84
|
+
..._lineItem.catalogReference,
|
|
85
|
+
options: {
|
|
86
|
+
..._lineItem.catalogReference?.options,
|
|
87
|
+
specialRequest: _specialRequest,
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
return {
|
|
93
|
+
item,
|
|
94
|
+
quantity,
|
|
95
|
+
updateQuantity,
|
|
96
|
+
updateSpecialRequest,
|
|
97
|
+
isLoading,
|
|
98
|
+
error,
|
|
99
|
+
specialRequest,
|
|
100
|
+
lineItem,
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
/**
|
|
104
|
+
* Loads item service configuration from the Wix Items API for SSR initialization.
|
|
105
|
+
* This function is designed to be used during Server-Side Rendering (SSR) to preload
|
|
106
|
+
* a specific item by id that will be used to configure the ItemService.
|
|
107
|
+
*
|
|
108
|
+
* @param itemSlug The item id to load
|
|
109
|
+
* @returns Promise that resolves to ItemServiceConfigResult (success with config or notFound)
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```astro
|
|
113
|
+
* ---
|
|
114
|
+
* // Astro page example - pages/item/[id].astro
|
|
115
|
+
* import { loadItemServiceConfig } from '@wix/stores/services';
|
|
116
|
+
* import { Item } from '@wix/stores/components';
|
|
117
|
+
*
|
|
118
|
+
* // Get item id from URL params
|
|
119
|
+
* const { id } = Astro.params;
|
|
120
|
+
*
|
|
121
|
+
* // Load item data during SSR
|
|
122
|
+
* const itemResult = await loadItemServiceConfig(id);
|
|
123
|
+
*
|
|
124
|
+
* // Handle not found case
|
|
125
|
+
* if (itemResult.type === 'notFound') {
|
|
126
|
+
* return Astro.redirect('/404');
|
|
127
|
+
* }
|
|
128
|
+
* ---
|
|
129
|
+
*
|
|
130
|
+
* <Item.Root itemConfig={itemResult.config}>
|
|
131
|
+
* <Item.Name>
|
|
132
|
+
* {({ name }) => <h1>{name}</h1>}
|
|
133
|
+
* </Item.Name>
|
|
134
|
+
* </Item.Root>
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```tsx
|
|
139
|
+
* // Next.js page example - pages/item/[id].tsx
|
|
140
|
+
* import { GetServerSideProps } from 'next';
|
|
141
|
+
* import { loadItemServiceConfig } from '@wix/stores/services';
|
|
142
|
+
* import { Item } from '@wix/stores/components';
|
|
143
|
+
*
|
|
144
|
+
* interface ItemPageProps {
|
|
145
|
+
* itemConfig: Extract<Awaited<ReturnType<typeof loadItemServiceConfig>>, { type: 'success' }>['config'];
|
|
146
|
+
* }
|
|
147
|
+
*
|
|
148
|
+
* export const getServerSideProps: GetServerSideProps<ItemPageProps> = async ({ params }) => {
|
|
149
|
+
* const id = params?.id as string;
|
|
150
|
+
*
|
|
151
|
+
* // Load item data during SSR
|
|
152
|
+
* const itemResult = await loadItemServiceConfig(id);
|
|
153
|
+
*
|
|
154
|
+
* // Handle not found case
|
|
155
|
+
* if (itemResult.type === 'notFound') {
|
|
156
|
+
* return {
|
|
157
|
+
* notFound: true,
|
|
158
|
+
* };
|
|
159
|
+
* }
|
|
160
|
+
*
|
|
161
|
+
* return {
|
|
162
|
+
* props: {
|
|
163
|
+
* itemConfig: itemResult.config,
|
|
164
|
+
* },
|
|
165
|
+
* };
|
|
166
|
+
* };
|
|
167
|
+
*
|
|
168
|
+
* export default function ItemPage({ itemConfig }: ItemPageProps) {
|
|
169
|
+
* return (
|
|
170
|
+
* <Item.Root itemConfig={itemConfig}>
|
|
171
|
+
* <Item.Name>
|
|
172
|
+
* {({ name }) => <h1>{name}</h1>}
|
|
173
|
+
* </Item.Name>
|
|
174
|
+
* </Item.Root>
|
|
175
|
+
* );
|
|
176
|
+
* }
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
export function loadItemServiceConfig({ item, operationId, }) {
|
|
180
|
+
return { item, operationId };
|
|
181
|
+
}
|
|
182
|
+
// try {
|
|
183
|
+
// if (item === null) {
|
|
184
|
+
// return { item: null };
|
|
185
|
+
// }
|
|
186
|
+
// console.log('loadItemServiceConfig', item);
|
|
187
|
+
// const itemResponse = await loadItemById(item._id);
|
|
188
|
+
// console.log('itemResponse', itemResponse);
|
|
189
|
+
// if (!itemResponse) {
|
|
190
|
+
// return { item: itemResponse, item };
|
|
191
|
+
// }
|
|
192
|
+
// return { item: itemResponse };
|
|
193
|
+
// } catch (error) {
|
|
194
|
+
// console.error(`Failed to load item "${itemId}":`, error);
|
|
195
|
+
// return { item: null, itemId };
|
|
196
|
+
// }}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as operationGroupsApi from '@wix/auto_sdk_restaurants_operation-groups';
|
|
2
|
+
import * as operationsApi from '@wix/auto_sdk_restaurants_operations';
|
|
3
|
+
import { type Signal } from '@wix/services-definitions/core-services/signals';
|
|
4
|
+
export interface OLOSettingsServiceAPI {
|
|
5
|
+
operationGroup: Signal<operationGroupsApi.OperationGroup | undefined>;
|
|
6
|
+
operation: Signal<operationsApi.Operation | undefined>;
|
|
7
|
+
selectedItem?: Signal<unknown>;
|
|
8
|
+
isLoading: Signal<boolean>;
|
|
9
|
+
error: Signal<string | null>;
|
|
10
|
+
}
|
|
11
|
+
export interface OLOSettingsServiceConfig {
|
|
12
|
+
operationGroup?: operationGroupsApi.OperationGroup;
|
|
13
|
+
operation?: operationsApi.Operation;
|
|
14
|
+
}
|
|
15
|
+
export declare const OLOSettingsServiceDefinition: string & {
|
|
16
|
+
__api: OLOSettingsServiceAPI;
|
|
17
|
+
__config: {};
|
|
18
|
+
isServiceDefinition?: boolean;
|
|
19
|
+
} & OLOSettingsServiceAPI;
|
|
20
|
+
export declare const OLOSettingsService: import("@wix/services-definitions").ServiceFactory<string & {
|
|
21
|
+
__api: OLOSettingsServiceAPI;
|
|
22
|
+
__config: {};
|
|
23
|
+
isServiceDefinition?: boolean;
|
|
24
|
+
} & OLOSettingsServiceAPI, OLOSettingsServiceConfig>;
|
|
25
|
+
export declare function loadOLOSettingsServiceConfig(): Promise<{
|
|
26
|
+
operationGroup: operationGroupsApi.OperationGroup | undefined;
|
|
27
|
+
operation: operationsApi.Operation | undefined;
|
|
28
|
+
isLoading?: undefined;
|
|
29
|
+
error?: undefined;
|
|
30
|
+
} | {
|
|
31
|
+
operationGroup: undefined;
|
|
32
|
+
operation: undefined;
|
|
33
|
+
isLoading: boolean;
|
|
34
|
+
error: string;
|
|
35
|
+
}>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { defineService, implementService } from '@wix/services-definitions';
|
|
2
|
+
import * as operationGroupsApi from '@wix/auto_sdk_restaurants_operation-groups';
|
|
3
|
+
import * as operationsApi from '@wix/auto_sdk_restaurants_operations';
|
|
4
|
+
import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
|
|
5
|
+
export const OLOSettingsServiceDefinition = defineService('oloSettings');
|
|
6
|
+
export const OLOSettingsService = implementService.withConfig()(OLOSettingsServiceDefinition, ({ getService, config }) => {
|
|
7
|
+
const signalsService = getService(SignalsServiceDefinition);
|
|
8
|
+
const operationGroup = signalsService.signal(config.operationGroup);
|
|
9
|
+
const operation = signalsService.signal(config.operation);
|
|
10
|
+
const selectedItem = signalsService.signal(null);
|
|
11
|
+
const isLoading = signalsService.signal(false);
|
|
12
|
+
const error = signalsService.signal(null);
|
|
13
|
+
return {
|
|
14
|
+
operationGroup,
|
|
15
|
+
operation,
|
|
16
|
+
isLoading,
|
|
17
|
+
error,
|
|
18
|
+
selectedItem,
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
export async function loadOLOSettingsServiceConfig() {
|
|
22
|
+
try {
|
|
23
|
+
// Fetch operation groups and operations in parallel
|
|
24
|
+
const [operationGroupsResponse, operationsResponse] = await Promise.all([
|
|
25
|
+
operationGroupsApi.queryOperationGroups().find(),
|
|
26
|
+
operationsApi.queryOperation().find(),
|
|
27
|
+
]);
|
|
28
|
+
return {
|
|
29
|
+
operationGroup: operationGroupsResponse.items[0] || undefined,
|
|
30
|
+
operation: operationsResponse.items[0] || undefined,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
console.error('Failed to load OLO settings service config:', error);
|
|
35
|
+
return {
|
|
36
|
+
operationGroup: undefined,
|
|
37
|
+
operation: undefined,
|
|
38
|
+
isLoading: false,
|
|
39
|
+
error: error?.message ||
|
|
40
|
+
'Failed to load OLO settings service config',
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wix/headless-restaurants-olo",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "npm run build:esm && npm run build:cjs",
|
|
7
|
+
"build:esm": "tsc -p tsconfig.json",
|
|
8
|
+
"build:cjs": "tsc -p tsconfig.cjs.json",
|
|
9
|
+
"test": "vitest",
|
|
10
|
+
"lint:fix": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,md}\"",
|
|
11
|
+
"lint:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json,md}\""
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"cjs",
|
|
16
|
+
"react",
|
|
17
|
+
"services",
|
|
18
|
+
"server-actions",
|
|
19
|
+
"astro"
|
|
20
|
+
],
|
|
21
|
+
"exports": {
|
|
22
|
+
"./react": {
|
|
23
|
+
"types": "./dist/react/index.d.ts",
|
|
24
|
+
"import": "./dist/react/index.js",
|
|
25
|
+
"require": "./cjs/dist/react/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./services": {
|
|
28
|
+
"types": "./dist/services/index.d.ts",
|
|
29
|
+
"import": "./dist/services/index.js",
|
|
30
|
+
"require": "./cjs/dist/services/index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@testing-library/dom": "^10.4.0",
|
|
35
|
+
"@testing-library/jest-dom": "^6.6.3",
|
|
36
|
+
"@testing-library/react": "^16.3.0",
|
|
37
|
+
"@types/node": "^20.9.0",
|
|
38
|
+
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
|
39
|
+
"@typescript-eslint/parser": "^6.21.0",
|
|
40
|
+
"@vitest/ui": "^3.1.4",
|
|
41
|
+
"eslint": "^8.57.0",
|
|
42
|
+
"eslint-config-prettier": "^10.1.8",
|
|
43
|
+
"eslint-plugin-react": "^7.34.1",
|
|
44
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
45
|
+
"jsdom": "^26.1.0",
|
|
46
|
+
"prettier": "^3.4.2",
|
|
47
|
+
"typescript": "^5.8.3",
|
|
48
|
+
"vitest": "^3.1.4"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@radix-ui/react-slot": "^1.1.0",
|
|
52
|
+
"@wix/auto_sdk_restaurants_items": "^1.0.48",
|
|
53
|
+
"@wix/headless-media": "^0.0.15",
|
|
54
|
+
"@wix/headless-utils": "^0.0.4",
|
|
55
|
+
"@wix/redirects": "^1.0.0",
|
|
56
|
+
"@wix/restaurants": "^1.0.396",
|
|
57
|
+
"@wix/sdk": "^1.15.24",
|
|
58
|
+
"@wix/services-definitions": "^0.1.4",
|
|
59
|
+
"@wix/services-manager-react": "^0.1.26"
|
|
60
|
+
},
|
|
61
|
+
"peerDependencies": {
|
|
62
|
+
"@wix/headless-components": "^0.0.16"
|
|
63
|
+
}
|
|
64
|
+
}
|