@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,81 @@
1
+ "use client";
2
+ import { ProductDimensionValueInventoryAvailability } from "@msdyn365-commerce/retail-proxy";
3
+ import React, { PropsWithChildren, ReactElement, createContext } from "react";
4
+ import { DimensionGroup } from "./dimensions-group";
5
+
6
+ /**
7
+ * @category Context
8
+ */
9
+ export interface DimensionsContext {
10
+ dimensionGroups: ProductDimensionValueInventoryAvailability[][];
11
+ selectDimensions: Record<number, ProductDimensionValueInventoryAvailability>;
12
+ handleChangeVariant: (
13
+ dimension: ProductDimensionValueInventoryAvailability,
14
+ ) => void;
15
+ showDimensionError?: boolean;
16
+ }
17
+
18
+ /**
19
+ * @internal
20
+ */
21
+ export const DimensionsContext = createContext<null | DimensionsContext>(null);
22
+
23
+ // TODO: When selecting a single dimension, loading spinner starts... not necessary, inefficient.
24
+
25
+ /**
26
+ * @category Props
27
+ */
28
+ export interface DimensionsProps extends PropsWithChildren<unknown> {
29
+ /** An doubly nested array of Dimensions */
30
+ dimensionGroups: ProductDimensionValueInventoryAvailability[][];
31
+ /** The currently selected dimension, identitfied with a numeric key */
32
+ selectDimensions: Record<number, ProductDimensionValueInventoryAvailability>;
33
+ /** Event handler that is called after the selected dimensions change */
34
+ handleChangeVariant: (
35
+ dimension: ProductDimensionValueInventoryAvailability,
36
+ ) => void;
37
+ /** Whether to show error, usually triggered when trying to add to cart before selecting all dimensions */
38
+ showDimensionError?: boolean;
39
+ }
40
+
41
+ /**
42
+ * The root level dimensions component. Provides dimensions context, insert dimension groups inside.
43
+ * @category Compound Component
44
+ * @example
45
+ * <ProductDimension
46
+ * dimensionGroups={dimensionGroups}
47
+ * selectDimensions={selectDimensions}
48
+ * handleChangeVariant={handleChangeVariant}
49
+ * showDimensionError={showDimensionError}
50
+ * >
51
+ * {dimensionGroups.map((group, i) => (
52
+ * <ProductDimension.Group dimensions={group} key={i}>
53
+ * <ProductDimension.Group.Label />
54
+ * <ProductDimension.Group.List />
55
+ * <ProductDimension.Group.Error />
56
+ * </ProductDimension.Group>
57
+ * ))}
58
+ * </ProductDimension>
59
+ */
60
+ export const Dimensions = ({
61
+ dimensionGroups,
62
+ selectDimensions,
63
+ handleChangeVariant,
64
+ showDimensionError,
65
+ children,
66
+ }: DimensionsProps): ReactElement => {
67
+ const contextValue = {
68
+ dimensionGroups,
69
+ selectDimensions,
70
+ handleChangeVariant,
71
+ showDimensionError,
72
+ };
73
+
74
+ return (
75
+ <DimensionsContext.Provider value={contextValue}>
76
+ {children}
77
+ </DimensionsContext.Provider>
78
+ );
79
+ };
80
+
81
+ Dimensions.Group = DimensionGroup;
@@ -0,0 +1,38 @@
1
+ "use client";
2
+ import { ProductDimensionValueInventoryAvailability } from "@msdyn365-commerce/retail-proxy";
3
+ import { Dimensions } from "./compound/dimensions";
4
+
5
+ // TODO: When selecting a single dimension, loading spinner starts... not necessary, inefficient.
6
+
7
+ export type Props = {
8
+ dimensionGroups: ProductDimensionValueInventoryAvailability[][];
9
+ selectDimensions: Record<number, ProductDimensionValueInventoryAvailability>;
10
+ handleChangeVariant: (
11
+ dimension: ProductDimensionValueInventoryAvailability,
12
+ ) => void;
13
+ showDimensionError?: boolean;
14
+ };
15
+
16
+ export default function ProductDimensions({
17
+ dimensionGroups,
18
+ selectDimensions,
19
+ handleChangeVariant,
20
+ showDimensionError,
21
+ }: Props) {
22
+ return (
23
+ <Dimensions
24
+ dimensionGroups={dimensionGroups}
25
+ selectDimensions={selectDimensions}
26
+ handleChangeVariant={handleChangeVariant}
27
+ showDimensionError={showDimensionError}
28
+ >
29
+ {dimensionGroups.map((group, i) => (
30
+ <Dimensions.Group dimensions={group} key={i}>
31
+ <Dimensions.Group.Label />
32
+ <Dimensions.Group.List />
33
+ <Dimensions.Group.Error />
34
+ </Dimensions.Group>
35
+ ))}
36
+ </Dimensions>
37
+ );
38
+ }
@@ -0,0 +1,20 @@
1
+ import { ProductDimensionValueInventoryAvailability } from "@msdyn365-commerce/retail-proxy";
2
+
3
+ /**
4
+ * Checks if dimension exists
5
+ * @param dimension
6
+ * @param selectDimensions
7
+ * @returns
8
+ */
9
+ export const hasSelectedDimension = (
10
+ dimension: ProductDimensionValueInventoryAvailability[],
11
+ selectDimensions: Record<number, ProductDimensionValueInventoryAvailability>,
12
+ ) => {
13
+ return dimension.some((dim) =>
14
+ Object.values(selectDimensions).some(
15
+ (selectedDimension) =>
16
+ selectedDimension.DimensionValue?.RecordId ===
17
+ dim.DimensionValue?.RecordId,
18
+ ),
19
+ );
20
+ };
@@ -0,0 +1,181 @@
1
+ /**
2
+ * @module ProductQuantityButtons
3
+ */
4
+ import React, { createContext, useContext, ReactNode, useMemo } from "react";
5
+ import { FlexBox } from "@evenicanpm/storefront-core/src/components-v2/flex-box";
6
+ import Button from "@mui/material/Button";
7
+ import { CartLine } from "@msdyn365-commerce/retail-proxy";
8
+ import { useTranslations } from "next-intl";
9
+ import { MdAdd as Add } from "react-icons/md";
10
+ import { MdRemove as Remove } from "react-icons/md";
11
+ import { H3 } from "@evenicanpm/storefront-core/src/components-v2/Typography";
12
+ import CircularProgress from "@mui/material/CircularProgress";
13
+ import useCart from "@evenicanpm/storefront-core/src/hooks/use-cart";
14
+ // TODO: Encapsulate the addToCart api calls inside this component
15
+ // so no need to pass in props.
16
+
17
+ /**
18
+ * @category Context
19
+ */
20
+ export interface QuantityContextType {
21
+ /** Loading state, usually triggered by mutating quantity */
22
+ loading: boolean;
23
+ /** Current quantity of the passed in cartline */
24
+ quantity: number;
25
+ /** Is the product out of stock? */
26
+ isOOS: boolean;
27
+ /** The cartline to display/mutate the quantity of */
28
+ productCartLine: CartLine;
29
+ /** Handler for when the quantity is changed via sub-component buttons */
30
+ handleCartAmountChange: (amount: number, currentCartLine: CartLine) => void;
31
+ }
32
+
33
+ /**
34
+ * @internal
35
+ */
36
+ export const QuantityContext = createContext<QuantityContextType | undefined>(
37
+ undefined,
38
+ );
39
+
40
+ /**
41
+ * @category Props
42
+ */
43
+ export interface QuantityButtonProps {
44
+ /** The cartline that this component will display the quantity of */
45
+ productId: number;
46
+ /** Is the item out of stock? */
47
+ isOOS?: boolean;
48
+ /** React children */
49
+ children?: ReactNode;
50
+ /** An optional custom handler for add to cart, if project needs to plug in logic */
51
+ customAddToCart?: () => void;
52
+ }
53
+
54
+ /**
55
+ * Quantity button component, takes quantity of a product, if it's zero
56
+ * will display an add to cart button, if it's not zero it will display the current
57
+ * quantity with small add and remove buttons on either side.
58
+ * @example
59
+ * <QuantityButtons {...props}>
60
+ * <QuantityButtons.Remove />
61
+ * <QuantityButtons.Quantity />
62
+ * <QuantityButtons.Add />
63
+ * </QuantityButtons>
64
+ *
65
+ * @category Compound Component
66
+ */
67
+ export function QuantityButtons({
68
+ productId,
69
+ isOOS = false,
70
+ customAddToCart,
71
+ children,
72
+ }: QuantityButtonProps) {
73
+ const t = useTranslations("productDetail");
74
+
75
+ const { handleAddToCart, handleCartAmountChange, loading, currentCartLine } =
76
+ useCart(productId);
77
+
78
+ if (!currentCartLine || currentCartLine?.Quantity === 0) {
79
+ return (
80
+ <Button
81
+ color="primary"
82
+ variant="contained"
83
+ onClick={() => {
84
+ customAddToCart ? customAddToCart() : handleAddToCart();
85
+ }}
86
+ disabled={isOOS}
87
+ >
88
+ {t("btnAddToCart")}
89
+ </Button>
90
+ );
91
+ }
92
+
93
+ const value: QuantityContextType = {
94
+ loading,
95
+ quantity: currentCartLine?.Quantity,
96
+ isOOS,
97
+ productCartLine: currentCartLine,
98
+ handleCartAmountChange,
99
+ };
100
+
101
+ return (
102
+ <QuantityContext.Provider value={value}>
103
+ <FlexBox alignItems="center">{children}</FlexBox>
104
+ </QuantityContext.Provider>
105
+ );
106
+ }
107
+
108
+ /**
109
+ * The remove/decrementor button that appears when the quantity is not 0
110
+ * @category Sub-Component
111
+ */
112
+ QuantityButtons.Remove = () => {
113
+ const { handleCartAmountChange, loading, productCartLine } =
114
+ useContext(QuantityContext);
115
+
116
+ return (
117
+ <Button
118
+ size="small"
119
+ sx={{ p: 1 }}
120
+ color="primary"
121
+ variant="outlined"
122
+ disabled={loading}
123
+ onClick={() =>
124
+ handleCartAmountChange(
125
+ (productCartLine?.Quantity || 0) - 1,
126
+ productCartLine,
127
+ )
128
+ }
129
+ >
130
+ <Remove fontSize="small" />
131
+ </Button>
132
+ );
133
+ };
134
+
135
+ /**
136
+ * The add/incrementor button that appears when the quantity is not 0
137
+ * @category Sub-Component
138
+ */
139
+ QuantityButtons.Add = () => {
140
+ const { handleCartAmountChange, loading, productCartLine } =
141
+ useContext(QuantityContext);
142
+
143
+ return (
144
+ <Button
145
+ size="small"
146
+ sx={{ p: 1 }}
147
+ color="primary"
148
+ variant="outlined"
149
+ disabled={loading}
150
+ onClick={() =>
151
+ handleCartAmountChange(
152
+ (productCartLine?.Quantity || 0) + 1,
153
+ productCartLine,
154
+ )
155
+ }
156
+ >
157
+ <Add fontSize="small" />
158
+ </Button>
159
+ );
160
+ };
161
+
162
+ /**
163
+ * The display component that shows the current quantity.
164
+ * @category Sub-Component
165
+ */
166
+ QuantityButtons.Quantity = () => {
167
+ const { loading, productCartLine } = useContext(QuantityContext);
168
+ return (
169
+ <H3
170
+ fontWeight="600"
171
+ mx={2.5}
172
+ sx={{ width: "20px", display: "flex", justifyContent: "center" }}
173
+ >
174
+ {loading ? (
175
+ <CircularProgress size={"10px"} />
176
+ ) : (
177
+ productCartLine?.Quantity.toString().padStart(2, "0")
178
+ )}
179
+ </H3>
180
+ );
181
+ };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @component
3
+ * @category Implementation component
4
+ */
5
+ import React from "react";
6
+ import { QuantityButtons } from "./compound/quantity-buttons-root";
7
+ import { QuantityButtonProps } from "./compound/quantity-buttons-root";
8
+
9
+ /**
10
+ * Pre-composed version of quantity buttons.
11
+ */
12
+ const ProductQuantityButtons = (props: QuantityButtonProps) => {
13
+ return (
14
+ <QuantityButtons {...props}>
15
+ <QuantityButtons.Remove />
16
+ <QuantityButtons.Quantity />
17
+ <QuantityButtons.Add />
18
+ </QuantityButtons>
19
+ );
20
+ };
21
+
22
+ export default ProductQuantityButtons;
@@ -0,0 +1,90 @@
1
+ "use client";
2
+ import { useState } from "react";
3
+ import Box from "@mui/material/Box";
4
+
5
+ // GLOBAL CUSTOM COMPONENTS
6
+ import QuantityButtons from "@evenicanpm/storefront-core/src/components-v2/product-quantity-buttons";
7
+ // API MANAGER
8
+ import { ProductDetails } from "@/api-manager/schemas/product.schema";
9
+ import getProductAvailability from "@/api-manager/services/product/queries/get-product-availability";
10
+
11
+ // LOCAL HOOKS
12
+ import useVariants from "@evenicanpm/storefront-core/src/hooks/use-variants";
13
+ import useCart, {
14
+ AddToCartBopisInput,
15
+ } from "@evenicanpm/storefront-core/src/hooks/use-cart";
16
+
17
+ // LOCAL COMPONENTS
18
+ import ProductDimensions from "@evenicanpm/storefront-core/src/components-v2/product-dimensions";
19
+
20
+ interface Props {
21
+ product: ProductDetails;
22
+ }
23
+
24
+ export default function QuantityVariantsSelect({ product }: Props) {
25
+ const [showDimensionError, setShowDimensionError] = useState(false);
26
+
27
+ const { DimensionValues, RecordId } = product;
28
+
29
+ const {
30
+ selectedVariant,
31
+ selectDimensions,
32
+ handleChangeVariant,
33
+ allDimensionsSelected,
34
+ } = useVariants(product);
35
+
36
+ const { handleAddToCart } = useCart(RecordId, selectedVariant.RecordId);
37
+
38
+ const searchCriteria = {
39
+ searchCriteria: {
40
+ defaultWarehouseOnly: true,
41
+ productIds: [selectedVariant?.RecordId || RecordId],
42
+ },
43
+ };
44
+
45
+ const { data: shippingInventoryData } =
46
+ getProductAvailability.useData(searchCriteria);
47
+
48
+ const addToCartDisabled = () => {
49
+ if (!allDimensionsSelected) {
50
+ 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.
51
+ }
52
+
53
+ const OOSCode = "OOS"; // Always means out of stock
54
+ const aggregate =
55
+ shippingInventoryData?.AggregatedProductInventoryAvailabilities &&
56
+ shippingInventoryData?.AggregatedProductInventoryAvailabilities[0];
57
+
58
+ if (aggregate) {
59
+ const { TotalAvailableInventoryLevelCode } = aggregate;
60
+ return TotalAvailableInventoryLevelCode === OOSCode;
61
+ }
62
+
63
+ return true;
64
+ };
65
+
66
+ const onAddToCart = (bopisInput?: AddToCartBopisInput) => {
67
+ if (!allDimensionsSelected) {
68
+ setShowDimensionError(true);
69
+ return;
70
+ }
71
+ setShowDimensionError(false);
72
+ handleAddToCart(bopisInput);
73
+ };
74
+
75
+ return (
76
+ <Box width="100%">
77
+ <ProductDimensions
78
+ dimensionGroups={DimensionValues}
79
+ selectDimensions={selectDimensions}
80
+ handleChangeVariant={handleChangeVariant}
81
+ showDimensionError={showDimensionError}
82
+ />
83
+ <QuantityButtons
84
+ customAddToCart={onAddToCart}
85
+ isOOS={addToCartDisabled()}
86
+ productId={selectedVariant?.RecordId}
87
+ />
88
+ </Box>
89
+ );
90
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @module ProductsView
3
+ */
4
+ import { createContext } from "react";
5
+ // DATA MODEL
6
+ import { ProductSearchResult as Product } from "@msdyn365-commerce/retail-proxy";
7
+ import { ProductPrice } from "@/api-manager/schemas/product.schema";
8
+
9
+ /**
10
+ * Shared context value for the products list passed into root component.
11
+ * @category Context
12
+ */
13
+ export interface ProductsViewContext {
14
+ /** List of products to display */
15
+ products: Product[];
16
+ /** Array of product pricing */
17
+ productPrices?: ProductPrice[];
18
+ }
19
+
20
+ /**
21
+ * @internal
22
+ */
23
+ export const ProductsViewContext = createContext<null | ProductsViewContext>(
24
+ null,
25
+ );
@@ -0,0 +1,109 @@
1
+ /**
2
+ * @module ProductsView
3
+ */
4
+ import React, { useContext, cloneElement } from "react";
5
+ import Grid from "@mui/material/Grid2";
6
+ // GLOBAL CUSTOM COMPONENTS
7
+ import { FlexBetween } from "@evenicanpm/storefront-core/src/components-v2/flex-box/index";
8
+ import ProductCardPlp from "@evenicanpm/storefront-core/src/components-v2/product-cards/product-card-plp/product-card";
9
+ // DATA MODEL
10
+ import { ProductSearchResult as Product } from "@msdyn365-commerce/retail-proxy";
11
+ import { ProductPrice } from "@/api-manager/schemas/product.schema";
12
+ import { ProductsViewContext } from "./context";
13
+ import { ProductsViewProps } from "./types";
14
+
15
+ /**
16
+ * Root component of products grid view.
17
+ * @category Compound Component
18
+ * @example
19
+ * <ProductsGridView products={products} productPrices={prices}>
20
+ * <ProductsGridView.Container>
21
+ * <ProductsGridView.Grid>
22
+ * <ProductsGridView.Card />
23
+ * </ProductsGridView.Grid>
24
+ * </ProductsGridView.Container>
25
+ * </ProductsGridView>
26
+ */
27
+ export default function ProductsGridView(props: ProductsViewProps) {
28
+ const { products, productPrices, pagination, children } = props;
29
+
30
+ return (
31
+ <ProductsViewContext.Provider value={{ products, productPrices }}>
32
+ <Grid container spacing={3}>
33
+ {children}
34
+ </Grid>
35
+ <FlexBetween flexWrap="wrap" mt={6}>
36
+ {pagination}
37
+ </FlexBetween>
38
+ </ProductsViewContext.Provider>
39
+ );
40
+ }
41
+
42
+ /**
43
+ *
44
+ * Grid that handles rendering the list of component and passing
45
+ * product and pricing props to individual items.
46
+ * @category Sub-Component
47
+ *
48
+ */
49
+ ProductsGridView.Grid = ({ children }: { children: React.ReactElement }) => {
50
+ const { products, productPrices } = useContext(ProductsViewContext);
51
+ return (
52
+ <>
53
+ {products.map((item: Product, i) => {
54
+ const matchingPrice = productPrices?.find(
55
+ (price) => price.ProductId === item.RecordId,
56
+ );
57
+ // Legacy API, consider alternatives.
58
+ // Using this to pass props to child.
59
+ return cloneElement(children, {
60
+ key: i,
61
+ product: item,
62
+ price: matchingPrice,
63
+ });
64
+ })}
65
+ </>
66
+ );
67
+ };
68
+
69
+ /**
70
+ * @category Props
71
+ */
72
+ export interface ProductCardProps {
73
+ product?: Product;
74
+ price?: ProductPrice;
75
+ }
76
+
77
+ /**
78
+ * Individual product card component displayed in the grid.
79
+ * @param props.item The product data to render.
80
+ * @param props.price The product price data.
81
+ * @category Sub-Component
82
+ */
83
+ ProductsGridView.Card = ({ product, price }: ProductCardProps) => {
84
+ return (
85
+ <Grid size={{ lg: 4, sm: 6, xs: 12 }} key={product.ItemId}>
86
+ <ProductCardPlp
87
+ key={product.RecordId}
88
+ product={{
89
+ title: product.Name ?? "",
90
+ slug: product.ItemId ?? "",
91
+ price: price?.CustomerContextualPrice ?? 0,
92
+ imgUrl: product.PrimaryImageUrl ?? "",
93
+ rating: product.TotalRatings ?? 0,
94
+ discount: 0, // Need to get discount info for product.
95
+ id: product.RecordId,
96
+ }}
97
+ >
98
+ <ProductCardPlp.Image />
99
+ <ProductCardPlp.Body>
100
+ <ProductCardPlp.Info>
101
+ <ProductCardPlp.Title />
102
+ <ProductCardPlp.Rating />
103
+ <ProductCardPlp.Price />
104
+ </ProductCardPlp.Info>
105
+ </ProductCardPlp.Body>
106
+ </ProductCardPlp>
107
+ </Grid>
108
+ );
109
+ };
@@ -0,0 +1,98 @@
1
+ /**
2
+ * @module ProductsView
3
+ */
4
+ import { useContext, cloneElement } from "react";
5
+ // GLOBAL CUSTOM COMPONENTS
6
+ import FlexBetween from "@evenicanpm/storefront-core/src/components-v2/flex-box/flex-between";
7
+ import { ProductCardPlpList } from "@evenicanpm/storefront-core/src/components-v2/product-cards/product-card-plp-list/index";
8
+ import { ProductPrice } from "@/api-manager/schemas/product.schema";
9
+ // DATA MODEL
10
+ import { ProductSearchResult as Product } from "@msdyn365-commerce/retail-proxy";
11
+ import { ProductsViewContext } from "./context";
12
+ import { ProductsViewProps } from "./types";
13
+
14
+ /**
15
+ * Root component of the ProductsListView.
16
+ */
17
+ export default function ProductsListView(props: ProductsViewProps) {
18
+ const { pagination, products, productPrices, children } = props;
19
+
20
+ return (
21
+ <ProductsViewContext.Provider value={{ products, productPrices }}>
22
+ {children}
23
+ <FlexBetween flexWrap="wrap" mt={4}>
24
+ {pagination}
25
+ </FlexBetween>
26
+ </ProductsViewContext.Provider>
27
+ );
28
+ }
29
+
30
+ /**
31
+ *
32
+ * Grid that handles rendering the list of component and passing
33
+ * product and pricing props to individual items.
34
+ * @category Sub-Component
35
+ *
36
+ */
37
+ ProductsListView.List = ({ children }: { children: React.ReactElement }) => {
38
+ const { products, productPrices } = useContext(ProductsViewContext);
39
+ return (
40
+ <>
41
+ {products.map((item: Product, i) => {
42
+ const matchingPrice = productPrices?.find(
43
+ (price) => price.ProductId === item.RecordId,
44
+ );
45
+ // Legacy API, consider alternatives.
46
+ // Using this to pass props to child.
47
+ return cloneElement(children, {
48
+ key: i,
49
+ product: item,
50
+ price: matchingPrice,
51
+ });
52
+ })}
53
+ </>
54
+ );
55
+ };
56
+
57
+ /**
58
+ * @category Props
59
+ */
60
+ export interface ProductCardProps {
61
+ product?: Product;
62
+ price?: ProductPrice;
63
+ }
64
+
65
+ /**
66
+ * Individual product card component displayed in the grid.
67
+ * @param props.item The product data to render.
68
+ * @param props.price The product price data.
69
+ * @category Sub-Component
70
+ */
71
+ ProductsListView.Card = ({ product, price }: ProductCardProps) => {
72
+ return (
73
+ <ProductCardPlpList
74
+ key={product.RecordId}
75
+ product={{
76
+ id: product.RecordId,
77
+ title: product.Name ?? "",
78
+ slug: product.ItemId ?? "",
79
+ price: price?.CustomerContextualPrice ?? 0,
80
+ imgUrl: product.PrimaryImageUrl ?? "",
81
+ rating: product.TotalRatings ?? 0,
82
+ discount: 0, // Need to get discount info for product.,
83
+ //tags: ["Bike", "Motor", "Ducati"], // Example tags
84
+ }}
85
+ >
86
+ <ProductCardPlpList.Body>
87
+ <ProductCardPlpList.Image />
88
+ <ProductCardPlpList.Content>
89
+ <ProductCardPlpList.Info>
90
+ <ProductCardPlpList.Title />
91
+ <ProductCardPlpList.Price />
92
+ <ProductCardPlpList.Rating />
93
+ </ProductCardPlpList.Info>
94
+ </ProductCardPlpList.Content>
95
+ </ProductCardPlpList.Body>
96
+ </ProductCardPlpList>
97
+ );
98
+ };
@@ -0,0 +1,12 @@
1
+ import { ProductsViewContext } from "./context";
2
+ import { PropsWithChildren, ReactNode } from "react";
3
+
4
+ /**
5
+ * This prop type is used for both the ProductsViewGrid and the ProductsViewList.
6
+ * @category Props
7
+ */
8
+ export interface ProductsViewProps
9
+ extends ProductsViewContext,
10
+ PropsWithChildren {
11
+ pagination?: ReactNode;
12
+ }