@evenicanpm/storefront-core 1.0.0-alpha → 1.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.
Files changed (196) hide show
  1. package/package.json +3 -2
  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 -68
  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 +22 -2
  10. package/src/api-manager/datasources/e4/e4.datasource.ts +1 -1
  11. package/src/api-manager/datasources/e4/e4.remaps.ts +24 -0
  12. package/src/api-manager/datasources/e4/e4.translator.ts +19 -1
  13. package/src/api-manager/datasources/e4/{e4-user.datasource.ts → user/e4-user.datasource.ts} +41 -19
  14. package/src/api-manager/datasources/e4/user/e4-user.remaps.ts +4 -0
  15. package/src/api-manager/datasources/e4/user/e4-user.translator.ts +10 -0
  16. package/src/api-manager/index.ts +77 -15
  17. package/src/api-manager/lib/get-graphql-client.ts +7 -7
  18. package/src/api-manager/schemas/address.schema.ts +1 -19
  19. package/src/api-manager/schemas/cart.schema.ts +18 -0
  20. package/src/api-manager/schemas/product.schema.ts +8 -1
  21. package/src/api-manager/schemas/user.schema.ts +52 -1
  22. package/src/api-manager/services/address/queries/get-states.ts +1 -1
  23. package/src/api-manager/services/cart/mutations/checkout.ts +16 -1
  24. package/src/api-manager/services/cart/queries/get-cart-lines-inventory.ts +15 -0
  25. package/src/api-manager/services/create-extension-query.ts +26 -0
  26. package/src/api-manager/services/create-mutation.ts +5 -1
  27. package/src/api-manager/services/create-query.ts +10 -4
  28. package/src/api-manager/services/organization/queries/get-channel-configuration.ts +1 -1
  29. package/src/api-manager/services/product/queries/get-product-prices.ts +16 -0
  30. package/src/api-manager/services/product/queries/search-products.ts +1 -0
  31. package/src/api-manager/services/user/mutations/add-to-wishlist.ts +24 -0
  32. package/src/api-manager/services/user/mutations/copy-cart-to-wishlist.ts +23 -0
  33. package/src/api-manager/services/user/mutations/create-wishlist.ts +4 -4
  34. package/src/api-manager/services/user/mutations/delete-wishlist.ts +4 -3
  35. package/src/api-manager/services/user/mutations/remove-from-wishlist.ts +21 -0
  36. package/src/api-manager/services/user/mutations/update-wishlist.ts +23 -0
  37. package/src/api-manager/services/user/queries/get-wishlist-details.ts +11 -4
  38. package/src/api-manager/services/user/queries/get-wishlists.ts +4 -3
  39. package/src/api-manager/types/Datasource.ts +42 -14
  40. package/src/auth/auth-options.ts +2 -2
  41. package/src/auth/msal.ts +9 -9
  42. package/src/auth/next-auth-cookie-manager.ts +5 -3
  43. package/src/auth/providers/aadb2c-provider.ts +3 -4
  44. package/src/cms/endpoints.ts +2 -3
  45. package/src/components/Blocks/Components/ProductCarousel/index.tsx +6 -6
  46. package/src/components/_components/LazyImage.tsx +5 -2
  47. package/src/components/_components/header/components/user.tsx +1 -2
  48. package/src/components/_components/navbar/category-based-menu/components/categories.tsx +1 -1
  49. package/src/components/_components/navbar/mega-menu/mega-menu.tsx +1 -1
  50. package/src/components/_components/navbar/nav-list/nav-item-child.tsx +2 -2
  51. package/src/components/_components/product-cards/product-card-1/components/quantity-buttons.tsx +17 -8
  52. package/src/components/_components/product-cards/product-card-1/product-card-1-wrapper.tsx +304 -0
  53. package/src/components/_components/product-cards/product-card-1/product-card.tsx +16 -55
  54. package/src/components/_components/product-cards/product-card-8/product-card.tsx +80 -60
  55. package/src/components/_components/product-cards/product-card-8/styles/index.ts +10 -0
  56. package/src/components/_components/product-cards/product-card-wishlist/components/hover-actions.tsx +37 -0
  57. package/src/components/_components/product-cards/product-card-wishlist/index.ts +1 -0
  58. package/src/components/_components/product-cards/product-card-wishlist/product-card.tsx +118 -0
  59. package/src/components/_components/product-cards/product-card-wishlist/styles/index.ts +51 -0
  60. package/src/components/_components/product-dimensions/product-dimensions.tsx +114 -0
  61. package/src/components/_components/product-quantity-buttons/product-quantity-buttons.tsx +88 -0
  62. package/src/components/_components/products-view/product-view-dialog.tsx +48 -10
  63. package/src/components/_components/products-view/products-grid-view.tsx +31 -17
  64. package/src/components/_components/products-view/products-list-view.tsx +30 -16
  65. package/src/components/_components/search-box/__test__/search-input-category.test.tsx +110 -0
  66. package/src/components/_components/search-box/__test__/search-input.test.tsx +137 -0
  67. package/src/components/_components/search-box/__test__/search-results.json +165 -0
  68. package/src/components/_components/search-box/components/search-result.tsx +66 -12
  69. package/src/components/_components/search-box/search-input-category.tsx +135 -32
  70. package/src/components/_components/search-box/styles/index.ts +2 -0
  71. package/src/components/_components/section-header/section-creator.tsx +1 -0
  72. package/src/components/_components/section-header/section-header.tsx +1 -1
  73. package/src/components/_components/settings/setting.tsx +1 -1
  74. package/src/components/_components/wishlist/add-to-wishlist-dialog.tsx +161 -0
  75. package/src/components/_components/wishlist/components/create-new-list.tsx +167 -0
  76. package/src/components/_components/wishlist/components/create-wishlist-button.tsx +40 -0
  77. package/src/components/_components/wishlist/components/dashboard-header.tsx +123 -0
  78. package/src/components/_components/wishlist/components/navigation.tsx +87 -0
  79. package/src/components/_components/wishlist/components/no-records.tsx +20 -0
  80. package/src/components/_components/wishlist/components/wishlist-modal-item.tsx +66 -0
  81. package/src/components/_components/wishlist/remove-from-wishlist-dialog.tsx +174 -0
  82. package/src/components/_components/wishlist/styles.ts +61 -0
  83. package/src/components/_components/wishlist-modal/TODO.md +10 -0
  84. package/src/components/_components/wishlist-modal/add-to-wishlist-button.tsx +68 -0
  85. package/src/components/_components/wishlist-modal/add-to-wishlist-dialog.tsx +161 -0
  86. package/src/components/_components/wishlist-modal/remove-from-wishlist-dialog.tsx +174 -0
  87. package/src/components/_components/wishlist-modal/wishlist-modal-item.tsx +65 -0
  88. package/src/components/countries-input.tsx +7 -12
  89. package/src/hooks/use-cart.tsx +82 -0
  90. package/src/hooks/use-variants.tsx +85 -0
  91. package/src/lib/cart-cookie-handler-constants.ts +8 -0
  92. package/src/lib/cart-cookie-handler.ts +27 -5
  93. package/src/lib/create-graphql-client.ts +1 -2
  94. package/src/lib/product-list-types.ts +41 -0
  95. package/src/pages/account/addresses/address-form.tsx +289 -0
  96. package/src/pages/account/addresses/address-item.tsx +104 -0
  97. package/src/pages/account/dashboard-header.tsx +123 -0
  98. package/src/pages/account/navigation.tsx +84 -0
  99. package/src/pages/account/no-records.tsx +20 -0
  100. package/src/pages/account/orders/icons/delivery.tsx +14 -0
  101. package/src/pages/account/orders/icons/package-box.tsx +13 -0
  102. package/src/pages/account/orders/icons/truck-filled.tsx +14 -0
  103. package/src/pages/account/orders/order-progress.tsx +111 -0
  104. package/src/pages/account/orders/order-row.tsx +61 -0
  105. package/src/pages/account/orders/order-summary.tsx +83 -0
  106. package/src/pages/account/orders/ordered-products.tsx +114 -0
  107. package/src/pages/account/profile/profile-button.test.tsx +59 -0
  108. package/src/pages/account/profile/profile-button.tsx +50 -0
  109. package/src/pages/account/profile/user-info.tsx +59 -0
  110. package/src/pages/account/styles.ts +32 -0
  111. package/src/pages/account/table-row.tsx +19 -0
  112. package/src/pages/account/wishlist/create-new-list.tsx +167 -0
  113. package/src/pages/account/wishlist/create-wishlist-button.tsx +40 -0
  114. package/src/pages/account/wishlist/wishlist-item.tsx +82 -0
  115. package/src/pages/blog/pagination.tsx +38 -0
  116. package/src/pages/cart/cart-item.tsx +312 -0
  117. package/src/pages/cart/checkout-form.tsx +122 -0
  118. package/src/pages/cart/coupon-entry.tsx +90 -0
  119. package/src/pages/cart/estimate-shipping.tsx +183 -0
  120. package/src/pages/cart/wrapper.tsx +30 -0
  121. package/src/pages/checkout/checkout-alt-form/address-card.tsx +73 -0
  122. package/src/pages/checkout/checkout-alt-form/checkout-form.tsx +133 -0
  123. package/src/pages/checkout/checkout-alt-form/checkout-step.tsx +120 -0
  124. package/src/pages/checkout/checkout-alt-form/customer-information.tsx +94 -0
  125. package/src/pages/checkout/checkout-alt-form/delivery-address.tsx +170 -0
  126. package/src/pages/checkout/checkout-alt-form/delivery-date.tsx +114 -0
  127. package/src/pages/checkout/checkout-alt-form/delivery-options.tsx +186 -0
  128. package/src/pages/checkout/checkout-alt-form/edit-address-form.tsx +130 -0
  129. package/src/pages/checkout/checkout-alt-form/heading.tsx +50 -0
  130. package/src/pages/checkout/checkout-alt-form/index.ts +1 -0
  131. package/src/pages/checkout/checkout-alt-form/new-address-form.tsx +294 -0
  132. package/src/pages/checkout/checkout-alt-form/node.tsx +9 -0
  133. package/src/pages/checkout/checkout-alt-form/payment-details.tsx +344 -0
  134. package/src/pages/checkout/checkout-alt-form/safe-card-preview-data.tsx +36 -0
  135. package/src/pages/checkout/checkout-alt-form/types.ts +20 -0
  136. package/src/pages/checkout/checkout-alt-summary/cart-item.tsx +39 -0
  137. package/src/pages/checkout/checkout-alt-summary/checkout-alt-summary.tsx +40 -0
  138. package/src/pages/checkout/checkout-alt-summary/index.ts +1 -0
  139. package/src/pages/checkout/checkout-alt-summary/list-item.tsx +31 -0
  140. package/src/pages/confirmation/address.tsx +22 -0
  141. package/src/pages/confirmation/confirmation-summary.tsx +52 -0
  142. package/src/pages/confirmation/ordered-products.tsx +108 -0
  143. package/src/pages/product-details/available-shops.tsx +48 -0
  144. package/src/pages/product-details/bopis/find-in-store-button.tsx +63 -0
  145. package/src/pages/product-details/bopis/find-in-store-modal.tsx +257 -0
  146. package/src/pages/product-details/bopis/pickup-option-select.tsx +127 -0
  147. package/src/pages/product-details/bopis/search-header.tsx +69 -0
  148. package/src/pages/product-details/checkbox-label.tsx +20 -0
  149. package/src/pages/product-details/currency.ts +64 -0
  150. package/src/pages/product-details/frequently-bought.tsx +90 -0
  151. package/src/pages/product-details/frequently-product-card.tsx +60 -0
  152. package/src/pages/product-details/product-comment.tsx +44 -0
  153. package/src/pages/product-details/product-description.tsx +22 -0
  154. package/src/pages/product-details/product-filter-card.tsx +257 -0
  155. package/src/pages/product-details/product-intro/product-intro-images.tsx +87 -0
  156. package/src/pages/product-details/product-intro/product-intro.tsx +250 -0
  157. package/src/pages/product-details/product-review.tsx +131 -0
  158. package/src/pages/product-details/product-tabs.tsx +51 -0
  159. package/src/pages/product-details/related-products.tsx +42 -0
  160. package/src/pages/product-details/types.ts +11 -0
  161. package/src/pages/product-list/breadcrumbs.tsx +39 -0
  162. package/src/pages/product-list/checkbox-label.tsx +20 -0
  163. package/src/pages/product-list/facet-group.tsx +125 -0
  164. package/src/pages/product-list/facet.tsx +36 -0
  165. package/src/pages/product-list/list-filter.tsx +40 -0
  166. package/src/pages/product-list/pagination.tsx +80 -0
  167. package/src/pages/product-list/product-list-context.tsx +302 -0
  168. package/src/pages/product-list/product-list-state.ts +187 -0
  169. package/src/pages/product-list/product-rating.tsx +16 -0
  170. package/src/pages/product-list/quick-view-dialog-content.tsx +205 -0
  171. package/src/pages/product-list/quick-view-dialog.tsx +54 -0
  172. package/src/pages/product-list/range-filter.tsx +125 -0
  173. package/src/pages/product-list/scrollbar.tsx +38 -0
  174. package/src/pages/product-list/search-bar.tsx +162 -0
  175. package/src/pages/product-list/selected-facets.tsx +80 -0
  176. package/src/pages/product-list/side-nav.tsx +49 -0
  177. package/src/pages/product-list/swatch.tsx +80 -0
  178. package/src/pages/product-list/types.ts +18 -0
  179. package/src/pages/product-list/use-product-list.ts +12 -0
  180. package/src/pages/product-list/useCategoryFilter.tsx +26 -0
  181. package/src/pages/product-list/utils/facet-helpers.ts +5 -0
  182. package/src/pages/product-list/utils/generate-breadcrumbs.ts +30 -0
  183. package/src/pages/product-list/utils/getCategoryFilterFromSlug.ts +153 -0
  184. package/src/pages/product-list/utils/product-list-helper.ts +111 -0
  185. package/src/pages/product-list/utils/product-list-types.ts +41 -0
  186. package/src/pages/product-list/utils/search-for-category.ts +76 -0
  187. package/src/pages/product-list/utils/sort-options.ts +44 -0
  188. package/src/pages/product-list/utils/use-previous-refiners.ts +14 -0
  189. package/src/pages/quickorder/order-upload.tsx +150 -0
  190. package/src/pages/quickorder/quick-order-form.tsx +343 -0
  191. package/src/pages/quickorder/quick-order-row.tsx +144 -0
  192. package/tsconfig.json +1 -0
  193. package/src/api-manager/datasources/e4/graphqlRequestSdk.ts +0 -43515
  194. package/src/config.ts +0 -47
  195. /package/src/{components/_components/hooks/useOverflowDetect.ts → hooks/use-overflow-detect.ts} +0 -0
  196. /package/src/{components/_components/hooks/useSettings.ts → hooks/use-settings.ts} +0 -0
@@ -31,7 +31,11 @@ export const useCreateMutation = <TInput, TOutput>(
31
31
  body: JSON.stringify({ input, apiManagerPath }),
32
32
  });
33
33
  if (!response.ok) {
34
- throw new Error("Mutation failed");
34
+ const error = await response.json();
35
+ let errorMsg = `${error.error}`;
36
+ if (error.message) errorMsg += ` - ${error.message}`;
37
+
38
+ throw new Error(errorMsg);
35
39
  }
36
40
  return response.json();
37
41
  },
@@ -13,6 +13,7 @@ import { Mutex } from "async-mutex";
13
13
  import { manuallyRetrieveSessionCookie } from "@/auth/next-auth-cookie-manager";
14
14
  import { getSession } from "next-auth/react";
15
15
  import jwt from "jsonwebtoken";
16
+ import signOut from "@/auth/signout";
16
17
 
17
18
  const QUERY_ROUTE = "/api";
18
19
  const mutex = new Mutex();
@@ -79,7 +80,6 @@ export const createQuery = <TInput, TOutput>(
79
80
  queryFn,
80
81
  enabled,
81
82
  };
82
-
83
83
  return data;
84
84
  };
85
85
 
@@ -105,6 +105,11 @@ export const createQuery = <TInput, TOutput>(
105
105
  body: JSON.stringify({ input, apiManagerPath }),
106
106
  headers,
107
107
  });
108
+
109
+ if (result.status === 401) {
110
+ // If unauthenticated , sign out the user
111
+ signOut();
112
+ }
108
113
  return await result.json();
109
114
  };
110
115
 
@@ -192,6 +197,9 @@ export const createQuery = <TInput, TOutput>(
192
197
 
193
198
  const currentTime = Math.floor(Date.now() / 1000);
194
199
 
200
+ // Use this for testing - expires after 60 seconds (1 min) from issued-at time
201
+ // const isExpired = !!decoded && typeof decoded.iat === "number" && currentTime > decoded.iat + 60;
202
+
195
203
  const isExpired =
196
204
  !!decoded && typeof decoded.exp === "number" && decoded.exp < currentTime;
197
205
 
@@ -221,9 +229,7 @@ export const createQuery = <TInput, TOutput>(
221
229
  headers.append("should-refresh-token", "true");
222
230
  }
223
231
  // Call do fetch with the headers
224
- const response = await doFetch(input, apiManagerPath, headers);
225
-
226
- return response.json();
232
+ return await doFetch(input, apiManagerPath, headers);
227
233
  } catch (error) {
228
234
  // Handle API Error
229
235
  console.error("Error fetching data:", error);
@@ -6,7 +6,7 @@ const config = {
6
6
  queryKey: "channelConfiguration",
7
7
  };
8
8
 
9
- const getChannelConfiguration = createQuery<null, ChannelConfiguration[]>(
9
+ const getChannelConfiguration = createQuery<null, ChannelConfiguration>(
10
10
  apiPath,
11
11
  config,
12
12
  );
@@ -0,0 +1,16 @@
1
+ import {
2
+ ProductPriceInput,
3
+ ProductPrice,
4
+ } from "@/api-manager/schemas/product.schema";
5
+ import { createApiPath, createQuery } from "../../create-query";
6
+
7
+ const apiPath = createApiPath("product", "getProductPrices");
8
+
9
+ const getProductPrices = createQuery<ProductPriceInput, ProductPrice[]>(
10
+ apiPath,
11
+ {
12
+ queryKey: "product-prices",
13
+ },
14
+ );
15
+
16
+ export default getProductPrices;
@@ -5,6 +5,7 @@ import { createApiPath, createQuery } from "../../create-query";
5
5
  const apiPath = createApiPath("product", "searchProducts");
6
6
  const searchProducts = createQuery<searchProductsInput, ProductSearchResult[]>(
7
7
  apiPath,
8
+ { disableProperties: ["searchText"] },
8
9
  );
9
10
 
10
11
  export default searchProducts;
@@ -0,0 +1,24 @@
1
+ import { useQueryClient } from "@tanstack/react-query";
2
+ import {
3
+ Wishlist,
4
+ WishlistLinesInput,
5
+ } from "@/api-manager/schemas/user.schema";
6
+ import { createApiPath } from "../../create-query";
7
+ import { useCreateMutation } from "../../create-mutation";
8
+ import { getWishlistsQueryKey } from "../queries/get-wishlists";
9
+
10
+ const apiPath = createApiPath("user", "addProductsToWishlist");
11
+
12
+ const useAddToWishlist = () => {
13
+ const queryClient = useQueryClient();
14
+
15
+ return useCreateMutation<WishlistLinesInput, Wishlist>(apiPath, {
16
+ onSuccess: (_data, variables) => {
17
+ queryClient.invalidateQueries({
18
+ queryKey: [getWishlistsQueryKey, variables.Id],
19
+ });
20
+ },
21
+ });
22
+ };
23
+
24
+ export default useAddToWishlist;
@@ -0,0 +1,23 @@
1
+ import { useQueryClient } from "@tanstack/react-query";
2
+ import {
3
+ CopyCartToWishlistInput,
4
+ Wishlist,
5
+ } from "@/api-manager/schemas/user.schema";
6
+ import { createApiPath } from "../../create-query";
7
+ import { useCreateMutation } from "../../create-mutation";
8
+
9
+ const apiPath = createApiPath("user", "copyCartToWishlist");
10
+
11
+ const useCopyCartToWishlist = () => {
12
+ const queryClient = useQueryClient();
13
+
14
+ return useCreateMutation<CopyCartToWishlistInput, Wishlist>(apiPath, {
15
+ onSuccess: (_data, _variables) => {
16
+ queryClient.invalidateQueries({
17
+ queryKey: ["wishlistDetails", _variables.Id],
18
+ });
19
+ },
20
+ });
21
+ };
22
+
23
+ export default useCopyCartToWishlist;
@@ -2,16 +2,16 @@ import { useQueryClient } from "@tanstack/react-query";
2
2
  import { createApiPath } from "../../create-query";
3
3
  import { useCreateMutation } from "../../create-mutation";
4
4
  import {
5
- CreateWishListInput,
6
- WishList,
7
- } from "../../../datasources/e4/graphqlRequestSdk";
5
+ Wishlist,
6
+ WishlistCreateInput,
7
+ } from "@/api-manager/schemas/user.schema";
8
8
 
9
9
  const apiPath = createApiPath("user", "createWishlist");
10
10
 
11
11
  const useCreateWishlist = () => {
12
12
  const queryClient = useQueryClient();
13
13
 
14
- return useCreateMutation<CreateWishListInput, WishList>(apiPath, {
14
+ return useCreateMutation<WishlistCreateInput, Wishlist>(apiPath, {
15
15
  onSuccess: () => {
16
16
  queryClient.invalidateQueries({ queryKey: ["wishlists"] });
17
17
  },
@@ -1,17 +1,18 @@
1
1
  import { useQueryClient } from "@tanstack/react-query";
2
2
  import { createApiPath } from "../../create-query";
3
3
  import { useCreateMutation } from "../../create-mutation";
4
+ import { WishlistDetailInput } from "@/api-manager/schemas/user.schema";
5
+ import { getWishlistsQueryKey } from "../queries/get-wishlists";
4
6
 
5
7
  const apiPath = createApiPath("user", "deleteWishlist");
6
8
 
7
9
  const useDeleteWishlist = () => {
8
10
  const queryClient = useQueryClient();
9
11
 
10
- return useCreateMutation<string, string>(apiPath, {
12
+ return useCreateMutation<WishlistDetailInput, void>(apiPath, {
11
13
  onSuccess: () => {
12
- queryClient.invalidateQueries({ queryKey: ["wishlists"] });
14
+ queryClient.invalidateQueries({ queryKey: [getWishlistsQueryKey] });
13
15
  },
14
16
  });
15
17
  };
16
-
17
18
  export default useDeleteWishlist;
@@ -0,0 +1,21 @@
1
+ import { useQueryClient } from "@tanstack/react-query";
2
+ import { WishlistLinesInput } from "@/api-manager/schemas/user.schema";
3
+ import { createApiPath } from "../../create-query";
4
+ import { useCreateMutation } from "../../create-mutation";
5
+ import { getWishlistDetailsQueryKey } from "../queries/get-wishlist-details";
6
+
7
+ const apiPath = createApiPath("user", "removeProductsFromWishlist");
8
+
9
+ const useRemoveFromWishlist = () => {
10
+ const queryClient = useQueryClient();
11
+
12
+ return useCreateMutation<WishlistLinesInput, void>(apiPath, {
13
+ onSuccess: (_data, _variables) => {
14
+ queryClient.invalidateQueries({
15
+ queryKey: [getWishlistDetailsQueryKey, { Id: _variables.Id }],
16
+ });
17
+ },
18
+ });
19
+ };
20
+
21
+ export default useRemoveFromWishlist;
@@ -0,0 +1,23 @@
1
+ import { useQueryClient } from "@tanstack/react-query";
2
+ import {
3
+ Wishlist,
4
+ WishlistLinesInput,
5
+ } from "@/api-manager/schemas/user.schema";
6
+ import { useCreateMutation } from "../../create-mutation";
7
+ import { createApiPath } from "../../create-query";
8
+
9
+ const apiPath = createApiPath("user", "updateWishlist");
10
+
11
+ const useUpdateWishlist = () => {
12
+ const queryClient = useQueryClient();
13
+
14
+ return useCreateMutation<WishlistLinesInput, Wishlist>(apiPath, {
15
+ onSuccess: (_data, _variables) => {
16
+ queryClient.invalidateQueries({
17
+ queryKey: ["wishlistDetails", _variables.Id],
18
+ });
19
+ },
20
+ });
21
+ };
22
+
23
+ export default useUpdateWishlist;
@@ -1,10 +1,17 @@
1
+ import {
2
+ ExtendedWishlist,
3
+ WishlistDetailInput,
4
+ } from "@/api-manager/schemas/user.schema";
1
5
  import { createApiPath, createQuery } from "../../create-query";
2
- import { WishList } from "../../../datasources/e4/graphqlRequestSdk";
3
6
 
7
+ export const getWishlistDetailsQueryKey = "wish-list-details";
4
8
  const apiPath = createApiPath("user", "getWishlistDetails");
5
9
 
6
- const getWishListDetails = createQuery<string, WishList>(apiPath, {
7
- queryKey: "wish-list-details",
8
- });
10
+ const getWishListDetails = createQuery<WishlistDetailInput, ExtendedWishlist>(
11
+ apiPath,
12
+ {
13
+ queryKey: getWishlistDetailsQueryKey,
14
+ },
15
+ );
9
16
 
10
17
  export default getWishListDetails;
@@ -1,10 +1,11 @@
1
- import { WishList } from "../../../datasources/e4/graphqlRequestSdk";
1
+ import { Wishlist } from "@/api-manager/schemas/user.schema";
2
2
  import { createApiPath, createQuery } from "../../create-query";
3
3
 
4
+ export const getWishlistsQueryKey = "wishlists";
4
5
  const apiPath = createApiPath("user", "getWishlists");
5
6
 
6
- const getWishlists = createQuery<null, WishList[]>(apiPath, {
7
- queryKey: "wish-lists",
7
+ const getWishlists = createQuery<null, Wishlist[]>(apiPath, {
8
+ queryKey: getWishlistsQueryKey,
8
9
  });
9
10
 
10
11
  export default getWishlists;
@@ -1,5 +1,6 @@
1
1
  import * as cartSchemas from "@/api-manager/schemas/cart.schema";
2
2
  import * as productSchemas from "@/api-manager/schemas/product.schema";
3
+ import * as userSchemas from "@/api-manager/schemas/user.schema";
3
4
  import { User, UserCounts } from "@/api-manager/schemas/user.schema";
4
5
  import {
5
6
  Session,
@@ -31,6 +32,7 @@ import {
31
32
  SimpleProduct,
32
33
  StateProvinceInfo,
33
34
  ProductWarehouseInventoryAvailability,
35
+ ProductWarehouseInventoryInformation,
34
36
  } from "@msdyn365-commerce/retail-proxy";
35
37
  import {
36
38
  CategoriesQuery,
@@ -52,16 +54,16 @@ export interface DatasourceApis {
52
54
  organization: OrganizationApi;
53
55
  }
54
56
 
55
- export abstract class Datasource implements DatasourceApis {
57
+ export abstract class Datasource {
56
58
  public name: string;
57
- abstract user: UserApi;
58
- abstract cart: CartApi;
59
- abstract product: ProductApi;
60
- abstract categories: CategoryApi;
61
- abstract order: OrderApi;
62
- abstract address: AddressApi;
63
- abstract organization: OrganizationApi;
64
- abstract session: SessionApi;
59
+ abstract user: Partial<UserApi>;
60
+ abstract cart: Partial<CartApi>;
61
+ abstract product: Partial<ProductApi>;
62
+ abstract categories: Partial<CategoryApi>;
63
+ abstract order: Partial<OrderApi>;
64
+ abstract address: Partial<AddressApi>;
65
+ abstract organization: Partial<OrganizationApi>;
66
+ abstract session: Partial<SessionApi>;
65
67
 
66
68
  constructor(name: string) {
67
69
  this.name = name;
@@ -89,14 +91,34 @@ export interface OrganizationApi {
89
91
  * User Data Actions
90
92
  */
91
93
  export interface UserApi {
94
+ updateUser(user: userSchemas.User): Promise<userSchemas.User>;
95
+ getUser(): Promise<userSchemas.User | null>;
96
+ getUserCounts(userId: string): Promise<UserCounts>;
97
+ // wishlists
98
+ getWishlists(): Promise<userSchemas.Wishlist[]>;
99
+ getWishlistDetails(
100
+ input: userSchemas.WishlistDetailInput,
101
+ ): Promise<userSchemas.ExtendedWishlist>;
102
+ createWishlist(
103
+ input: userSchemas.WishlistCreateInput,
104
+ ): Promise<userSchemas.Wishlist>;
105
+ deleteWishlist(input: userSchemas.WishlistDetailInput): Promise<void>;
106
+ updateWishlist(
107
+ // input: userSchemas.UpdateWishlistInput, // used to change wishlist name
108
+ input: userSchemas.WishlistLinesInput,
109
+ ): Promise<userSchemas.Wishlist>;
110
+ addProductsToWishlist(
111
+ input: userSchemas.WishlistLinesInput,
112
+ ): Promise<userSchemas.Wishlist>;
113
+ removeProductsFromWishlist(
114
+ input: userSchemas.WishlistLinesInput,
115
+ ): Promise<void>;
116
+ copyCartToWishlist(
117
+ input: userSchemas.CopyCartToWishlistInput,
118
+ ): Promise<userSchemas.Wishlist>;
92
119
  updateUser(user: User): Promise<User>;
93
120
  getUser(): Promise<User | null>;
94
121
  getUserCounts(userId: string): Promise<UserCounts>;
95
- // wishlists
96
- getWishlists(): Promise<WishList[]>;
97
- getWishlistDetails(id: string): Promise<WishList>;
98
- createWishlist(wishlist: CreateWishListInput): Promise<WishList>;
99
- deleteWishlist(id: string): Promise<string>;
100
122
  }
101
123
 
102
124
  /**
@@ -142,6 +164,9 @@ export interface CartApi {
142
164
  input: cartSchemas.RetrieveCardPaymentAcceptResultInput,
143
165
  ): Promise<CardPaymentAcceptResult>;
144
166
  checkout(input: cartSchemas.CheckoutInput): Promise<SalesOrder>;
167
+ getCartLinesInventory(
168
+ input: cartSchemas.InventorySearchCartLinesCriteriaInput,
169
+ ): Promise<ProductWarehouseInventoryInformation>;
145
170
  }
146
171
 
147
172
  /**
@@ -167,6 +192,9 @@ export interface ProductApi {
167
192
  getInventory(
168
193
  input: productSchemas.InventorySearchCriteriaInput,
169
194
  ): Promise<ProductWarehouseInventoryAvailability>;
195
+ getProductPrices(
196
+ input: productSchemas.ProductPriceInput,
197
+ ): Promise<productSchemas.ProductPrice[]>;
170
198
  }
171
199
 
172
200
  /**
@@ -8,7 +8,7 @@ import {
8
8
  } from "next";
9
9
  import { getProviders } from "./providers";
10
10
  import { deleteCartCookie } from "@/lib/cart-cookie-handler";
11
- import { getConfig } from "@config";
11
+ import { getSecret } from "@evenicanpm/common-core/keyvault";
12
12
 
13
13
  // Split providers into separate array so we can iterate them and match the provider ID
14
14
  export type ExtendedJwtToken = JWT & {
@@ -20,7 +20,7 @@ export type ExtendedSession = Session & { token?: JWT };
20
20
 
21
21
  const createAuthOptions = (): NextAuthOptions => {
22
22
  const providers = getProviders();
23
- const secret = getConfig().NEXTAUTH_SECRET;
23
+ const secret = getSecret("NEXTAUTH_SECRET");
24
24
  return {
25
25
  providers,
26
26
  secret,
package/src/auth/msal.ts CHANGED
@@ -1,15 +1,15 @@
1
1
  import { PublicClientApplication, Configuration } from "@azure/msal-browser";
2
- import { getConfig } from "@config";
3
2
 
4
3
  const createMsalConfig = (): Configuration => {
5
4
  return {
6
5
  auth: {
7
- clientId: getConfig().AZURE_AD_B2C_CLIENTID, //process.env.NEXT_PUBLIC_AZURE_AD_B2C_CLIENTID || "",
8
- authority: getConfig().AZURE_AD_B2C_LOGIN_AUTHORITY, //process.env.NEXT_PUBLIC_AZURE_AD_B2C_LOGIN_AUTHORITY || "",
9
- redirectUri: "/", //process.env.NEXT_PUBLIC_AZURE_AD_B2C_REDIRECT || "/",
10
- postLogoutRedirectUri: getConfig().AZURE_AD_B2C_POST_LOGOUT_REDIRECT, //process.env.NEXT_PUBLIC_AZURE_AD_B2C_POST_LOGOUT_REDIRECT || "/",
6
+ clientId: process.env.NEXT_PUBLIC_AZURE_AD_B2C_CLIENTID || "",
7
+ authority: process.env.NEXT_PUBLIC_AZURE_AD_B2C_LOGIN_AUTHORITY || "",
8
+ redirectUri: process.env.NEXT_PUBLIC_AZURE_AD_B2C_REDIRECT || "/",
9
+ postLogoutRedirectUri:
10
+ process.env.NEXT_PUBLIC_AZURE_AD_B2C_POST_LOGOUT_REDIRECT || "/",
11
11
  knownAuthorities: [
12
- getConfig().AZURE_AD_B2C_KNOWN_AUTHORITY, //process.env.NEXT_PUBLIC_AZURE_AD_B2C_KNOWN_AUTHORITY || "",
12
+ process.env.NEXT_PUBLIC_AZURE_AD_B2C_KNOWN_AUTHORITY || "",
13
13
  ],
14
14
  navigateToLoginRequestUrl: true,
15
15
  },
@@ -44,11 +44,11 @@ const getMsalInstance = () => {
44
44
  };
45
45
 
46
46
  const getRequestConfig = (requestType?: string) => {
47
- const editAuthority = getConfig().AZURE_AD_B2C_EDIT_AUTHORITY;
48
- const resetAuthority = getConfig().AZURE_AD_B2C_RESET_AUTHORITY;
47
+ const editAuthority = process.env.NEXT_PUBLIC_AZURE_AD_B2C_EDIT_AUTHORITY;
48
+ const resetAuthority = process.env.NEXT_PUBLIC_AZURE_AD_B2C_RESET_AUTHORITY;
49
49
 
50
50
  const baseRequest = {
51
- scopes: [getConfig().AZURE_AD_B2C_API_PERMISSION],
51
+ scopes: [process.env.NEXT_PUBLIC_AZURE_AD_B2C_API_PERMISSION],
52
52
  authority: createMsalConfig().auth.authority,
53
53
  };
54
54
 
@@ -6,6 +6,8 @@ import { ExtendedJwtToken } from "@/auth/auth-options";
6
6
  const NEXT_AUTH_COOKIE_NAME = "next-auth.session-token";
7
7
  const SECURE_COOKIE_PREFIX = "__Secure-";
8
8
 
9
+ import { getSecret } from "@evenicanpm/common-core/keyvault";
10
+
9
11
  /**
10
12
  * Retrieves and decodes the NextAuth session cookie from the request.
11
13
  *
@@ -28,7 +30,7 @@ const manuallyRetrieveSessionCookie = async () => {
28
30
  if (cookie) {
29
31
  return decode({
30
32
  token: cookie.value,
31
- secret: process.env.NEXTAUTH_SECRET || "",
33
+ secret: getSecret("NEXTAUTH_SECRET") || "",
32
34
  });
33
35
  }
34
36
  //If the cookie is not found, we need to see if there is a chunked cookie
@@ -49,7 +51,7 @@ const manuallyRetrieveSessionCookie = async () => {
49
51
  if (cookieValues.length) {
50
52
  return decode({
51
53
  token: cookieValues.join(""),
52
- secret: process.env.NEXTAUTH_SECRET || "",
54
+ secret: getSecret("NEXTAUTH_SECRET") || "",
53
55
  });
54
56
  }
55
57
 
@@ -73,7 +75,7 @@ const manuallySetSessionCookie = async (token: JWT | ExtendedJwtToken) => {
73
75
  // Set the cookie with the name __Secure-next-auth.session-token
74
76
  const value = await encode({
75
77
  token,
76
- secret: process.env.NEXTAUTH_SECRET || "",
78
+ secret: getSecret("NEXTAUTH_SECRET") || "",
77
79
  });
78
80
  cookieStore.set({
79
81
  name: `${SECURE_COOKIE_PREFIX}${NEXT_AUTH_COOKIE_NAME}`,
@@ -1,4 +1,3 @@
1
- import { getConfig } from "@config";
2
1
  import AzureADB2CProvider from "next-auth/providers/azure-ad-b2c";
3
2
 
4
3
  // By default, NextAuth tries to use either PKCE or Client Secret-based authentication, depending on how the provider is configured.
@@ -6,9 +5,9 @@ import AzureADB2CProvider from "next-auth/providers/azure-ad-b2c";
6
5
  // If clientSecret is missing, it assumes PKCE.
7
6
  // But Azure AD B2C sometimes requires PKCE explicitly, so NextAuth needs to be told to always use PKCE.
8
7
  const azureADB2CProvider = () => {
9
- const CLIENT_ID = getConfig().AZURE_AD_B2C_CLIENTID;
10
- const SCOPE = `${getConfig().AZURE_AD_B2C_API_PERMISSION} offline_access openid`;
11
- const LOGIN_AUTHORITY = getConfig().AZURE_AD_B2C_LOGIN_AUTHORITY;
8
+ const CLIENT_ID = process.env.NEXT_PUBLIC_AZURE_AD_B2C_CLIENTID || "";
9
+ const SCOPE = `${process.env.NEXT_PUBLIC_AZURE_AD_B2C_API_PERMISSION} offline_access openid`;
10
+ const LOGIN_AUTHORITY = process.env.NEXT_PUBLIC_AZURE_AD_B2C_LOGIN_AUTHORITY;
12
11
 
13
12
  return AzureADB2CProvider({
14
13
  clientId: CLIENT_ID,
@@ -1,5 +1,4 @@
1
1
  import { Formats } from "./interfaces/productData";
2
- import { getConfig } from "@config";
3
2
 
4
3
  const apiKeys = {
5
4
  pages: "/cms/pages",
@@ -17,12 +16,12 @@ type ApiKeysType = typeof apiKeys;
17
16
  type ApiKey = keyof ApiKeysType;
18
17
 
19
18
  const getCmsApiUrl = (apiKey: ApiKey) => {
20
- const cmsApiEndpoint = getConfig().E4_API_ENDPOINT;
19
+ const cmsApiEndpoint = process.env.NEXT_PUBLIC_E4_API_ENDPOINT;
21
20
  return `${cmsApiEndpoint}${apiKeys[apiKey]}`;
22
21
  };
23
22
 
24
23
  const buildCmsMediaUrl = (mediaUrl: string) => {
25
- const cmsEndpoint = getConfig().CMS_ENDPOINT;
24
+ const cmsEndpoint = process.env.NEXT_PUBLIC_CMS_ENDPOINT;
26
25
 
27
26
  if (mediaUrl === undefined || mediaUrl === null) {
28
27
  return "";
@@ -1,23 +1,22 @@
1
1
  // Template: Market1
2
2
  import React from "react";
3
3
 
4
- // Custom Icon Component
4
+ // ICONS
5
5
  import { Light } from "../../Icons/index";
6
6
  import { Box } from "@mui/system";
7
7
 
8
- // Global Custom Components
8
+ // GLOBAL COMPONENTS
9
9
  import { Carousel } from "@/components/_components/carousel/index";
10
10
  import { SectionCreator } from "@/components/_components/section-header/index";
11
- import ProductCard1 from "@/components/_components/product-cards/product-card-1/index";
11
+ import ProductCard1Wrapper from "@/components/_components/product-cards/product-card-1/product-card-1-wrapper";
12
12
 
13
- // @/cms
13
+ // CMS
14
14
  import { getImageUrl } from "@/cms/endpoints";
15
15
 
16
16
  // API
17
17
  import getProductByIds from "@/services/product/queries/get-product-by-ids";
18
18
  import { getQueryClient } from "@/services/get-query-client";
19
19
  import { SimpleProduct } from "@msdyn365-commerce/retail-proxy";
20
-
21
20
  import { Product, ProductCarouselBlock } from "../../interfaces";
22
21
 
23
22
  type CombinedProduct = Product & SimpleProduct;
@@ -63,7 +62,7 @@ export default async function ProductCarousel(data: ProductCarouselBlock) {
63
62
  <Carousel responsive={responsive} height={445} autoplay={true}>
64
63
  {combinedData?.map((item: CombinedProduct) => (
65
64
  <Box pb={0.6} key={item.id}>
66
- <ProductCard1
65
+ <ProductCard1Wrapper
67
66
  id={item?.RecordId}
68
67
  slug={item?.ItemId ?? ""}
69
68
  title={item?.Name ?? ""}
@@ -71,6 +70,7 @@ export default async function ProductCarousel(data: ProductCarouselBlock) {
71
70
  rating={0}
72
71
  imgUrl={getImageUrl(item?.image?.[0]?.formats ?? {})}
73
72
  discount={0}
73
+ mode="PLP"
74
74
  //uom={item?.uom?.nodes[0].id}
75
75
  />
76
76
  </Box>
@@ -1,9 +1,12 @@
1
1
  "use client";
2
2
 
3
- import NextImage from "next/image";
3
+ import NextImage, { ImageProps } from "next/image";
4
4
  import styled from "@mui/material/styles/styled";
5
+ import { ComponentType } from "react";
5
6
 
6
- export default styled(NextImage)({
7
+ const LazyImage: ComponentType<ImageProps> = styled(NextImage)({
7
8
  width: "100%",
8
9
  height: "auto", //If we use CSS to change the size of image, we should include the styles 'width: "auto"' or 'height: "auto"' to maintain the aspect ratio.
9
10
  });
11
+
12
+ export default LazyImage;
@@ -42,7 +42,6 @@ const MENU_ITEMS = [
42
42
  interface Props {
43
43
  mobile?: boolean;
44
44
  }
45
-
46
45
  const User = ({ mobile = false }: Props) => {
47
46
  const { data: session, status } = useSession();
48
47
 
@@ -115,7 +114,7 @@ const User = ({ mobile = false }: Props) => {
115
114
 
116
115
  const setAnchorElNull = () => setAnchorEl(null);
117
116
 
118
- if (status === "loading") return <>Loading...</>;
117
+ if (status === "loading") return <></>;
119
118
 
120
119
  if (mobile) {
121
120
  return (
@@ -1,6 +1,6 @@
1
1
  import ChevronRight from "@mui/icons-material/ChevronRight";
2
2
  // GLOBAL CUSTOM HOOK
3
- import useSettings from "@/components/_components/hooks/useSettings";
3
+ import useSettings from "@/hooks/use-settings";
4
4
  // STYLED COMPONENTS
5
5
  import { CategoryList, CategoryListItem } from "../styles";
6
6
 
@@ -5,7 +5,7 @@ import KeyboardArrowDown from "@mui/icons-material/KeyboardArrowDown";
5
5
  // GLOBAL CUSTOM COMPONENTS
6
6
  import FlexRowCenter from "@/components/_components/flex-box/flex-row-center";
7
7
  // GLOBAL CUSTOM HOOKS
8
- import useOverflowDetect from "@/components/_components/hooks/useOverflowDetect";
8
+ import useOverflowDetect from "@/hooks/use-overflow-detect";
9
9
  // LOCAL CUSTOM COMPONENT
10
10
  import CategoryList from "./category-list";
11
11
  // STYLED COMPONENTS
@@ -7,8 +7,8 @@ import MenuItem from "@mui/material/MenuItem";
7
7
  import ArrowLeft from "@mui/icons-material/ArrowLeft";
8
8
  import ArrowRight from "@mui/icons-material/ArrowRight";
9
9
  // GLOBAL CUSTOM HOOKS
10
- import useOverflowDetect from "@/components/_components/hooks/useOverflowDetect";
11
- import useSettings from "@/components/_components/hooks/useSettings";
10
+ import useOverflowDetect from "@/hooks/use-overflow-detect";
11
+ import useSettings from "@/hooks/use-settings";
12
12
  // GLOBAL CUSTOM COMPONENTS
13
13
  import { Span } from "@/components/_components/Typography";
14
14
  import BazaarCard from "@/components/_components/BazaarCard";