@evenicanpm/storefront-core 1.0.0-alpha → 1.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 (78) hide show
  1. package/package.json +1 -1
  2. package/src/api-manager/api-manager.config.json +1 -1
  3. package/src/api-manager/datasources/d365/d365-address.datasource.ts +4 -4
  4. package/src/api-manager/datasources/d365/d365-cart.datasource.ts +100 -7
  5. package/src/api-manager/datasources/d365/d365-product.datasource.ts +39 -17
  6. package/src/api-manager/datasources/d365/d365-user.datasource.ts +220 -49
  7. package/src/api-manager/datasources/d365/utils/decode-jwt.ts +2 -2
  8. package/src/api-manager/datasources/e4/e4-cart.datasource.ts +6 -0
  9. package/src/api-manager/datasources/e4/e4-product.datasource.ts +5 -0
  10. package/src/api-manager/datasources/e4/e4-user.datasource.ts +39 -15
  11. package/src/api-manager/datasources/e4/e4.datasource.ts +1 -0
  12. package/src/api-manager/datasources/e4/e4.translator.ts +2 -1
  13. package/src/api-manager/datasources/e4/graphqlRequestSdk.ts +5231 -38282
  14. package/src/api-manager/index.ts +58 -11
  15. package/src/api-manager/lib/get-graphql-client.ts +7 -7
  16. package/src/api-manager/schemas/address.schema.ts +1 -19
  17. package/src/api-manager/schemas/cart.schema.ts +18 -0
  18. package/src/api-manager/schemas/product.schema.ts +7 -0
  19. package/src/api-manager/schemas/user.schema.ts +52 -1
  20. package/src/api-manager/services/address/queries/get-states.ts +1 -1
  21. package/src/api-manager/services/cart/mutations/checkout.ts +16 -1
  22. package/src/api-manager/services/cart/queries/get-cart-lines-inventory.ts +15 -0
  23. package/src/api-manager/services/create-extension-query.ts +26 -0
  24. package/src/api-manager/services/create-mutation.ts +5 -1
  25. package/src/api-manager/services/create-query.ts +0 -1
  26. package/src/api-manager/services/organization/queries/get-channel-configuration.ts +1 -1
  27. package/src/api-manager/services/product/queries/get-product-prices.ts +16 -0
  28. package/src/api-manager/services/product/queries/search-products.ts +1 -0
  29. package/src/api-manager/services/user/mutations/add-to-wishlist.ts +24 -0
  30. package/src/api-manager/services/user/mutations/copy-cart-to-wishlist.ts +23 -0
  31. package/src/api-manager/services/user/mutations/create-wishlist.ts +4 -4
  32. package/src/api-manager/services/user/mutations/delete-wishlist.ts +4 -3
  33. package/src/api-manager/services/user/mutations/remove-from-wishlist.ts +21 -0
  34. package/src/api-manager/services/user/mutations/update-wishlist.ts +23 -0
  35. package/src/api-manager/services/user/queries/get-wishlist-details.ts +11 -4
  36. package/src/api-manager/services/user/queries/get-wishlists.ts +4 -3
  37. package/src/api-manager/types/Datasource.ts +33 -5
  38. package/src/auth/auth-options.ts +2 -2
  39. package/src/auth/msal.ts +9 -9
  40. package/src/auth/next-auth-cookie-manager.ts +5 -3
  41. package/src/auth/providers/aadb2c-provider.ts +3 -4
  42. package/src/cms/endpoints.ts +2 -3
  43. package/src/components/_components/LazyImage.tsx +5 -2
  44. package/src/components/_components/header/components/user.tsx +1 -2
  45. package/src/components/_components/product-cards/product-card-1/components/quantity-buttons.tsx +17 -8
  46. package/src/components/_components/product-cards/product-card-1/product-card-1-wrapper.tsx +304 -0
  47. package/src/components/_components/product-cards/product-card-1/product-card.tsx +16 -55
  48. package/src/components/_components/product-cards/product-card-8/product-card.tsx +80 -60
  49. package/src/components/_components/product-cards/product-card-8/styles/index.ts +10 -0
  50. package/src/components/_components/product-cards/product-card-wishlist/components/hover-actions.tsx +37 -0
  51. package/src/components/_components/product-cards/product-card-wishlist/index.ts +1 -0
  52. package/src/components/_components/product-cards/product-card-wishlist/product-card.tsx +118 -0
  53. package/src/components/_components/product-cards/product-card-wishlist/styles/index.ts +51 -0
  54. package/src/components/_components/products-view/product-view-dialog.tsx +48 -10
  55. package/src/components/_components/products-view/products-grid-view.tsx +31 -17
  56. package/src/components/_components/products-view/products-list-view.tsx +30 -16
  57. package/src/components/_components/search-box/__test__/search-input-category.test.tsx +110 -0
  58. package/src/components/_components/search-box/__test__/search-input.test.tsx +137 -0
  59. package/src/components/_components/search-box/__test__/search-results.json +165 -0
  60. package/src/components/_components/search-box/components/search-result.tsx +66 -12
  61. package/src/components/_components/search-box/search-input-category.tsx +135 -32
  62. package/src/components/_components/search-box/styles/index.ts +2 -0
  63. package/src/components/_components/section-header/section-creator.tsx +1 -0
  64. package/src/components/_components/wishlist/add-to-wishlist-dialog.tsx +161 -0
  65. package/src/components/_components/wishlist/components/create-new-list.tsx +167 -0
  66. package/src/components/_components/wishlist/components/create-wishlist-button.tsx +40 -0
  67. package/src/components/_components/wishlist/components/dashboard-header.tsx +123 -0
  68. package/src/components/_components/wishlist/components/navigation.tsx +87 -0
  69. package/src/components/_components/wishlist/components/no-records.tsx +20 -0
  70. package/src/components/_components/wishlist/components/wishlist-modal-item.tsx +66 -0
  71. package/src/components/_components/wishlist/remove-from-wishlist-dialog.tsx +174 -0
  72. package/src/components/_components/wishlist/styles.ts +61 -0
  73. package/src/components/countries-input.tsx +6 -12
  74. package/src/lib/cart-cookie-handler-constants.ts +8 -0
  75. package/src/lib/cart-cookie-handler.ts +27 -5
  76. package/src/lib/create-graphql-client.ts +1 -2
  77. package/src/lib/product-list-types.ts +41 -0
  78. package/src/config.ts +0 -47
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evenicanpm/storefront-core",
3
- "version": "1.0.0-alpha",
3
+ "version": "1.0.0",
4
4
  "description": "Core module for D365/e4 Headless Storefront",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -1,5 +1,5 @@
1
1
  {
2
- "primary": "e4",
2
+ "primary": "d365",
3
3
  "secondary": [],
4
4
  "overrides": {},
5
5
  "d365": {
@@ -70,11 +70,11 @@ class D365AddressDatasource extends D365DatasourceBase implements AddressApi {
70
70
  }
71
71
 
72
72
  const updatedCustomer = await updateAsync(context as any, customer);
73
- const rec = updatedCustomer.Addresses?.find(
74
- (a) => a.RecordId?.toString() === address.Id,
75
- );
73
+ const rec = updatedCustomer.Addresses[idx];
76
74
  if (!rec || rec.RecordId == null) {
77
- throw new Error(`Failed to update address Id=${address.Id}`);
75
+ throw new Error(
76
+ `Failed to update address Id=${address.Id}. Updated address record with a matching id not found.`,
77
+ );
78
78
  }
79
79
 
80
80
  return {
@@ -13,6 +13,9 @@ import {
13
13
  CartSearchCriteria,
14
14
  ICallerContext,
15
15
  CartLine,
16
+ ProductWarehouse,
17
+ ProductWarehouseInventoryInformation,
18
+ InventoryAvailabilitySearchCriteria,
16
19
  } from "@msdyn365-commerce/retail-proxy";
17
20
  import {
18
21
  addCartLinesAsync,
@@ -41,13 +44,18 @@ import {
41
44
  GetCardPaymentAcceptPointInput,
42
45
  RetrieveCardPaymentAcceptResultInput,
43
46
  CheckoutInput,
47
+ InventorySearchCartLinesCriteriaInput,
44
48
  } from "@/schemas/cart.schema";
45
49
  import { uniq, omit } from "lodash";
46
50
  import { D365ProductDatasource } from "./d365-product.datasource";
47
- import pojo from "./utils/parse-object";
48
51
  import { getCartCookie } from "@/lib/cart-cookie-handler";
49
52
  import { SalesOrder } from "@/schemas/order.schema";
50
53
  import { D365DatasourceBase } from "./d365-base.datasource";
54
+ import D365OrganizationDatasource from "./d365-organization.datasource";
55
+ import {
56
+ getEstimatedAvailabilityAsync,
57
+ getEstimatedProductWarehouseAvailabilityAsync,
58
+ } from "@msdyn365-commerce/retail-proxy/dist/DataActions/ProductsDataActions.g";
51
59
 
52
60
  export class D365CartDatasource extends D365DatasourceBase implements CartApi {
53
61
  async checkout(input: CheckoutInput): Promise<SalesOrder> {
@@ -74,15 +82,22 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
74
82
  ): Promise<CardPaymentAcceptResult> {
75
83
  const context = this.context;
76
84
  const { cartId, resultAccessCode, settings } = input;
77
- return pojo(
78
- retrieveCardPaymentAcceptResultAsync(
85
+ try {
86
+ const result = await retrieveCardPaymentAcceptResultAsync(
79
87
  context as any,
80
88
  resultAccessCode,
81
89
  [],
82
90
  cartId,
83
91
  settings,
84
- ),
85
- );
92
+ );
93
+ return result;
94
+ } catch (error) {
95
+ console.warn(
96
+ "Failed to retrieve card payment accept result:",
97
+ JSON.stringify(error),
98
+ );
99
+ throw error;
100
+ }
86
101
  }
87
102
  async getCardAcceptPoint(
88
103
  input: GetCardPaymentAcceptPointInput,
@@ -104,8 +119,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
104
119
  input.cartId,
105
120
  paymentAcceptSettings,
106
121
  );
107
-
108
- return pojo(data);
122
+ return data;
109
123
  } catch (error) {
110
124
  console.warn(error);
111
125
  return {};
@@ -200,6 +214,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
200
214
  throw new Error("CartId and Version are required to add a cart line");
201
215
  }
202
216
  const _cartLines = cartLine.map((line) => omit(line, "Product"));
217
+
203
218
  try {
204
219
  const updatedCart = await addCartLinesAsync(
205
220
  context as any,
@@ -343,6 +358,84 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
343
358
  const cartResult = await searchAsync(ctx, searchCriteria);
344
359
  return cartResult[0];
345
360
  }
361
+
362
+ async getCartLinesInventory(
363
+ input: InventorySearchCartLinesCriteriaInput,
364
+ ): Promise<ProductWarehouseInventoryInformation> {
365
+ const context = this.context;
366
+ const bopisItems: ProductWarehouse[] = [];
367
+ const shippingItems: number[] = [];
368
+
369
+ const d365OrganizationDatasource = new D365OrganizationDatasource(
370
+ this.context,
371
+ );
372
+ const config = await d365OrganizationDatasource.getChannelConfiguration();
373
+
374
+ input.searchCriteria.cartLines.forEach((cartLine) => {
375
+ if (cartLine.deliveryMode === "60") {
376
+ bopisItems.push({
377
+ ProductId: cartLine.productId,
378
+ InventLocationId: cartLine.inventLocationId,
379
+ DataAreaId: config.InventLocationDataAreaId,
380
+ });
381
+ } else {
382
+ shippingItems.push(cartLine.productId);
383
+ }
384
+ });
385
+
386
+ let shippingData;
387
+ if (shippingItems.length) {
388
+ try {
389
+ const searchCriteria: InventoryAvailabilitySearchCriteria = {
390
+ ProductIds: shippingItems,
391
+ QuantityUnitTypeValue: 2, // Sales Type
392
+ DefaultWarehouseOnly: true,
393
+ SearchArea: input.searchCriteria.searchArea,
394
+ FilterByChannelFulfillmentGroup: true,
395
+ };
396
+ shippingData = await getEstimatedAvailabilityAsync(
397
+ context as any,
398
+ searchCriteria,
399
+ );
400
+ } catch (error) {
401
+ console.error("Error getting shipping inventory:", error);
402
+ throw error;
403
+ }
404
+ }
405
+
406
+ let warehouseData;
407
+ if (bopisItems.length) {
408
+ try {
409
+ warehouseData = await getEstimatedProductWarehouseAvailabilityAsync(
410
+ context as any,
411
+ bopisItems,
412
+ 2,
413
+ );
414
+ } catch (error) {
415
+ console.error("Error getting pick up inventory:", error);
416
+ throw error;
417
+ }
418
+ }
419
+
420
+ if (shippingData && warehouseData) {
421
+ shippingData.ProductWarehouseInventoryAvailabilities?.push(
422
+ ...(warehouseData.ProductWarehouseInventoryAvailabilities ?? []),
423
+ );
424
+ shippingData.AggregatedProductInventoryAvailabilities?.push(
425
+ ...(warehouseData.AggregatedProductInventoryAvailabilities ?? []),
426
+ );
427
+ shippingData.ExtensionProperties?.push(
428
+ ...(warehouseData.ExtensionProperties ?? []),
429
+ );
430
+
431
+ return shippingData;
432
+ } else if (shippingData) {
433
+ return shippingData;
434
+ } else if (warehouseData) {
435
+ return warehouseData;
436
+ }
437
+ return {};
438
+ }
346
439
  }
347
440
 
348
441
  const mergeCartWithProducts = async (
@@ -4,6 +4,7 @@ import { ProductApi } from "../../types/Datasource";
4
4
  import {
5
5
  InventoryAvailabilitySearchCriteria,
6
6
  IQueryResultSettings,
7
+ ProductPrice,
7
8
  ProductRefinerSource,
8
9
  ProductSearchCriteria,
9
10
  ProductSearchResult,
@@ -18,11 +19,13 @@ import {
18
19
  getAttributeValuesAsync,
19
20
  getProductSearchRefinersAsync,
20
21
  getEstimatedAvailabilityAsync,
22
+ getActivePricesAsync,
21
23
  } from "@msdyn365-commerce/retail-proxy/dist/DataActions/ProductsDataActions.g";
22
24
  import {
23
25
  GetProductByIdInput,
24
26
  GetProductByIdsInput,
25
27
  GetRelatedProductsInput,
28
+ ProductPriceInput,
26
29
  SearchByCriteriaInput,
27
30
  SearchByCriteriaResponse,
28
31
  searchProductsInput,
@@ -51,22 +54,6 @@ const setFullProductImgUrl = async (
51
54
  product.PrimaryImageUrl = imgUrl;
52
55
  };
53
56
 
54
- // const getProductRefinersByCollection = async (context: ICallerContext, categoryId: number) => {
55
- // const searchCriteria = getSearchCriteriaFromInput(context, categoryId);
56
- // const ctx: any = { ...context };
57
- // try {
58
- // const refiners = await getProductSearchRefinersAsync(ctx, searchCriteria);
59
- // if (!refiners) {
60
- // console.warn('getProductSearchRefinersAsync returned no refiners');
61
- // return [];
62
- // }
63
- // return refiners as any[];
64
- // } catch (error) {
65
- // console.warn('Failed to fetch refiners, returning empty array:', error);
66
- // return [];
67
- // }
68
- // };
69
-
70
57
  class D365ProductDatasource extends D365DatasourceBase implements ProductApi {
71
58
  /**
72
59
  * Gets product by id, sets full image url and dimension values
@@ -87,7 +74,6 @@ class D365ProductDatasource extends D365DatasourceBase implements ProductApi {
87
74
  product,
88
75
  context.requestContext.apiSettings.baseImageUrl,
89
76
  );
90
- //setFullProductImgUrl(product, context.requestContext.apiSettings.baseImageUrl);
91
77
 
92
78
  const dimensionPromises =
93
79
  product?.Dimensions?.map(async ({ DimensionTypeValue }) => {
@@ -224,6 +210,16 @@ class D365ProductDatasource extends D365DatasourceBase implements ProductApi {
224
210
  }));
225
211
  }
226
212
  const results = await searchByCriteriaAsync(ctx as any, searchCriteria);
213
+ const promises = [];
214
+ for (const product of results) {
215
+ promises.push(
216
+ setFullProductImgUrl(
217
+ product,
218
+ context.requestContext.apiSettings.baseImageUrl,
219
+ ),
220
+ );
221
+ }
222
+ await Promise.all(promises);
227
223
  const parsed = JSON.parse(JSON.stringify(results));
228
224
  return parsed;
229
225
  }
@@ -267,6 +263,32 @@ class D365ProductDatasource extends D365DatasourceBase implements ProductApi {
267
263
  throw error;
268
264
  }
269
265
  }
266
+
267
+ async getProductPrices(input: ProductPriceInput): Promise<ProductPrice[]> {
268
+ const context = this.context;
269
+
270
+ const projectionDomain = {
271
+ ChannelId: context.requestContext.apiSettings.channelId,
272
+ CatalogId: context.requestContext.apiSettings.catalogId,
273
+ };
274
+
275
+ try {
276
+ const data = await getActivePricesAsync(
277
+ context as any,
278
+ projectionDomain,
279
+ input.productIds,
280
+ new Date(),
281
+ null,
282
+ undefined,
283
+ true,
284
+ );
285
+
286
+ return data;
287
+ } catch (error) {
288
+ console.error("Error getting product prices:", error);
289
+ throw error;
290
+ }
291
+ }
270
292
  }
271
293
 
272
294
  export { D365ProductDatasource };
@@ -1,10 +1,22 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import { UserApi } from "@/api-manager/types/Datasource";
3
- import { User, UserCounts } from "@/schemas/user.schema";
3
+ import {
4
+ CopyCartToWishlistInput,
5
+ ExtendedWishlist,
6
+ User,
7
+ UserCounts,
8
+ Wishlist,
9
+ WishlistCreateInput,
10
+ WishlistDetailInput,
11
+ WishlistLinesInput,
12
+ } from "@/schemas/user.schema";
4
13
  import {
5
14
  Customer,
6
15
  CommerceProperty,
7
- ICallerContext,
16
+ ProductListType,
17
+ ProductListSearchCriteria,
18
+ SimpleProduct,
19
+ ProductList,
8
20
  } from "@msdyn365-commerce/retail-proxy";
9
21
  import {
10
22
  createCustomerAsync,
@@ -12,26 +24,20 @@ import {
12
24
  updateAsync,
13
25
  } from "@msdyn365-commerce/retail-proxy/dist/DataActions/CustomersDataActions.g";
14
26
  import jwt from "jsonwebtoken";
15
- import { WishList } from "../e4/graphqlRequestSdk";
16
27
  import { D365DatasourceBase } from "./d365-base.datasource";
17
-
28
+ import {
29
+ addProductListLinesAsync,
30
+ copyCartToProductListAsync,
31
+ createProductListAsync,
32
+ deleteAsync,
33
+ removeProductListLinesAsync,
34
+ searchAsync,
35
+ updateProductListLinesAsync,
36
+ } from "@msdyn365-commerce/retail-proxy/dist/DataActions/ProductListsDataActions.g";
37
+ import { D365ProductDatasource } from "./d365-product.datasource";
38
+ import { uniq } from "lodash";
39
+ import { readAsync as wishlistReadAsync } from "@msdyn365-commerce/retail-proxy/dist/DataActions/ProductListsDataActions.g";
18
40
  class D365UserDatasource extends D365DatasourceBase implements UserApi {
19
- getUserCounts(): Promise<UserCounts> {
20
- throw new Error("Method not implemented.");
21
- }
22
- getWishlists(): Promise<WishList[]> {
23
- throw new Error("Method not implemented.");
24
- }
25
- getWishlistDetails(): Promise<WishList> {
26
- throw new Error("Method not implemented.");
27
- }
28
- createWishlist(): Promise<WishList> {
29
- throw new Error("Method not implemented.");
30
- }
31
- deleteWishlist(): Promise<string> {
32
- throw new Error("Method not implemented.");
33
- }
34
-
35
41
  async updateUser(user: User): Promise<User> {
36
42
  const context = this.context;
37
43
  const existing: Customer = await readAsync(context as any, "");
@@ -66,17 +72,17 @@ class D365UserDatasource extends D365DatasourceBase implements UserApi {
66
72
  async getUser(): Promise<User | null> {
67
73
  const context = this.context;
68
74
  if (!context.requestContext.user.isAuthenticated) return null;
69
-
70
- let customer: Customer | null;
75
+ let customer: Customer;
71
76
  try {
72
77
  customer = await readAsync(context as any, "");
73
- } catch (error) {
74
- //For now, we assume this error means the user does not exist
75
- //So we create a new user
76
- console.warn(JSON.stringify(error));
77
- const token = jwt.decode(context.requestContext.user.token) as TokenData;
78
- customer = await createUser(context as any, token);
79
- return customer;
78
+ } catch {
79
+ const token = jwt.decode(context.requestContext.user.token) as any;
80
+ customer = await createCustomerAsync(context as any, {
81
+ AccountNumber: "",
82
+ Email: Array.isArray(token.emails) ? token.emails[0] : token.email,
83
+ FirstName: token.given_name,
84
+ LastName: token.family_name || ".",
85
+ });
80
86
  }
81
87
  const mappedAddresses = (customer.Addresses ?? []).map((a) => ({
82
88
  ...a,
@@ -87,29 +93,194 @@ class D365UserDatasource extends D365DatasourceBase implements UserApi {
87
93
  Addresses: mappedAddresses,
88
94
  } as User;
89
95
  }
90
- }
91
96
 
92
- const createUser = async (context: ICallerContext, token: TokenData) => {
93
- const firstName = token.given_name;
94
- let lastName = token.family_name;
95
- let email;
96
- if (token.emails && Array.isArray(token.emails)) {
97
- email = token.emails[0];
98
- } else if (token.hasOwnProperty("email")) {
99
- email = token.email;
97
+ async getUserCounts(): Promise<UserCounts> {
98
+ throw new Error("Method not implemented.");
99
+ }
100
+
101
+ async getWishlists(): Promise<Wishlist[]> {
102
+ const context = this.context;
103
+ const productListType = ProductListType.WishList;
104
+ const productListSearchCriteria: ProductListSearchCriteria = {
105
+ ProductListType: productListType.toString(),
106
+ };
107
+ const isAuthenticated =
108
+ context.requestContext.user.isAuthenticated &&
109
+ !!context.requestContext.user.token;
110
+ if (!isAuthenticated) return [];
111
+
112
+ try {
113
+ const wishlists = await searchAsync(
114
+ context as any,
115
+ productListSearchCriteria,
116
+ );
117
+ const wishlistProductDataPromises = wishlists.map((wishlist) => {
118
+ return wishlistReadAsync(context as any, wishlist.Id);
119
+ });
120
+ const wishlistProductData = await Promise.all(
121
+ wishlistProductDataPromises,
122
+ );
123
+ return wishlistProductData;
124
+ } catch (error) {
125
+ throw new Error("Error getting wishlists: " + error);
126
+ }
100
127
  }
101
- if (!lastName) {
102
- lastName = ".";
128
+
129
+ async getWishlistDetails(
130
+ input: WishlistDetailInput,
131
+ ): Promise<ExtendedWishlist> {
132
+ const context = this.context;
133
+ let wishlist: Wishlist;
134
+ try {
135
+ wishlist = await wishlistReadAsync(context as any, input.Id);
136
+ } catch (error) {
137
+ throw new Error("Error getting wishlist details" + JSON.stringify(error));
138
+ }
139
+
140
+ const extendedWishlist = { ...wishlist } as ExtendedWishlist;
141
+
142
+ if (extendedWishlist.ProductListLines?.length) {
143
+ const productIds = extendedWishlist.ProductListLines.map(
144
+ (line) => line.ProductId,
145
+ ).filter((p) => p !== undefined);
146
+
147
+ if (productIds.length) {
148
+ const productDataSource = new D365ProductDatasource(this.context);
149
+ let products: SimpleProduct[];
150
+ try {
151
+ products = await productDataSource.getProductByIds({
152
+ id: uniq(productIds),
153
+ });
154
+ } catch (error) {
155
+ throw new Error("Error getting wishlist products: " + error);
156
+ }
157
+
158
+ if (products) {
159
+ extendedWishlist.ProductListLines.forEach((line) => {
160
+ const product = products.find((p) => p.RecordId === line.ProductId);
161
+ if (product) {
162
+ line.Product = product;
163
+ }
164
+ });
165
+ }
166
+ }
167
+ }
168
+ return extendedWishlist;
103
169
  }
104
- const userPromise = createCustomerAsync(context as any, {
105
- AccountNumber: "",
106
- Email: email,
107
- FirstName: firstName,
108
- LastName: lastName,
109
- });
110
- const user = await userPromise;
111
- return user;
112
- };
170
+
171
+ async createWishlist(input: WishlistCreateInput): Promise<Wishlist> {
172
+ const context = this.context;
173
+ const productList: ProductList = {
174
+ Name: input.Name,
175
+ DataAreaId: input.Comment,
176
+ Id: "",
177
+ ProductListTypeValue: ProductListType.WishList,
178
+ };
179
+ try {
180
+ const wishlist = await createProductListAsync(
181
+ context as any,
182
+ productList as ProductList,
183
+ );
184
+ return wishlist;
185
+ } catch (error) {
186
+ throw new Error("Error creating wishlist: " + JSON.stringify(error));
187
+ }
188
+ }
189
+
190
+ async deleteWishlist(input: WishlistDetailInput): Promise<void> {
191
+ const context = this.context;
192
+ if (input.Id === undefined || input.Id === "") {
193
+ throw new Error("Wishlist ID is required for deletion.");
194
+ }
195
+ try {
196
+ await deleteAsync(context as any, { Id: input.Id });
197
+ } catch (error) {
198
+ throw new Error("Error deleting wishlist: " + error);
199
+ }
200
+ }
201
+
202
+ // async updateWishlist(input: WishlistLinesInput): Promise<Wishlist> {
203
+ // const context = await getContextFromCookie();
204
+
205
+ // try {
206
+ // const wishlist = await updateAsync(context as any, input);
207
+ // return wishlist;
208
+ // } catch (error) {
209
+ // console.log('input', input);
210
+ // throw new Error("Error updating wishlist: " + error);
211
+ // }
212
+ // }
213
+
214
+ async updateWishlist(input: WishlistLinesInput): Promise<Wishlist> {
215
+ const context = this.context;
216
+ const id = input.Id;
217
+ const productListLines = input.ProductListLines;
218
+
219
+ try {
220
+ const updatedProductListLines = await updateProductListLinesAsync(
221
+ context as any,
222
+ id,
223
+ productListLines,
224
+ );
225
+ const wishlist = { Id: id, productListLines: updatedProductListLines };
226
+ return wishlist;
227
+ } catch (error) {
228
+ throw new Error("Error updating wishlist: " + error);
229
+ }
230
+ }
231
+
232
+ async addProductsToWishlist(input: WishlistLinesInput): Promise<Wishlist> {
233
+ const context = this.context;
234
+ const id = input.Id;
235
+ const productListLines = input.ProductListLines;
236
+
237
+ try {
238
+ const updatedProductListLines = await addProductListLinesAsync(
239
+ context as any,
240
+ id,
241
+ productListLines,
242
+ );
243
+
244
+ const wishlist = { Id: id, productListLines: updatedProductListLines };
245
+ return wishlist;
246
+ } catch (error) {
247
+ throw new Error("Error adding to wishlist: " + error);
248
+ }
249
+ }
250
+
251
+ // TODO: void return
252
+ async removeProductsFromWishlist(input: WishlistLinesInput): Promise<void> {
253
+ const context = this.context;
254
+ const id = input.Id;
255
+ const productListLines = input.ProductListLines;
256
+ try {
257
+ await removeProductListLinesAsync(context as any, id, productListLines);
258
+ } catch (error) {
259
+ throw new Error("Error removing from wishlist: " + error);
260
+ }
261
+ }
262
+
263
+ async copyCartToWishlist(input: CopyCartToWishlistInput): Promise<Wishlist> {
264
+ const context = this.context;
265
+ const productListId = input.Id;
266
+ const cartId = input.CartID;
267
+ const isRewrite = false;
268
+ const isQuantityAggregate = true;
269
+
270
+ try {
271
+ const wishlist = copyCartToProductListAsync(
272
+ context as any,
273
+ productListId,
274
+ cartId,
275
+ isRewrite,
276
+ isQuantityAggregate,
277
+ );
278
+ return wishlist;
279
+ } catch (error) {
280
+ throw new Error("Error copying cart to wishlist: " + error);
281
+ }
282
+ }
283
+ }
113
284
  export default D365UserDatasource;
114
285
 
115
286
  type TokenData = {
@@ -1,9 +1,9 @@
1
1
  "use server";
2
2
  import { decode } from "next-auth/jwt";
3
- import { getConfig } from "@config";
3
+ import { getSecret } from "@evenicanpm/common-core/keyvault";
4
4
 
5
5
  export async function decodeToken(token: string) {
6
- const secret = getConfig().NEXTAUTH_SECRET;
6
+ const secret = getSecret("NEXTAUTH_SECRET");
7
7
  if (!secret) {
8
8
  throw new Error("Environment variable NEXTAUTH_SECRET is not set.");
9
9
  }
@@ -7,6 +7,7 @@ import {
7
7
  CardPaymentAcceptPoint,
8
8
  CardPaymentAcceptResult,
9
9
  LineDeliverySpecification,
10
+ ProductWarehouseInventoryInformation,
10
11
  } from "@msdyn365-commerce/retail-proxy";
11
12
  import { CartApi } from "../../types/Datasource";
12
13
  import { Cart as E4Cart } from "./graphqlRequestSdk";
@@ -243,6 +244,11 @@ const cart: CartApi = {
243
244
  SalesLines: [],
244
245
  };
245
246
  },
247
+ getCartLinesInventory: function (
248
+ input: cartSchema.InventorySearchCartLinesCriteriaInput,
249
+ ): Promise<ProductWarehouseInventoryInformation> {
250
+ throw new Error("Function not implemented.");
251
+ },
246
252
  };
247
253
 
248
254
  export { cart };
@@ -152,6 +152,11 @@ const product: ProductApi = {
152
152
  ): Promise<ProductSearchResult[]> {
153
153
  throw new Error(`Function not implemented.${input}`);
154
154
  },
155
+ getProductPrices: function (
156
+ input: productSchema.ProductPriceInput,
157
+ ): Promise<productSchema.ProductPrice[]> {
158
+ throw new Error("Function not implemented.");
159
+ },
155
160
  };
156
161
 
157
162
  export default product;