@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.
- package/.storybook/main.ts +37 -0
- package/.storybook/preview.ts +14 -0
- package/README.md +17 -2
- package/__mocks__/next-font.js +4 -0
- package/package.json +19 -13
- package/src/api-manager/datasources/e4/graphqlRequestSdk.ts +265 -5
- package/src/api-manager/schemas/product.schema.ts +2 -2
- package/src/api-manager/services/cart/mutations/add-discount-code.ts +11 -0
- package/src/api-manager/services/cart/mutations/checkout.ts +1 -1
- package/src/api-manager/services/create-query.ts +11 -4
- package/src/api-manager/services/product/queries/get-product-availability.ts +1 -2
- package/src/api-manager/services/user/mutations/add-to-wishlist.ts +2 -2
- package/src/api-manager/services/user/mutations/copy-cart-to-wishlist.ts +2 -1
- package/src/api-manager/services/user/mutations/remove-from-wishlist.ts +4 -4
- package/src/api-manager/services/user/mutations/update-wishlist.ts +2 -1
- package/src/api-manager/services/user/queries/get-wishlist-details.ts +2 -2
- package/src/cms/blocks/components/product-carousel/index.tsx +6 -3
- package/src/cms/blocks/components/product-section-fullwidth/index.tsx +2 -2
- package/src/cms/blocks/components/shared/product-grid.tsx +5 -2
- package/src/cms/interfaces/navigation.ts +9 -9
- package/src/components/Blocks/Components/CategoryCarousel/index.tsx +3 -3
- package/src/components/Blocks/Components/HeroCarousel/index.tsx +2 -2
- package/src/components/Blocks/Components/ProductCarousel/index.tsx +5 -5
- package/src/components/Blocks/Components/ProductSectionFullWidth/index.tsx +6 -6
- package/src/components/Blocks/Components/Services/service-card.tsx +4 -1
- package/src/components/Blocks/Components/shared/featured-product-card.tsx +2 -2
- package/src/components/Blocks/Components/shared/product-category-item.tsx +3 -3
- package/src/components/Blocks/Components/shared/product-grid.tsx +2 -2
- package/src/components/Blocks/Components/shared/top-categories-card.tsx +1 -1
- package/src/components/Blocks/Components/shared/top-rating-product-card.tsx +6 -3
- package/src/components/Footer/sections/FooterAppStore.tsx +1 -1
- package/src/components/Footer/sections/FooterContact.tsx +1 -1
- package/src/components/Footer/sections/FooterLogo.tsx +2 -2
- package/src/components/Footer/sections/FooterSocialLinks.tsx +1 -1
- package/src/components/_components/MiniCartClient.tsx +2 -2
- package/src/components/_components/accordion/accordion-header.tsx +1 -1
- package/src/components/_components/carousel-cards/carousel-card-1/carousel-card-1.tsx +2 -2
- package/src/components/_components/carousel-cards/carousel-card-2/carousel-card-2.tsx +9 -4
- package/src/components/_components/carousel-cards/carousel-card-3/carousel-card-3.tsx +6 -3
- package/src/components/_components/carousel-cards/carousel-card-4/carousel-card-4.tsx +6 -1
- package/src/components/_components/categories/category-list/category-list.tsx +3 -3
- package/src/components/_components/categories/mega-menu/banner.tsx +7 -3
- package/src/components/_components/categories/mega-menu/column-list.tsx +3 -3
- package/src/components/_components/categories/mega-menu/mega-menu-1.tsx +2 -2
- package/src/components/_components/category-cards/category-card-1/category-card-1.tsx +2 -2
- package/src/components/_components/countdown/count-box.tsx +4 -1
- package/src/components/_components/countdown/count-down.tsx +1 -1
- package/src/components/_components/data-table/table-header.tsx +1 -1
- package/src/components/_components/footer/components/app-store.tsx +1 -1
- package/src/components/_components/footer/components/logo.tsx +2 -2
- package/src/components/_components/footer/components/social-links.tsx +1 -1
- package/src/components/_components/footer/footer-1.tsx +1 -1
- package/src/components/_components/footer/footer-2.tsx +2 -2
- package/src/components/_components/footer/footer-3.tsx +2 -2
- package/src/components/_components/footer/footer-4.tsx +3 -3
- package/src/components/_components/header/components/categories-menu.tsx +3 -3
- package/src/components/_components/header/components/mobile-header.tsx +9 -6
- package/src/components/_components/header/components/user.tsx +5 -5
- package/src/components/_components/header/header.tsx +2 -2
- package/src/components/_components/header/sticky-header.tsx +3 -3
- package/src/components/_components/mini-cart/components/cart-item.tsx +5 -2
- package/src/components/_components/mini-cart/components/empty-view.tsx +2 -2
- package/src/components/_components/mini-cart/components/top-header.tsx +5 -2
- package/src/components/_components/mini-cart/mini-cart.tsx +3 -3
- package/src/components/_components/mobile-navigation/mobile-navigation-bar.tsx +5 -5
- package/src/components/_components/nav-link/nav-link-2.tsx +1 -1
- package/src/components/_components/nav-link/nav-link-3.tsx +1 -1
- package/src/components/_components/navbar/categories.tsx +3 -3
- package/src/components/_components/navbar/category-based-menu/category-based-menu.tsx +1 -1
- package/src/components/_components/navbar/category-based-menu/components/child-categories.tsx +2 -2
- package/src/components/_components/navbar/mega-menu/category-list.tsx +1 -1
- package/src/components/_components/navbar/mega-menu/mega-menu.tsx +1 -1
- package/src/components/_components/navbar/mobile-menu/mobile-menu.tsx +2 -2
- package/src/components/_components/navbar/mobile-menu/render-levels.tsx +3 -3
- package/src/components/_components/navbar/nav-list/nav-item-child.tsx +3 -3
- package/src/components/_components/navbar/nav-list/nav-list.tsx +4 -4
- package/src/components/_components/newsletter/newsletter.tsx +5 -1
- package/src/components/_components/newsletter/social-icons.tsx +1 -1
- package/src/components/_components/page-sidenav/grocery-side-nav/components/link-item.tsx +2 -2
- package/src/components/_components/page-sidenav/grocery-side-nav/components/list-item.tsx +2 -2
- package/src/components/_components/page-sidenav/grocery-side-nav/components/nav-accordion.tsx +2 -2
- package/src/components/_components/page-sidenav/grocery-side-nav/grocery-side-nav.tsx +3 -3
- package/src/components/_components/page-sidenav/health-beauty-side-nav/components/list-item.tsx +2 -2
- package/src/components/_components/page-sidenav/health-beauty-side-nav/components/nav-accordion.tsx +2 -2
- package/src/components/_components/page-sidenav/health-beauty-side-nav/components/render-child.tsx +2 -2
- package/src/components/_components/page-sidenav/health-beauty-side-nav/health-beauty-side-nav.tsx +5 -5
- package/src/components/_components/page-sidenav/side-navbar/components/list-item.tsx +1 -1
- package/src/components/_components/page-sidenav/side-navbar/components/nav-accordion.tsx +3 -3
- package/src/components/_components/page-sidenav/side-navbar/components/render-child.tsx +1 -1
- package/src/components/_components/page-sidenav/side-navbar/side-nav-bar.tsx +4 -4
- package/src/components/_components/page-sidenav/side-navbar-2/components/sidebar-accordion.tsx +1 -1
- package/src/components/_components/page-sidenav/side-navbar-2/side-navbar-2.tsx +2 -2
- package/src/components/_components/product-cards/product-card-1/components/quantity-buttons.tsx +2 -2
- package/src/components/_components/product-cards/product-card-1/product-card.tsx +2 -2
- package/src/components/_components/product-cards/product-card-10/product-card.tsx +9 -5
- package/src/components/_components/product-cards/product-card-11/product-card.tsx +6 -3
- package/src/components/_components/product-cards/product-card-12/product-card.tsx +4 -4
- package/src/components/_components/product-cards/product-card-13/product-card.tsx +6 -3
- package/src/components/_components/product-cards/product-card-14/product-card.tsx +7 -4
- package/src/components/_components/product-cards/product-card-15/product-card.tsx +6 -3
- package/src/components/_components/product-cards/product-card-16/components/quantity-buttons.tsx +2 -2
- package/src/components/_components/product-cards/product-card-16/product-card.tsx +5 -2
- package/src/components/_components/product-cards/product-card-2/components/product-price.tsx +2 -2
- package/src/components/_components/product-cards/product-card-2/product-card.tsx +4 -4
- package/src/components/_components/product-cards/product-card-3/components/hover-actions.tsx +1 -1
- package/src/components/_components/product-cards/product-card-3/product-card.tsx +2 -2
- package/src/components/_components/product-cards/product-card-4/components/hover-actions.tsx +1 -1
- package/src/components/_components/product-cards/product-card-4/product-card.tsx +2 -2
- package/src/components/_components/product-cards/product-card-5/components/hover-actions.tsx +1 -1
- package/src/components/_components/product-cards/product-card-5/product-card.tsx +2 -2
- package/src/components/_components/product-cards/product-card-6/components/hover-actions.tsx +1 -1
- package/src/components/_components/product-cards/product-card-6/product-card.tsx +3 -3
- package/src/components/_components/product-cards/product-card-7/components/quantity-buttons.tsx +2 -2
- package/src/components/_components/product-cards/product-card-7/product-card.tsx +5 -2
- package/src/components/_components/product-cards/product-card-8/product-card.tsx +9 -5
- package/src/components/_components/product-cards/product-card-9/components/add-to-cart.tsx +5 -2
- package/src/components/_components/product-cards/product-card-9/product-card.tsx +1 -1
- package/src/components/_components/product-cards/product-price.tsx +2 -2
- package/src/components/_components/product-cards/product-rating.tsx +2 -2
- package/src/components/_components/product-cards/product-title.tsx +1 -1
- package/src/components/_components/product-cards/use-product.ts +1 -1
- package/src/components/_components/product-dimensions/product-dimensions.tsx +1 -1
- package/src/components/_components/product-quantity-buttons/product-quantity-buttons.tsx +2 -2
- package/src/components/_components/products-view/products-grid-view.tsx +2 -2
- package/src/components/_components/products-view/products-list-view.tsx +2 -2
- package/src/components/_components/search-box/components/category-dropdown.tsx +1 -1
- package/src/components/_components/search-box/components/search-result.tsx +1 -1
- package/src/components/_components/search-box/hooks/use-search.ts +1 -1
- package/src/components/_components/search-box/search-input-category.tsx +3 -3
- package/src/components/_components/service-cards/service-card-1/service-card-1.tsx +5 -2
- package/src/components/_components/service-cards/service-card-2/service-card-2.tsx +5 -2
- package/src/components/_components/service-cards/service-card-3/service-card-3.tsx +4 -1
- package/src/components/_components/settings/setting.tsx +3 -3
- package/src/components/_components/side-nav/side-nav.tsx +1 -1
- package/src/components/_components/stories/story-content/story-content.tsx +1 -1
- package/src/components/_components/stories/story-item/story-item.tsx +1 -1
- package/src/components/_components/topbar/top-bar.tsx +6 -3
- package/src/components/_components/wishlist-modal/wishlist-modal-item.tsx +1 -1
- package/src/components-v2/accordion/accordion-header.stories.tsx +28 -0
- package/src/components-v2/categories/category-list/category-list.tsx +2 -2
- package/src/components-v2/categories/category-list/styles.ts +3 -2
- package/src/components-v2/categories/mega-menu/column-list.tsx +1 -1
- package/src/components-v2/categories/mega-menu/mega-menu-1.tsx +6 -3
- package/src/components-v2/categories/mega-menu/mega-menu-2.tsx +2 -2
- package/src/components-v2/header/__tests__/user.test.tsx +12 -12
- package/src/components-v2/header/components/user.tsx +12 -11
- package/src/components-v2/mini-cart/mini-cart.tsx +9 -14
- package/src/components-v2/mobile-navigation/mobile-navigation-bar.tsx +1 -1
- package/src/components-v2/navbar/mobile-menu/mobile-menu.tsx +2 -2
- package/src/components-v2/product-cards/favorite-button.tsx +52 -0
- package/src/components-v2/product-cards/product-card/product-card.tsx +87 -47
- package/src/components-v2/product-cards/product-card-plp/product-card.tsx +140 -51
- package/src/components-v2/product-cards/product-card-plp/styles/index.ts +17 -0
- package/src/components-v2/product-cards/product-card-plp-list/product-card.tsx +76 -42
- package/src/components-v2/product-cards/product-card-search/product-card.tsx +50 -21
- package/src/components-v2/product-cards/product-card-search/styles/index.ts +0 -10
- package/src/components-v2/product-dialog/compound/product-dialog.tsx +39 -15
- package/src/components-v2/product-quantity-buttons/compound/quantity-buttons-root.tsx +22 -7
- package/src/components-v2/product-quantity-variants/index.tsx +1 -1
- package/src/components-v2/products-view/compound/context.ts +46 -1
- package/src/components-v2/products-view/compound/products-grid-view.tsx +23 -14
- package/src/components-v2/products-view/compound/products-list-view.tsx +12 -3
- package/src/components-v2/search-bar/compound/context.ts +24 -3
- package/src/components-v2/search-bar/compound/results-item-lg.tsx +14 -13
- package/src/components-v2/search-bar/compound/results-item-sm.tsx +5 -5
- package/src/components-v2/search-bar/compound/results-suspense.tsx +3 -3
- package/src/components-v2/search-bar/compound/results.tsx +4 -4
- package/src/components-v2/search-bar/compound/textfield-adornment-category.tsx +1 -1
- package/src/components-v2/search-bar/compound/textfield.tsx +3 -3
- package/src/components-v2/search-bar/hooks/use-click-outside.ts +1 -1
- package/src/components-v2/wishlist-dialogs/add-to-wishlist/add-to-wishlist-button.tsx +2 -6
- package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-bottom-ui.tsx +6 -1
- package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-dialog.tsx +22 -15
- package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-list.tsx +8 -7
- package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/context.ts +8 -8
- package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/wishlist-dialog-item.tsx +29 -19
- package/src/components-v2/wishlist-dialogs/add-to-wishlist/hooks/use-add-to-wishlist.ts +27 -77
- package/src/components-v2/wishlist-dialogs/add-to-wishlist/index.tsx +1 -9
- package/src/components-v2/wishlist-dialogs/create-wishlist/compound/create-wishlist-bottom-ui.tsx +7 -2
- package/src/components-v2/wishlist-dialogs/create-wishlist/compound/create-wishlist-dialog.tsx +20 -12
- package/src/components-v2/wishlist-dialogs/create-wishlist/compound/create-wishlist-form.tsx +25 -5
- package/src/hooks/use-cart.ts +11 -14
- package/src/hooks/use-favorite.ts +17 -0
- package/src/hooks/use-variants.ts +4 -3
- package/src/pages/account/addresses/address-item.tsx +1 -1
- package/src/pages/account/dashboard-header.tsx +3 -3
- package/src/pages/account/navigation.tsx +5 -2
- package/src/pages/account/no-records.tsx +1 -1
- package/src/pages/account/orders/order-progress.tsx +5 -2
- package/src/pages/account/orders/order-row.tsx +4 -1
- package/src/pages/account/orders/order-summary.tsx +6 -2
- package/src/pages/account/orders/ordered-products.tsx +9 -2
- package/src/pages/account/profile/user-info.tsx +5 -2
- package/src/pages/account/wishlist/create-new-list.tsx +1 -1
- package/src/pages/account/wishlist/wishlist-item.tsx +2 -2
- package/src/pages/checkout/checkout-alt-form/address-card.tsx +5 -2
- package/src/pages/checkout/checkout-alt-form/checkout-step.tsx +3 -3
- package/src/pages/checkout/checkout-alt-form/customer-information.tsx +1 -1
- package/src/pages/checkout/checkout-alt-form/delivery-address.tsx +5 -1
- package/src/pages/checkout/checkout-alt-form/delivery-options.tsx +6 -2
- package/src/pages/checkout/checkout-alt-form/edit-address-form.tsx +1 -1
- package/src/pages/checkout/checkout-alt-form/heading.tsx +2 -2
- package/src/pages/checkout/checkout-alt-form/new-address-form.tsx +9 -4
- package/src/pages/checkout/checkout-alt-form/payment-details.tsx +6 -3
- package/src/pages/checkout/checkout-alt-summary/cart-item.tsx +5 -2
- package/src/pages/checkout/checkout-alt-summary/checkout-alt-summary.tsx +4 -2
- package/src/pages/checkout/checkout-alt-summary/list-item.tsx +2 -2
- package/src/pages/confirmation/address.tsx +4 -1
- package/src/pages/confirmation/confirmation-summary.tsx +6 -3
- package/src/pages/confirmation/ordered-products.tsx +9 -2
- package/src/pages/product-details/available-shops.tsx +5 -2
- package/src/pages/product-details/bopis/find-in-store-modal.tsx +1 -1
- package/src/pages/product-details/bopis/pickup-option-select.tsx +1 -1
- package/src/pages/product-details/frequently-bought.tsx +9 -2
- package/src/pages/product-details/frequently-product-card.tsx +8 -5
- package/src/pages/product-details/product-comment.tsx +7 -2
- package/src/pages/product-details/product-description.tsx +1 -1
- package/src/pages/product-details/product-filter-card.tsx +11 -3
- package/src/pages/product-details/product-intro/product-intro-images.tsx +4 -1
- package/src/pages/product-details/product-intro/product-intro.tsx +8 -5
- package/src/pages/product-details/product-review.tsx +5 -2
- package/src/pages/product-details/related-products.tsx +2 -2
- package/src/pages/product-list/facet-group.tsx +1 -1
- package/src/pages/product-list/list-filter.tsx +5 -2
- package/src/pages/product-list/pagination.tsx +1 -1
- package/src/pages/product-list/quick-view-dialog-content.tsx +2 -2
- package/src/pages/product-list/selected-facets.tsx +1 -1
- package/src/pages/quickorder/order-upload.tsx +1 -1
- package/src/pages/quickorder/quick-order-form.tsx +6 -3
- package/src/pages/quickorder/quick-order-row.tsx +1 -1
- package/src/pages-v2/account/account-navigation.tsx +1 -1
- package/src/pages-v2/account/orders/order-summary.tsx +5 -2
- package/src/pages-v2/account/profile/user-info.tsx +6 -3
- package/src/pages-v2/account/wishlist/wishlist-item.tsx +1 -1
- package/src/pages-v2/cart/__tests__/checkout-form.test.tsx +1 -1
- package/src/pages-v2/cart/estimate-shipping.tsx +3 -0
- package/src/pages-v2/checkout/checkout-alt-form/checkout-step.tsx +4 -4
- package/src/pages-v2/checkout/checkout-alt-form/steps/address/address-card.tsx +1 -1
- package/src/pages-v2/checkout/checkout-alt-form/steps/address/delivery-address.tsx +12 -5
- package/src/pages-v2/checkout/checkout-alt-form/steps/address/new-address-form.tsx +27 -5
- package/src/pages-v2/checkout/checkout-alt-form/steps/address/styles.ts +2 -1
- package/src/pages-v2/checkout/checkout-alt-form/steps/customer-info/customer-information.tsx +27 -7
- package/src/pages-v2/checkout/checkout-alt-form/steps/shipping/delivery-options.tsx +8 -1
- package/src/pages-v2/confirmation/address.tsx +5 -1
- package/src/pages-v2/product-details/available-shops.tsx +4 -1
- package/src/pages-v2/product-details/bopis/find-in-store-button.tsx +1 -1
- package/src/pages-v2/product-details/bopis/find-in-store-modal.tsx +3 -5
- package/src/pages-v2/product-details/product-intro/compound/context.ts +69 -12
- package/src/pages-v2/product-details/product-intro/compound/product-info.tsx +73 -27
- package/src/pages-v2/product-details/product-intro/compound/product-intro-images.tsx +19 -6
- package/src/pages-v2/product-details/product-intro/utils.ts +2 -2
- package/src/pages-v2/product-details/product-tabs.tsx +19 -4
- package/src/pages-v2/product-details/related-products.tsx +3 -3
- package/src/pages-v2/quickorder/context.ts +2 -2
- package/src/pages-v2/quickorder/order-upload.tsx +6 -2
- package/src/pages-v2/quickorder/provider.tsx +24 -9
- package/src/pages-v2/quickorder/quick-order-actions.tsx +2 -2
- package/src/pages-v2/quickorder/quick-order-header.tsx +6 -3
- package/src/pages-v2/quickorder/quick-order-row.tsx +1 -1
- package/src/pages-v2/quickorder/quick-order-table.tsx +10 -4
- package/src/pages-v2/quickorder/quick-order-upload.tsx +2 -2
- package/src/stories/Button.stories.ts +54 -0
- package/src/stories/Button.tsx +35 -0
- package/src/stories/Configure.mdx +364 -0
- package/src/stories/Header.stories.ts +34 -0
- package/src/stories/Header.tsx +54 -0
- package/src/stories/Page.stories.ts +33 -0
- package/src/stories/Page.tsx +73 -0
- package/src/stories/assets/accessibility.png +0 -0
- package/src/stories/assets/accessibility.svg +1 -0
- package/src/stories/assets/addon-library.png +0 -0
- package/src/stories/assets/assets.png +0 -0
- package/src/stories/assets/avif-test-image.avif +0 -0
- package/src/stories/assets/context.png +0 -0
- package/src/stories/assets/discord.svg +1 -0
- package/src/stories/assets/docs.png +0 -0
- package/src/stories/assets/figma-plugin.png +0 -0
- package/src/stories/assets/github.svg +1 -0
- package/src/stories/assets/share.png +0 -0
- package/src/stories/assets/styling.png +0 -0
- package/src/stories/assets/testing.png +0 -0
- package/src/stories/assets/theming.png +0 -0
- package/src/stories/assets/tutorials.svg +1 -0
- package/src/stories/assets/youtube.svg +1 -0
- package/src/stories/button.css +30 -0
- package/src/stories/header.css +32 -0
- package/src/stories/page.css +68 -0
- package/src/theme/build-mui-theme.ts +104 -0
- package/src/theme/components.ts +163 -0
- package/src/theme/emotion-cache.tsx +101 -0
- package/src/theme/theme-colors.ts +205 -0
- package/src/theme/theme-options-sample.ts +69 -0
- package/src/theme/theme-options.ts +172 -0
- package/src/theme/theme-provider.tsx +44 -0
- package/src/theme/typography.ts +22 -0
- package/src/theme/utils.ts +17 -0
- package/tsconfig.json +3 -1
- package/src/api-manager/lib/cart-cookie-handler.ts +0 -14
- package/src/components-v2/product-cards/product-card/components/hover-actions.tsx +0 -37
- package/src/components-v2/product-cards/product-card-plp/components/quantity-buttons.tsx +0 -54
- package/src/components-v2/product-cards/product-card-plp-list/components/add-to-cart.tsx +0 -63
- package/src/components-v2/product-cards/product-card-plp-list/components/favorite-button.tsx +0 -27
- package/src/components-v2/product-cards/use-product.ts +0 -35
- package/src/components-v2/products-view/products-grid-view.tsx +0 -65
- package/src/components-v2/products-view/products-list-view.tsx +0 -66
- package/src/components-v2/wishlist-dialogs/create-wishlist/compound/context.ts +0 -2
- /package/src/components-v2/product-cards/{product-card/components/quantity-buttons.tsx → quantity-buttons.tsx} +0 -0
|
@@ -29,7 +29,7 @@ import AddressCard from "@evenicanpm/storefront-core/src/pages-v2/checkout/check
|
|
|
29
29
|
import { CheckoutStepComponentProps } from "@evenicanpm/storefront-core/src/pages-v2/checkout/checkout-alt-form/checkout-step";
|
|
30
30
|
import { AddressDropDownHandler } from "@evenicanpm/storefront-core/src/pages-v2/checkout/checkout-alt-form/steps/address/styles";
|
|
31
31
|
|
|
32
|
-
type Translator =
|
|
32
|
+
type Translator = ReturnType<typeof useTranslations>;
|
|
33
33
|
|
|
34
34
|
type DeliveryAddressCompound = React.FC<DeliveryAddressProps> & {
|
|
35
35
|
Modal: React.FC;
|
|
@@ -261,10 +261,14 @@ const DeliveryAddress: DeliveryAddressCompound = ({
|
|
|
261
261
|
setModalOpen(true);
|
|
262
262
|
};
|
|
263
263
|
const openEdit = (addr: Address) => {
|
|
264
|
-
setEditAddress(addr);
|
|
264
|
+
setEditAddress({ ...addr });
|
|
265
265
|
setModalOpen(true);
|
|
266
266
|
};
|
|
267
|
-
|
|
267
|
+
|
|
268
|
+
const closeModal = () => {
|
|
269
|
+
setModalOpen(false);
|
|
270
|
+
setEditAddress(undefined);
|
|
271
|
+
};
|
|
268
272
|
|
|
269
273
|
// context value
|
|
270
274
|
const ctx: DeliveryAddressContextValue = {
|
|
@@ -322,6 +326,7 @@ DeliveryAddress.Modal = () => {
|
|
|
322
326
|
|
|
323
327
|
return (
|
|
324
328
|
<NewAddressForm
|
|
329
|
+
key={editAddress?.Id ?? "new"}
|
|
325
330
|
countries={countries ?? []}
|
|
326
331
|
open={modalOpen}
|
|
327
332
|
isGuest={isGuest}
|
|
@@ -336,7 +341,8 @@ DeliveryAddress.Modal = () => {
|
|
|
336
341
|
DeliveryAddress.Dropdown = () => {
|
|
337
342
|
const ctx = useContext(DeliveryAddressCtx);
|
|
338
343
|
if (!ctx) return null;
|
|
339
|
-
const { showDropDown, title, addressList, pickAddress } =
|
|
344
|
+
const { showDropDown, title, addressList, pickAddress, handleSaveAddress } =
|
|
345
|
+
ctx;
|
|
340
346
|
|
|
341
347
|
if (!showDropDown) return null;
|
|
342
348
|
|
|
@@ -355,9 +361,10 @@ DeliveryAddress.Dropdown = () => {
|
|
|
355
361
|
addressList.map((value, index) => (
|
|
356
362
|
<MenuItem
|
|
357
363
|
key={index}
|
|
358
|
-
onClick={() => {
|
|
364
|
+
onClick={async () => {
|
|
359
365
|
pickAddress(value.RecordId as number);
|
|
360
366
|
onClose();
|
|
367
|
+
await handleSaveAddress(value);
|
|
361
368
|
}}
|
|
362
369
|
>
|
|
363
370
|
{`${value.Name}, ${value.FullAddress}`}
|
|
@@ -73,10 +73,12 @@ const NewAddressForm = ({
|
|
|
73
73
|
const [selectedCountry, setSelectedCountry] =
|
|
74
74
|
React.useState<CountryRegionInfo | null>(defaultCountry);
|
|
75
75
|
|
|
76
|
-
const { data
|
|
76
|
+
const { data } = getStates.useData({
|
|
77
77
|
countryId: selectedCountry?.CountryRegionId,
|
|
78
78
|
});
|
|
79
79
|
|
|
80
|
+
const states = data ?? [];
|
|
81
|
+
|
|
80
82
|
const validationSchema = z.object({
|
|
81
83
|
name: z
|
|
82
84
|
.string()
|
|
@@ -145,6 +147,20 @@ const NewAddressForm = ({
|
|
|
145
147
|
}
|
|
146
148
|
}, [address, setValue, reset]);
|
|
147
149
|
|
|
150
|
+
// sync selectedCountry whenever address changes, not only on initial mount, so that state field populates.
|
|
151
|
+
React.useEffect(() => {
|
|
152
|
+
if (address) {
|
|
153
|
+
const sel =
|
|
154
|
+
countries.find(
|
|
155
|
+
(c) => c.CountryRegionId === address.ThreeLetterISORegionName,
|
|
156
|
+
) ?? null;
|
|
157
|
+
setSelectedCountry(sel);
|
|
158
|
+
if (sel) {
|
|
159
|
+
setValue("country", sel.CountryRegionId ?? "");
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}, [address, countries, setValue]);
|
|
163
|
+
|
|
148
164
|
const onFormSubmit = (data: AddressFormInput) => {
|
|
149
165
|
const tempAddress: Address = {
|
|
150
166
|
Name: data.name,
|
|
@@ -165,7 +181,7 @@ const NewAddressForm = ({
|
|
|
165
181
|
form,
|
|
166
182
|
countries,
|
|
167
183
|
states: states
|
|
168
|
-
? states
|
|
184
|
+
? states?.map((s) => ({
|
|
169
185
|
StateName: s.StateName ?? "",
|
|
170
186
|
StateId: s.StateId ?? "",
|
|
171
187
|
}))
|
|
@@ -216,7 +232,13 @@ const NewAddressForm = ({
|
|
|
216
232
|
};
|
|
217
233
|
|
|
218
234
|
// Generic text field
|
|
219
|
-
NewAddressForm.Field = ({
|
|
235
|
+
NewAddressForm.Field = ({
|
|
236
|
+
name,
|
|
237
|
+
label,
|
|
238
|
+
}: {
|
|
239
|
+
name: keyof AddressFormInput;
|
|
240
|
+
label: string;
|
|
241
|
+
}) => {
|
|
220
242
|
const ctx = React.useContext(FormContext);
|
|
221
243
|
if (!ctx) return null;
|
|
222
244
|
|
|
@@ -260,8 +282,8 @@ NewAddressForm.CountrySelect = () => {
|
|
|
260
282
|
}}
|
|
261
283
|
>
|
|
262
284
|
<MenuItem value="">Select country</MenuItem>
|
|
263
|
-
{countries.map((c) => (
|
|
264
|
-
<MenuItem key={c.CountryRegionId} value={c.CountryRegionId}>
|
|
285
|
+
{countries.map((c, index) => (
|
|
286
|
+
<MenuItem key={`${c.CountryRegionId}-${index}`} value={c.CountryRegionId}>
|
|
265
287
|
{c.ShortName}
|
|
266
288
|
</MenuItem>
|
|
267
289
|
))}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import Box from "@mui/material/Box";
|
|
2
2
|
import styled from "@mui/material/styles/styled";
|
|
3
|
+
import { Theme } from "@mui/material/styles";
|
|
3
4
|
|
|
4
|
-
const dropDownHandlerStyles = (theme) => ({
|
|
5
|
+
const dropDownHandlerStyles = (theme: Theme) => ({
|
|
5
6
|
width: 260,
|
|
6
7
|
minWidth: 260,
|
|
7
8
|
height: "100%",
|
package/src/pages-v2/checkout/checkout-alt-form/steps/customer-info/customer-information.tsx
CHANGED
|
@@ -9,11 +9,20 @@ import { Paragraph } from "@evenicanpm/storefront-core/src/components-v2/Typogra
|
|
|
9
9
|
import * as yup from "yup";
|
|
10
10
|
import { useForm } from "react-hook-form";
|
|
11
11
|
import { yupResolver } from "@hookform/resolvers/yup";
|
|
12
|
+
import type { SubmitHandler, UseFormReturn } from "react-hook-form";
|
|
13
|
+
import getUser from "@/api-manager/services/user/queries/get-user";
|
|
14
|
+
|
|
15
|
+
const vSchema = yup.object({
|
|
16
|
+
email: yup.string().email().required(),
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
type CustomerFormValues = yup.InferType<typeof vSchema>;
|
|
20
|
+
|
|
12
21
|
interface CustomerCtx extends CheckoutStepComponentProps {
|
|
13
22
|
email: string | null;
|
|
14
23
|
cartId: string;
|
|
15
|
-
form:
|
|
16
|
-
handleSave:
|
|
24
|
+
form: UseFormReturn<CustomerFormValues, undefined, CustomerFormValues>;
|
|
25
|
+
handleSave: SubmitHandler<CustomerFormValues>;
|
|
17
26
|
}
|
|
18
27
|
const CustomerContext = createContext<CustomerCtx | null>(null);
|
|
19
28
|
|
|
@@ -22,13 +31,24 @@ const CustomerInformation = (
|
|
|
22
31
|
) => {
|
|
23
32
|
const {
|
|
24
33
|
stepViewState,
|
|
25
|
-
cart: { Id: cartId, ReceiptEmail:
|
|
34
|
+
cart: { Id: cartId, ReceiptEmail: cartEmail },
|
|
26
35
|
stepSubmissionState,
|
|
27
36
|
setStepSubmissionState,
|
|
28
37
|
handleStepCompletion,
|
|
29
38
|
children,
|
|
30
39
|
} = props;
|
|
31
40
|
|
|
41
|
+
const { data: user, isLoading: userLoading } = getUser.useData();
|
|
42
|
+
const isGuest = !userLoading && !user?.RecordId;
|
|
43
|
+
|
|
44
|
+
const resolveEmail = () => {
|
|
45
|
+
if (isGuest) return cartEmail;
|
|
46
|
+
// In case of authenticated user, pick user email when no email in cart
|
|
47
|
+
return cartEmail || user?.Email || "";
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const email = resolveEmail();
|
|
51
|
+
|
|
32
52
|
const { mutateAsync: updateCart } = useUpdateCart();
|
|
33
53
|
const t = useTranslations("Checkout.CustomerInformation");
|
|
34
54
|
|
|
@@ -36,7 +56,7 @@ const CustomerInformation = (
|
|
|
36
56
|
email: yup.string().email(t("emailInvalid")).required(t("emailRequired")),
|
|
37
57
|
});
|
|
38
58
|
|
|
39
|
-
const form = useForm({
|
|
59
|
+
const form = useForm<CustomerFormValues, undefined, CustomerFormValues>({
|
|
40
60
|
defaultValues: { email: email || "" },
|
|
41
61
|
resolver: yupResolver(validationSchema),
|
|
42
62
|
});
|
|
@@ -47,8 +67,8 @@ const CustomerInformation = (
|
|
|
47
67
|
setValue("email", email || "");
|
|
48
68
|
}, [email, setValue]);
|
|
49
69
|
|
|
50
|
-
const handleSave = React.useCallback(
|
|
51
|
-
(formData
|
|
70
|
+
const handleSave: SubmitHandler<CustomerFormValues> = React.useCallback(
|
|
71
|
+
(formData) => {
|
|
52
72
|
updateCart({
|
|
53
73
|
cart: { ReceiptEmail: formData.email, Id: cartId },
|
|
54
74
|
})
|
|
@@ -79,7 +99,7 @@ const CustomerInformation = (
|
|
|
79
99
|
|
|
80
100
|
const ctx: CustomerCtx = {
|
|
81
101
|
...props,
|
|
82
|
-
email,
|
|
102
|
+
email: email ?? null,
|
|
83
103
|
cartId,
|
|
84
104
|
form,
|
|
85
105
|
handleSave,
|
|
@@ -115,7 +115,14 @@ const DeliveryOptions: DeliveryOptionsCompound = (props) => {
|
|
|
115
115
|
React.useEffect(() => {
|
|
116
116
|
if (currentShippingAddress) {
|
|
117
117
|
const { Id, CartLines } = cart;
|
|
118
|
-
|
|
118
|
+
// Filter out undefined values and assert string[]
|
|
119
|
+
const cartLineIds: string[] = CartLines.map((cl) => cl.LineId).filter(
|
|
120
|
+
(id): id is string => Boolean(id),
|
|
121
|
+
);
|
|
122
|
+
if (!Id || !cartLineIds?.length) {
|
|
123
|
+
setDeliveryOptions([]);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
119
126
|
getDeliveryOptions({
|
|
120
127
|
cartId: Id,
|
|
121
128
|
cartLineIds,
|
|
@@ -33,7 +33,11 @@ OrderAddress.Heading = ({ children }: { children?: ReactNode }) => {
|
|
|
33
33
|
);
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
OrderAddress.Field = ({
|
|
36
|
+
OrderAddress.Field = ({
|
|
37
|
+
property,
|
|
38
|
+
}: {
|
|
39
|
+
property: Exclude<keyof Address, "ExtensionProperties">;
|
|
40
|
+
}) => {
|
|
37
41
|
const ctx = useContext(AddressContext);
|
|
38
42
|
if (!ctx) return null;
|
|
39
43
|
const address = ctx;
|
|
@@ -6,7 +6,10 @@ import Card from "@mui/material/Card";
|
|
|
6
6
|
import Grid from "@mui/material/Grid2";
|
|
7
7
|
import Avatar from "@mui/material/Avatar";
|
|
8
8
|
// GLOBAL CUSTOM COMPONENTS
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
H3,
|
|
11
|
+
H4,
|
|
12
|
+
} from "@evenicanpm/storefront-core/src/components-v2/Typography";
|
|
10
13
|
import FlexRowCenter from "@evenicanpm/storefront-core/src/components-v2/flex-box/flex-row-center";
|
|
11
14
|
|
|
12
15
|
export default function AvailableShops() {
|
|
@@ -5,7 +5,7 @@ import { AddToCartBopisInput } from "@evenicanpm/storefront-core/src/hooks/use-c
|
|
|
5
5
|
import { useTranslations } from "next-intl";
|
|
6
6
|
|
|
7
7
|
type Props = {
|
|
8
|
-
productId
|
|
8
|
+
productId?: number;
|
|
9
9
|
allDimensionsSelected: boolean;
|
|
10
10
|
handleAddToCart: (bopisInput: AddToCartBopisInput) => void;
|
|
11
11
|
setDimensionsError: (state: boolean) => void;
|
|
@@ -22,7 +22,6 @@ import { geolocate } from "@/lib/map-helper";
|
|
|
22
22
|
import getStores from "@/api-manager/services/organization/queries/get-stores";
|
|
23
23
|
import { AddToCartBopisInput } from "@evenicanpm/storefront-core/src/hooks/use-cart";
|
|
24
24
|
import getProductAvailability from "@/api-manager/services/product/queries/get-product-availability";
|
|
25
|
-
import { InventorySearchCriteriaInput } from "@/api-manager/schemas/product.schema";
|
|
26
25
|
import { OrgUnitLocationReturnType } from "@/api-manager/schemas/organization.schema";
|
|
27
26
|
import { useTranslations } from "next-intl";
|
|
28
27
|
import getChannelConfiguration from "@/api-manager/services/organization/queries/get-channel-configuration";
|
|
@@ -31,7 +30,7 @@ type Props = {
|
|
|
31
30
|
open: boolean;
|
|
32
31
|
handleClose: () => void;
|
|
33
32
|
handleAddToCart: (bopisInput: AddToCartBopisInput) => void;
|
|
34
|
-
productId
|
|
33
|
+
productId?: number;
|
|
35
34
|
allDimensionsSelected: boolean;
|
|
36
35
|
};
|
|
37
36
|
|
|
@@ -87,12 +86,11 @@ const FindInStoreModal = ({
|
|
|
87
86
|
searchArea,
|
|
88
87
|
});
|
|
89
88
|
|
|
90
|
-
const inventoryInput
|
|
89
|
+
const inventoryInput = React.useMemo(
|
|
91
90
|
() => ({
|
|
92
|
-
allDimensionsSelected,
|
|
93
91
|
searchCriteria: {
|
|
94
92
|
defaultWarehouseOnly: false,
|
|
95
|
-
productIds: [productId],
|
|
93
|
+
productIds: [productId || 0],
|
|
96
94
|
searchArea,
|
|
97
95
|
},
|
|
98
96
|
}),
|
|
@@ -1,26 +1,31 @@
|
|
|
1
|
-
import { createContext } from "react";
|
|
1
|
+
import { createContext, Dispatch, SetStateAction, useContext } from "react";
|
|
2
2
|
import { ProductDetails } from "@/api-manager/schemas/product.schema";
|
|
3
3
|
import { SelectedDimensions } from "@evenicanpm/storefront-core/src/hooks/use-variants";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
ProductWarehouseInventoryInformation,
|
|
6
|
+
ProductDimensionValueInventoryAvailability,
|
|
7
|
+
} from "@msdyn365-commerce/retail-proxy";
|
|
5
8
|
|
|
6
9
|
export interface ProductIntroContext {
|
|
7
10
|
/** The current master product of the PDP */
|
|
8
11
|
masterProduct: ProductDetails;
|
|
9
12
|
/** The currently selected variant that is deduced from dimensions */
|
|
10
|
-
selectedVariant: ProductDetails;
|
|
13
|
+
selectedVariant: ProductDetails | undefined;
|
|
11
14
|
/** Is the data for variant loading? */
|
|
12
15
|
variantPending: boolean;
|
|
13
16
|
/** State that tracks which dimensions are currently selected */
|
|
14
17
|
selectDimensions: SelectedDimensions;
|
|
15
18
|
/** Handler for when dimensions are selected **/
|
|
16
|
-
handleChangeVariant: (
|
|
19
|
+
handleChangeVariant: (
|
|
20
|
+
dimensionValue: ProductDimensionValueInventoryAvailability,
|
|
21
|
+
) => void;
|
|
17
22
|
/** Calculated value are all dimensions selected? **/
|
|
18
23
|
allDimensionsSelected: boolean;
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
export interface ProductImagesContext {
|
|
22
27
|
/** Currently selected index from images array of product details */
|
|
23
|
-
selectedImageIndex
|
|
28
|
+
selectedImageIndex: number;
|
|
24
29
|
/** The default image to show on PDP */
|
|
25
30
|
primaryImageUrl: string;
|
|
26
31
|
/* Handler when thumbnails are clicked */
|
|
@@ -32,18 +37,70 @@ export interface ProductImagesContext {
|
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
export interface ProductInfoContext {
|
|
35
|
-
/**
|
|
36
|
-
|
|
40
|
+
/** Does the product have variants? If not we do not verify dimensions before adding to cart etc. **/
|
|
41
|
+
hasVariants: boolean;
|
|
37
42
|
/** **/
|
|
38
43
|
inventoryPending: boolean;
|
|
39
44
|
/** */
|
|
40
|
-
shippingInventoryData: ProductWarehouseInventoryInformation;
|
|
45
|
+
shippingInventoryData: ProductWarehouseInventoryInformation | undefined;
|
|
41
46
|
/** */
|
|
42
47
|
showDimensionError: boolean;
|
|
43
48
|
/** */
|
|
44
|
-
setShowDimensionError:
|
|
49
|
+
setShowDimensionError: Dispatch<SetStateAction<boolean>>;
|
|
45
50
|
}
|
|
46
51
|
|
|
47
|
-
export const ProductImagesContext = createContext(
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
export const ProductImagesContext = createContext<ProductImagesContext | null>(
|
|
53
|
+
null,
|
|
54
|
+
);
|
|
55
|
+
export const ProductIntroContext = createContext<ProductIntroContext | null>(
|
|
56
|
+
null,
|
|
57
|
+
);
|
|
58
|
+
export const ProductInfoContext = createContext<ProductInfoContext | null>(
|
|
59
|
+
null,
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Hook to safely access ProductImagesContext
|
|
64
|
+
* @throws {Error} When used outside of ProductImagesProvider
|
|
65
|
+
*/
|
|
66
|
+
export const useProductImages = () => {
|
|
67
|
+
const context = useContext(ProductImagesContext);
|
|
68
|
+
|
|
69
|
+
if (context === null) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
"useProductImages must be used within a ProductImagesProvider",
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return context;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Hook to safely access ProductIntroContext
|
|
80
|
+
* @throws {Error} When used outside of ProductIntroProvider
|
|
81
|
+
*/
|
|
82
|
+
export const useProductIntro = () => {
|
|
83
|
+
const context = useContext(ProductIntroContext);
|
|
84
|
+
|
|
85
|
+
if (context === null) {
|
|
86
|
+
throw new Error(
|
|
87
|
+
"useProductIntro must be used within a ProductIntroProvider",
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return context;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Hook to safely access ProductInfoContext
|
|
96
|
+
* @throws {Error} When used outside of ProductInfoProvider
|
|
97
|
+
*/
|
|
98
|
+
export const useProductInfo = () => {
|
|
99
|
+
const context = useContext(ProductInfoContext);
|
|
100
|
+
|
|
101
|
+
if (context === null) {
|
|
102
|
+
throw new Error("useProductInfo must be used within a ProductInfoProvider");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return context;
|
|
106
|
+
};
|
|
@@ -29,7 +29,8 @@ import useCart, {
|
|
|
29
29
|
import ProductDimensions from "@evenicanpm/storefront-core/src/components-v2/product-dimensions";
|
|
30
30
|
import FindInStoreButton from "@evenicanpm/storefront-core/src/pages-v2/product-details/bopis/find-in-store-button";
|
|
31
31
|
import {
|
|
32
|
-
|
|
32
|
+
useProductInfo,
|
|
33
|
+
useProductIntro,
|
|
33
34
|
ProductInfoContext,
|
|
34
35
|
} from "@evenicanpm/storefront-core/src/pages-v2/product-details/product-intro/compound/context";
|
|
35
36
|
|
|
@@ -48,19 +49,27 @@ export interface Props {
|
|
|
48
49
|
*/
|
|
49
50
|
const ProductInfo = ({ children }: Props) => {
|
|
50
51
|
const [showDimensionError, setShowDimensionError] = useState(false);
|
|
51
|
-
const { selectedVariant } =
|
|
52
|
+
const { masterProduct, selectedVariant } = useProductIntro();
|
|
52
53
|
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
const hasVariants = masterProduct?.Dimensions?.length !== 0;
|
|
55
|
+
|
|
56
|
+
const id = hasVariants ? selectedVariant?.RecordId : masterProduct?.RecordId;
|
|
57
|
+
|
|
58
|
+
const shippingInventorySearchCriteria =
|
|
59
|
+
!hasVariants || selectedVariant
|
|
60
|
+
? buildInventorySearchCriteria(id as number)
|
|
61
|
+
: null;
|
|
56
62
|
|
|
57
63
|
// Query disabled if the input is null
|
|
58
64
|
const { data: shippingInventoryData, isLoading: inventoryPending } =
|
|
59
|
-
getProductAvailability.useData(shippingInventorySearchCriteria
|
|
65
|
+
getProductAvailability.useData(shippingInventorySearchCriteria, {
|
|
66
|
+
enabled: !!shippingInventorySearchCriteria,
|
|
67
|
+
});
|
|
60
68
|
|
|
61
69
|
return (
|
|
62
70
|
<ProductInfoContext.Provider
|
|
63
71
|
value={{
|
|
72
|
+
hasVariants,
|
|
64
73
|
inventoryPending,
|
|
65
74
|
shippingInventoryData,
|
|
66
75
|
showDimensionError,
|
|
@@ -78,7 +87,12 @@ const ProductInfo = ({ children }: Props) => {
|
|
|
78
87
|
* @category Sub-Component
|
|
79
88
|
*/
|
|
80
89
|
ProductInfo.Name = () => {
|
|
81
|
-
const
|
|
90
|
+
const IntroCtx = useProductIntro();
|
|
91
|
+
if (!IntroCtx)
|
|
92
|
+
throw new Error(
|
|
93
|
+
"ProductInfo.Inventory must be wrapped in ProductInfoContext and a ProductIntroContext",
|
|
94
|
+
);
|
|
95
|
+
const { masterProduct } = IntroCtx;
|
|
82
96
|
return <H1 mb={1}>{masterProduct.Name}</H1>;
|
|
83
97
|
};
|
|
84
98
|
|
|
@@ -86,7 +100,12 @@ ProductInfo.Name = () => {
|
|
|
86
100
|
* @category Sub-Component
|
|
87
101
|
*/
|
|
88
102
|
ProductInfo.Sku = () => {
|
|
89
|
-
const
|
|
103
|
+
const IntroCtx = useProductIntro();
|
|
104
|
+
if (!IntroCtx)
|
|
105
|
+
throw new Error(
|
|
106
|
+
"ProductInfo.Inventory must be wrapped in ProductInfoContext and a ProductIntroContext",
|
|
107
|
+
);
|
|
108
|
+
const { masterProduct, selectedVariant } = IntroCtx;
|
|
90
109
|
return (
|
|
91
110
|
<FlexBox alignItems="center" mb={1}>
|
|
92
111
|
<H6>SKU: {selectedVariant?.ItemId || masterProduct.ItemId}</H6>
|
|
@@ -111,9 +130,19 @@ ProductInfo.Sku = () => {
|
|
|
111
130
|
* @category Sub-Component
|
|
112
131
|
*/
|
|
113
132
|
ProductInfo.Dimensions = () => {
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
133
|
+
const InfoCtx = useContext(ProductInfoContext);
|
|
134
|
+
const IntroCtx = useProductIntro();
|
|
135
|
+
if (!InfoCtx || !IntroCtx)
|
|
136
|
+
throw new Error(
|
|
137
|
+
"ProductInfo.Inventory must be wrapped in ProductInfoContext and a ProductIntroContext",
|
|
138
|
+
);
|
|
139
|
+
if (!IntroCtx)
|
|
140
|
+
throw new Error(
|
|
141
|
+
"ProductInfo.Inventory must be wrapped in ProductInfoContext and a ProductIntroContext",
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
const { masterProduct, selectDimensions, handleChangeVariant } = IntroCtx;
|
|
145
|
+
const { showDimensionError } = InfoCtx;
|
|
117
146
|
return (
|
|
118
147
|
<ProductDimensions
|
|
119
148
|
dimensionGroups={masterProduct.DimensionValues}
|
|
@@ -125,7 +154,12 @@ ProductInfo.Dimensions = () => {
|
|
|
125
154
|
};
|
|
126
155
|
|
|
127
156
|
ProductInfo.Price = () => {
|
|
128
|
-
const
|
|
157
|
+
const IntroCtx = useProductIntro();
|
|
158
|
+
if (!IntroCtx)
|
|
159
|
+
throw new Error(
|
|
160
|
+
"ProductInfo.Inventory must be wrapped in ProductInfoContext and a ProductIntroContext",
|
|
161
|
+
);
|
|
162
|
+
const { masterProduct, selectedVariant } = IntroCtx;
|
|
129
163
|
const { formatCurrency } = useCurrencyFormatter();
|
|
130
164
|
|
|
131
165
|
const { data: productPrices, isPending: pricesPending } =
|
|
@@ -139,7 +173,7 @@ ProductInfo.Price = () => {
|
|
|
139
173
|
{pricesPending || !productPrices ? (
|
|
140
174
|
<CircularProgress size={20} />
|
|
141
175
|
) : (
|
|
142
|
-
formatCurrency(productPrices?.[0]?.CustomerContextualPrice)
|
|
176
|
+
formatCurrency(productPrices?.[0]?.CustomerContextualPrice || 0)
|
|
143
177
|
)}
|
|
144
178
|
</H2>
|
|
145
179
|
<Box color="inherit">{}</Box>
|
|
@@ -151,11 +185,14 @@ ProductInfo.Price = () => {
|
|
|
151
185
|
* @category Sub-Component
|
|
152
186
|
*/
|
|
153
187
|
ProductInfo.Inventory = () => {
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
188
|
+
const InfoCtx = useContext(ProductInfoContext);
|
|
189
|
+
const IntroCtx = useProductIntro();
|
|
190
|
+
if (!InfoCtx || !IntroCtx)
|
|
191
|
+
throw new Error(
|
|
192
|
+
"ProductInfo.Inventory must be wrapped in ProductInfoContext and a ProductIntroContext",
|
|
193
|
+
);
|
|
194
|
+
const { variantPending, allDimensionsSelected } = IntroCtx;
|
|
195
|
+
const { shippingInventoryData, inventoryPending } = InfoCtx;
|
|
159
196
|
if (!allDimensionsSelected)
|
|
160
197
|
return (
|
|
161
198
|
<FlexBox alignItems="center" gap={1}>
|
|
@@ -186,14 +223,21 @@ ProductInfo.Inventory = () => {
|
|
|
186
223
|
};
|
|
187
224
|
|
|
188
225
|
/**
|
|
226
|
+
* These are grouped together because they have similar functionality and callbacks
|
|
227
|
+
* addToCart Etc
|
|
189
228
|
* @category Sub-Component
|
|
190
229
|
*/
|
|
191
230
|
ProductInfo.Buttons = () => {
|
|
192
231
|
const { masterProduct, selectedVariant, allDimensionsSelected } =
|
|
193
|
-
|
|
194
|
-
const { setShowDimensionError, shippingInventoryData } =
|
|
195
|
-
|
|
196
|
-
|
|
232
|
+
useProductIntro();
|
|
233
|
+
const { setShowDimensionError, shippingInventoryData, hasVariants } =
|
|
234
|
+
useProductInfo();
|
|
235
|
+
|
|
236
|
+
const productId = hasVariants
|
|
237
|
+
? selectedVariant?.RecordId
|
|
238
|
+
: masterProduct?.RecordId;
|
|
239
|
+
|
|
240
|
+
const { handleAddToCart } = useCart(productId);
|
|
197
241
|
|
|
198
242
|
/**
|
|
199
243
|
* A wrapper around the add to cart handler that
|
|
@@ -208,24 +252,26 @@ ProductInfo.Buttons = () => {
|
|
|
208
252
|
handleAddToCart(bopisInput);
|
|
209
253
|
};
|
|
210
254
|
|
|
211
|
-
const isOOS =
|
|
255
|
+
const isOOS = hasVariants
|
|
256
|
+
? allDimensionsSelected && checkProductOOS(shippingInventoryData)
|
|
257
|
+
: checkProductOOS(shippingInventoryData);
|
|
212
258
|
|
|
213
259
|
return (
|
|
214
260
|
<FlexBox gap={2}>
|
|
215
261
|
<QuantityButtons
|
|
216
262
|
customAddToCart={onAddToCart}
|
|
217
263
|
isOOS={isOOS}
|
|
218
|
-
productId={
|
|
264
|
+
productId={productId}
|
|
219
265
|
/>
|
|
220
266
|
<FindInStoreButton
|
|
221
267
|
setDimensionsError={setShowDimensionError}
|
|
222
|
-
productId={
|
|
223
|
-
handleAddToCart={
|
|
268
|
+
productId={productId}
|
|
269
|
+
handleAddToCart={handleAddToCart}
|
|
224
270
|
allDimensionsSelected={allDimensionsSelected}
|
|
225
271
|
/>
|
|
226
272
|
<AddToWishlistButton
|
|
227
273
|
path="Account.Wishlists.btnAddToWishlist"
|
|
228
|
-
|
|
274
|
+
productId={masterProduct?.RecordId}
|
|
229
275
|
/>
|
|
230
276
|
</FlexBox>
|
|
231
277
|
);
|
|
@@ -23,7 +23,10 @@ type Props = {
|
|
|
23
23
|
export default function ProductImages({ children }: Props) {
|
|
24
24
|
const [selectedImageIndex, setSelectedImageIndex] = useState<number>(0);
|
|
25
25
|
|
|
26
|
-
const
|
|
26
|
+
const ctx = useContext(ProductIntroContext);
|
|
27
|
+
if (!ctx)
|
|
28
|
+
throw new Error("ProductImages must be used inside a ProductIntroContext");
|
|
29
|
+
const { selectedVariant, masterProduct } = ctx;
|
|
27
30
|
const { Name } = masterProduct;
|
|
28
31
|
|
|
29
32
|
/**
|
|
@@ -38,7 +41,7 @@ export default function ProductImages({ children }: Props) {
|
|
|
38
41
|
: [];
|
|
39
42
|
|
|
40
43
|
const primaryImageUrl =
|
|
41
|
-
selectedVariant?.
|
|
44
|
+
selectedVariant?.PrimaryImageUrl || masterProduct?.PrimaryImageUrl || "";
|
|
42
45
|
|
|
43
46
|
// HANDLE SELECT IMAGE
|
|
44
47
|
const handleImageClick = (ind: number) => () => {
|
|
@@ -67,8 +70,13 @@ export default function ProductImages({ children }: Props) {
|
|
|
67
70
|
* @category Sub-Component
|
|
68
71
|
*/
|
|
69
72
|
ProductImages.Thumbnails = () => {
|
|
70
|
-
const
|
|
71
|
-
|
|
73
|
+
const ctx = useContext(ProductImagesContext);
|
|
74
|
+
if (!ctx)
|
|
75
|
+
throw new Error(
|
|
76
|
+
"ProductImages.Main must be used inside a product images context",
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
const { images, handleImageClick, selectedImageIndex } = ctx;
|
|
72
80
|
|
|
73
81
|
return (
|
|
74
82
|
<>
|
|
@@ -104,8 +112,13 @@ ProductImages.Thumbnails = () => {
|
|
|
104
112
|
* @category Sub-Component
|
|
105
113
|
*/
|
|
106
114
|
ProductImages.Main = () => {
|
|
107
|
-
const
|
|
108
|
-
|
|
115
|
+
const ctx = useContext(ProductImagesContext);
|
|
116
|
+
if (!ctx)
|
|
117
|
+
throw new Error(
|
|
118
|
+
"ProductImages.Main must be used inside a product images context",
|
|
119
|
+
);
|
|
120
|
+
const { name, images, primaryImageUrl, selectedImageIndex } = ctx;
|
|
121
|
+
|
|
109
122
|
return (
|
|
110
123
|
<FlexBox borderRadius={3} overflow="hidden" justifyContent="center" mb={6}>
|
|
111
124
|
<ImageWithFallback
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ProductWarehouseInventoryInformation } from "@msdyn365-commerce/retail-proxy";
|
|
2
2
|
|
|
3
3
|
export const getInventoryLabel = (
|
|
4
|
-
shippingInventoryData
|
|
4
|
+
shippingInventoryData?: ProductWarehouseInventoryInformation,
|
|
5
5
|
): string | null => {
|
|
6
6
|
const aggregate =
|
|
7
7
|
shippingInventoryData?.AggregatedProductInventoryAvailabilities &&
|
|
@@ -14,7 +14,7 @@ export const getInventoryLabel = (
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
export const checkProductOOS = (
|
|
17
|
-
shippingInventoryData
|
|
17
|
+
shippingInventoryData?: ProductWarehouseInventoryInformation,
|
|
18
18
|
) => {
|
|
19
19
|
//TODO: Incorporate global inventory enabled flag.
|
|
20
20
|
const OOSCode = "OOS"; // Always means out of stock
|