@evenicanpm/storefront-core 2.3.0 → 2.4.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.
- package/CHANGELOG.md +8 -0
- package/package.json +29 -9
- package/src/api-manager/datasources/d365/d365-address.datasource.ts +11 -0
- package/src/api-manager/datasources/d365/d365-cart.datasource.ts +23 -1
- package/src/api-manager/datasources/d365/d365-order.datasource.ts +6 -1
- package/src/api-manager/datasources/d365/d365-user.datasource.ts +29 -14
- package/src/api-manager/datasources/e4/graphqlRequestSdk.ts +7 -0
- package/src/api-manager/index.ts +2 -1
- package/src/api-manager/schemas/product.schema.ts +1 -1
- package/src/auth/msal.ts +1 -4
- package/src/cms/blocks/block-manager.tsx +1 -1
- package/src/cms/blocks/components/footer/footer-content.tsx +61 -0
- package/src/cms/blocks/components/footer/index.tsx +9 -71
- package/src/cms/blocks/components/footer/interfaces.ts +4 -0
- package/src/cms/blocks/components/footer/sections/footer-contact.tsx +18 -9
- package/src/cms/blocks/components/footer/sections/footer-logo.tsx +17 -2
- package/src/cms/endpoints.ts +7 -2
- package/src/components/BazaarMenu.tsx +1 -1
- package/src/components/Typography.tsx +4 -2
- package/src/components/_tests_/site-logo.test.tsx +1 -1
- package/src/components/carousel-cards/carousel-card-1/CarouselCard1.stories.tsx +1 -1
- package/src/components/categories/category-menu.tsx +1 -1
- package/src/components/countries-input.tsx +4 -0
- package/src/components/header/components/user.tsx +4 -5
- package/src/components/navbar/mobile-menu/mobile-menu.test.tsx +1 -1
- package/src/components/navbar/utils/transform-nav.test.ts +1 -1
- package/src/components/navbar/utils/transform-nav.ts +1 -1
- package/src/components/product-cards/product-card/product-card.tsx +5 -2
- package/src/components/product-cards/product-card/styles/index.ts +1 -5
- package/src/components/product-cards/product-card-plp/product-card.tsx +4 -12
- package/src/components/product-cards/product-card-plp/styles/index.ts +15 -0
- package/src/components/products-view/compound/products-grid-view.tsx +5 -1
- package/src/components/products-view/compound/products-list-view.tsx +5 -1
- package/src/components/site-logo.tsx +1 -1
- package/src/components/wishlist-dialogs/add-to-wishlist/compound/wishlist-dialog-item.tsx +3 -1
- package/src/global.d.ts +3 -0
- package/src/pages/account/account-navigation.tsx +2 -2
- package/src/pages/account/account-routes.ts +38 -4
- package/src/pages/account/addresses/address-form.tsx +20 -2
- package/src/pages/account/table-row-skeleton.tsx +31 -0
- package/src/pages/account/wishlist/wishlist-item.tsx +3 -1
- package/src/pages/blog/blog-detail-view.tsx +3 -1
- package/src/pages/cart/cart-item.tsx +1 -7
- package/src/pages/checkout/checkout-alt-form/checkout-form.tsx +14 -3
- package/src/pages/checkout/checkout-alt-form/steps/address/address-card.tsx +5 -3
- package/src/pages/checkout/checkout-alt-form/steps/address/new-address-form.tsx +1 -1
- package/src/pages/cms-page-view.tsx +1 -1
- package/src/pages/confirmation/ordered-products.tsx +3 -1
- package/src/pages/product-details/bopis/find-in-store-modal.tsx +4 -4
- package/src/pages/product-details/bopis/pickup-option-select.tsx +2 -2
- package/src/pages/product-details/bopis/search-header.tsx +2 -2
- package/src/pages/product-details/product-description.tsx +25 -13
- package/src/pages/product-details/product-intro/compound/context.ts +8 -3
- package/src/pages/product-details/product-intro/compound/product-info.tsx +25 -19
- package/src/pages/product-details/product-intro/compound/product-intro-images.tsx +26 -8
- package/src/pages/product-details/product-intro/compound/thumbnail-with-skeleton.tsx +17 -21
- package/src/pages/product-details/product-tabs.tsx +20 -4
- package/src/pages/product-list/product-list-view.tsx +2 -1
- package/src/providers/nav-provider/index.tsx +1 -1
- package/src/providers/nav-provider/utils/createLink.ts +1 -1
- package/tsconfig.json +1 -2
- package/__mocks__/countries.ts +0 -11
- package/__mocks__/create-mutation.ts +0 -68
- package/__mocks__/create-query.ts +0 -94
- package/__mocks__/data/categories.json +0 -795
- package/__mocks__/get-product-by-id.ts +0 -6
- package/__mocks__/next-auth-react.ts +0 -9
- package/__mocks__/next-font.js +0 -4
- package/__mocks__/next-headers.js +0 -13
- package/__mocks__/next-image.tsx +0 -18
- package/__mocks__/next-link.js +0 -19
- package/__mocks__/next-navigation.ts +0 -29
- package/__mocks__/product-dimensions.ts +0 -635
- package/__mocks__/products.ts +0 -533
- package/__mocks__/query-client.ts +0 -3
- package/__mocks__/wishlists.json +0 -408
- package/src/cms/blog.ts +0 -229
- package/src/cms/interfaces/navigation.ts +0 -52
- package/src/cms/interfaces/product-data.ts +0 -83
- package/src/cms/pages.ts +0 -149
package/CHANGELOG.md
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evenicanpm/storefront-core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Core module for D365/e4 Headless Storefront",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -16,33 +16,54 @@
|
|
|
16
16
|
"author": "Evenica",
|
|
17
17
|
"license": "ISC",
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@evenicanpm/cms": "
|
|
20
|
-
"@evenicanpm/ui": "
|
|
21
|
-
"strapi-sdk-js": "^3.0.0"
|
|
19
|
+
"@evenicanpm/cms": "workspace:*",
|
|
20
|
+
"@evenicanpm/ui": "workspace:*",
|
|
21
|
+
"strapi-sdk-js": "^3.0.0",
|
|
22
|
+
"clsx": "^2.1.1"
|
|
22
23
|
},
|
|
23
24
|
"devDependencies": {
|
|
25
|
+
"@emotion/react": "catalog:",
|
|
26
|
+
"@emotion/styled": "catalog:",
|
|
27
|
+
"@mui/icons-material": "catalog:",
|
|
28
|
+
"@mui/material": "catalog:",
|
|
29
|
+
"@mui/types": "catalog:",
|
|
30
|
+
"@mui/system": "catalog:",
|
|
24
31
|
"@storybook/addon-docs": "^9.1.6",
|
|
25
32
|
"@storybook/addon-webpack5-compiler-swc": "^4.0.1",
|
|
26
33
|
"@storybook/nextjs": "^9.1.6",
|
|
34
|
+
"@storybook/react": "^9.1.6",
|
|
27
35
|
"@storybook/react-webpack5": "^9.1.6",
|
|
28
36
|
"@types/jsonwebtoken": "^9.0.9",
|
|
29
37
|
"@types/lodash": "^4.17.17",
|
|
30
38
|
"@types/node": "^22.15.20",
|
|
31
39
|
"@types/object-mapper": "^6.2.2",
|
|
40
|
+
"@types/react": "catalog:",
|
|
41
|
+
"@types/react-dom": "catalog:",
|
|
42
|
+
"react": "catalog:",
|
|
43
|
+
"react-dom": "catalog:",
|
|
32
44
|
"storybook": "^9.1.6"
|
|
33
45
|
},
|
|
34
46
|
"peerDependencies": {
|
|
47
|
+
"@emotion/react": "catalog:",
|
|
48
|
+
"@emotion/styled": "catalog:",
|
|
35
49
|
"@msdyn365-commerce/retail-proxy": "9.50",
|
|
50
|
+
"@mui/icons-material": "catalog:",
|
|
51
|
+
"@mui/material": "catalog:",
|
|
52
|
+
"@mui/system": "catalog:",
|
|
36
53
|
"@opentelemetry/api": "^1.9.1",
|
|
37
54
|
"@strapi/blocks-react-renderer": "^1.0.1",
|
|
38
|
-
"@tanstack/react-query": "
|
|
39
|
-
"
|
|
55
|
+
"@tanstack/react-query": "catalog:",
|
|
56
|
+
"@tanstack/query-core": "catalog:",
|
|
57
|
+
"better-auth": "catalog:",
|
|
40
58
|
"graphql": "^16.11.0",
|
|
41
59
|
"graphql-request": "^7.1.2",
|
|
42
60
|
"jsonwebtoken": "^9.0.2",
|
|
43
61
|
"lodash": "^4.17.21",
|
|
44
|
-
"next": "
|
|
62
|
+
"next": "catalog:",
|
|
63
|
+
"next-intl": "catalog:",
|
|
45
64
|
"object-mapper": "^6.2.0",
|
|
65
|
+
"react": "catalog:",
|
|
66
|
+
"react-dom": "catalog:",
|
|
46
67
|
"set-cookie-parser": "^2.7.1",
|
|
47
68
|
"typedoc": "^0.28.9",
|
|
48
69
|
"typedoc-plugin-merge-modules": "^7.0.0",
|
|
@@ -53,6 +74,5 @@
|
|
|
53
74
|
"@storybook/builder-manager": {
|
|
54
75
|
"esbuild": "0.19.11"
|
|
55
76
|
}
|
|
56
|
-
}
|
|
57
|
-
"gitHead": "72bf1aeb02a3d96c587706c0d91606698e38ff6a"
|
|
77
|
+
}
|
|
58
78
|
}
|
|
@@ -28,12 +28,15 @@ import type {
|
|
|
28
28
|
class D365AddressDatasource extends D365DatasourceBase implements AddressApi {
|
|
29
29
|
async createAddress(address: Address): Promise<Address> {
|
|
30
30
|
const context = await getContextFromCookie();
|
|
31
|
+
// biome-ignore lint: api datasources should not be typed
|
|
31
32
|
const customer = await readAsync(context as any, "");
|
|
32
33
|
const accountNumber = customer.AccountNumber;
|
|
33
34
|
|
|
34
35
|
const prevAddresses = customer.Addresses ?? [];
|
|
36
|
+
// biome-ignore lint: api datasources should not be typed
|
|
35
37
|
customer.Addresses = [...prevAddresses, address as any];
|
|
36
38
|
|
|
39
|
+
// biome-ignore lint: api datasources should not be typed
|
|
37
40
|
const updatedCustomer = await updateAsync(context as any, {
|
|
38
41
|
...customer,
|
|
39
42
|
AccountNumber: accountNumber,
|
|
@@ -54,12 +57,14 @@ class D365AddressDatasource extends D365DatasourceBase implements AddressApi {
|
|
|
54
57
|
|
|
55
58
|
async updateAddress(address: Address): Promise<Address> {
|
|
56
59
|
const context = await getContextFromCookie();
|
|
60
|
+
// biome-ignore lint: api datasources should not be typed
|
|
57
61
|
const customer = await readAsync(context as any, "");
|
|
58
62
|
customer.Addresses = customer.Addresses ?? [];
|
|
59
63
|
|
|
60
64
|
const idx = customer.Addresses.findIndex(
|
|
61
65
|
(a) => a.RecordId?.toString() === address.Id,
|
|
62
66
|
);
|
|
67
|
+
// biome-ignore lint: api datasources should not be typed
|
|
63
68
|
const updatedRecord = { ...(address as any) };
|
|
64
69
|
|
|
65
70
|
if (idx >= 0) {
|
|
@@ -71,6 +76,7 @@ class D365AddressDatasource extends D365DatasourceBase implements AddressApi {
|
|
|
71
76
|
customer.Addresses.push(updatedRecord);
|
|
72
77
|
}
|
|
73
78
|
|
|
79
|
+
// biome-ignore lint: api datasources should not be typed
|
|
74
80
|
const updatedCustomer = await updateAsync(context as any, customer);
|
|
75
81
|
const rec = updatedCustomer?.Addresses?.[idx];
|
|
76
82
|
if (rec?.RecordId == null) {
|
|
@@ -87,6 +93,7 @@ class D365AddressDatasource extends D365DatasourceBase implements AddressApi {
|
|
|
87
93
|
|
|
88
94
|
async deleteAddress(addressId: string): Promise<string> {
|
|
89
95
|
const context = await getContextFromCookie();
|
|
96
|
+
// biome-ignore lint: api datasources should not be typed
|
|
90
97
|
const customer = await readAsync(context as any, "");
|
|
91
98
|
customer.Addresses = customer.Addresses ?? [];
|
|
92
99
|
|
|
@@ -95,6 +102,7 @@ class D365AddressDatasource extends D365DatasourceBase implements AddressApi {
|
|
|
95
102
|
);
|
|
96
103
|
if (rec) {
|
|
97
104
|
rec.Deactivate = true;
|
|
105
|
+
// biome-ignore lint: api datasources should not be typed
|
|
98
106
|
await updateAsync(context as any, customer);
|
|
99
107
|
}
|
|
100
108
|
|
|
@@ -108,6 +116,7 @@ class D365AddressDatasource extends D365DatasourceBase implements AddressApi {
|
|
|
108
116
|
throw new Error("Locale is required to fetch countries");
|
|
109
117
|
}
|
|
110
118
|
|
|
119
|
+
// biome-ignore lint: api datasources should not be typed
|
|
111
120
|
return getCountryRegionsByLanguageIdAsync(context as any, locale);
|
|
112
121
|
}
|
|
113
122
|
|
|
@@ -117,6 +126,7 @@ class D365AddressDatasource extends D365DatasourceBase implements AddressApi {
|
|
|
117
126
|
throw new Error("countryId is required to fetch states");
|
|
118
127
|
}
|
|
119
128
|
|
|
129
|
+
// biome-ignore lint: api datasources should not be typed
|
|
120
130
|
return getStateProvincesAsync(context as any, input.countryId);
|
|
121
131
|
}
|
|
122
132
|
|
|
@@ -126,6 +136,7 @@ class D365AddressDatasource extends D365DatasourceBase implements AddressApi {
|
|
|
126
136
|
const context = await getContextFromCookie();
|
|
127
137
|
try {
|
|
128
138
|
return getDeliveryOptionsAsync(
|
|
139
|
+
// biome-ignore lint: api datasources should not be typed
|
|
129
140
|
context as any,
|
|
130
141
|
input.cartId,
|
|
131
142
|
input.shippingAddress,
|
|
@@ -11,14 +11,17 @@ function serializeError(error: unknown): string {
|
|
|
11
11
|
const allKeys = new Set<string>();
|
|
12
12
|
let proto = value;
|
|
13
13
|
while (proto && proto !== Object.prototype) {
|
|
14
|
+
// biome-ignore lint: api datasources should not be typed
|
|
14
15
|
Object.getOwnPropertyNames(proto).forEach((k) => allKeys.add(k));
|
|
15
16
|
proto = Object.getPrototypeOf(proto);
|
|
16
17
|
}
|
|
18
|
+
// biome-ignore lint: api datasources should not be typed
|
|
17
19
|
Object.keys(value).forEach((k) => allKeys.add(k));
|
|
18
20
|
const result: Record<string, unknown> = {};
|
|
19
21
|
for (const key of allKeys) {
|
|
20
22
|
if (key !== "constructor") {
|
|
21
23
|
try {
|
|
24
|
+
// biome-ignore lint: api datasources should not be typed
|
|
22
25
|
result[key] = (value as any)[key];
|
|
23
26
|
} catch {}
|
|
24
27
|
}
|
|
@@ -135,6 +138,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
135
138
|
}
|
|
136
139
|
|
|
137
140
|
const result = await checkoutAsync(
|
|
141
|
+
// biome-ignore lint: api datasources should not be typed
|
|
138
142
|
context as any,
|
|
139
143
|
input.id,
|
|
140
144
|
input.receiptEmail,
|
|
@@ -164,6 +168,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
164
168
|
const { cartId, resultAccessCode, settings } = input;
|
|
165
169
|
try {
|
|
166
170
|
const result = await retrieveCardPaymentAcceptResultAsync(
|
|
171
|
+
// biome-ignore lint: api datasources should not be typed
|
|
167
172
|
context as any,
|
|
168
173
|
resultAccessCode,
|
|
169
174
|
[],
|
|
@@ -194,6 +199,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
194
199
|
};
|
|
195
200
|
try {
|
|
196
201
|
const data = await getCardPaymentAcceptPointAsync(
|
|
202
|
+
// biome-ignore lint: api datasources should not be typed
|
|
197
203
|
context as any,
|
|
198
204
|
input.cartId,
|
|
199
205
|
paymentAcceptSettings,
|
|
@@ -210,6 +216,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
210
216
|
const context = this.context;
|
|
211
217
|
const { cartId, cartLineDeliverySpecification } = input;
|
|
212
218
|
const cart = await updateLineDeliverySpecificationsAsync(
|
|
219
|
+
// biome-ignore lint: api datasources should not be typed
|
|
213
220
|
context as any,
|
|
214
221
|
cartId,
|
|
215
222
|
cartLineDeliverySpecification,
|
|
@@ -231,6 +238,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
231
238
|
|
|
232
239
|
// Update cartlines to remove the delivery mode
|
|
233
240
|
const cartWithoutDeliveryMode = await updateCartLinesAsync(
|
|
241
|
+
// biome-ignore lint: api datasources should not be typed
|
|
234
242
|
context as any,
|
|
235
243
|
String(newCart?.Id),
|
|
236
244
|
newCart?.CartLines,
|
|
@@ -251,6 +259,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
251
259
|
if (!input.cartId) {
|
|
252
260
|
throw new Error("CartId is required to remove a discount code");
|
|
253
261
|
}
|
|
262
|
+
// biome-ignore lint: api datasources should not be typed
|
|
254
263
|
const cart = await removeDiscountCodesAsync(context as any, input.cartId, [
|
|
255
264
|
input.discountCode,
|
|
256
265
|
]);
|
|
@@ -263,6 +272,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
263
272
|
throw new Error("CartId is required to add a discount code");
|
|
264
273
|
}
|
|
265
274
|
const cart = await addDiscountCodeAsync(
|
|
275
|
+
// biome-ignore lint: api datasources should not be typed
|
|
266
276
|
context as any,
|
|
267
277
|
cartId,
|
|
268
278
|
discountCode,
|
|
@@ -279,6 +289,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
279
289
|
omit(line, "Product"),
|
|
280
290
|
);
|
|
281
291
|
const cart = await updateCartLinesAsync(
|
|
292
|
+
// biome-ignore lint: api datasources should not be typed
|
|
282
293
|
context as any,
|
|
283
294
|
cartId,
|
|
284
295
|
cartLinesWithoutProduct,
|
|
@@ -296,6 +307,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
296
307
|
|
|
297
308
|
try {
|
|
298
309
|
const updatedCart = await addCartLinesAsync(
|
|
310
|
+
// biome-ignore lint: api datasources should not be typed
|
|
299
311
|
context as any,
|
|
300
312
|
cartId,
|
|
301
313
|
_cartLines,
|
|
@@ -304,7 +316,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
304
316
|
return await mergeCartWithProducts(updatedCart, this.context);
|
|
305
317
|
} catch (err) {
|
|
306
318
|
console.error(err);
|
|
307
|
-
throw new Error(
|
|
319
|
+
throw new Error(`Error adding to cart: ${JSON.stringify(err)}`);
|
|
308
320
|
}
|
|
309
321
|
}
|
|
310
322
|
async updateCart(input: UpdateCartInput): Promise<Cart> {
|
|
@@ -313,6 +325,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
313
325
|
if (cart.CartLines) {
|
|
314
326
|
cart.CartLines.map((cl) => omit(cl, "Product"));
|
|
315
327
|
}
|
|
328
|
+
// biome-ignore lint: api datasources should not be typed
|
|
316
329
|
const updatedCart = await updateAsync(context as any, <DynCart>cart);
|
|
317
330
|
return await mergeCartWithProducts(updatedCart, this.context);
|
|
318
331
|
}
|
|
@@ -326,6 +339,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
326
339
|
throw new Error("CartId and Version are required to delete a cart line");
|
|
327
340
|
}
|
|
328
341
|
const cart = await removeCartLinesAsync(
|
|
342
|
+
// biome-ignore lint: api datasources should not be typed
|
|
329
343
|
context as any,
|
|
330
344
|
cartId,
|
|
331
345
|
cartLineIds,
|
|
@@ -339,6 +353,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
339
353
|
let cart: DynCart;
|
|
340
354
|
|
|
341
355
|
if (id) {
|
|
356
|
+
// biome-ignore lint: api datasources should not be typed
|
|
342
357
|
cart = (await readAsync(context as any, id)) as DynCart;
|
|
343
358
|
if (!cart) {
|
|
344
359
|
return this.createCart(context);
|
|
@@ -359,6 +374,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
359
374
|
omit(line, "Product"),
|
|
360
375
|
);
|
|
361
376
|
const cart = await updateCartLinesAsync(
|
|
377
|
+
// biome-ignore lint: api datasources should not be typed
|
|
362
378
|
context as any,
|
|
363
379
|
cartId,
|
|
364
380
|
cartLinesWithoutProduct,
|
|
@@ -411,6 +427,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
411
427
|
}
|
|
412
428
|
|
|
413
429
|
async createCart(context: ICallerContext): Promise<Cart> {
|
|
430
|
+
// biome-ignore lint: api datasources should not be typed
|
|
414
431
|
return (await createCartAsync(context as any, <DynCart>{
|
|
415
432
|
CartTypeValue: CartType.Checkout,
|
|
416
433
|
})) as Cart;
|
|
@@ -432,6 +449,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
432
449
|
CartTypeValue: CartType.Checkout,
|
|
433
450
|
IncludeAnonymous: false,
|
|
434
451
|
};
|
|
452
|
+
// biome-ignore lint: api datasources should not be typed
|
|
435
453
|
const ctx = { ...context } as any;
|
|
436
454
|
ctx.queryResultSettings = queryResultSettings;
|
|
437
455
|
const cartResult = await searchAsync(ctx, searchCriteria);
|
|
@@ -473,6 +491,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
473
491
|
FilterByChannelFulfillmentGroup: true,
|
|
474
492
|
};
|
|
475
493
|
const shippingAsyncResult = await getEstimatedAvailabilityAsync(
|
|
494
|
+
// biome-ignore lint: api datasources should not be typed
|
|
476
495
|
context as any,
|
|
477
496
|
searchCriteria,
|
|
478
497
|
);
|
|
@@ -489,6 +508,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
489
508
|
try {
|
|
490
509
|
const warehouseAsyncResult =
|
|
491
510
|
await getEstimatedProductWarehouseAvailabilityAsync(
|
|
511
|
+
// biome-ignore lint: api datasources should not be typed
|
|
492
512
|
context as any,
|
|
493
513
|
bopisItems,
|
|
494
514
|
2,
|
|
@@ -534,6 +554,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
534
554
|
if (cart.Version) {
|
|
535
555
|
try {
|
|
536
556
|
const updatedCart = await addInvoicesAsync(
|
|
557
|
+
// biome-ignore lint: api datasources should not be typed
|
|
537
558
|
context as any,
|
|
538
559
|
cart.Id,
|
|
539
560
|
invoiceIds,
|
|
@@ -566,6 +587,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
|
|
|
566
587
|
if (input.cartId) {
|
|
567
588
|
try {
|
|
568
589
|
const updatedCart = await setInvoiceLinePriceAsync(
|
|
590
|
+
// biome-ignore lint: api datasources should not be typed
|
|
569
591
|
context as any,
|
|
570
592
|
input.cartId,
|
|
571
593
|
input.cartLineId,
|
|
@@ -30,13 +30,14 @@ class D365OrderDatasource extends D365DatasourceBase implements OrderApi {
|
|
|
30
30
|
input: GetSalesOrdersInput,
|
|
31
31
|
): Promise<SalesOrder[]> => {
|
|
32
32
|
const context = await getContextFromCookie();
|
|
33
|
+
// biome-ignore lint: api datasources should not be typed
|
|
33
34
|
const customer = await readAsync(context as any, "");
|
|
34
35
|
|
|
35
36
|
const searchCriteria: OrderSearchCriteria = {
|
|
36
37
|
...input.orderSearchCriteria,
|
|
37
38
|
OrderType: CustomerOrderType.SalesOrder,
|
|
38
39
|
CustomerAccountNumber: customer.AccountNumber,
|
|
39
|
-
};
|
|
40
|
+
} as OrderSearchCriteria;
|
|
40
41
|
|
|
41
42
|
const queryResultSettings: QueryResultSettings = {};
|
|
42
43
|
if (input.paging) queryResultSettings.Paging = input.paging;
|
|
@@ -45,10 +46,12 @@ class D365OrderDatasource extends D365DatasourceBase implements OrderApi {
|
|
|
45
46
|
Columns: [input.sort],
|
|
46
47
|
};
|
|
47
48
|
|
|
49
|
+
// biome-ignore lint: api datasources should not be typed
|
|
48
50
|
(context as any).queryResultSettings = queryResultSettings;
|
|
49
51
|
|
|
50
52
|
try {
|
|
51
53
|
const searchOrdersResults = await searchOrdersAsync(
|
|
54
|
+
// biome-ignore lint: api datasources should not be typed
|
|
52
55
|
context as any,
|
|
53
56
|
searchCriteria,
|
|
54
57
|
null,
|
|
@@ -72,6 +75,7 @@ class D365OrderDatasource extends D365DatasourceBase implements OrderApi {
|
|
|
72
75
|
if (transactionId) {
|
|
73
76
|
try {
|
|
74
77
|
data = await getSalesOrderDetailsByTransactionIdAsync(
|
|
78
|
+
// biome-ignore lint: api datasources should not be typed
|
|
75
79
|
context as any,
|
|
76
80
|
transactionId,
|
|
77
81
|
SearchLocation.All,
|
|
@@ -83,6 +87,7 @@ class D365OrderDatasource extends D365DatasourceBase implements OrderApi {
|
|
|
83
87
|
} else {
|
|
84
88
|
try {
|
|
85
89
|
data = await getSalesOrderDetailsBySalesIdAsync(
|
|
90
|
+
// biome-ignore lint: api datasources should not be typed
|
|
86
91
|
context as any,
|
|
87
92
|
salesId,
|
|
88
93
|
);
|
|
@@ -320,22 +320,37 @@ class D365UserDatasource extends D365DatasourceBase implements UserApi {
|
|
|
320
320
|
}
|
|
321
321
|
|
|
322
322
|
async addProductsToWishlist(input: WishlistLinesInput): Promise<Wishlist> {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
323
|
+
return tracer.startActiveSpan(
|
|
324
|
+
"d365.addProductsToWishlist",
|
|
325
|
+
async (span) => {
|
|
326
|
+
const context = this.context;
|
|
327
|
+
const id = input.Id;
|
|
328
|
+
const catalogId = this.context.requestContext.apiSettings.catalogId;
|
|
326
329
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
productListLines
|
|
332
|
-
|
|
330
|
+
const productListLines = input.ProductListLines.map((line) => ({
|
|
331
|
+
...line,
|
|
332
|
+
CatalogId: catalogId,
|
|
333
|
+
}));
|
|
334
|
+
console.log(productListLines);
|
|
335
|
+
try {
|
|
336
|
+
const updatedProductListLines = await addProductListLinesAsync(
|
|
337
|
+
this.getRetailContext(context),
|
|
338
|
+
id,
|
|
339
|
+
productListLines,
|
|
340
|
+
);
|
|
333
341
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
342
|
+
const wishlist = {
|
|
343
|
+
Id: id,
|
|
344
|
+
productListLines: updatedProductListLines,
|
|
345
|
+
};
|
|
346
|
+
return wishlist;
|
|
347
|
+
} catch (error) {
|
|
348
|
+
throw new Error(`Error adding to wishlist: ${error}`);
|
|
349
|
+
} finally {
|
|
350
|
+
span.end();
|
|
351
|
+
}
|
|
352
|
+
},
|
|
353
|
+
);
|
|
339
354
|
}
|
|
340
355
|
|
|
341
356
|
async removeProductsFromWishlist(input: WishlistLinesInput): Promise<void> {
|
|
@@ -3428,6 +3428,7 @@ export type Mutation = {
|
|
|
3428
3428
|
reindex: IndexAttemptResponse;
|
|
3429
3429
|
relatedAccountCreate?: Maybe<RelatedAccountCreateMutationResponse>;
|
|
3430
3430
|
relatedAccountDelete?: Maybe<RelatedAccountDeleteMutationResponse>;
|
|
3431
|
+
removeIndexHistory?: Maybe<Scalars['ID']['output']>;
|
|
3431
3432
|
/** Removes role and returns removed role */
|
|
3432
3433
|
removeRole?: Maybe<Role>;
|
|
3433
3434
|
/**
|
|
@@ -4290,6 +4291,12 @@ export type MutationRelatedAccountDeleteArgs = {
|
|
|
4290
4291
|
};
|
|
4291
4292
|
|
|
4292
4293
|
|
|
4294
|
+
export type MutationRemoveIndexHistoryArgs = {
|
|
4295
|
+
id: Scalars['ID']['input'];
|
|
4296
|
+
index?: InputMaybe<Scalars['String']['input']>;
|
|
4297
|
+
};
|
|
4298
|
+
|
|
4299
|
+
|
|
4293
4300
|
export type MutationRemoveRoleArgs = {
|
|
4294
4301
|
input: RemoveRoleInput;
|
|
4295
4302
|
};
|
package/src/api-manager/index.ts
CHANGED
|
@@ -29,9 +29,9 @@ async function createApiManager(): Promise<Datasource> {
|
|
|
29
29
|
datasource = E4Datasource;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
// biome-ignore lint: api datasources should not be typed
|
|
32
33
|
const storefrontOverrides: { [key: string]: any } = {};
|
|
33
34
|
|
|
34
|
-
// @ts-expect-error
|
|
35
35
|
function importAll(r) {
|
|
36
36
|
r.keys().forEach((key: string) => {
|
|
37
37
|
storefrontOverrides[key] = r(key);
|
|
@@ -63,6 +63,7 @@ async function createApiManager(): Promise<Datasource> {
|
|
|
63
63
|
Object.assign(datasource[entityName] as object, entityOverrides);
|
|
64
64
|
} else {
|
|
65
65
|
// Non-core entity added entirely from overrides
|
|
66
|
+
// biome-ignore lint: api datasources should not be typed
|
|
66
67
|
(datasource as any)[entityName] = entityOverrides;
|
|
67
68
|
}
|
|
68
69
|
}
|
|
@@ -41,7 +41,7 @@ export const productSchema = z.object({
|
|
|
41
41
|
ItemId: z.string(), // sku?
|
|
42
42
|
RecordId: z.number(),
|
|
43
43
|
Name: z.string(),
|
|
44
|
-
Price: z.number()
|
|
44
|
+
Price: z.number(),
|
|
45
45
|
BasePrice: z.number().optional(),
|
|
46
46
|
AdjustedPrice: z.number().optional(),
|
|
47
47
|
Description: z.string().optional(),
|
package/src/auth/msal.ts
CHANGED
|
@@ -14,11 +14,8 @@ const createMsalConfig = (): Configuration => {
|
|
|
14
14
|
knownAuthorities: [
|
|
15
15
|
process.env.NEXT_PUBLIC_AZURE_AD_B2C_KNOWN_AUTHORITY || "",
|
|
16
16
|
],
|
|
17
|
-
navigateToLoginRequestUrl: true,
|
|
18
|
-
},
|
|
19
|
-
system: {
|
|
20
|
-
allowNativeBroker: false, // Disables WAM Broker
|
|
21
17
|
},
|
|
18
|
+
system: {},
|
|
22
19
|
};
|
|
23
20
|
};
|
|
24
21
|
|
|
@@ -41,7 +41,7 @@ const componentMap = {
|
|
|
41
41
|
const getBlockComponent: <B extends Block>(
|
|
42
42
|
block: B,
|
|
43
43
|
idx: number,
|
|
44
|
-
) => JSX.Element | null = (block: Block) => {
|
|
44
|
+
) => React.JSX.Element | null = (block: Block) => {
|
|
45
45
|
const Component = componentMap[
|
|
46
46
|
block.__component as keyof typeof componentMap
|
|
47
47
|
] as React.ComponentType<Block> | undefined;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { FooterBlock } from "@evenicanpm/cms/src/content/footer/types";
|
|
2
|
+
import { Box, Container } from "@mui/material";
|
|
3
|
+
import Grid from "@mui/material/Grid2";
|
|
4
|
+
import Contact from "@/cms/blocks/components/footer/sections/footer-contact";
|
|
5
|
+
import Links from "@/cms/blocks/components/footer/sections/footer-links";
|
|
6
|
+
import Logo from "@/cms/blocks/components/footer/sections/footer-logo";
|
|
7
|
+
|
|
8
|
+
const getBlockComponent = (block: FooterBlock, index: number) => {
|
|
9
|
+
switch (block.__component) {
|
|
10
|
+
case "footer.links":
|
|
11
|
+
return (
|
|
12
|
+
<Links key={`index-${index}`} title={block.title} links={block.links} />
|
|
13
|
+
);
|
|
14
|
+
case "footer.logo":
|
|
15
|
+
return (
|
|
16
|
+
<Logo
|
|
17
|
+
key={`index-${index}`}
|
|
18
|
+
logoImage={block.logoImage}
|
|
19
|
+
description={block.description}
|
|
20
|
+
/>
|
|
21
|
+
);
|
|
22
|
+
case "footer.contact":
|
|
23
|
+
return (
|
|
24
|
+
<Contact
|
|
25
|
+
key={`index-${index}`}
|
|
26
|
+
address={block.address}
|
|
27
|
+
email={block.email}
|
|
28
|
+
phoneNumber={block.phoneNumber}
|
|
29
|
+
social={block.social}
|
|
30
|
+
/>
|
|
31
|
+
);
|
|
32
|
+
default:
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const FooterContent = ({ sections }: { sections: FooterBlock[] }) => {
|
|
38
|
+
if (!sections?.length) return null;
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<Box
|
|
42
|
+
component="footer"
|
|
43
|
+
bgcolor="#222935"
|
|
44
|
+
mt={{ xs: 7 }}
|
|
45
|
+
mb={{ sm: 0, xs: 7 }}
|
|
46
|
+
>
|
|
47
|
+
<Box
|
|
48
|
+
component={Container}
|
|
49
|
+
color="white"
|
|
50
|
+
overflow="hidden"
|
|
51
|
+
py={{ sm: 10, xs: 4 }}
|
|
52
|
+
>
|
|
53
|
+
<Grid container spacing={6}>
|
|
54
|
+
{sections.map((block, index) => getBlockComponent(block, index))}
|
|
55
|
+
</Grid>
|
|
56
|
+
</Box>
|
|
57
|
+
</Box>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export default FooterContent;
|
|
@@ -1,86 +1,24 @@
|
|
|
1
1
|
// MUI
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
FooterBlock,
|
|
6
|
-
FooterResponse,
|
|
7
|
-
} from "@/cms/blocks/components/footer/interfaces";
|
|
8
|
-
import Contact from "@/cms/blocks/components/footer/sections/footer-contact";
|
|
9
|
-
import Links from "@/cms/blocks/components/footer/sections/footer-links";
|
|
10
|
-
// Local Custom Components
|
|
11
|
-
import Logo from "@/cms/blocks/components/footer/sections/footer-logo";
|
|
12
|
-
import cms from "@/cms/endpoints";
|
|
2
|
+
import { cms } from "@evenicanpm/cms";
|
|
3
|
+
import type { FooterBlock } from "@evenicanpm/cms/src/content/footer/types";
|
|
4
|
+
import FooterContent from "@/cms/blocks/components/footer/footer-content";
|
|
13
5
|
|
|
14
|
-
const
|
|
15
|
-
let
|
|
16
|
-
|
|
17
|
-
switch (block.__component) {
|
|
18
|
-
case "footer.links":
|
|
19
|
-
Block = Links;
|
|
20
|
-
return (
|
|
21
|
-
<Block key={`index-${index}`} title={block.title} links={block.links} />
|
|
22
|
-
);
|
|
23
|
-
case "footer.logo":
|
|
24
|
-
Block = Logo;
|
|
25
|
-
return <Block key={`index-${index}`} description={block.description} />;
|
|
26
|
-
case "footer.contact":
|
|
27
|
-
Block = Contact;
|
|
28
|
-
return <Block key={`index-${index}`} social={block.social} />;
|
|
29
|
-
default:
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const fetchFooterData = async (): Promise<FooterResponse | null> => {
|
|
6
|
+
const Footer = async () => {
|
|
7
|
+
let sections: FooterBlock[] | undefined;
|
|
35
8
|
try {
|
|
36
|
-
const response = await
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (!response.ok) {
|
|
41
|
-
return null;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const text = await response.text();
|
|
45
|
-
|
|
46
|
-
if (!text) {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return JSON.parse(text) as FooterResponse;
|
|
9
|
+
const response = await cms.footer.getFooter();
|
|
10
|
+
sections = (response as { data?: { sections?: FooterBlock[] } })?.data
|
|
11
|
+
?.sections;
|
|
51
12
|
} catch (error) {
|
|
52
13
|
console.error("Error fetching footer data:", error);
|
|
53
14
|
return null;
|
|
54
15
|
}
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const Footer = async () => {
|
|
58
|
-
const data = await fetchFooterData();
|
|
59
|
-
const sections = data?.data?.sections;
|
|
60
16
|
|
|
61
17
|
if (!sections?.length) {
|
|
62
18
|
return null;
|
|
63
19
|
}
|
|
64
20
|
|
|
65
|
-
return
|
|
66
|
-
<Box
|
|
67
|
-
component="footer"
|
|
68
|
-
bgcolor="#222935"
|
|
69
|
-
mt={{ xs: 7 }}
|
|
70
|
-
mb={{ sm: 0, xs: 7 }}
|
|
71
|
-
>
|
|
72
|
-
<Box
|
|
73
|
-
component={Container}
|
|
74
|
-
color="white"
|
|
75
|
-
overflow="hidden"
|
|
76
|
-
py={{ sm: 10, xs: 4 }}
|
|
77
|
-
>
|
|
78
|
-
<Grid container spacing={6}>
|
|
79
|
-
{sections.map((block, index) => getBlockComponent(block, index))}
|
|
80
|
-
</Grid>
|
|
81
|
-
</Box>
|
|
82
|
-
</Box>
|
|
83
|
-
);
|
|
21
|
+
return <FooterContent sections={sections} />;
|
|
84
22
|
};
|
|
85
23
|
|
|
86
24
|
export default Footer;
|
|
@@ -9,6 +9,7 @@ export interface SocialLink {
|
|
|
9
9
|
interface FooterLogoBlock {
|
|
10
10
|
id: number;
|
|
11
11
|
__component: "footer.logo";
|
|
12
|
+
logoImage?: { url: string; alternativeText?: string };
|
|
12
13
|
description: string;
|
|
13
14
|
}
|
|
14
15
|
|
|
@@ -22,6 +23,9 @@ interface FooterLinksBlock {
|
|
|
22
23
|
interface FooterContactBlock {
|
|
23
24
|
id: number;
|
|
24
25
|
__component: "footer.contact";
|
|
26
|
+
address?: string;
|
|
27
|
+
email?: string;
|
|
28
|
+
phoneNumber?: string;
|
|
25
29
|
social: SocialLink[];
|
|
26
30
|
}
|
|
27
31
|
|