@evenicanpm/storefront-core 1.0.5 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (307) hide show
  1. package/.storybook/main.ts +37 -0
  2. package/.storybook/preview.ts +14 -0
  3. package/README.md +17 -2
  4. package/__mocks__/next-font.js +4 -0
  5. package/package.json +19 -13
  6. package/src/api-manager/datasources/e4/graphqlRequestSdk.ts +265 -5
  7. package/src/api-manager/schemas/product.schema.ts +2 -2
  8. package/src/api-manager/services/cart/mutations/add-discount-code.ts +11 -0
  9. package/src/api-manager/services/cart/mutations/checkout.ts +1 -1
  10. package/src/api-manager/services/create-query.ts +11 -4
  11. package/src/api-manager/services/product/queries/get-product-availability.ts +1 -2
  12. package/src/api-manager/services/user/mutations/add-to-wishlist.ts +2 -2
  13. package/src/api-manager/services/user/mutations/copy-cart-to-wishlist.ts +2 -1
  14. package/src/api-manager/services/user/mutations/remove-from-wishlist.ts +4 -4
  15. package/src/api-manager/services/user/mutations/update-wishlist.ts +2 -1
  16. package/src/api-manager/services/user/queries/get-wishlist-details.ts +2 -2
  17. package/src/cms/blocks/components/product-carousel/index.tsx +6 -3
  18. package/src/cms/blocks/components/product-section-fullwidth/index.tsx +2 -2
  19. package/src/cms/blocks/components/shared/product-grid.tsx +5 -2
  20. package/src/cms/interfaces/navigation.ts +9 -9
  21. package/src/components/Blocks/Components/CategoryCarousel/index.tsx +3 -3
  22. package/src/components/Blocks/Components/HeroCarousel/index.tsx +2 -2
  23. package/src/components/Blocks/Components/ProductCarousel/index.tsx +5 -5
  24. package/src/components/Blocks/Components/ProductSectionFullWidth/index.tsx +6 -6
  25. package/src/components/Blocks/Components/Services/service-card.tsx +4 -1
  26. package/src/components/Blocks/Components/shared/featured-product-card.tsx +2 -2
  27. package/src/components/Blocks/Components/shared/product-category-item.tsx +3 -3
  28. package/src/components/Blocks/Components/shared/product-grid.tsx +2 -2
  29. package/src/components/Blocks/Components/shared/top-categories-card.tsx +1 -1
  30. package/src/components/Blocks/Components/shared/top-rating-product-card.tsx +6 -3
  31. package/src/components/Footer/sections/FooterAppStore.tsx +1 -1
  32. package/src/components/Footer/sections/FooterContact.tsx +1 -1
  33. package/src/components/Footer/sections/FooterLogo.tsx +2 -2
  34. package/src/components/Footer/sections/FooterSocialLinks.tsx +1 -1
  35. package/src/components/_components/MiniCartClient.tsx +2 -2
  36. package/src/components/_components/accordion/accordion-header.tsx +1 -1
  37. package/src/components/_components/carousel-cards/carousel-card-1/carousel-card-1.tsx +2 -2
  38. package/src/components/_components/carousel-cards/carousel-card-2/carousel-card-2.tsx +9 -4
  39. package/src/components/_components/carousel-cards/carousel-card-3/carousel-card-3.tsx +6 -3
  40. package/src/components/_components/carousel-cards/carousel-card-4/carousel-card-4.tsx +6 -1
  41. package/src/components/_components/categories/category-list/category-list.tsx +3 -3
  42. package/src/components/_components/categories/mega-menu/banner.tsx +7 -3
  43. package/src/components/_components/categories/mega-menu/column-list.tsx +3 -3
  44. package/src/components/_components/categories/mega-menu/mega-menu-1.tsx +2 -2
  45. package/src/components/_components/category-cards/category-card-1/category-card-1.tsx +2 -2
  46. package/src/components/_components/countdown/count-box.tsx +4 -1
  47. package/src/components/_components/countdown/count-down.tsx +1 -1
  48. package/src/components/_components/data-table/table-header.tsx +1 -1
  49. package/src/components/_components/footer/components/app-store.tsx +1 -1
  50. package/src/components/_components/footer/components/logo.tsx +2 -2
  51. package/src/components/_components/footer/components/social-links.tsx +1 -1
  52. package/src/components/_components/footer/footer-1.tsx +1 -1
  53. package/src/components/_components/footer/footer-2.tsx +2 -2
  54. package/src/components/_components/footer/footer-3.tsx +2 -2
  55. package/src/components/_components/footer/footer-4.tsx +3 -3
  56. package/src/components/_components/header/components/categories-menu.tsx +3 -3
  57. package/src/components/_components/header/components/mobile-header.tsx +9 -6
  58. package/src/components/_components/header/components/user.tsx +5 -5
  59. package/src/components/_components/header/header.tsx +2 -2
  60. package/src/components/_components/header/sticky-header.tsx +3 -3
  61. package/src/components/_components/mini-cart/components/cart-item.tsx +5 -2
  62. package/src/components/_components/mini-cart/components/empty-view.tsx +2 -2
  63. package/src/components/_components/mini-cart/components/top-header.tsx +5 -2
  64. package/src/components/_components/mini-cart/mini-cart.tsx +3 -3
  65. package/src/components/_components/mobile-navigation/mobile-navigation-bar.tsx +5 -5
  66. package/src/components/_components/nav-link/nav-link-2.tsx +1 -1
  67. package/src/components/_components/nav-link/nav-link-3.tsx +1 -1
  68. package/src/components/_components/navbar/categories.tsx +3 -3
  69. package/src/components/_components/navbar/category-based-menu/category-based-menu.tsx +1 -1
  70. package/src/components/_components/navbar/category-based-menu/components/child-categories.tsx +2 -2
  71. package/src/components/_components/navbar/mega-menu/category-list.tsx +1 -1
  72. package/src/components/_components/navbar/mega-menu/mega-menu.tsx +1 -1
  73. package/src/components/_components/navbar/mobile-menu/mobile-menu.tsx +2 -2
  74. package/src/components/_components/navbar/mobile-menu/render-levels.tsx +3 -3
  75. package/src/components/_components/navbar/nav-list/nav-item-child.tsx +3 -3
  76. package/src/components/_components/navbar/nav-list/nav-list.tsx +4 -4
  77. package/src/components/_components/newsletter/newsletter.tsx +5 -1
  78. package/src/components/_components/newsletter/social-icons.tsx +1 -1
  79. package/src/components/_components/page-sidenav/grocery-side-nav/components/link-item.tsx +2 -2
  80. package/src/components/_components/page-sidenav/grocery-side-nav/components/list-item.tsx +2 -2
  81. package/src/components/_components/page-sidenav/grocery-side-nav/components/nav-accordion.tsx +2 -2
  82. package/src/components/_components/page-sidenav/grocery-side-nav/grocery-side-nav.tsx +3 -3
  83. package/src/components/_components/page-sidenav/health-beauty-side-nav/components/list-item.tsx +2 -2
  84. package/src/components/_components/page-sidenav/health-beauty-side-nav/components/nav-accordion.tsx +2 -2
  85. package/src/components/_components/page-sidenav/health-beauty-side-nav/components/render-child.tsx +2 -2
  86. package/src/components/_components/page-sidenav/health-beauty-side-nav/health-beauty-side-nav.tsx +5 -5
  87. package/src/components/_components/page-sidenav/side-navbar/components/list-item.tsx +1 -1
  88. package/src/components/_components/page-sidenav/side-navbar/components/nav-accordion.tsx +3 -3
  89. package/src/components/_components/page-sidenav/side-navbar/components/render-child.tsx +1 -1
  90. package/src/components/_components/page-sidenav/side-navbar/side-nav-bar.tsx +4 -4
  91. package/src/components/_components/page-sidenav/side-navbar-2/components/sidebar-accordion.tsx +1 -1
  92. package/src/components/_components/page-sidenav/side-navbar-2/side-navbar-2.tsx +2 -2
  93. package/src/components/_components/product-cards/product-card-1/components/quantity-buttons.tsx +2 -2
  94. package/src/components/_components/product-cards/product-card-1/product-card.tsx +2 -2
  95. package/src/components/_components/product-cards/product-card-10/product-card.tsx +9 -5
  96. package/src/components/_components/product-cards/product-card-11/product-card.tsx +6 -3
  97. package/src/components/_components/product-cards/product-card-12/product-card.tsx +4 -4
  98. package/src/components/_components/product-cards/product-card-13/product-card.tsx +6 -3
  99. package/src/components/_components/product-cards/product-card-14/product-card.tsx +7 -4
  100. package/src/components/_components/product-cards/product-card-15/product-card.tsx +6 -3
  101. package/src/components/_components/product-cards/product-card-16/components/quantity-buttons.tsx +2 -2
  102. package/src/components/_components/product-cards/product-card-16/product-card.tsx +5 -2
  103. package/src/components/_components/product-cards/product-card-2/components/product-price.tsx +2 -2
  104. package/src/components/_components/product-cards/product-card-2/product-card.tsx +4 -4
  105. package/src/components/_components/product-cards/product-card-3/components/hover-actions.tsx +1 -1
  106. package/src/components/_components/product-cards/product-card-3/product-card.tsx +2 -2
  107. package/src/components/_components/product-cards/product-card-4/components/hover-actions.tsx +1 -1
  108. package/src/components/_components/product-cards/product-card-4/product-card.tsx +2 -2
  109. package/src/components/_components/product-cards/product-card-5/components/hover-actions.tsx +1 -1
  110. package/src/components/_components/product-cards/product-card-5/product-card.tsx +2 -2
  111. package/src/components/_components/product-cards/product-card-6/components/hover-actions.tsx +1 -1
  112. package/src/components/_components/product-cards/product-card-6/product-card.tsx +3 -3
  113. package/src/components/_components/product-cards/product-card-7/components/quantity-buttons.tsx +2 -2
  114. package/src/components/_components/product-cards/product-card-7/product-card.tsx +5 -2
  115. package/src/components/_components/product-cards/product-card-8/product-card.tsx +9 -5
  116. package/src/components/_components/product-cards/product-card-9/components/add-to-cart.tsx +5 -2
  117. package/src/components/_components/product-cards/product-card-9/product-card.tsx +1 -1
  118. package/src/components/_components/product-cards/product-price.tsx +2 -2
  119. package/src/components/_components/product-cards/product-rating.tsx +2 -2
  120. package/src/components/_components/product-cards/product-title.tsx +1 -1
  121. package/src/components/_components/product-cards/use-product.ts +1 -1
  122. package/src/components/_components/product-dimensions/product-dimensions.tsx +1 -1
  123. package/src/components/_components/product-quantity-buttons/product-quantity-buttons.tsx +2 -2
  124. package/src/components/_components/products-view/products-grid-view.tsx +2 -2
  125. package/src/components/_components/products-view/products-list-view.tsx +2 -2
  126. package/src/components/_components/search-box/components/category-dropdown.tsx +1 -1
  127. package/src/components/_components/search-box/components/search-result.tsx +1 -1
  128. package/src/components/_components/search-box/hooks/use-search.ts +1 -1
  129. package/src/components/_components/search-box/search-input-category.tsx +3 -3
  130. package/src/components/_components/service-cards/service-card-1/service-card-1.tsx +5 -2
  131. package/src/components/_components/service-cards/service-card-2/service-card-2.tsx +5 -2
  132. package/src/components/_components/service-cards/service-card-3/service-card-3.tsx +4 -1
  133. package/src/components/_components/settings/setting.tsx +3 -3
  134. package/src/components/_components/side-nav/side-nav.tsx +1 -1
  135. package/src/components/_components/stories/story-content/story-content.tsx +1 -1
  136. package/src/components/_components/stories/story-item/story-item.tsx +1 -1
  137. package/src/components/_components/topbar/top-bar.tsx +6 -3
  138. package/src/components/_components/wishlist-modal/wishlist-modal-item.tsx +1 -1
  139. package/src/components-v2/accordion/accordion-header.stories.tsx +28 -0
  140. package/src/components-v2/categories/category-list/category-list.tsx +2 -2
  141. package/src/components-v2/categories/category-list/styles.ts +3 -2
  142. package/src/components-v2/categories/mega-menu/column-list.tsx +1 -1
  143. package/src/components-v2/categories/mega-menu/mega-menu-1.tsx +6 -3
  144. package/src/components-v2/categories/mega-menu/mega-menu-2.tsx +2 -2
  145. package/src/components-v2/header/__tests__/user.test.tsx +12 -12
  146. package/src/components-v2/header/components/user.tsx +12 -11
  147. package/src/components-v2/mini-cart/mini-cart.tsx +9 -14
  148. package/src/components-v2/mobile-navigation/mobile-navigation-bar.tsx +1 -1
  149. package/src/components-v2/navbar/mobile-menu/mobile-menu.tsx +2 -2
  150. package/src/components-v2/product-cards/favorite-button.tsx +52 -0
  151. package/src/components-v2/product-cards/product-card/product-card.tsx +87 -47
  152. package/src/components-v2/product-cards/product-card-plp/product-card.tsx +140 -51
  153. package/src/components-v2/product-cards/product-card-plp/styles/index.ts +17 -0
  154. package/src/components-v2/product-cards/product-card-plp-list/product-card.tsx +76 -42
  155. package/src/components-v2/product-cards/product-card-search/product-card.tsx +50 -21
  156. package/src/components-v2/product-cards/product-card-search/styles/index.ts +0 -10
  157. package/src/components-v2/product-dialog/compound/product-dialog.tsx +39 -15
  158. package/src/components-v2/product-quantity-buttons/compound/quantity-buttons-root.tsx +22 -7
  159. package/src/components-v2/product-quantity-variants/index.tsx +1 -1
  160. package/src/components-v2/products-view/compound/context.ts +46 -1
  161. package/src/components-v2/products-view/compound/products-grid-view.tsx +23 -14
  162. package/src/components-v2/products-view/compound/products-list-view.tsx +12 -3
  163. package/src/components-v2/search-bar/compound/context.ts +24 -3
  164. package/src/components-v2/search-bar/compound/results-item-lg.tsx +14 -13
  165. package/src/components-v2/search-bar/compound/results-item-sm.tsx +5 -5
  166. package/src/components-v2/search-bar/compound/results-suspense.tsx +3 -3
  167. package/src/components-v2/search-bar/compound/results.tsx +4 -4
  168. package/src/components-v2/search-bar/compound/textfield-adornment-category.tsx +1 -1
  169. package/src/components-v2/search-bar/compound/textfield.tsx +3 -3
  170. package/src/components-v2/search-bar/hooks/use-click-outside.ts +1 -1
  171. package/src/components-v2/wishlist-dialogs/add-to-wishlist/add-to-wishlist-button.tsx +2 -6
  172. package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-bottom-ui.tsx +6 -1
  173. package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-dialog.tsx +22 -15
  174. package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-list.tsx +8 -7
  175. package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/context.ts +8 -8
  176. package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/wishlist-dialog-item.tsx +29 -19
  177. package/src/components-v2/wishlist-dialogs/add-to-wishlist/hooks/use-add-to-wishlist.ts +27 -77
  178. package/src/components-v2/wishlist-dialogs/add-to-wishlist/index.tsx +1 -9
  179. package/src/components-v2/wishlist-dialogs/create-wishlist/compound/create-wishlist-bottom-ui.tsx +7 -2
  180. package/src/components-v2/wishlist-dialogs/create-wishlist/compound/create-wishlist-dialog.tsx +20 -12
  181. package/src/components-v2/wishlist-dialogs/create-wishlist/compound/create-wishlist-form.tsx +25 -5
  182. package/src/hooks/use-cart.ts +11 -14
  183. package/src/hooks/use-favorite.ts +17 -0
  184. package/src/hooks/use-variants.ts +4 -3
  185. package/src/pages/account/addresses/address-item.tsx +1 -1
  186. package/src/pages/account/dashboard-header.tsx +3 -3
  187. package/src/pages/account/navigation.tsx +5 -2
  188. package/src/pages/account/no-records.tsx +1 -1
  189. package/src/pages/account/orders/order-progress.tsx +5 -2
  190. package/src/pages/account/orders/order-row.tsx +4 -1
  191. package/src/pages/account/orders/order-summary.tsx +6 -2
  192. package/src/pages/account/orders/ordered-products.tsx +9 -2
  193. package/src/pages/account/profile/user-info.tsx +5 -2
  194. package/src/pages/account/wishlist/create-new-list.tsx +1 -1
  195. package/src/pages/account/wishlist/wishlist-item.tsx +2 -2
  196. package/src/pages/checkout/checkout-alt-form/address-card.tsx +5 -2
  197. package/src/pages/checkout/checkout-alt-form/checkout-step.tsx +3 -3
  198. package/src/pages/checkout/checkout-alt-form/customer-information.tsx +1 -1
  199. package/src/pages/checkout/checkout-alt-form/delivery-address.tsx +5 -1
  200. package/src/pages/checkout/checkout-alt-form/delivery-options.tsx +6 -2
  201. package/src/pages/checkout/checkout-alt-form/edit-address-form.tsx +1 -1
  202. package/src/pages/checkout/checkout-alt-form/heading.tsx +2 -2
  203. package/src/pages/checkout/checkout-alt-form/new-address-form.tsx +9 -4
  204. package/src/pages/checkout/checkout-alt-form/payment-details.tsx +6 -3
  205. package/src/pages/checkout/checkout-alt-summary/cart-item.tsx +5 -2
  206. package/src/pages/checkout/checkout-alt-summary/checkout-alt-summary.tsx +4 -2
  207. package/src/pages/checkout/checkout-alt-summary/list-item.tsx +2 -2
  208. package/src/pages/confirmation/address.tsx +4 -1
  209. package/src/pages/confirmation/confirmation-summary.tsx +6 -3
  210. package/src/pages/confirmation/ordered-products.tsx +9 -2
  211. package/src/pages/product-details/available-shops.tsx +5 -2
  212. package/src/pages/product-details/bopis/find-in-store-modal.tsx +1 -1
  213. package/src/pages/product-details/bopis/pickup-option-select.tsx +1 -1
  214. package/src/pages/product-details/frequently-bought.tsx +9 -2
  215. package/src/pages/product-details/frequently-product-card.tsx +8 -5
  216. package/src/pages/product-details/product-comment.tsx +7 -2
  217. package/src/pages/product-details/product-description.tsx +1 -1
  218. package/src/pages/product-details/product-filter-card.tsx +11 -3
  219. package/src/pages/product-details/product-intro/product-intro-images.tsx +4 -1
  220. package/src/pages/product-details/product-intro/product-intro.tsx +8 -5
  221. package/src/pages/product-details/product-review.tsx +5 -2
  222. package/src/pages/product-details/related-products.tsx +2 -2
  223. package/src/pages/product-list/facet-group.tsx +1 -1
  224. package/src/pages/product-list/list-filter.tsx +5 -2
  225. package/src/pages/product-list/pagination.tsx +1 -1
  226. package/src/pages/product-list/quick-view-dialog-content.tsx +2 -2
  227. package/src/pages/product-list/selected-facets.tsx +1 -1
  228. package/src/pages/quickorder/order-upload.tsx +1 -1
  229. package/src/pages/quickorder/quick-order-form.tsx +6 -3
  230. package/src/pages/quickorder/quick-order-row.tsx +1 -1
  231. package/src/pages-v2/account/account-navigation.tsx +1 -1
  232. package/src/pages-v2/account/orders/order-summary.tsx +5 -2
  233. package/src/pages-v2/account/profile/user-info.tsx +6 -3
  234. package/src/pages-v2/account/wishlist/wishlist-item.tsx +1 -1
  235. package/src/pages-v2/cart/__tests__/checkout-form.test.tsx +1 -1
  236. package/src/pages-v2/cart/estimate-shipping.tsx +3 -0
  237. package/src/pages-v2/checkout/checkout-alt-form/checkout-step.tsx +4 -4
  238. package/src/pages-v2/checkout/checkout-alt-form/steps/address/address-card.tsx +1 -1
  239. package/src/pages-v2/checkout/checkout-alt-form/steps/address/delivery-address.tsx +12 -5
  240. package/src/pages-v2/checkout/checkout-alt-form/steps/address/new-address-form.tsx +27 -5
  241. package/src/pages-v2/checkout/checkout-alt-form/steps/address/styles.ts +2 -1
  242. package/src/pages-v2/checkout/checkout-alt-form/steps/customer-info/customer-information.tsx +27 -7
  243. package/src/pages-v2/checkout/checkout-alt-form/steps/shipping/delivery-options.tsx +8 -1
  244. package/src/pages-v2/confirmation/address.tsx +5 -1
  245. package/src/pages-v2/product-details/available-shops.tsx +4 -1
  246. package/src/pages-v2/product-details/bopis/find-in-store-button.tsx +1 -1
  247. package/src/pages-v2/product-details/bopis/find-in-store-modal.tsx +3 -5
  248. package/src/pages-v2/product-details/product-intro/compound/context.ts +69 -12
  249. package/src/pages-v2/product-details/product-intro/compound/product-info.tsx +73 -27
  250. package/src/pages-v2/product-details/product-intro/compound/product-intro-images.tsx +19 -6
  251. package/src/pages-v2/product-details/product-intro/utils.ts +2 -2
  252. package/src/pages-v2/product-details/product-tabs.tsx +19 -4
  253. package/src/pages-v2/product-details/related-products.tsx +3 -3
  254. package/src/pages-v2/quickorder/context.ts +2 -2
  255. package/src/pages-v2/quickorder/order-upload.tsx +6 -2
  256. package/src/pages-v2/quickorder/provider.tsx +24 -9
  257. package/src/pages-v2/quickorder/quick-order-actions.tsx +2 -2
  258. package/src/pages-v2/quickorder/quick-order-header.tsx +6 -3
  259. package/src/pages-v2/quickorder/quick-order-row.tsx +1 -1
  260. package/src/pages-v2/quickorder/quick-order-table.tsx +10 -4
  261. package/src/pages-v2/quickorder/quick-order-upload.tsx +2 -2
  262. package/src/stories/Button.stories.ts +54 -0
  263. package/src/stories/Button.tsx +35 -0
  264. package/src/stories/Configure.mdx +364 -0
  265. package/src/stories/Header.stories.ts +34 -0
  266. package/src/stories/Header.tsx +54 -0
  267. package/src/stories/Page.stories.ts +33 -0
  268. package/src/stories/Page.tsx +73 -0
  269. package/src/stories/assets/accessibility.png +0 -0
  270. package/src/stories/assets/accessibility.svg +1 -0
  271. package/src/stories/assets/addon-library.png +0 -0
  272. package/src/stories/assets/assets.png +0 -0
  273. package/src/stories/assets/avif-test-image.avif +0 -0
  274. package/src/stories/assets/context.png +0 -0
  275. package/src/stories/assets/discord.svg +1 -0
  276. package/src/stories/assets/docs.png +0 -0
  277. package/src/stories/assets/figma-plugin.png +0 -0
  278. package/src/stories/assets/github.svg +1 -0
  279. package/src/stories/assets/share.png +0 -0
  280. package/src/stories/assets/styling.png +0 -0
  281. package/src/stories/assets/testing.png +0 -0
  282. package/src/stories/assets/theming.png +0 -0
  283. package/src/stories/assets/tutorials.svg +1 -0
  284. package/src/stories/assets/youtube.svg +1 -0
  285. package/src/stories/button.css +30 -0
  286. package/src/stories/header.css +32 -0
  287. package/src/stories/page.css +68 -0
  288. package/src/theme/build-mui-theme.ts +104 -0
  289. package/src/theme/components.ts +163 -0
  290. package/src/theme/emotion-cache.tsx +101 -0
  291. package/src/theme/theme-colors.ts +205 -0
  292. package/src/theme/theme-options-sample.ts +69 -0
  293. package/src/theme/theme-options.ts +172 -0
  294. package/src/theme/theme-provider.tsx +44 -0
  295. package/src/theme/typography.ts +22 -0
  296. package/src/theme/utils.ts +17 -0
  297. package/tsconfig.json +3 -1
  298. package/src/api-manager/lib/cart-cookie-handler.ts +0 -14
  299. package/src/components-v2/product-cards/product-card/components/hover-actions.tsx +0 -37
  300. package/src/components-v2/product-cards/product-card-plp/components/quantity-buttons.tsx +0 -54
  301. package/src/components-v2/product-cards/product-card-plp-list/components/add-to-cart.tsx +0 -63
  302. package/src/components-v2/product-cards/product-card-plp-list/components/favorite-button.tsx +0 -27
  303. package/src/components-v2/product-cards/use-product.ts +0 -35
  304. package/src/components-v2/products-view/products-grid-view.tsx +0 -65
  305. package/src/components-v2/products-view/products-list-view.tsx +0 -66
  306. package/src/components-v2/wishlist-dialogs/create-wishlist/compound/context.ts +0 -2
  307. /package/src/components-v2/product-cards/{product-card/components/quantity-buttons.tsx → quantity-buttons.tsx} +0 -0
@@ -1,16 +1,20 @@
1
1
  /**
2
2
  * @module ProductsView
3
3
  */
4
- import React, { useContext, cloneElement } from "react";
4
+ import React from "react";
5
5
  import Grid from "@mui/material/Grid2";
6
6
  // GLOBAL CUSTOM COMPONENTS
7
7
  import { FlexBetween } from "@evenicanpm/storefront-core/src/components-v2/flex-box/index";
8
8
  import ProductCardPlp from "@evenicanpm/storefront-core/src/components-v2/product-cards/product-card-plp/product-card";
9
9
  // DATA MODEL
10
10
  import { ProductSearchResult as Product } from "@msdyn365-commerce/retail-proxy";
11
- import { ProductPrice } from "@/api-manager/schemas/product.schema";
12
- import { ProductsViewContext } from "@evenicanpm/storefront-core/src/components-v2/products-view/compound/context";
11
+ import {
12
+ ProductsViewContext,
13
+ useProductsView,
14
+ } from "@evenicanpm/storefront-core/src/components-v2/products-view/compound/context";
13
15
  import { ProductsViewProps } from "@evenicanpm/storefront-core/src/components-v2/products-view/compound/types";
16
+ import { cloneElement } from "react";
17
+ import { ProductPrice } from "@/api-manager/schemas/product.schema";
14
18
 
15
19
  /**
16
20
  * Root component of products grid view.
@@ -47,18 +51,17 @@ export default function ProductsGridView(props: ProductsViewProps) {
47
51
  *
48
52
  */
49
53
  ProductsGridView.Grid = ({ children }: { children: React.ReactElement }) => {
50
- const { products, productPrices } = useContext(ProductsViewContext);
54
+ const { products, productPrices } = useProductsView();
55
+
51
56
  return (
52
57
  <>
53
- {products.map((item: Product, i) => {
58
+ {products.map((product: Product, i) => {
54
59
  const matchingPrice = productPrices?.find(
55
- (price) => price.ProductId === item.RecordId,
60
+ (price) => price.ProductId === product.RecordId,
56
61
  );
57
- // Legacy API, consider alternatives.
58
- // Using this to pass props to child.
59
62
  return cloneElement(children, {
60
63
  key: i,
61
- product: item,
64
+ product: product,
62
65
  price: matchingPrice,
63
66
  });
64
67
  })}
@@ -66,14 +69,10 @@ ProductsGridView.Grid = ({ children }: { children: React.ReactElement }) => {
66
69
  );
67
70
  };
68
71
 
69
- /**
70
- * @category Props
71
- */
72
72
  export interface ProductCardProps {
73
73
  product?: Product;
74
74
  price?: ProductPrice;
75
75
  }
76
-
77
76
  /**
78
77
  * Individual product card component displayed in the grid.
79
78
  * @param props.item The product data to render.
@@ -81,6 +80,7 @@ export interface ProductCardProps {
81
80
  * @category Sub-Component
82
81
  */
83
82
  ProductsGridView.Card = ({ product, price }: ProductCardProps) => {
83
+ if (!product) return null;
84
84
  return (
85
85
  <Grid size={{ lg: 4, sm: 6, xs: 12 }} key={product.ItemId}>
86
86
  <ProductCardPlp
@@ -95,13 +95,22 @@ ProductsGridView.Card = ({ product, price }: ProductCardProps) => {
95
95
  id: product.RecordId,
96
96
  }}
97
97
  >
98
- <ProductCardPlp.Image />
98
+ <ProductCardPlp.ImageWrapper>
99
+ <ProductCardPlp.Image />
100
+ <ProductCardPlp.HoverActions>
101
+ <ProductCardPlp.QuickViewButton />
102
+ <ProductCardPlp.FavoriteButton />
103
+ </ProductCardPlp.HoverActions>
104
+ </ProductCardPlp.ImageWrapper>
99
105
  <ProductCardPlp.Body>
100
106
  <ProductCardPlp.Info>
101
107
  <ProductCardPlp.Title />
102
108
  <ProductCardPlp.Rating />
103
109
  <ProductCardPlp.Price />
104
110
  </ProductCardPlp.Info>
111
+ {/* <ProductCardPlp.Actions>
112
+ <ProductCardPlp.QuantityButtons />
113
+ </ProductCardPlp.Actions> */}
105
114
  </ProductCardPlp.Body>
106
115
  </ProductCardPlp>
107
116
  </Grid>
@@ -1,14 +1,17 @@
1
1
  /**
2
2
  * @module ProductsView
3
3
  */
4
- import { useContext, cloneElement } from "react";
4
+ import { cloneElement } from "react";
5
5
  // GLOBAL CUSTOM COMPONENTS
6
6
  import FlexBetween from "@evenicanpm/storefront-core/src/components-v2/flex-box/flex-between";
7
7
  import { ProductCardPlpList } from "@evenicanpm/storefront-core/src/components-v2/product-cards/product-card-plp-list/index";
8
8
  import { ProductPrice } from "@/api-manager/schemas/product.schema";
9
9
  // DATA MODEL
10
10
  import { ProductSearchResult as Product } from "@msdyn365-commerce/retail-proxy";
11
- import { ProductsViewContext } from "@evenicanpm/storefront-core/src/components-v2/products-view/compound/context";
11
+ import {
12
+ ProductsViewContext,
13
+ useProductsView,
14
+ } from "@evenicanpm/storefront-core/src/components-v2/products-view/compound/context";
12
15
  import { ProductsViewProps } from "@evenicanpm/storefront-core/src/components-v2/products-view/compound/types";
13
16
 
14
17
  /**
@@ -35,7 +38,7 @@ export default function ProductsListView(props: ProductsViewProps) {
35
38
  *
36
39
  */
37
40
  ProductsListView.List = ({ children }: { children: React.ReactElement }) => {
38
- const { products, productPrices } = useContext(ProductsViewContext);
41
+ const { products, productPrices } = useProductsView();
39
42
  return (
40
43
  <>
41
44
  {products.map((item: Product, i) => {
@@ -69,6 +72,7 @@ export interface ProductCardProps {
69
72
  * @category Sub-Component
70
73
  */
71
74
  ProductsListView.Card = ({ product, price }: ProductCardProps) => {
75
+ if (!product) return null;
72
76
  return (
73
77
  <ProductCardPlpList
74
78
  key={product.RecordId}
@@ -83,6 +87,7 @@ ProductsListView.Card = ({ product, price }: ProductCardProps) => {
83
87
  //tags: ["Bike", "Motor", "Ducati"], // Example tags
84
88
  }}
85
89
  >
90
+ <ProductCardPlpList.QuickViewButton />
86
91
  <ProductCardPlpList.Body>
87
92
  <ProductCardPlpList.Image />
88
93
  <ProductCardPlpList.Content>
@@ -91,6 +96,10 @@ ProductsListView.Card = ({ product, price }: ProductCardProps) => {
91
96
  <ProductCardPlpList.Price />
92
97
  <ProductCardPlpList.Rating />
93
98
  </ProductCardPlpList.Info>
99
+ <ProductCardPlpList.Actions>
100
+ <ProductCardPlpList.FavoriteButton />
101
+ {/* <ProductCardPlpList.QuantityButtons /> */}
102
+ </ProductCardPlpList.Actions>
94
103
  </ProductCardPlpList.Content>
95
104
  </ProductCardPlpList.Body>
96
105
  </ProductCardPlpList>
@@ -1,5 +1,5 @@
1
1
  import { ProductSearchResult } from "@msdyn365-commerce/retail-proxy";
2
- import { createContext } from "react";
2
+ import { createContext, useContext } from "react";
3
3
  import { FormEvent } from "react";
4
4
 
5
5
  /**
@@ -21,11 +21,32 @@ export interface SearchBarContext {
21
21
  handleSubmit: (event: FormEvent<HTMLFormElement>) => void;
22
22
  handleSearch: (e: React.ChangeEvent<HTMLInputElement>) => void;
23
23
  };
24
- handleCloseDrawer: () => void;
24
+ handleCloseDrawer?: () => void;
25
25
  }
26
26
  export const SearchContext = createContext<SearchBarContext>(null);
27
27
 
28
28
  /**
29
29
  * @internal
30
30
  */
31
- export const SearchResultItemContext = createContext<ProductSearchResult>(null);
31
+ export const SearchResultItemContext =
32
+ createContext<ProductSearchResult | null>(null);
33
+
34
+ export const useSearchContext = () => {
35
+ const context = useContext(SearchContext);
36
+ if (!context) {
37
+ throw new Error(
38
+ "useSearchContext must be used within a SearchContext provider",
39
+ );
40
+ }
41
+ return context;
42
+ };
43
+
44
+ export const useSearchResultItem = () => {
45
+ const context = useContext(SearchResultItemContext);
46
+ if (!context) {
47
+ throw new Error(
48
+ "useSearchResultItem must be used within a SearchResultItemContext provider",
49
+ );
50
+ }
51
+ return context;
52
+ };
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * @module SearchBar
3
3
  */
4
- import React, { useContext } from "react";
4
+ import React from "react";
5
5
  import Grid from "@mui/material/Grid";
6
6
  import ProductCardSearch from "@evenicanpm/storefront-core/src/components-v2/product-cards/product-card-search";
7
7
  import {
8
- SearchContext,
9
- SearchResultItemContext,
8
+ useSearchContext,
9
+ useSearchResultItem,
10
10
  } from "@evenicanpm/storefront-core/src/components-v2/search-bar/compound/context";
11
11
 
12
12
  /**
@@ -14,25 +14,26 @@ import {
14
14
  * @category Sub-Component
15
15
  */
16
16
  export default function ResultItemLg() {
17
- const { handleCloseDrawer } = useContext(SearchContext);
18
- const item = useContext(SearchResultItemContext);
19
-
17
+ const { handleCloseDrawer } = useSearchContext();
18
+ const item = useSearchResultItem();
20
19
  return (
21
20
  <Grid item xs={12} sm={6} md={4} onClick={handleCloseDrawer}>
22
21
  <ProductCardSearch
23
22
  product={{
24
- slug: item.ItemId ?? "",
25
- price: item.Price,
26
- title: item.Name ?? "",
27
- thumbnail: item.PrimaryImageUrl ?? "",
28
- id: item.RecordId ?? "",
29
- rating: item.AverageRating ?? 0,
30
- reviews: item.TotalRatings ?? 0,
23
+ slug: item?.ItemId ?? "",
24
+ price: item?.Price,
25
+ title: item?.Name ?? "",
26
+ thumbnail: item?.PrimaryImageUrl ?? "",
27
+ id: item?.RecordId ?? "",
28
+ rating: item?.AverageRating ?? 0,
29
+ reviews: item?.TotalRatings ?? 0,
31
30
  categories: [], // TODO: Category info not available in item
32
31
  }}
33
32
  >
34
33
  <ProductCardSearch.CardMedia>
35
34
  <ProductCardSearch.Image />
35
+ <ProductCardSearch.QuickViewButton />
36
+ <ProductCardSearch.FavoriteButton />
36
37
  </ProductCardSearch.CardMedia>
37
38
  <ProductCardSearch.Info>
38
39
  <ProductCardSearch.Category />
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @module SearchBar
3
3
  */
4
- import React, { useContext } from "react";
4
+ import React from "react";
5
5
  import NavLink from "@evenicanpm/storefront-core/src/components-v2/nav-link/nav-link";
6
6
  import MenuItem from "@mui/material/MenuItem";
7
7
  import { getProductDetailUrl } from "@/lib/build-product-detail-url";
@@ -13,8 +13,8 @@ import {
13
13
  } from "@evenicanpm/storefront-core/src/components-v2/Typography";
14
14
  import { currency } from "@/lib/lib";
15
15
  import {
16
- SearchContext,
17
- SearchResultItemContext,
16
+ useSearchContext,
17
+ useSearchResultItem,
18
18
  } from "@evenicanpm/storefront-core/src/components-v2/search-bar/compound/context";
19
19
 
20
20
  /**
@@ -22,8 +22,8 @@ import {
22
22
  * @category Sub-Component
23
23
  */
24
24
  export default function ResultItemSm() {
25
- const { handleCloseDrawer } = useContext(SearchContext);
26
- const item = useContext(SearchResultItemContext);
25
+ const { handleCloseDrawer } = useSearchContext();
26
+ const item = useSearchResultItem();
27
27
 
28
28
  return (
29
29
  <Grid item xs={12}>
@@ -3,8 +3,8 @@
3
3
  */
4
4
  "use client";
5
5
 
6
- import React, { Suspense, useContext } from "react";
7
- import { SearchContext } from "@evenicanpm/storefront-core/src/components-v2/search-bar/compound/context";
6
+ import React, { Suspense } from "react";
7
+ import { useSearchContext } from "@evenicanpm/storefront-core/src/components-v2/search-bar/compound/context";
8
8
  import { CircularProgress } from "@mui/material";
9
9
  import SearchResult from "@evenicanpm/storefront-core/src/components-v2/search-bar/compound/results";
10
10
  import { SearchResultCard } from "@evenicanpm/storefront-core/src/components-v2/search-bar/styles/index";
@@ -26,7 +26,7 @@ export default function SearchResultSuspense({
26
26
  }: {
27
27
  children: React.ReactNode;
28
28
  }) {
29
- const { state } = useContext(SearchContext);
29
+ const { state } = useSearchContext();
30
30
  return (
31
31
  <Suspense
32
32
  fallback={
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * @module SearchBar
3
3
  */
4
- import React, { useContext } from "react";
4
+ import React from "react";
5
5
  import { useTranslations } from "next-intl";
6
- import searchProducts from "@/services/product/queries/search-products";
6
+ import searchProducts from "@evenicanpm/storefront-core/src/api-manager/services/product/queries/search-products";
7
7
  import { SearchResultCard } from "@evenicanpm/storefront-core/src/components-v2/search-bar/styles/index";
8
8
  import {
9
- SearchContext,
9
+ useSearchContext,
10
10
  SearchResultItemContext,
11
11
  } from "@evenicanpm/storefront-core/src/components-v2/search-bar/compound/context";
12
12
  import Grid from "@mui/material/Grid";
@@ -21,7 +21,7 @@ export default function SearchResultsContainer({
21
21
  children: React.ReactNode;
22
22
  }) {
23
23
  const t = useTranslations();
24
- const { state } = useContext(SearchContext);
24
+ const { state } = useSearchContext();
25
25
  const { data: results } = searchProducts.useSuspenseData({
26
26
  searchText: state.searchText,
27
27
  category: state.searchCategory,
@@ -6,7 +6,7 @@ import React from "react";
6
6
  import MenuItem from "@mui/material/MenuItem";
7
7
  import TouchRipple from "@mui/material/ButtonBase";
8
8
  import useTheme from "@mui/material/styles/useTheme";
9
- import getCategories from "@/services/categories/queries/get-categories";
9
+ import getCategories from "@evenicanpm/storefront-core/src/api-manager/services/categories/queries/get-categories";
10
10
  import { MdKeyboardArrowDown as KeyboardArrowDownOutlined } from "react-icons/md";
11
11
  import { findCategoryNameById } from "@evenicanpm/storefront-core/src/components-v2/search-bar/utils/findCategoryNameById";
12
12
  import Menu from "@evenicanpm/storefront-core/src/components-v2/BazaarMenu";
@@ -2,7 +2,7 @@
2
2
  * @module SearchBar
3
3
  */
4
4
  "use client";
5
- import React, { useContext } from "react";
5
+ import React from "react";
6
6
  import TextField from "@mui/material/TextField";
7
7
 
8
8
  import SearchIconAdornment from "@evenicanpm/storefront-core/src/components-v2/search-bar/compound/textfield-adornment-search-icon";
@@ -13,7 +13,7 @@ import { INPUT_SX } from "@evenicanpm/storefront-core/src/components-v2/search-b
13
13
  import { useTheme, useMediaQuery } from "@mui/material";
14
14
  import _ from "lodash";
15
15
  import { useTranslations } from "next-intl";
16
- import { SearchContext } from "@evenicanpm/storefront-core/src/components-v2/search-bar/compound/context";
16
+ import { useSearchContext } from "@evenicanpm/storefront-core/src/components-v2/search-bar/compound/context";
17
17
 
18
18
  /**
19
19
  * The actual input field for the search bar.
@@ -22,7 +22,7 @@ import { SearchContext } from "@evenicanpm/storefront-core/src/components-v2/sea
22
22
  * @category Sub-Component
23
23
  */
24
24
  export default function SearchBarTextField() {
25
- const { handlers, state } = useContext(SearchContext);
25
+ const { handlers, state } = useSearchContext();
26
26
  const t = useTranslations();
27
27
  const theme = useTheme();
28
28
  const downMd = useMediaQuery(theme.breakpoints.down(1150));
@@ -8,7 +8,7 @@ export const useClickOutside = (
8
8
  callback: () => void,
9
9
  ) => {
10
10
  useEffect(() => {
11
- const handleClick = (e: PointerEvent) => {
11
+ const handleClick = (e: Event) => {
12
12
  if (ref.current && !ref.current.contains(e.target as Node)) callback();
13
13
  };
14
14
 
@@ -4,13 +4,10 @@ import { useState } from "react";
4
4
  import { Button, ButtonProps } from "@mui/material";
5
5
  import T from "@evenicanpm/storefront-core/src/components-v2/T";
6
6
  import AddToWishlistDialog from "@evenicanpm/storefront-core/src/components-v2/wishlist-dialogs/add-to-wishlist/index";
7
- import { ProductDetails } from "@/api-manager/schemas/product.schema";
8
- import { Cart } from "@/api-manager/schemas/cart.schema";
9
7
 
10
8
  interface Props {
11
9
  path: string;
12
- product?: ProductDetails;
13
- cart?: Cart;
10
+ productId?: number;
14
11
  variant?: string;
15
12
  }
16
13
 
@@ -59,8 +56,7 @@ const AddToWishlistButton = (props: Props) => {
59
56
  <AddToWishlistDialog
60
57
  open={openAddListDialog}
61
58
  handleClose={handleCloseDialog}
62
- productId={props.product?.RecordId}
63
- cart={props.cart}
59
+ productId={props?.productId}
64
60
  />
65
61
  </>
66
62
  );
@@ -5,7 +5,12 @@ import { AddToWishListDialogContext } from "@evenicanpm/storefront-core/src/comp
5
5
 
6
6
  const AddToWishListBottomUI = () => {
7
7
  const t = useTranslations("Account.Wishlists");
8
- const { handleClose } = useContext(AddToWishListDialogContext);
8
+ const ctx = useContext(AddToWishListDialogContext);
9
+ if (!ctx)
10
+ throw new Error(
11
+ "CreateNewWishlistForm must be used within a CreateNewWishlistContext",
12
+ );
13
+ const { handleClose } = ctx;
9
14
  return (
10
15
  <Grid container spacing={3}>
11
16
  <Grid
@@ -10,15 +10,12 @@ import AddToWishListBottomUI from "@evenicanpm/storefront-core/src/components-v2
10
10
 
11
11
  // API AND CONTEXT
12
12
  import getWishlists from "@/api-manager/services/user/queries/get-wishlists";
13
- import { Cart } from "@evenicanpm/storefront-core/src/api-manager/schemas/cart.schema";
14
13
  import { AddToWishListDialogContext } from "@evenicanpm/storefront-core/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/context";
15
14
 
16
15
  export interface AddToWishlistDialogProps {
17
16
  open: boolean;
18
17
  handleClose: () => void;
19
18
  productId?: number;
20
- cart?: Cart;
21
- onSuccess?: () => void;
22
19
  children: React.ReactNode;
23
20
  }
24
21
 
@@ -43,17 +40,20 @@ export interface AddToWishlistDialogProps {
43
40
  * </AddToWishlistDialog>
44
41
  *
45
42
  */
46
- export default function AddToWishlistDialog(props: AddToWishlistDialogProps) {
47
- const { data: wishlists, isPending: isLoading } = getWishlists.useData();
43
+ export default function AddToWishlistDialog({
44
+ open,
45
+ handleClose,
46
+ productId,
47
+ children,
48
+ }: AddToWishlistDialogProps) {
49
+ const { data: wishlists } = getWishlists.useSuspenseData();
48
50
 
49
51
  const { data: session } = useSession();
50
52
  const isAuthenticated = !!session;
51
53
 
52
- if (isLoading) return null;
53
-
54
- const handleClose = () => {
55
- if (typeof props.handleClose === "function") {
56
- props.handleClose();
54
+ const handleCloseDialog = () => {
55
+ if (typeof handleClose === "function") {
56
+ handleClose();
57
57
  }
58
58
  };
59
59
 
@@ -61,14 +61,21 @@ export default function AddToWishlistDialog(props: AddToWishlistDialogProps) {
61
61
  <AddToWishListDialogContext.Provider
62
62
  value={{
63
63
  wishlists,
64
- isLoading,
65
- props,
64
+ productId,
66
65
  isAuthenticated,
67
- handleClose,
66
+ handleClose: handleCloseDialog,
68
67
  }}
69
68
  >
70
- <Dialog open={props.open} onClose={handleClose}>
71
- <DialogContent>{props.children}</DialogContent>
69
+ <Dialog
70
+ open={open}
71
+ onClick={(e) => {
72
+ e.stopPropagation();
73
+ handleClose?.();
74
+ }}
75
+ >
76
+ <DialogContent onClick={(e) => e.stopPropagation()}>
77
+ {children}
78
+ </DialogContent>
72
79
  </Dialog>
73
80
  </AddToWishListDialogContext.Provider>
74
81
  );
@@ -19,22 +19,23 @@ import { Wishlist } from "@evenicanpm/storefront-core/src/api-manager/schemas/us
19
19
  * @category Sub-Component
20
20
  */
21
21
  const WishlistList = ({ children }: { children: React.ReactNode }) => {
22
- const { wishlists, isAuthenticated, isLoading } = useContext(
23
- AddToWishListDialogContext,
24
- );
25
-
26
- if (isLoading) return;
22
+ const ctx = useContext(AddToWishListDialogContext);
23
+ if (!ctx)
24
+ throw new Error(
25
+ "CreateNewWishlistForm must be used within a CreateNewWishlistContext",
26
+ );
27
+ const { wishlists, isAuthenticated } = ctx;
27
28
 
28
29
  if (!isAuthenticated) {
29
30
  return <NoRecords message="Account.Wishlists.wishlistAddUnauthenticated" />;
30
31
  }
31
32
 
32
- if (wishlists.length === 0) {
33
+ if (wishlists?.length === 0) {
33
34
  return <NoRecords message="Account.Wishlists.noWishlists" />;
34
35
  }
35
36
 
36
37
  return wishlists?.map((wishlist: Wishlist, i: number) => (
37
- <WishListItemContext.Provider value={{ wishlist }} key={i + wishlist.Name}>
38
+ <WishListItemContext.Provider value={{ wishlist }} key={i}>
38
39
  {children}
39
40
  </WishListItemContext.Provider>
40
41
  ));
@@ -3,21 +3,19 @@
3
3
  */
4
4
  import { createContext } from "react";
5
5
  import { Wishlist } from "@/api-manager/schemas/user.schema";
6
- import { AddToWishlistDialogProps } from "@evenicanpm/storefront-core/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-dialog";
7
6
 
8
7
  /**
9
8
  * @category Context
10
9
  */
11
10
  export interface AddToWishlistDialogContext {
12
- wishlists: Wishlist[];
13
- isLoading: boolean;
14
- props: AddToWishlistDialogProps;
15
- isAuthenticated: boolean;
16
- handleClose: () => void;
11
+ wishlists?: Wishlist[];
12
+ productId?: number;
13
+ isAuthenticated?: boolean;
14
+ handleClose?: () => void;
17
15
  }
18
16
 
19
17
  export const AddToWishListDialogContext =
20
- createContext<AddToWishlistDialogContext>(null);
18
+ createContext<AddToWishlistDialogContext | null>(null);
21
19
 
22
20
  /**
23
21
  * @category Context
@@ -26,4 +24,6 @@ export interface WishlistItemContext {
26
24
  wishlist: Wishlist;
27
25
  }
28
26
 
29
- export const WishListItemContext = createContext<WishlistItemContext>(null);
27
+ export const WishListItemContext = createContext<WishlistItemContext | null>(
28
+ null,
29
+ );
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * @module Add-To-Wishlist-Dialog
3
3
  */
4
- import { Button, CircularProgress } from "@mui/material";
5
4
  import { useContext, useState } from "react";
5
+ import Link from "next/link";
6
6
  import {
7
7
  AddToWishListDialogContext,
8
8
  WishListItemContext,
@@ -11,31 +11,40 @@ import UseWishlist from "@evenicanpm/storefront-core/src/components-v2/wishlist-
11
11
  import { format } from "date-fns";
12
12
  import { Paragraph } from "@evenicanpm/storefront-core/src/components-v2/Typography";
13
13
  import { StyledTableRow } from "@evenicanpm/storefront-core/src/components-v2/wishlist-dialogs/styles";
14
-
14
+ import { Add } from "@mui/icons-material";
15
+ import { IconButton } from "@mui/material";
16
+ import { Delete } from "@mui/icons-material";
15
17
  /**
16
18
  * Wishlist dialog list item. Displays info about the wishlist and
17
19
  * also has a context-aware "action" button, either add or remove depending on
18
20
  * if the currently selected product is in the list or not.
19
21
  * @category Sub-Component
20
22
  */
21
- export default function WishlistModalItem() {
23
+ export default function WishlistDialogItem() {
22
24
  const [isDisabled, setIsDisabled] = useState(false);
23
25
 
24
- const { wishlist } = useContext(WishListItemContext);
25
- const { wishlists } = useContext(AddToWishListDialogContext);
26
- const { props } = useContext(AddToWishListDialogContext);
26
+ const itemCtx = useContext(WishListItemContext);
27
+ const dialogCtx = useContext(AddToWishListDialogContext);
28
+
29
+ if (!itemCtx || !dialogCtx)
30
+ throw new Error("WishlistModalItem must be used within a wishlist context");
31
+
27
32
  const { handleAddToWishlist, handleRemoveFromWishlist, loading } =
28
33
  UseWishlist();
34
+ const { productId } = dialogCtx;
35
+ const { wishlist } = itemCtx;
29
36
 
30
37
  const productInWishlist = wishlist.ProductListLines?.some(
31
- (line) => line.ProductId === props.productId,
38
+ (line) => line?.ProductId === productId,
32
39
  );
33
40
 
41
+ if (!productId) return null;
42
+
34
43
  const action = productInWishlist
35
- ? () => handleRemoveFromWishlist(wishlist.Id, props.productId)
36
- : () => handleAddToWishlist(wishlist.Id, wishlists, props);
44
+ ? () => handleRemoveFromWishlist(wishlist.Id, productId)
45
+ : () => handleAddToWishlist(wishlist.Id, productId);
37
46
 
38
- const buttonText = productInWishlist ? "Remove" : "Add";
47
+ const buttonText = productInWishlist ? <Delete /> : <Add />;
39
48
 
40
49
  return (
41
50
  <StyledTableRow
@@ -50,7 +59,9 @@ export default function WishlistModalItem() {
50
59
  }}
51
60
  >
52
61
  <Paragraph ellipsis sx={{ fontWeight: "bold" }}>
53
- {wishlist?.Name ?? ""}
62
+ <Link href={`/account/wish-lists/${wishlist?.Id}`}>
63
+ {wishlist?.Name ?? ""}
64
+ </Link>
54
65
  </Paragraph>
55
66
  <Paragraph ellipsis>
56
67
  {" "}
@@ -61,25 +72,24 @@ export default function WishlistModalItem() {
61
72
  </Paragraph>
62
73
  <Paragraph ellipsis>
63
74
  {" "}
64
- {`${wishlist?.ProductListLines?.length} products`}
75
+ {`${wishlist?.ProductListLines?.length ?? 0} products`}
65
76
  </Paragraph>
66
- <Button
77
+ <IconButton
67
78
  onClick={() => {
68
79
  // throttle to prevent race conditions
69
80
  setIsDisabled(true);
70
81
  action();
71
82
  setTimeout(() => setIsDisabled(false), 1000);
72
83
  }}
73
- color="primary"
84
+ color={productInWishlist ? "secondary" : "primary"}
74
85
  sx={{
75
- bgcolor: loading ? "grey.100" : "primary.light",
76
- height: "35px",
77
- px: 4,
86
+ justifySelf: "end",
78
87
  }}
88
+ loading={loading}
79
89
  disabled={isDisabled || loading}
80
90
  >
81
- {loading ? <CircularProgress size={10} /> : buttonText}
82
- </Button>
91
+ {buttonText}
92
+ </IconButton>
83
93
  </StyledTableRow>
84
94
  );
85
95
  }