@evenicanpm/storefront-core 1.0.2 → 1.0.4

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 (409) hide show
  1. package/docs.tsconfig.json +35 -0
  2. package/package.json +6 -3
  3. package/src/api-manager/README.md +30 -22
  4. package/src/api-manager/datasources/e4/{e4-address.datasource.ts → address/e4-address.datasource.ts} +10 -10
  5. package/src/api-manager/datasources/e4/address/e4-address.remaps.ts +70 -0
  6. package/src/api-manager/datasources/e4/address/e4-address.translator.ts +98 -0
  7. package/src/api-manager/datasources/e4/{e4-cart.datasource.ts → cart/e4-cart.datasource.ts} +17 -16
  8. package/src/api-manager/datasources/e4/cart/e4-cart.remaps.ts +94 -0
  9. package/src/api-manager/datasources/e4/cart/e4-cart.translator.ts +23 -0
  10. package/src/api-manager/datasources/e4/categories/e4-categories.datasource.ts +38 -0
  11. package/src/api-manager/datasources/e4/categories/e4-categories.translator.ts +161 -0
  12. package/src/api-manager/datasources/e4/e4.datasource.ts +8 -39
  13. package/src/api-manager/datasources/e4/{e4-order.datasource.ts → order/e4-order.datasource.ts} +3 -3
  14. package/src/api-manager/datasources/e4/order/e4-order.remaps.ts +101 -0
  15. package/src/api-manager/datasources/e4/{e4-organization.datasource.ts → organization/e4-organization.datasource.ts} +1 -1
  16. package/src/api-manager/datasources/e4/{e4-product.datasource.ts → product/e4-product.datasource.ts} +13 -11
  17. package/src/api-manager/datasources/e4/product/e4-product.remaps.ts +88 -0
  18. package/src/api-manager/datasources/e4/{e4.translator.ts → product/e4-product.translator.ts} +9 -329
  19. package/src/api-manager/datasources/e4/{e4-session.datasource.ts → session/e4-session.datasource.ts} +3 -3
  20. package/src/api-manager/datasources/e4/session/e4-session.translator.ts +18 -0
  21. package/src/api-manager/datasources/e4/user/e4-user.datasource.ts +13 -6
  22. package/src/api-manager/datasources/e4/user/e4-user.remaps.ts +49 -0
  23. package/src/api-manager/datasources/e4/user/e4-user.translator.ts +23 -2
  24. package/src/api-manager/datasources/e4/utils/unwrap-e4-variants.ts +1 -1
  25. package/src/api-manager/index.ts +11 -6
  26. package/src/api-manager/schemas/product.schema.ts +0 -1
  27. package/src/api-manager/schemas/user.schema.ts +3 -1
  28. package/src/api-manager/services/cart/mutations/add-to-cart.ts +1 -1
  29. package/src/api-manager/services/cart/mutations/checkout.ts +1 -2
  30. package/src/api-manager/services/create-query.ts +10 -0
  31. package/src/api-manager/services/product/queries/get-product-availability.ts +1 -1
  32. package/src/api-manager/services/product/server/product.server.ts +4 -1
  33. package/src/api-manager/services/user/mutations/add-to-wishlist.ts +23 -3
  34. package/src/api-manager/services/user/mutations/remove-from-wishlist.ts +23 -0
  35. package/src/api-manager/types/Datasource.ts +1 -5
  36. package/src/cms/blocks/BlockManager.tsx +67 -0
  37. package/src/cms/blocks/Components/BrandLogosScroller.tsx +72 -0
  38. package/src/cms/blocks/Components/CategoryCard.tsx +47 -0
  39. package/src/cms/blocks/Components/CategoryCarousel/index.tsx +59 -0
  40. package/src/cms/blocks/Components/FeaturePill.tsx +99 -0
  41. package/src/cms/blocks/Components/FeaturedCategories.tsx +41 -0
  42. package/src/cms/blocks/Components/FeaturedProducts.tsx +41 -0
  43. package/src/cms/blocks/Components/Footer/data/index.ts +32 -0
  44. package/src/cms/blocks/Components/Footer/index.tsx +88 -0
  45. package/src/cms/blocks/Components/Footer/interfaces.ts +37 -0
  46. package/src/cms/blocks/Components/Footer/sections/FooterAppStore.tsx +45 -0
  47. package/src/cms/blocks/Components/Footer/sections/FooterContact.tsx +36 -0
  48. package/src/cms/blocks/Components/Footer/sections/FooterLinks.tsx +30 -0
  49. package/src/cms/blocks/Components/Footer/sections/FooterLogo.tsx +26 -0
  50. package/src/cms/blocks/Components/Footer/sections/FooterSocialLinks.tsx +70 -0
  51. package/src/cms/blocks/Components/Footer/styles/index.ts +39 -0
  52. package/src/cms/blocks/Components/Footer.tsx +77 -0
  53. package/src/cms/blocks/Components/Hero.tsx +73 -0
  54. package/src/cms/blocks/Components/HeroCarousel/index.tsx +48 -0
  55. package/src/cms/blocks/Components/Image.tsx +39 -0
  56. package/src/cms/blocks/Components/MediaCard.tsx +41 -0
  57. package/src/cms/blocks/Components/ProductCarousel/index.tsx +88 -0
  58. package/src/cms/blocks/Components/ProductSectionFullWidth/index.tsx +107 -0
  59. package/src/cms/blocks/Components/RichText.tsx +19 -0
  60. package/src/cms/blocks/Components/Seo/index.tsx +48 -0
  61. package/src/cms/blocks/Components/Services/index.tsx +21 -0
  62. package/src/cms/blocks/Components/Services/service-card.tsx +73 -0
  63. package/src/cms/blocks/Components/shared/featured-product-card.tsx +29 -0
  64. package/src/cms/blocks/Components/shared/product-category-item.tsx +49 -0
  65. package/src/cms/blocks/Components/shared/product-grid.tsx +63 -0
  66. package/src/cms/blocks/Components/shared/top-categories-card.tsx +66 -0
  67. package/src/cms/blocks/Components/shared/top-rating-product-card.tsx +66 -0
  68. package/src/cms/blocks/Icons/Components/Category.tsx +14 -0
  69. package/src/cms/blocks/Icons/Components/DottedStar.tsx +40 -0
  70. package/src/cms/blocks/Icons/Components/FallbackIcon.tsx +33 -0
  71. package/src/cms/blocks/Icons/Components/GiftBox.tsx +18 -0
  72. package/src/cms/blocks/Icons/Components/Light.tsx +13 -0
  73. package/src/cms/blocks/Icons/Components/NewArrival.tsx +18 -0
  74. package/src/cms/blocks/Icons/Components/RankBadge.tsx +39 -0
  75. package/src/cms/blocks/Icons/index.ts +32 -0
  76. package/src/cms/blocks/index.tsx +16 -0
  77. package/src/cms/blocks/interfaces.ts +240 -0
  78. package/src/components/Notifications/README.md +1 -1
  79. package/src/components/Notifications/notification-context.tsx +1 -1
  80. package/src/components/README.md +3 -8
  81. package/src/components/_components/MiniCartClient.tsx +1 -1
  82. package/src/components/_components/navbar/category-based-menu/components/categories.tsx +1 -1
  83. package/src/components/_components/navbar/mega-menu/mega-menu.tsx +1 -1
  84. package/src/components/_components/navbar/nav-list/nav-item-child.tsx +2 -2
  85. package/src/components/_components/product-cards/product-card-1/product-card-1-wrapper.tsx +1 -1
  86. package/src/components/_components/products-view/product-view-dialog.tsx +1 -1
  87. package/src/components/_components/settings/setting.tsx +1 -1
  88. package/src/components/_components/wishlist/add-to-wishlist-dialog.tsx +2 -2
  89. package/src/components/_components/wishlist/components/create-new-list.tsx +1 -1
  90. package/src/components/_components/wishlist/remove-from-wishlist-dialog.tsx +2 -2
  91. package/src/components/_components/wishlist-modal/add-to-wishlist-dialog.tsx +2 -2
  92. package/src/components/_components/wishlist-modal/remove-from-wishlist-dialog.tsx +2 -2
  93. package/src/components/countries-input.tsx +0 -1
  94. package/src/components-v2/BazaarCard.tsx +21 -0
  95. package/src/components-v2/BazaarImage.tsx +12 -0
  96. package/src/components-v2/BazaarMenu.tsx +47 -0
  97. package/src/components-v2/BazaarSwitch.tsx +37 -0
  98. package/src/components-v2/BazaarTextField.tsx +73 -0
  99. package/src/components-v2/BoxShadowCard.tsx +16 -0
  100. package/src/components-v2/DropZone.tsx +86 -0
  101. package/src/components-v2/HoverBox.tsx +22 -0
  102. package/src/components-v2/Image.tsx +5 -0
  103. package/src/components-v2/ImageWithFallback.tsx +51 -0
  104. package/src/components-v2/LazyImage.tsx +12 -0
  105. package/src/components-v2/Loading.tsx +36 -0
  106. package/src/components-v2/README.md +4 -0
  107. package/src/components-v2/SearchInput.tsx +28 -0
  108. package/src/components-v2/SnackbarProvider.tsx +32 -0
  109. package/src/components-v2/T/index.tsx +15 -0
  110. package/src/components-v2/Typography.tsx +227 -0
  111. package/src/components-v2/WhiteButton.tsx +20 -0
  112. package/src/components-v2/accordion/accordion-header.tsx +43 -0
  113. package/src/components-v2/accordion/index.ts +1 -0
  114. package/src/components-v2/bazaar-types.ts +84 -0
  115. package/src/components-v2/carousel/carousel.tsx +106 -0
  116. package/src/components-v2/carousel/components/carousel-arrows.tsx +54 -0
  117. package/src/components-v2/carousel/components/carousel-dots.tsx +18 -0
  118. package/src/components-v2/carousel/index.ts +1 -0
  119. package/src/components-v2/carousel/styles/index.ts +93 -0
  120. package/src/components-v2/carousel-cards/carousel-card-1/carousel-card-1.tsx +83 -0
  121. package/src/components-v2/carousel-cards/carousel-card-1/index.ts +1 -0
  122. package/src/components-v2/carousel-cards/carousel-card-1/styles.ts +34 -0
  123. package/src/components-v2/categories/category-list/category-list.tsx +101 -0
  124. package/src/components-v2/categories/category-list/index.ts +1 -0
  125. package/src/components-v2/categories/category-list/styles.ts +35 -0
  126. package/src/components-v2/categories/category-list/types.ts +4 -0
  127. package/src/components-v2/categories/category-list-item/category-menu-item.tsx +37 -0
  128. package/src/components-v2/categories/category-list-item/index.ts +1 -0
  129. package/src/components-v2/categories/category-list-item/styles.ts +35 -0
  130. package/src/components-v2/categories/category-menu.tsx +53 -0
  131. package/src/components-v2/categories/mega-menu/banner.tsx +91 -0
  132. package/src/components-v2/categories/mega-menu/column-list.tsx +77 -0
  133. package/src/components-v2/categories/mega-menu/mega-menu-1.tsx +55 -0
  134. package/src/components-v2/categories/mega-menu/mega-menu-2.tsx +67 -0
  135. package/src/components-v2/categories/mega-menu/styles.ts +25 -0
  136. package/src/components-v2/categories/types.ts +16 -0
  137. package/src/components-v2/countries-input.tsx +73 -0
  138. package/src/components-v2/flex-box/flex-between.tsx +14 -0
  139. package/src/components-v2/flex-box/flex-box.tsx +9 -0
  140. package/src/components-v2/flex-box/flex-row-center.tsx +9 -0
  141. package/src/components-v2/flex-box/index.ts +5 -0
  142. package/src/components-v2/header/components/categories-menu.tsx +23 -0
  143. package/src/components-v2/header/components/mobile-header.tsx +148 -0
  144. package/src/components-v2/header/components/user.test.tsx +200 -0
  145. package/src/components-v2/header/components/user.tsx +250 -0
  146. package/src/components-v2/header/header.tsx +83 -0
  147. package/src/components-v2/header/hooks/use-header.ts +13 -0
  148. package/src/components-v2/header/index.ts +1 -0
  149. package/src/components-v2/header/sticky-header.tsx +49 -0
  150. package/src/components-v2/header/styles/index.ts +24 -0
  151. package/src/components-v2/icons/cart-bag.tsx +13 -0
  152. package/src/components-v2/icons/category-outline.tsx +29 -0
  153. package/src/components-v2/icons/category.tsx +12 -0
  154. package/src/components-v2/icons/home.tsx +19 -0
  155. package/src/components-v2/icons/search.tsx +13 -0
  156. package/src/components-v2/icons/shopping-bag-outlined.tsx +13 -0
  157. package/src/components-v2/icons/up-down.tsx +21 -0
  158. package/src/components-v2/icons/user.tsx +13 -0
  159. package/src/components-v2/icons/user2.tsx +14 -0
  160. package/src/components-v2/mini-cart/__tests__/cart-item.test.tsx +174 -0
  161. package/src/components-v2/mini-cart/__tests__/mini-cart.test.tsx +121 -0
  162. package/src/components-v2/mini-cart/__tests__/test-cart-empty.json +84 -0
  163. package/src/components-v2/mini-cart/__tests__/test-cart-with-item.json +244 -0
  164. package/src/components-v2/mini-cart/components/bottom-actions.tsx +81 -0
  165. package/src/components-v2/mini-cart/components/cart-item.tsx +205 -0
  166. package/src/components-v2/mini-cart/components/empty-view.tsx +69 -0
  167. package/src/components-v2/mini-cart/components/top-header.tsx +76 -0
  168. package/src/components-v2/mini-cart/index.ts +1 -0
  169. package/src/components-v2/mini-cart/mini-cart-trigger.tsx +99 -0
  170. package/src/components-v2/mini-cart/mini-cart.tsx +175 -0
  171. package/src/components-v2/mobile-navigation/index.ts +3 -0
  172. package/src/components-v2/mobile-navigation/mobile-navigation-bar.tsx +118 -0
  173. package/src/components-v2/mobile-navigation/styles/index.ts +63 -0
  174. package/src/components-v2/nav-link/index.ts +5 -0
  175. package/src/components-v2/nav-link/nav-link-2.tsx +32 -0
  176. package/src/components-v2/nav-link/nav-link-3.tsx +67 -0
  177. package/src/components-v2/nav-link/nav-link.tsx +53 -0
  178. package/src/components-v2/navbar/categories.tsx +81 -0
  179. package/src/components-v2/navbar/category-based-menu/category-based-menu.tsx +146 -0
  180. package/src/components-v2/navbar/category-based-menu/index.ts +1 -0
  181. package/src/components-v2/navbar/category-based-menu/styles.ts +81 -0
  182. package/src/components-v2/navbar/category-based-menu/types.ts +18 -0
  183. package/src/components-v2/navbar/index.ts +1 -0
  184. package/src/components-v2/navbar/mega-menu/index.ts +1 -0
  185. package/src/components-v2/navbar/mega-menu/mega-menu.tsx +138 -0
  186. package/src/components-v2/navbar/mega-menu/styles.ts +43 -0
  187. package/src/components-v2/navbar/mobile-menu/index.ts +1 -0
  188. package/src/components-v2/navbar/mobile-menu/mobile-menu.test.tsx +111 -0
  189. package/src/components-v2/navbar/mobile-menu/mobile-menu.tsx +141 -0
  190. package/src/components-v2/navbar/nav-list/cms-nav.test.tsx +84 -0
  191. package/src/components-v2/navbar/nav-list/index.ts +1 -0
  192. package/src/components-v2/navbar/nav-list/nav-item-child.tsx +66 -0
  193. package/src/components-v2/navbar/nav-list/nav-list.tsx +141 -0
  194. package/src/components-v2/navbar/navbar.tsx +95 -0
  195. package/src/components-v2/navbar/styles.ts +90 -0
  196. package/src/components-v2/navbar/utils/transform-nav.test.ts +209 -0
  197. package/src/components-v2/navbar/utils/transform-nav.ts +43 -0
  198. package/src/components-v2/no-records.tsx +20 -0
  199. package/src/components-v2/product-cards/discount-chip.tsx +43 -0
  200. package/src/components-v2/product-cards/product-card/components/hover-actions.tsx +37 -0
  201. package/src/components-v2/product-cards/product-card/components/quantity-buttons.tsx +65 -0
  202. package/src/components-v2/product-cards/product-card/index.ts +1 -0
  203. package/src/components-v2/product-cards/product-card/product-card.tsx +410 -0
  204. package/src/components-v2/product-cards/product-card/styles/index.ts +52 -0
  205. package/src/components-v2/product-cards/product-card-plp/components/quantity-buttons.tsx +54 -0
  206. package/src/components-v2/product-cards/product-card-plp/index.ts +1 -0
  207. package/src/components-v2/product-cards/product-card-plp/product-card.tsx +161 -0
  208. package/src/components-v2/product-cards/product-card-plp/styles/index.ts +18 -0
  209. package/src/components-v2/product-cards/product-card-plp-list/components/add-to-cart.tsx +63 -0
  210. package/src/components-v2/product-cards/product-card-plp-list/components/favorite-button.tsx +27 -0
  211. package/src/components-v2/product-cards/product-card-plp-list/components/tags.tsx +33 -0
  212. package/src/components-v2/product-cards/product-card-plp-list/index.ts +1 -0
  213. package/src/components-v2/product-cards/product-card-plp-list/product-card.tsx +219 -0
  214. package/src/components-v2/product-cards/product-card-search/index.ts +1 -0
  215. package/src/components-v2/product-cards/product-card-search/product-card.tsx +166 -0
  216. package/src/components-v2/product-cards/product-card-search/styles/index.ts +61 -0
  217. package/src/components-v2/product-cards/product-price.tsx +26 -0
  218. package/src/components-v2/product-cards/product-rating.tsx +28 -0
  219. package/src/components-v2/product-cards/product-title.tsx +24 -0
  220. package/src/components-v2/product-cards/use-product.ts +35 -0
  221. package/src/components-v2/product-dialog/compound/product-dialog.tsx +225 -0
  222. package/src/components-v2/product-dialog/index.tsx +29 -0
  223. package/src/components-v2/product-dimensions/compound/dimensions-group-error.tsx +46 -0
  224. package/src/components-v2/product-dimensions/compound/dimensions-group-label.tsx +27 -0
  225. package/src/components-v2/product-dimensions/compound/dimensions-group-list-chip.tsx +78 -0
  226. package/src/components-v2/product-dimensions/compound/dimensions-group-list.tsx +24 -0
  227. package/src/components-v2/product-dimensions/compound/dimensions-group.tsx +55 -0
  228. package/src/components-v2/product-dimensions/compound/dimensions.tsx +81 -0
  229. package/src/components-v2/product-dimensions/index.tsx +38 -0
  230. package/src/components-v2/product-dimensions/utils/has-selected-dimension.ts +20 -0
  231. package/src/components-v2/product-quantity-buttons/compound/quantity-buttons-root.tsx +181 -0
  232. package/src/components-v2/product-quantity-buttons/index.tsx +22 -0
  233. package/src/components-v2/product-quantity-variants/index.tsx +90 -0
  234. package/src/components-v2/products-view/compound/context.ts +25 -0
  235. package/src/components-v2/products-view/compound/products-grid-view.tsx +109 -0
  236. package/src/components-v2/products-view/compound/products-list-view.tsx +98 -0
  237. package/src/components-v2/products-view/compound/types.ts +12 -0
  238. package/src/components-v2/products-view/index.tsx +45 -0
  239. package/src/components-v2/products-view/products-grid-view.tsx +65 -0
  240. package/src/components-v2/products-view/products-list-view.tsx +66 -0
  241. package/src/components-v2/progress/index.ts +1 -0
  242. package/src/components-v2/progress/progress.tsx +77 -0
  243. package/src/components-v2/scrollbar/index.ts +1 -0
  244. package/src/components-v2/scrollbar/scrollbar.tsx +27 -0
  245. package/src/components-v2/scrollbar/styles.ts +15 -0
  246. package/src/components-v2/search-bar/compound/context.ts +31 -0
  247. package/src/components-v2/search-bar/compound/results-item-lg.tsx +43 -0
  248. package/src/components-v2/search-bar/compound/results-item-sm.tsx +48 -0
  249. package/src/components-v2/search-bar/compound/results-suspense.tsx +49 -0
  250. package/src/components-v2/search-bar/compound/results.tsx +42 -0
  251. package/src/components-v2/search-bar/compound/search-bar-root.tsx +64 -0
  252. package/src/components-v2/search-bar/compound/textfield-adornment-button.tsx +22 -0
  253. package/src/components-v2/search-bar/compound/textfield-adornment-category.tsx +83 -0
  254. package/src/components-v2/search-bar/compound/textfield-adornment-search-icon.tsx +34 -0
  255. package/src/components-v2/search-bar/compound/textfield.tsx +58 -0
  256. package/src/components-v2/search-bar/hooks/use-click-outside.ts +20 -0
  257. package/src/components-v2/search-bar/hooks/use-search.ts +63 -0
  258. package/src/components-v2/search-bar/index.tsx +36 -0
  259. package/src/components-v2/search-bar/styles/index.ts +49 -0
  260. package/src/components-v2/search-bar/utils/findCategoryNameById.ts +18 -0
  261. package/src/components-v2/section/compound/section-header.tsx +63 -0
  262. package/src/components-v2/section/compound/section.tsx +26 -0
  263. package/src/components-v2/section/index.ts +1 -0
  264. package/src/components-v2/side-nav/index.ts +1 -0
  265. package/src/components-v2/side-nav/side-nav.tsx +48 -0
  266. package/src/components-v2/site-logo.tsx +17 -0
  267. package/src/components-v2/sticky/index.ts +1 -0
  268. package/src/components-v2/sticky/sticky.tsx +62 -0
  269. package/src/components-v2/sticky/styles.ts +38 -0
  270. package/src/components-v2/utils/constants.ts +8 -0
  271. package/src/components-v2/wishlist-dialogs/add-to-wishlist/add-to-wishlist-button.tsx +69 -0
  272. package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-bottom-ui.tsx +35 -0
  273. package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-dialog.tsx +79 -0
  274. package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-list.tsx +41 -0
  275. package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/context.ts +29 -0
  276. package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/wishlist-dialog-header.tsx +74 -0
  277. package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/wishlist-dialog-item.tsx +82 -0
  278. package/src/components-v2/wishlist-dialogs/add-to-wishlist/hooks/use-add-to-wishlist.ts +152 -0
  279. package/src/components-v2/wishlist-dialogs/add-to-wishlist/index.tsx +39 -0
  280. package/src/components-v2/wishlist-dialogs/create-wishlist/compound/context.ts +2 -0
  281. package/src/components-v2/wishlist-dialogs/create-wishlist/compound/create-wishlist-bottom-ui.tsx +42 -0
  282. package/src/components-v2/wishlist-dialogs/create-wishlist/compound/create-wishlist-dialog.tsx +92 -0
  283. package/src/components-v2/wishlist-dialogs/create-wishlist/compound/create-wishlist-form.tsx +96 -0
  284. package/src/components-v2/wishlist-dialogs/create-wishlist/create-wishlist-button.tsx +42 -0
  285. package/src/components-v2/wishlist-dialogs/create-wishlist/index.tsx +22 -0
  286. package/src/components-v2/wishlist-dialogs/styles.ts +61 -0
  287. package/src/hooks/{use-cart.tsx → use-cart.ts} +29 -23
  288. package/src/hooks/use-variants.ts +138 -0
  289. package/src/lib/build-detail-url.ts +2 -1
  290. package/src/pages/README.md +4 -0
  291. package/src/pages/product-details/product-intro/product-intro.tsx +29 -24
  292. package/src/pages/product-list/quick-view-dialog-content.tsx +22 -11
  293. package/src/pages-v2/README.md +4 -0
  294. package/src/pages-v2/account/addresses/address-form.tsx +289 -0
  295. package/src/pages-v2/account/addresses/address-item.tsx +104 -0
  296. package/src/pages-v2/account/dashboard-header.tsx +123 -0
  297. package/src/pages-v2/account/navigation.tsx +87 -0
  298. package/src/pages-v2/account/orders/icons/delivery.tsx +14 -0
  299. package/src/pages-v2/account/orders/icons/package-box.tsx +13 -0
  300. package/src/pages-v2/account/orders/icons/truck-filled.tsx +14 -0
  301. package/src/pages-v2/account/orders/order-progress.tsx +114 -0
  302. package/src/pages-v2/account/orders/order-row.tsx +64 -0
  303. package/src/pages-v2/account/orders/order-summary.tsx +87 -0
  304. package/src/pages-v2/account/orders/ordered-products.tsx +121 -0
  305. package/src/pages-v2/account/profile/profile-button.test.tsx +59 -0
  306. package/src/pages-v2/account/profile/profile-button.tsx +50 -0
  307. package/src/pages-v2/account/profile/user-info.tsx +62 -0
  308. package/src/pages-v2/account/styles.ts +32 -0
  309. package/src/pages-v2/account/table-row.tsx +19 -0
  310. package/src/pages-v2/account/wishlist/create-new-list.tsx +167 -0
  311. package/src/pages-v2/account/wishlist/create-wishlist-button.tsx +40 -0
  312. package/src/pages-v2/account/wishlist/wishlist-item.tsx +82 -0
  313. package/src/pages-v2/blog/pagination.tsx +38 -0
  314. package/src/pages-v2/cart/cart-item.tsx +312 -0
  315. package/src/pages-v2/cart/checkout-form.tsx +122 -0
  316. package/src/pages-v2/cart/coupon-entry.tsx +90 -0
  317. package/src/pages-v2/cart/estimate-shipping.tsx +183 -0
  318. package/src/pages-v2/cart/wrapper.tsx +30 -0
  319. package/src/pages-v2/checkout/checkout-alt-form/address-card.tsx +76 -0
  320. package/src/pages-v2/checkout/checkout-alt-form/checkout-form.tsx +131 -0
  321. package/src/pages-v2/checkout/checkout-alt-form/checkout-step.tsx +120 -0
  322. package/src/pages-v2/checkout/checkout-alt-form/customer-information.tsx +94 -0
  323. package/src/pages-v2/checkout/checkout-alt-form/delivery-address.tsx +174 -0
  324. package/src/pages-v2/checkout/checkout-alt-form/delivery-date.tsx +114 -0
  325. package/src/pages-v2/checkout/checkout-alt-form/delivery-options.tsx +190 -0
  326. package/src/pages-v2/checkout/checkout-alt-form/edit-address-form.tsx +130 -0
  327. package/src/pages-v2/checkout/checkout-alt-form/heading.tsx +50 -0
  328. package/src/pages-v2/checkout/checkout-alt-form/index.ts +1 -0
  329. package/src/pages-v2/checkout/checkout-alt-form/new-address-form.tsx +299 -0
  330. package/src/pages-v2/checkout/checkout-alt-form/node.tsx +9 -0
  331. package/src/pages-v2/checkout/checkout-alt-form/payment-details.tsx +347 -0
  332. package/src/pages-v2/checkout/checkout-alt-form/safe-card-preview-data.tsx +36 -0
  333. package/src/pages-v2/checkout/checkout-alt-form/types.ts +20 -0
  334. package/src/pages-v2/checkout/checkout-alt-summary/cart-item.tsx +42 -0
  335. package/src/pages-v2/checkout/checkout-alt-summary/checkout-alt-summary.tsx +42 -0
  336. package/src/pages-v2/checkout/checkout-alt-summary/index.ts +1 -0
  337. package/src/pages-v2/checkout/checkout-alt-summary/list-item.tsx +31 -0
  338. package/src/pages-v2/confirmation/address.tsx +25 -0
  339. package/src/pages-v2/confirmation/confirmation-summary.tsx +55 -0
  340. package/src/pages-v2/confirmation/ordered-products.tsx +115 -0
  341. package/src/pages-v2/product-details/available-shops.tsx +48 -0
  342. package/src/pages-v2/product-details/bopis/find-in-store-button.tsx +64 -0
  343. package/src/pages-v2/product-details/bopis/find-in-store-modal.tsx +257 -0
  344. package/src/pages-v2/product-details/bopis/pickup-option-select.tsx +127 -0
  345. package/src/pages-v2/product-details/bopis/search-header.tsx +69 -0
  346. package/src/pages-v2/product-details/bopis/store-card/index.ts +1 -0
  347. package/src/pages-v2/product-details/bopis/store-card/shop-card.tsx +121 -0
  348. package/src/pages-v2/product-details/bopis/store-card/styles.ts +33 -0
  349. package/src/pages-v2/product-details/bopis/store-card/utils/convertSecondsToTime.ts +8 -0
  350. package/src/pages-v2/product-details/bopis/store-card/utils/getDaysResources.ts +25 -0
  351. package/src/pages-v2/product-details/checkbox-label.tsx +20 -0
  352. package/src/pages-v2/product-details/currency.ts +64 -0
  353. package/src/pages-v2/product-details/frequently-bought.tsx +97 -0
  354. package/src/pages-v2/product-details/frequently-product-card.tsx +63 -0
  355. package/src/pages-v2/product-details/product-comment.tsx +49 -0
  356. package/src/pages-v2/product-details/product-description.tsx +22 -0
  357. package/src/pages-v2/product-details/product-filter-card.tsx +265 -0
  358. package/src/pages-v2/product-details/product-intro/compound/context.ts +52 -0
  359. package/src/pages-v2/product-details/product-intro/compound/product-info.tsx +231 -0
  360. package/src/pages-v2/product-details/product-intro/compound/product-intro-images.tsx +124 -0
  361. package/src/pages-v2/product-details/product-intro/compound/product-intro.tsx +49 -0
  362. package/src/pages-v2/product-details/product-intro/compound/thumbnail-with-skeleton.tsx +28 -0
  363. package/src/pages-v2/product-details/product-intro/utils.ts +42 -0
  364. package/src/pages-v2/product-details/product-review.tsx +131 -0
  365. package/src/pages-v2/product-details/product-tabs.tsx +117 -0
  366. package/src/pages-v2/product-details/related-products.tsx +56 -0
  367. package/src/pages-v2/product-details/types.ts +11 -0
  368. package/src/pages-v2/product-list/breadcrumbs.tsx +39 -0
  369. package/src/pages-v2/product-list/checkbox-label.tsx +20 -0
  370. package/src/pages-v2/product-list/facet-group.tsx +125 -0
  371. package/src/pages-v2/product-list/facet.tsx +36 -0
  372. package/src/pages-v2/product-list/list-filter.tsx +43 -0
  373. package/src/pages-v2/product-list/pagination.tsx +80 -0
  374. package/src/pages-v2/product-list/product-list-context.tsx +302 -0
  375. package/src/pages-v2/product-list/product-list-state.ts +187 -0
  376. package/src/pages-v2/product-list/product-rating.tsx +16 -0
  377. package/src/pages-v2/product-list/quick-view-dialog-content.tsx +214 -0
  378. package/src/pages-v2/product-list/quick-view-dialog.tsx +54 -0
  379. package/src/pages-v2/product-list/range-filter.tsx +125 -0
  380. package/src/pages-v2/product-list/scrollbar.tsx +38 -0
  381. package/src/pages-v2/product-list/search-bar.tsx +162 -0
  382. package/src/pages-v2/product-list/selected-facets.tsx +80 -0
  383. package/src/pages-v2/product-list/side-nav.tsx +49 -0
  384. package/src/pages-v2/product-list/swatch.tsx +80 -0
  385. package/src/pages-v2/product-list/types.ts +18 -0
  386. package/src/pages-v2/product-list/use-product-list.ts +12 -0
  387. package/src/pages-v2/product-list/useCategoryFilter.tsx +26 -0
  388. package/src/pages-v2/product-list/utils/facet-helpers.ts +5 -0
  389. package/src/pages-v2/product-list/utils/generate-breadcrumbs.ts +30 -0
  390. package/src/pages-v2/product-list/utils/getCategoryFilterFromSlug.ts +153 -0
  391. package/src/pages-v2/product-list/utils/product-list-helper.ts +111 -0
  392. package/src/pages-v2/product-list/utils/product-list-types.ts +41 -0
  393. package/src/pages-v2/product-list/utils/search-for-category.ts +76 -0
  394. package/src/pages-v2/product-list/utils/sort-options.ts +44 -0
  395. package/src/pages-v2/product-list/utils/use-previous-refiners.ts +14 -0
  396. package/src/pages-v2/quickorder/order-upload.tsx +150 -0
  397. package/src/pages-v2/quickorder/quick-order-form.tsx +346 -0
  398. package/src/pages-v2/quickorder/quick-order-row.tsx +144 -0
  399. package/src/providers/nav-provider/index.tsx +59 -0
  400. package/src/providers/nav-provider/utils/createLink.ts +15 -0
  401. package/src/providers/notifications/README.md +15 -0
  402. package/src/providers/notifications/notification-context.tsx +82 -0
  403. package/src/providers/notifications/use-notification.ts +12 -0
  404. package/tsconfig.json +3 -2
  405. package/typedoc.js +12 -0
  406. package/src/api-manager/api-manager.config.json +0 -12
  407. package/src/api-manager/datasources/e4/e4.remaps.ts +0 -355
  408. package/src/api-manager/datasources/e4/e4.translator.test.ts +0 -202
  409. package/src/hooks/use-variants.tsx +0 -85
@@ -0,0 +1,92 @@
1
+ import React from "react";
2
+ import isFunction from "lodash/isFunction";
3
+ import { useTranslations } from "next-intl";
4
+ import { Dialog, DialogContent, CircularProgress } from "@mui/material";
5
+ // Global Custom components
6
+ import { H5 } from "@evenicanpm/storefront-core/src/components-v2/Typography";
7
+ import { useNotification } from "@evenicanpm/storefront-core/src/providers/notifications/use-notification";
8
+ // Forms
9
+ import { useFormik } from "formik";
10
+ import { z } from "zod";
11
+ import { withZodSchema } from "formik-validator-zod";
12
+ // API
13
+ import useCreateWishlist from "@evenicanpm/storefront-core/src/api-manager/services/user/mutations/create-wishlist";
14
+ import { CreateNewWishlistContext } from "./context";
15
+ import CreateNewWishlistForm from "./create-wishlist-form";
16
+
17
+ interface Props {
18
+ open: boolean;
19
+ handleClose: () => void;
20
+ children: React.ReactNode;
21
+ }
22
+
23
+ export default function CreateNewList(props: Props) {
24
+ const { children } = props;
25
+ const t = useTranslations("Account.Wishlists");
26
+ const { setNotification } = useNotification();
27
+
28
+ const { mutateAsync: createWishlist } = useCreateWishlist();
29
+
30
+ const FormSchema = z.object({
31
+ Id: z.string(),
32
+ Name: z.string().nonempty(t("Validation.required", { field: t("name") })),
33
+ Comment: z.string().optional(),
34
+ IsPublic: z.boolean().optional(),
35
+ });
36
+
37
+ type FormSchemaType = z.infer<typeof FormSchema>;
38
+
39
+ const handleSubmit = async (values: FormSchemaType) => {
40
+ try {
41
+ await createWishlist({ ...values, IsPublic: !values.IsPublic });
42
+ handleClose();
43
+ setNotification({
44
+ message: t("wishlistSuccess"),
45
+ severity: "success",
46
+ });
47
+ } catch (error) {
48
+ setNotification({
49
+ message: t("wishlistFailed"),
50
+ severity: "error",
51
+ });
52
+ }
53
+ };
54
+
55
+ const formik = useFormik<FormSchemaType>({
56
+ initialValues: {
57
+ Id: "",
58
+ Name: "",
59
+ Comment: "",
60
+ IsPublic: false,
61
+ },
62
+ onSubmit: handleSubmit,
63
+ validate: withZodSchema(FormSchema),
64
+ });
65
+
66
+ const { resetForm, isSubmitting } = formik;
67
+
68
+ const handleClose = () => {
69
+ if (isFunction(props.handleClose)) {
70
+ props.handleClose();
71
+ resetForm();
72
+ }
73
+ };
74
+
75
+ return (
76
+ <CreateNewWishlistContext.Provider value={{ formik, handleClose }}>
77
+ <Dialog open={props.open} onClose={handleClose}>
78
+ <DialogContent>
79
+ {isSubmitting ? <CircularProgress /> : children}
80
+ </DialogContent>
81
+ </Dialog>
82
+ </CreateNewWishlistContext.Provider>
83
+ );
84
+ }
85
+
86
+ const FormTitle = () => {
87
+ const t = useTranslations("Account.Wishlists");
88
+ return <H5 mb={4}>{t("formTitle")}</H5>;
89
+ };
90
+
91
+ CreateNewList.Title = FormTitle;
92
+ CreateNewList.Form = CreateNewWishlistForm;
@@ -0,0 +1,96 @@
1
+ /**
2
+ * @module Create-Wishlist-Dialog
3
+ */
4
+ import React, { useContext } from "react";
5
+ import { useTranslations } from "next-intl";
6
+ import { Box, TextField, FormControlLabel, Checkbox } from "@mui/material";
7
+ import Grid from "@mui/material/Grid2";
8
+ // Global Custom components
9
+ import BottomUI from "./create-wishlist-bottom-ui";
10
+ import { CreateNewWishlistContext } from "./context";
11
+
12
+ /*
13
+ * @category Sub-Component
14
+ */
15
+ const CreateNewWishlistForm = ({ children }: { children: React.ReactNode }) => {
16
+ const { formik } = useContext(CreateNewWishlistContext);
17
+ return (
18
+ <Box component="form" onSubmit={formik.handleSubmit}>
19
+ <Grid container spacing={3}>
20
+ {children}
21
+ </Grid>
22
+ </Box>
23
+ );
24
+ };
25
+
26
+ /*
27
+ * @category Sub-Component
28
+ */
29
+ function NameTextField() {
30
+ const t = useTranslations("Account.Wishlists");
31
+ const { formik } = useContext(CreateNewWishlistContext);
32
+ return (
33
+ <Grid size={{ sm: 6, xs: 12 }}>
34
+ <TextField
35
+ name="Name"
36
+ fullWidth
37
+ label={t("name")}
38
+ value={formik.values.Name}
39
+ onChange={formik.handleChange}
40
+ onBlur={formik.handleBlur}
41
+ error={formik.touched.Name && Boolean(formik.errors.Name)}
42
+ helperText={formik.touched.Name && formik.errors.Name}
43
+ required
44
+ />
45
+ </Grid>
46
+ );
47
+ }
48
+
49
+ /*
50
+ * @category Sub-Component
51
+ */
52
+ function DescriptionTextField() {
53
+ const t = useTranslations("Account.Wishlists");
54
+ const { formik } = useContext(CreateNewWishlistContext);
55
+ return (
56
+ <Grid size={{ sm: 6, xs: 12 }}>
57
+ <TextField
58
+ name="Comment"
59
+ fullWidth
60
+ label={t("comment")}
61
+ value={formik.values.Comment}
62
+ onChange={formik.handleChange}
63
+ onBlur={formik.handleBlur}
64
+ error={formik.touched.Comment && Boolean(formik.errors.Comment)}
65
+ helperText={formik.touched.Comment && formik.errors.Comment}
66
+ />
67
+ </Grid>
68
+ );
69
+ }
70
+
71
+ function IsPrivateCheckbox() {
72
+ const t = useTranslations("Account.Wishlists");
73
+ const { formik } = useContext(CreateNewWishlistContext);
74
+ return (
75
+ <Grid size={{ sm: 6, xs: 12 }}>
76
+ <FormControlLabel
77
+ control={
78
+ <Checkbox
79
+ name="IsPublic"
80
+ checked={formik.values.IsPublic}
81
+ onChange={formik.handleChange}
82
+ onBlur={formik.handleBlur}
83
+ />
84
+ }
85
+ label={t("private")}
86
+ />
87
+ </Grid>
88
+ );
89
+ }
90
+
91
+ CreateNewWishlistForm.BottomUI = BottomUI;
92
+ CreateNewWishlistForm.NameTextField = NameTextField;
93
+ CreateNewWishlistForm.IsPrivateCheckBox = IsPrivateCheckbox;
94
+ CreateNewWishlistForm.DescriptionTextField = DescriptionTextField;
95
+
96
+ export default CreateNewWishlistForm;
@@ -0,0 +1,42 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import { Button } from "@mui/material";
5
+ import T from "@evenicanpm/storefront-core/src/components-v2/T";
6
+ import CreateNewListDialog from "./";
7
+
8
+ interface Props {
9
+ path?: string;
10
+ }
11
+
12
+ const CreateWishlistButton = ({
13
+ path = "Account.Wishlists.btnCreateNewList",
14
+ }: Props) => {
15
+ const [openCreateListDialog, setOpenCreateListDialog] = useState(false);
16
+
17
+ const handleCloseDialog = () => {
18
+ setOpenCreateListDialog(false);
19
+ };
20
+
21
+ const handleCreateNewList = () => {
22
+ setOpenCreateListDialog(true);
23
+ };
24
+
25
+ return (
26
+ <>
27
+ <Button
28
+ onClick={handleCreateNewList}
29
+ color="primary"
30
+ sx={{ bgcolor: "primary.light", px: 4 }}
31
+ >
32
+ <T path={path} />
33
+ </Button>
34
+ <CreateNewListDialog
35
+ open={openCreateListDialog}
36
+ handleClose={handleCloseDialog}
37
+ />
38
+ </>
39
+ );
40
+ };
41
+
42
+ export default CreateWishlistButton;
@@ -0,0 +1,22 @@
1
+ import CreateNewList from "./compound/create-wishlist-dialog";
2
+
3
+ interface Props {
4
+ open: boolean;
5
+ handleClose: () => void;
6
+ }
7
+
8
+ const CreateNewWishlistDialog = ({ open, handleClose }: Props) => {
9
+ return (
10
+ <CreateNewList open={open} handleClose={handleClose}>
11
+ <CreateNewList.Title />
12
+ <CreateNewList.Form>
13
+ <CreateNewList.Form.NameTextField />
14
+ <CreateNewList.Form.DescriptionTextField />
15
+ <CreateNewList.Form.IsPrivateCheckBox />
16
+ <CreateNewList.Form.BottomUI />
17
+ </CreateNewList.Form>
18
+ </CreateNewList>
19
+ );
20
+ };
21
+
22
+ export default CreateNewWishlistDialog;
@@ -0,0 +1,61 @@
1
+ import Card, { CardProps } from "@mui/material/Card";
2
+ import styled from "@mui/material/styles/styled";
3
+ import NavLink, {
4
+ NavLinkProps,
5
+ } from "@evenicanpm/storefront-core/src/components-v2/nav-link/nav-link";
6
+ import { ComponentType } from "react";
7
+
8
+ type ExtendedNavLinkProps = NavLinkProps & {
9
+ isCurrentPath?: boolean;
10
+ };
11
+
12
+ export const MainContainer: ComponentType<CardProps> = styled(Card)(
13
+ ({ theme }) => ({
14
+ paddingBottom: "1.5rem",
15
+ [theme.breakpoints.down("md")]: {
16
+ boxShadow: "none",
17
+ overflowY: "auto",
18
+ height: "calc(100vh - 64px)",
19
+ },
20
+ }),
21
+ ) as typeof Card;
22
+
23
+ export const StyledNavLink: ComponentType<ExtendedNavLinkProps> = styled(
24
+ NavLink,
25
+ {
26
+ shouldForwardProp: (prop) => prop !== "isCurrentPath",
27
+ },
28
+ )<ExtendedNavLinkProps>(({ theme, isCurrentPath }) => ({
29
+ display: "flex",
30
+ alignItems: "center",
31
+ borderLeft: "4px solid",
32
+ paddingLeft: "1.5rem",
33
+ paddingRight: "1.5rem",
34
+ marginBottom: "1.25rem",
35
+ justifyContent: "space-between",
36
+ borderColor: isCurrentPath ? theme.palette.primary.main : "transparent",
37
+ "& .nav-icon": {
38
+ color: isCurrentPath ? theme.palette.primary.main : theme.palette.grey[600],
39
+ },
40
+ "&:hover": {
41
+ borderColor: theme.palette.primary.main,
42
+ "& .nav-icon": { color: theme.palette.primary.main },
43
+ },
44
+ }));
45
+
46
+ export const StyledTableRow: ComponentType<CardProps> = styled(Card)(
47
+ ({ theme }) => ({
48
+ gap: 16,
49
+ marginBlock: 16,
50
+ display: "grid",
51
+ borderRadius: 10,
52
+ cursor: "pointer",
53
+ alignItems: "center",
54
+ padding: ".6rem 1.2rem",
55
+ gridTemplateColumns: "1.5fr 2fr 1.5fr auto",
56
+ [theme.breakpoints.down("sm")]: {
57
+ gap: 8,
58
+ gridTemplateColumns: "repeat(2, 1fr)",
59
+ },
60
+ }),
61
+ );
@@ -1,25 +1,29 @@
1
- import useDeleteCartLine from "@/api-manager/services/cart/mutations/delete-cart-line";
2
- import useAddToCart from "@/api-manager/services/cart/mutations/add-to-cart";
3
- import useUpdateCartLines from "@/api-manager/services/cart/mutations/update-cart-lines";
4
- import { Cart } from "@/api-manager/schemas/cart.schema";
5
- import { CartLine } from "@msdyn365-commerce/retail-proxy";
6
-
7
- type UseCartProps = {
8
- cart: Cart;
9
- selectVariantId: number | undefined;
10
- recordId: number;
11
- };
12
-
13
- export type AddToCartBopisInput = {
1
+ "use client";
2
+ import useDeleteCartLine from "@evenicanpm/storefront-core/src/api-manager/services/cart/mutations/delete-cart-line";
3
+ import useAddToCart from "@evenicanpm/storefront-core/src/api-manager/services/cart/mutations/add-to-cart";
4
+ import useUpdateCartLines from "@evenicanpm/storefront-core/src/api-manager/services/cart/mutations/update-cart-lines";
5
+ import getCart from "@evenicanpm/storefront-core/src/api-manager/services/cart/queries/get-cart";
6
+ /**
7
+ * Optional input for BOPIS
8
+ */
9
+ export interface AddToCartBopisInput {
14
10
  deliveryMode: string;
15
11
  warehouseId: string;
16
- };
12
+ }
17
13
 
18
- export default function useCart({
19
- cart,
20
- selectVariantId,
21
- recordId,
22
- }: UseCartProps) {
14
+ /**
15
+ * TODO: Why does this take variant id and record id.... no need. just take a single ID
16
+ *
17
+ * Handles adding and changing product in cart. To be re-used across the app.
18
+ * @param selectVariantId the variant id of the product's cartline.
19
+ * @param recordId the record id of the product's cartline to modify.
20
+ *
21
+ */
22
+ export default function useCart(
23
+ recordId: number,
24
+ selectVariantId?: number | undefined,
25
+ ) {
26
+ const { data: cart } = getCart.useData();
23
27
  const { mutate: deleteCartLine, isPending: deletePending } =
24
28
  useDeleteCartLine();
25
29
  const { mutate: updateCartLine, isPending: updatePending } =
@@ -28,10 +32,11 @@ export default function useCart({
28
32
 
29
33
  const loading = deletePending || updatePending || addPending;
30
34
 
31
- const handleCartAmountChange = (
32
- amount: number,
33
- currentCartLine?: CartLine,
34
- ) => {
35
+ const currentCartLine = cart?.CartLines?.find((item) => {
36
+ return item?.ProductId === (Number(selectVariantId) || recordId);
37
+ });
38
+
39
+ const handleCartAmountChange = (amount: number) => {
35
40
  if (amount === 0) {
36
41
  deleteCartLine({
37
42
  cartId: cart.Id,
@@ -78,5 +83,6 @@ export default function useCart({
78
83
  loading,
79
84
  handleCartAmountChange,
80
85
  handleAddToCart,
86
+ currentCartLine,
81
87
  };
82
88
  }
@@ -0,0 +1,138 @@
1
+ "use client";
2
+ // react and react-query
3
+ import { useReducer } from "react";
4
+ import { QueryClient, useQueryClient } from "@tanstack/react-query";
5
+
6
+ // Types
7
+ import { ProductDetails } from "@/api-manager/schemas/product.schema";
8
+ import { ProductDimensionValueInventoryAvailability } from "@msdyn365-commerce/retail-proxy";
9
+
10
+ // Data fetching
11
+ import getProductById from "@/api-manager/services/product/queries/get-product-by-id";
12
+ import getProductPrices from "@/api-manager/services/product/queries/get-product-prices";
13
+ import getProductAvailability from "@/api-manager/services/product/queries/get-product-availability";
14
+
15
+ // Define Types for Hook
16
+ export type SelectedDimensions = Record<
17
+ number,
18
+ ProductDimensionValueInventoryAvailability
19
+ >;
20
+
21
+ type VariantState = {
22
+ selectDimensions: SelectedDimensions;
23
+ selectedVariantRecordId: number | undefined;
24
+ };
25
+
26
+ type VariantAction = {
27
+ type: "SELECT_DIMENSION";
28
+ dimensionValue: ProductDimensionValueInventoryAvailability;
29
+ totalDimensions: number;
30
+ };
31
+
32
+ /**
33
+ * This Hook handles the product variant selection and updates the selected variant id
34
+ * based on the selected dimensions.
35
+ */
36
+ export default function useVariants(product: ProductDetails) {
37
+ const { DimensionValues } = product;
38
+ const queryClient = useQueryClient();
39
+ const [state, dispatch] = useReducer(variantReducer, {
40
+ selectDimensions: {},
41
+ selectedVariantRecordId: undefined,
42
+ });
43
+
44
+ // Query is disabled if no variant selected
45
+ const { data: selectedVariant, isLoading: variantPending } =
46
+ getProductById.useData({ id: state.selectedVariantRecordId });
47
+
48
+ const allDimensionsSelected =
49
+ Object.keys(state.selectDimensions).length === DimensionValues.length;
50
+
51
+ /**
52
+ * Adds selected dimension to the current selectDimensions state
53
+ * Updates the selectVariantId if all dimensions are selected
54
+ * @param dimensionValue dimension that was last changed to trigger this function
55
+ */
56
+ const handleSelectDimension = async (
57
+ dimensionValue: ProductDimensionValueInventoryAvailability,
58
+ ) => {
59
+ prefetchPDPData(dimensionValue, queryClient);
60
+ dispatch({
61
+ type: "SELECT_DIMENSION",
62
+ dimensionValue,
63
+ totalDimensions: DimensionValues.length,
64
+ });
65
+ };
66
+
67
+ return {
68
+ allDimensionsSelected,
69
+ handleChangeVariant: handleSelectDimension,
70
+ selectedVariant,
71
+ selectDimensions: state.selectDimensions,
72
+ variantPending,
73
+ };
74
+ }
75
+
76
+ /**
77
+ * To minimize loading time for the PDP dimensions.
78
+ */
79
+ const prefetchPDPData = (
80
+ dimensionValue: ProductDimensionValueInventoryAvailability,
81
+ queryClient: QueryClient,
82
+ ) => {
83
+ dimensionValue.ProductIds.map((id) => {
84
+ getProductById.prefetchData(queryClient, { id: id });
85
+ getProductPrices.prefetchData(queryClient, {
86
+ productIds: [id],
87
+ });
88
+
89
+ const shippingInventorySearchCriteria = {
90
+ searchCriteria: {
91
+ defaultWarehouseOnly: true,
92
+ productIds: [id],
93
+ },
94
+ };
95
+
96
+ getProductAvailability.prefetchData(
97
+ queryClient,
98
+ shippingInventorySearchCriteria,
99
+ );
100
+ });
101
+ };
102
+
103
+ /**
104
+ * Reducer synchronizes selected dimensions and variant ID
105
+ */
106
+ const variantReducer = (state: VariantState, action: VariantAction) => {
107
+ switch (action.type) {
108
+ case "SELECT_DIMENSION":
109
+ const newDimensionsState: SelectedDimensions = {
110
+ ...state.selectDimensions,
111
+ [action.dimensionValue?.DimensionTypeValue]: action.dimensionValue,
112
+ };
113
+
114
+ const allDimensionsSelected =
115
+ Object.keys(newDimensionsState).length === action.totalDimensions;
116
+
117
+ // We cannot select a variant until all dimensions are selected
118
+ if (!allDimensionsSelected)
119
+ return {
120
+ ...state,
121
+ selectDimensions: newDimensionsState,
122
+ selectedVariantRecordId: undefined,
123
+ };
124
+
125
+ const dimensionsArray = Object.values(newDimensionsState);
126
+
127
+ // Deduce product id from selected dimensions
128
+ const intersectedVariantIds = dimensionsArray.reduce((ids, dimension) => {
129
+ return ids.filter((id) => dimension.ProductIds?.includes(id));
130
+ }, dimensionsArray[0]?.ProductIds || []);
131
+
132
+ return {
133
+ ...state,
134
+ selectDimensions: newDimensionsState,
135
+ selectedVariantRecordId: intersectedVariantIds[0], // There can be only one!
136
+ };
137
+ }
138
+ };
@@ -3,6 +3,7 @@ import { PageSlug } from "./page-slugs";
3
3
  const buildDetailUrl = (name: string, id: number) =>
4
4
  `/${PageSlug.ProductDetail}/${normalizeName(name)}/${id}`;
5
5
 
6
- const normalizeName = (name: string) => name.toLowerCase().replace(/ /g, "-");
6
+ const normalizeName = (name: string) =>
7
+ name ? name.toLowerCase().replace(/ /g, "-") : "";
7
8
 
8
9
  export default buildDetailUrl;
@@ -0,0 +1,4 @@
1
+ # Pages V1 Folder
2
+
3
+ - Keeping this temporarily to maintain compatability for OLCC while we create the new component system
4
+ - OLCC will start moving over to components-v2 and pages-v2 and then we will remove this folder
@@ -25,7 +25,9 @@ import getProductAvailability from "@/api-manager/services/product/queries/get-p
25
25
 
26
26
  // LOCAL HOOKS
27
27
  import useVariants from "../../../hooks/use-variants";
28
- import useCart, { AddToCartBopisInput } from "@/hooks/use-cart";
28
+ import useCart, {
29
+ AddToCartBopisInput,
30
+ } from "@evenicanpm/storefront-core/src/hooks/use-cart";
29
31
 
30
32
  // LOCAL COMPONENTS
31
33
  import ProductDimensions from "@/_components/product-dimensions/product-dimensions";
@@ -54,37 +56,40 @@ export default function ProductIntro({ product, cart }: Props) {
54
56
 
55
57
  // HOOKS
56
58
  const {
57
- productVariant,
58
- selectVariantId,
59
+ selectedVariant,
59
60
  selectDimensions,
60
61
  handleChangeVariant,
61
62
  allDimensionsSelected,
62
- } = useVariants({ product });
63
+ } = useVariants(product);
63
64
 
64
- const { handleCartAmountChange, handleAddToCart, loading } = useCart({
65
- cart,
66
- selectVariantId,
67
- recordId: RecordId,
68
- });
65
+ const { handleCartAmountChange, handleAddToCart, loading } = useCart(
66
+ selectedVariant.RecordId,
67
+ RecordId,
68
+ );
69
69
 
70
70
  const { formatCurrency } = useCurrencyFormatter();
71
71
 
72
72
  const searchCriteria = useMemo<InventorySearchCriteriaInput>(
73
73
  () => ({
74
- allDimensionsSelected: allDimensionsSelected(selectDimensions),
74
+ allDimensionsSelected: allDimensionsSelected,
75
75
  searchCriteria: {
76
76
  defaultWarehouseOnly: true,
77
- productIds: [selectVariantId || RecordId],
77
+ productIds: [selectedVariant?.RecordId || RecordId],
78
78
  },
79
79
  }),
80
- [allDimensionsSelected, selectDimensions, selectVariantId, RecordId],
80
+ [
81
+ allDimensionsSelected,
82
+ selectDimensions,
83
+ selectedVariant?.RecordId,
84
+ RecordId,
85
+ ],
81
86
  );
82
87
 
83
88
  const { data: shippingInventoryData, isLoading: inventoryLoading } =
84
89
  getProductAvailability.useData(searchCriteria);
85
90
  // HELPERS
86
91
  const currentCartLine = cart?.CartLines?.find((item) => {
87
- return item?.ProductId === (Number(selectVariantId) || RecordId);
92
+ return item?.ProductId === (Number(selectedVariant?.RecordId) || RecordId);
88
93
  });
89
94
 
90
95
  const getInventoryLabel = (): string | null => {
@@ -100,7 +105,7 @@ export default function ProductIntro({ product, cart }: Props) {
100
105
 
101
106
  const shouldDisableAddToCart = () => {
102
107
  //TODO: Incorporate global inventory enabled flag.
103
- if (!allDimensionsSelected(selectDimensions)) {
108
+ if (!allDimensionsSelected) {
104
109
  return false; // Don't disable add to cart if dimensions are not selected, so clicking the button will provide an error message showing the user what to do.
105
110
  }
106
111
  const OOSCode = "OOS"; // Always means out of stock
@@ -120,8 +125,8 @@ export default function ProductIntro({ product, cart }: Props) {
120
125
  };
121
126
 
122
127
  const images =
123
- Array.isArray(productVariant?.Images) && productVariant.Images.length > 0
124
- ? productVariant.Images
128
+ Array.isArray(selectedVariant?.Images) && selectedVariant.Images.length > 0
129
+ ? selectedVariant.Images
125
130
  : Array.isArray(Images) && Images.length > 0
126
131
  ? Images
127
132
  : [];
@@ -136,7 +141,7 @@ export default function ProductIntro({ product, cart }: Props) {
136
141
  };
137
142
 
138
143
  const onAddToCart = (bopisInput?: AddToCartBopisInput) => {
139
- if (!allDimensionsSelected(selectDimensions)) {
144
+ if (!allDimensionsSelected) {
140
145
  setShowDimensionError(true);
141
146
  return;
142
147
  }
@@ -145,7 +150,7 @@ export default function ProductIntro({ product, cart }: Props) {
145
150
  };
146
151
 
147
152
  const shouldOpenHelperModal = () => {
148
- if (!allDimensionsSelected(selectDimensions)) {
153
+ if (!allDimensionsSelected) {
149
154
  setShowDimensionError(true);
150
155
  return false;
151
156
  }
@@ -160,9 +165,9 @@ export default function ProductIntro({ product, cart }: Props) {
160
165
  name={Name}
161
166
  selectedImageIndex={selectedImageIndex}
162
167
  primaryImageUrl={
163
- Array.isArray(productVariant?.Images) &&
164
- productVariant.Images.length > 0
165
- ? productVariant.Images[0]
168
+ Array.isArray(selectedVariant?.Images) &&
169
+ selectedVariant.Images.length > 0
170
+ ? selectedVariant.Images[0]
166
171
  : Array.isArray(Images) && Images.length > 0
167
172
  ? Images[0]
168
173
  : ""
@@ -178,7 +183,7 @@ export default function ProductIntro({ product, cart }: Props) {
178
183
 
179
184
  {/* PRODUCT BRAND */}
180
185
  <FlexBox alignItems="center" mb={1}>
181
- <H6>SKU: {productVariant?.ItemId || ItemId}</H6>
186
+ <H6>SKU: {selectedVariant?.ItemId || ItemId}</H6>
182
187
  </FlexBox>
183
188
 
184
189
  {/* PRODUCT RATING */}
@@ -232,10 +237,10 @@ export default function ProductIntro({ product, cart }: Props) {
232
237
  isOOS={shouldDisableAddToCart()}
233
238
  />
234
239
  <FindInStoreButton
235
- productId={selectVariantId || RecordId}
240
+ productId={selectedVariant?.RecordId || RecordId}
236
241
  canOpenModal={shouldOpenHelperModal}
237
242
  handleAddToCart={handleAddToCart}
238
- allDimensionsSelected={allDimensionsSelected(selectDimensions)}
243
+ allDimensionsSelected={allDimensionsSelected}
239
244
  />
240
245
  <AddToWishlistButton
241
246
  path="Account.Wishlists.btnAddToWishlist"