@evenicanpm/storefront-core 1.8.4 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.storybook/main.ts +2 -3
- package/.storybook/preview.tsx +0 -2
- package/__mocks__/create-mutation.ts +16 -8
- package/__mocks__/next-image.tsx +12 -3
- package/docs.tsconfig.json +5 -5
- package/package.json +3 -3
- package/src/api-manager/datasources/d365/d365-cart.datasource.ts +13 -8
- package/src/api-manager/datasources/d365/d365-categories.datasource.ts +2 -3
- package/src/api-manager/datasources/d365/d365-order.datasource.ts +4 -4
- package/src/api-manager/datasources/d365/d365-organization.datasource.ts +15 -8
- package/src/api-manager/datasources/d365/d365-product.datasource.ts +34 -19
- package/src/api-manager/datasources/d365/d365-user.datasource.ts +47 -19
- package/src/api-manager/datasources/e4/address/e4-address.remaps.ts +2 -2
- package/src/api-manager/datasources/e4/cart/e4-cart.datasource.ts +7 -5
- package/src/api-manager/datasources/e4/cart/e4-cart.remaps.ts +1 -1
- package/src/api-manager/datasources/e4/categories/e4-categories.translator.ts +3 -3
- package/src/api-manager/datasources/e4/product/e4-product.remaps.ts +3 -3
- package/src/api-manager/datasources/e4/product/e4-product.translator.ts +3 -1
- package/src/api-manager/datasources/e4/user/e4-user.datasource.ts +4 -8
- package/src/api-manager/index.ts +10 -128
- package/src/api-manager/lib/category-helpers.ts +1 -1
- package/src/api-manager/lib/get-graphql-client.ts +2 -2
- package/src/api-manager/schemas/product.schema.ts +9 -0
- package/src/api-manager/services/create-extension-query.ts +1 -1
- package/src/api-manager/services/create-query.ts +106 -266
- package/src/api-manager/types/Datasource.ts +0 -3
- package/src/auth/auth-options.test.ts +1 -1
- package/src/auth/msal.ts +1 -1
- package/src/auth/providers/entra-external-id-provider.ts +1 -1
- package/src/auth/providers/index.ts +1 -1
- package/src/cms/blocks/components/category-card.tsx +0 -1
- package/src/cms/blocks/components/category-carousel/index.tsx +3 -4
- package/src/cms/blocks/components/featured-categories.tsx +1 -2
- package/src/cms/blocks/components/featured-products.tsx +1 -2
- package/src/cms/blocks/components/footer/index.tsx +1 -2
- package/src/cms/blocks/components/footer/sections/footer-app-store.tsx +2 -2
- package/src/cms/blocks/components/footer/sections/footer-contact.tsx +1 -2
- package/src/cms/blocks/components/footer/sections/footer-links.tsx +1 -1
- package/src/cms/blocks/components/footer/sections/footer-logo.tsx +2 -3
- package/src/cms/blocks/components/footer/sections/footer-social-links.tsx +7 -3
- package/src/cms/blocks/components/footer.tsx +0 -1
- package/src/cms/blocks/components/hero-carousel/index.tsx +2 -3
- package/src/cms/blocks/components/hero.tsx +0 -1
- package/src/cms/blocks/components/image.tsx +0 -1
- package/src/cms/blocks/components/media-card.tsx +0 -1
- package/src/cms/blocks/components/product-carousel/index.tsx +3 -4
- package/src/cms/blocks/components/product-section-fullwidth/index.tsx +4 -5
- package/src/cms/blocks/components/rich-text.tsx +0 -1
- package/src/cms/blocks/components/seo/index.tsx +1 -2
- package/src/cms/blocks/components/services/index.tsx +0 -1
- package/src/cms/blocks/components/services/service-card.tsx +1 -2
- package/src/cms/blocks/components/shared/featured-product-card.tsx +3 -4
- package/src/cms/blocks/components/shared/product-category-item.tsx +4 -4
- package/src/cms/blocks/components/shared/product-grid.tsx +2 -3
- package/src/cms/blocks/components/shared/top-categories-card.tsx +2 -3
- package/src/cms/blocks/components/shared/top-rating-product-card.tsx +4 -5
- package/src/cms/blocks/icons/components/category.tsx +1 -1
- package/src/cms/blocks/icons/components/dotted-star.tsx +1 -1
- package/src/cms/blocks/icons/components/fallback-icon.tsx +0 -1
- package/src/cms/blocks/icons/components/gift-box.tsx +1 -1
- package/src/cms/blocks/icons/components/light.tsx +1 -1
- package/src/cms/blocks/icons/components/new-arrival.tsx +1 -1
- package/src/cms/blocks/icons/components/rank-badge.tsx +1 -1
- package/src/cms/blocks/icons/index.ts +1 -6
- package/src/{components-v2 → components}/BazaarTextField.tsx +8 -8
- package/src/{components-v2 → components}/CountryInput.stories.tsx +4 -2
- package/src/{components-v2 → components}/DropZone.tsx +1 -1
- package/src/{components-v2 → components}/ImageWithFallback.tsx +1 -1
- package/src/{components-v2 → components}/T/__tests__/T.test.tsx +9 -13
- package/src/{components-v2 → components}/T/index.tsx +0 -1
- package/src/{components-v2 → components}/Typography.tsx +0 -1
- package/src/components/_tests_/BazaarCard.test.tsx +16 -0
- package/src/components/_tests_/BazaarImage.test.tsx +18 -0
- package/src/components/_tests_/BazaarMenu.test.tsx +46 -0
- package/src/components/_tests_/BazaarSwitch.test.tsx +17 -0
- package/src/components/_tests_/BazaarTextField.test.tsx +22 -0
- package/src/components/_tests_/BoxShadowCard.test.tsx +14 -0
- package/src/components/_tests_/DropZone.test.tsx +51 -0
- package/src/components/_tests_/HoverBox.test.tsx +9 -0
- package/src/components/_tests_/Image.test.tsx +12 -0
- package/src/components/_tests_/ImageWithFallback.test.tsx +76 -0
- package/src/components/_tests_/LazyImage.test.tsx +32 -0
- package/src/components/_tests_/Loading.test.tsx +15 -0
- package/src/components/_tests_/SearchInput.test.tsx +14 -0
- package/src/components/_tests_/SnackbarProvider.test.tsx +22 -0
- package/src/components/_tests_/Typography.test.tsx +53 -0
- package/src/components/_tests_/WhiteButton.test.tsx +20 -0
- package/src/components/_tests_/countries-input.test.tsx +39 -0
- package/src/components/_tests_/no-records.test.tsx +14 -0
- package/src/components/_tests_/site-logo.test.tsx +28 -0
- package/src/{components-v2 → components}/accordion/accordion-header.tsx +1 -1
- package/src/{components-v2 → components}/accordion/index.ts +1 -1
- package/src/{components-v2 → components}/carousel/carousel.tsx +3 -3
- package/src/{components-v2 → components}/carousel/components/carousel-arrows.tsx +1 -1
- package/src/{components-v2 → components}/carousel/components/carousel-dots.tsx +1 -1
- package/src/{components-v2 → components}/carousel/index.ts +1 -1
- package/src/{components-v2 → components}/carousel-cards/carousel-card-1/carousel-card-1.tsx +3 -3
- package/src/components/carousel-cards/carousel-card-1/index.ts +1 -0
- package/src/{components-v2 → components}/categories/Categories.stories.tsx +1 -1
- package/src/{components-v2 → components}/categories/__tests__/category-menu.test.tsx +1 -1
- package/src/{components-v2 → components}/categories/category-list/category-list.tsx +5 -5
- package/src/{components-v2/navbar/mega-menu → components/categories/category-list}/index.ts +1 -1
- package/src/{components-v2 → components}/categories/category-list/styles.ts +1 -1
- package/src/{components-v2 → components}/categories/category-list-item/category-menu-item.tsx +1 -1
- package/src/components/categories/category-list-item/index.ts +1 -0
- package/src/{components-v2 → components}/categories/category-menu.tsx +1 -1
- package/src/{components-v2 → components}/categories/mega-menu/banner.tsx +3 -3
- package/src/{components-v2 → components}/categories/mega-menu/column-list.tsx +4 -4
- package/src/{components-v2 → components}/categories/mega-menu/mega-menu-1.tsx +3 -3
- package/src/{components-v2 → components}/categories/mega-menu/mega-menu-2.tsx +4 -4
- package/src/{components-v2 → components}/countries-input.tsx +1 -1
- package/src/{components-v2 → components}/flex-box/__tests__/flex-box.test.tsx +6 -8
- package/src/components/flex-box/index.ts +5 -0
- package/src/{components-v2 → components}/header/__tests__/header.test.tsx +8 -4
- package/src/{components-v2 → components}/header/__tests__/user.test.tsx +1 -1
- package/src/{components-v2 → components}/header/components/categories-menu.tsx +3 -3
- package/src/{components-v2 → components}/header/components/mobile-header.tsx +11 -11
- package/src/{components-v2 → components}/header/components/user.tsx +3 -3
- package/src/{components-v2 → components}/header/header.tsx +6 -6
- package/src/{components-v2 → components}/header/index.ts +1 -1
- package/src/{components-v2 → components}/header/sticky-header.tsx +3 -3
- package/src/{components-v2 → components}/icons/cart-bag.tsx +1 -0
- package/src/{components-v2 → components}/icons/category-outline.tsx +1 -0
- package/src/{components-v2 → components}/icons/category.tsx +1 -0
- package/src/{components-v2 → components}/icons/home.tsx +1 -0
- package/src/{components-v2 → components}/icons/search.tsx +1 -0
- package/src/{components-v2 → components}/icons/shopping-bag-outlined.tsx +1 -0
- package/src/{components-v2 → components}/icons/up-down.tsx +1 -0
- package/src/{components-v2 → components}/icons/user.tsx +1 -0
- package/src/{components-v2 → components}/icons/user2.tsx +1 -0
- package/src/{components-v2 → components}/mini-cart/components/cart-item.tsx +2 -2
- package/src/{components-v2 → components}/mini-cart/components/empty-view.tsx +2 -2
- package/src/{components-v2 → components}/mini-cart/components/top-header.tsx +2 -2
- package/src/{components-v2 → components}/mini-cart/index.ts +1 -1
- package/src/{components-v2 → components}/mini-cart/mini-cart-trigger.tsx +3 -5
- package/src/{components-v2 → components}/mini-cart/mini-cart.tsx +5 -5
- package/src/{components-v2 → components}/mobile-navigation/MobileNavigationBar.stories.tsx +2 -2
- package/src/{components-v2 → components}/mobile-navigation/index.ts +1 -1
- package/src/{components-v2 → components}/mobile-navigation/mobile-navigation-bar.tsx +5 -5
- package/src/{components-v2 → components}/mobile-navigation/styles/index.ts +2 -2
- package/src/{components-v2 → components}/nav-link/__tests__/nav-link.test.tsx +2 -1
- package/src/{components-v2 → components}/nav-link/index.ts +3 -3
- package/src/{components-v2 → components}/nav-link/nav-link-2.tsx +1 -1
- package/src/{components-v2 → components}/nav-link/nav-link-3.tsx +1 -1
- package/src/{components-v2 → components}/nav-link/nav-link.tsx +20 -10
- package/src/{components-v2 → components}/navbar/__tests__/navbar.test.tsx +4 -7
- package/src/{components-v2 → components}/navbar/categories.tsx +4 -4
- package/src/{components-v2 → components}/navbar/category-based-menu/category-based-menu.tsx +5 -5
- package/src/components/navbar/category-based-menu/index.ts +1 -0
- package/src/{components-v2 → components}/navbar/category-based-menu/styles.ts +4 -4
- package/src/{components-v2 → components}/navbar/index.ts +1 -1
- package/src/components/navbar/mega-menu/index.ts +1 -0
- package/src/{components-v2 → components}/navbar/mega-menu/mega-menu.tsx +10 -4
- package/src/{components-v2 → components}/navbar/mega-menu/styles.ts +1 -1
- package/src/{components-v2 → components}/navbar/mobile-menu/index.ts +1 -1
- package/src/{components-v2 → components}/navbar/mobile-menu/mobile-menu.test.tsx +4 -3
- package/src/{components-v2 → components}/navbar/mobile-menu/mobile-menu.tsx +4 -4
- package/src/{components-v2 → components}/navbar/nav-list/cms-nav.test.tsx +1 -2
- package/src/components/navbar/nav-list/index.ts +1 -0
- package/src/{components-v2 → components}/navbar/nav-list/nav-item-child.tsx +4 -4
- package/src/{components-v2 → components}/navbar/nav-list/nav-list.tsx +8 -8
- package/src/{components-v2 → components}/navbar/navbar.tsx +3 -3
- package/src/{components-v2 → components}/navbar/styles.ts +2 -2
- package/src/{components-v2 → components}/navbar/utils/transform-nav.test.ts +1 -1
- package/src/{components-v2 → components}/no-records.tsx +1 -2
- package/src/{components-v2 → components}/product-cards/favorite-button.tsx +0 -1
- package/src/{components-v2/navbar/nav-list → components/product-cards/product-card}/index.ts +1 -1
- package/src/{components-v2 → components}/product-cards/product-card/product-card.tsx +11 -11
- package/src/{components-v2 → components}/product-cards/product-card/styles/index.ts +3 -3
- package/src/{components-v2/categories/category-list → components/product-cards/product-card-plp}/index.ts +1 -1
- package/src/{components-v2 → components}/product-cards/product-card-plp/product-card.tsx +9 -9
- package/src/{components-v2 → components}/product-cards/product-card-plp-list/ProductCardPlpList.stories.tsx +0 -1
- package/src/components/product-cards/product-card-plp-list/index.ts +1 -0
- package/src/{components-v2 → components}/product-cards/product-card-plp-list/product-card.tsx +9 -9
- package/src/{components-v2 → components}/product-cards/product-card-search/ProductCardSearch.stories.tsx +0 -1
- package/src/components/product-cards/product-card-search/index.ts +1 -0
- package/src/{components-v2 → components}/product-cards/product-card-search/product-card.tsx +7 -7
- package/src/{components-v2 → components}/product-cards/product-price.tsx +2 -2
- package/src/{components-v2 → components}/product-cards/product-rating.tsx +2 -2
- package/src/{components-v2 → components}/product-cards/product-title.tsx +1 -1
- package/src/{components-v2 → components}/product-cards/quantity-buttons.tsx +2 -2
- package/src/{components-v2 → components}/product-dialog/__tests__/product-dialog.test.tsx +1 -1
- package/src/{components-v2 → components}/product-dialog/compound/product-dialog.tsx +5 -5
- package/src/{components-v2 → components}/product-dialog/index.tsx +1 -1
- package/src/{components-v2 → components}/product-dimensions/Dimensions.stories.tsx +2 -4
- package/src/{components-v2 → components}/product-dimensions/__tests__/product-dimensions.test.tsx +2 -2
- package/src/{components-v2 → components}/product-dimensions/compound/dimensions-group-error.tsx +4 -4
- package/src/{components-v2 → components}/product-dimensions/compound/dimensions-group-label.tsx +2 -2
- package/src/{components-v2 → components}/product-dimensions/compound/dimensions-group-list-chip.tsx +2 -2
- package/src/{components-v2 → components}/product-dimensions/compound/dimensions-group-list.tsx +2 -2
- package/src/{components-v2 → components}/product-dimensions/compound/dimensions-group.tsx +3 -3
- package/src/{components-v2 → components}/product-dimensions/compound/dimensions.tsx +2 -2
- package/src/{components-v2 → components}/product-dimensions/index.tsx +1 -1
- package/src/{components-v2 → components}/product-quantity-buttons/ProductQuantity.stories.tsx +1 -3
- package/src/{components-v2 → components}/product-quantity-buttons/__tests__/product-quantity-buttons.test.tsx +12 -2
- package/src/{components-v2 → components}/product-quantity-buttons/compound/quantity-buttons-root.tsx +3 -3
- package/src/{components-v2 → components}/product-quantity-buttons/index.tsx +1 -2
- package/src/{components-v2 → components}/product-quantity-variants/ProductQuantity.stories.tsx +1 -3
- package/src/{components-v2 → components}/product-quantity-variants/__tests__/product-quantity-variants.test.tsx +6 -4
- package/src/{components-v2 → components}/product-quantity-variants/index.tsx +2 -2
- package/src/{components-v2 → components}/products-view/ProductsGrid.stories.tsx +1 -3
- package/src/{components-v2 → components}/products-view/ProductsList.stories.tsx +1 -3
- package/src/{components-v2 → components}/products-view/__tests__/products-view.test.tsx +31 -12
- package/src/{components-v2 → components}/products-view/compound/products-grid-view.tsx +7 -7
- package/src/{components-v2 → components}/products-view/compound/products-list-view.tsx +4 -4
- package/src/{components-v2 → components}/products-view/compound/types.ts +1 -1
- package/src/{components-v2 → components}/products-view/index.tsx +3 -3
- package/src/{components-v2/side-nav → components/progress}/index.ts +1 -1
- package/src/{components-v2 → components}/progress/progress.tsx +3 -3
- package/src/{components-v2 → components}/scrollbar/Scrollbar.stories.tsx +1 -3
- package/src/{components-v2 → components}/scrollbar/__tests__/scrollbar.test.tsx +7 -1
- package/src/{components-v2/progress → components/scrollbar}/index.ts +1 -1
- package/src/{components-v2 → components}/scrollbar/scrollbar.tsx +1 -1
- package/src/{components-v2 → components}/search-bar/SearchBarLarge.stories.tsx +1 -3
- package/src/{components-v2 → components}/search-bar/__tests__/search-bar.test.tsx +7 -1
- package/src/{components-v2 → components}/search-bar/compound/results-item-lg.tsx +2 -3
- package/src/{components-v2 → components}/search-bar/compound/results-item-sm.tsx +4 -5
- package/src/{components-v2 → components}/search-bar/compound/results-suspense.tsx +5 -5
- package/src/{components-v2 → components}/search-bar/compound/results.tsx +2 -2
- package/src/{components-v2 → components}/search-bar/compound/search-bar-root.tsx +5 -5
- package/src/{components-v2 → components}/search-bar/compound/textfield-adornment-category.tsx +3 -4
- package/src/{components-v2 → components}/search-bar/compound/textfield-adornment-search-icon.tsx +1 -1
- package/src/{components-v2 → components}/search-bar/compound/textfield.tsx +5 -6
- package/src/{components-v2 → components}/search-bar/index.tsx +1 -1
- package/src/{components-v2 → components}/search-bar/utils/findCategoryNameById.ts +3 -3
- package/src/{components-v2 → components}/section/__tests__/section.test.tsx +14 -7
- package/src/{components-v2 → components}/section/compound/section-header.tsx +2 -2
- package/src/{components-v2 → components}/section/compound/section.tsx +1 -1
- package/src/{components-v2 → components}/section/index.ts +1 -1
- package/src/{components-v2 → components}/side-nav/SideNav.stories.tsx +1 -1
- package/src/{components-v2 → components}/side-nav/__tests__/side-nav.test.tsx +17 -14
- package/src/{components-v2/scrollbar → components/side-nav}/index.ts +1 -1
- package/src/{components-v2 → components}/side-nav/side-nav.tsx +1 -1
- package/src/{components-v2 → components}/site-logo.tsx +8 -1
- package/src/{components-v2 → components}/wishlist-dialogs/__tests__/create-new-list.test.tsx +1 -1
- package/src/{components-v2 → components}/wishlist-dialogs/add-to-wishlist/add-to-wishlist-button.tsx +3 -3
- package/src/{components-v2 → components}/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-bottom-ui.tsx +2 -2
- package/src/{components-v2 → components}/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-dialog.tsx +4 -4
- package/src/{components-v2 → components}/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-list.tsx +3 -3
- package/src/{components-v2 → components}/wishlist-dialogs/add-to-wishlist/compound/wishlist-dialog-header.tsx +3 -4
- package/src/{components-v2 → components}/wishlist-dialogs/add-to-wishlist/compound/wishlist-dialog-item.tsx +4 -4
- package/src/{components-v2 → components}/wishlist-dialogs/add-to-wishlist/index.tsx +1 -1
- package/src/{components-v2 → components}/wishlist-dialogs/create-wishlist/compound/create-wishlist-bottom-ui.tsx +2 -2
- package/src/{components-v2 → components}/wishlist-dialogs/create-wishlist/compound/create-wishlist-dialog.tsx +2 -2
- package/src/{components-v2 → components}/wishlist-dialogs/create-wishlist/compound/create-wishlist-form.tsx +2 -2
- package/src/{components-v2 → components}/wishlist-dialogs/create-wishlist/create-wishlist-button.tsx +2 -2
- package/src/{components-v2 → components}/wishlist-dialogs/create-wishlist/index.tsx +1 -1
- package/src/{components-v2 → components}/wishlist-dialogs/styles.ts +1 -1
- package/src/hooks/use-nextauth-session.ts +4 -1
- package/src/hooks/use-overflow-detect.ts +4 -4
- package/src/lib/cart-cookie-handler.ts +2 -2
- package/src/lib/category-helpers.ts +1 -1
- package/src/lib/lib.ts +2 -2
- package/src/lib/page-slugs.ts +0 -2
- package/src/lib/refiner-utils.ts +5 -5
- package/src/{pages-v2 → pages}/account/account-navigation.tsx +20 -23
- package/src/{pages-v2 → pages}/account/addresses/address-form.tsx +15 -7
- package/src/{pages-v2 → pages}/account/addresses/address-item.tsx +2 -2
- package/src/{pages-v2 → pages}/account/dashboard-header.tsx +5 -5
- package/src/{pages-v2 → pages}/account/orders/icons/delivery.tsx +1 -0
- package/src/{pages-v2 → pages}/account/orders/icons/package-box.tsx +1 -0
- package/src/{pages-v2 → pages}/account/orders/icons/truck-filled.tsx +1 -0
- package/src/{pages-v2 → pages}/account/orders/order-progress.tsx +5 -5
- package/src/{pages-v2 → pages}/account/orders/order-row.tsx +2 -2
- package/src/{pages-v2 → pages}/account/orders/order-summary.tsx +4 -4
- package/src/{pages-v2 → pages}/account/orders/ordered-products.tsx +2 -2
- package/src/{pages-v2 → pages}/account/profile/profile-button.test.tsx +2 -2
- package/src/{pages-v2 → pages}/account/profile/profile-button.tsx +1 -1
- package/src/{pages-v2 → pages}/account/profile/user-info.tsx +2 -2
- package/src/{pages-v2 → pages}/account/styles.ts +1 -1
- package/src/{pages-v2 → pages}/account/wishlist/create-new-list.tsx +2 -2
- package/src/{pages-v2 → pages}/account/wishlist/create-wishlist-button.tsx +2 -2
- package/src/{pages-v2 → pages}/account/wishlist/wishlist-item.tsx +3 -3
- package/src/{pages-v2 → pages}/blog/blog-card.tsx +4 -4
- package/src/{pages-v2 → pages}/cart/__tests__/cart-item.test.tsx +1 -1
- package/src/{pages-v2 → pages}/cart/__tests__/checkout-form.test.tsx +1 -1
- package/src/{pages-v2 → pages}/cart/__tests__/estimate-shipping.test.tsx +11 -11
- package/src/{pages-v2 → pages}/cart/cart-item.tsx +50 -22
- package/src/{pages-v2 → pages}/cart/checkout-form.tsx +5 -5
- package/src/{pages-v2 → pages}/cart/coupon-entry.tsx +2 -2
- package/src/{pages-v2 → pages}/cart/estimate-shipping.tsx +2 -2
- package/src/{pages-v2 → pages}/checkout/checkout-alt-form/checkout-form.tsx +2 -2
- package/src/{pages-v2 → pages}/checkout/checkout-alt-form/checkout-step.tsx +5 -5
- package/src/{pages-v2 → pages}/checkout/checkout-alt-form/index.ts +1 -1
- package/src/{pages-v2 → pages}/checkout/checkout-alt-form/step-heading.tsx +4 -4
- package/src/{pages-v2 → pages}/checkout/checkout-alt-form/steps/address/address-card.tsx +2 -2
- package/src/{pages-v2 → pages}/checkout/checkout-alt-form/steps/address/delivery-address.tsx +25 -21
- package/src/{pages-v2 → pages}/checkout/checkout-alt-form/steps/address/new-address-form.tsx +3 -3
- package/src/{pages-v2 → pages}/checkout/checkout-alt-form/steps/customer-info/customer-information.tsx +2 -2
- package/src/{pages-v2 → pages}/checkout/checkout-alt-form/steps/payment/payment-details.tsx +36 -16
- package/src/{pages-v2 → pages}/checkout/checkout-alt-form/steps/shipping/delivery-date.tsx +2 -2
- package/src/{pages-v2 → pages}/checkout/checkout-alt-form/steps/shipping/delivery-options.tsx +3 -3
- package/src/{pages-v2 → pages}/checkout/checkout-alt-summary/cart-item.tsx +3 -3
- package/src/{pages-v2 → pages}/checkout/checkout-alt-summary/checkout-alt-summary.tsx +4 -4
- package/src/pages/checkout/checkout-alt-summary/index.ts +1 -0
- package/src/{pages-v2 → pages}/checkout/checkout-alt-summary/list-item.tsx +2 -2
- package/src/{pages-v2 → pages}/confirmation/address.tsx +2 -2
- package/src/{pages-v2 → pages}/confirmation/confirmation-summary.tsx +3 -3
- package/src/{pages-v2 → pages}/confirmation/ordered-products.tsx +2 -2
- package/src/{pages-v2 → pages}/product-details/available-shops.tsx +2 -5
- package/src/{pages-v2 → pages}/product-details/bopis/find-in-store-button.tsx +1 -2
- package/src/{pages-v2 → pages}/product-details/bopis/find-in-store-modal.tsx +4 -8
- package/src/{pages-v2 → pages}/product-details/bopis/pickup-option-select.tsx +1 -1
- package/src/pages/product-details/bopis/store-card/index.ts +1 -0
- package/src/{pages-v2 → pages}/product-details/bopis/store-card/shop-card.tsx +5 -5
- package/src/{pages-v2 → pages}/product-details/currency.ts +2 -2
- package/src/{pages-v2 → pages}/product-details/frequently-bought.tsx +3 -3
- package/src/{pages-v2 → pages}/product-details/frequently-product-card.tsx +5 -5
- package/src/{pages-v2 → pages}/product-details/product-comment.tsx +2 -2
- package/src/{pages-v2 → pages}/product-details/product-description.tsx +4 -2
- package/src/{pages-v2 → pages}/product-details/product-filter-card.tsx +5 -5
- package/src/{pages-v2 → pages}/product-details/product-intro/compound/product-info.tsx +8 -9
- package/src/{pages-v2 → pages}/product-details/product-intro/compound/product-intro-images.tsx +4 -4
- package/src/{pages-v2 → pages}/product-details/product-intro/compound/product-intro.tsx +3 -3
- package/src/{pages-v2 → pages}/product-details/product-intro/compound/thumbnail-with-skeleton.tsx +4 -1
- package/src/{pages-v2 → pages}/product-details/product-review.tsx +3 -6
- package/src/{pages-v2 → pages}/product-details/product-tabs.tsx +1 -1
- package/src/{pages-v2 → pages}/product-details/related-products.tsx +2 -2
- package/src/{pages-v2 → pages}/product-list/breadcrumbs.tsx +0 -1
- package/src/{pages-v2 → pages}/product-list/facet-group.tsx +1 -1
- package/src/{pages-v2 → pages}/product-list/list-filter.tsx +2 -3
- package/src/{pages-v2 → pages}/product-list/pagination.tsx +1 -1
- package/src/{pages-v2 → pages}/product-list/product-list-context.tsx +4 -4
- package/src/{pages-v2 → pages}/product-list/product-list-view.tsx +6 -6
- package/src/{pages-v2 → pages}/product-list/quick-view-dialog-content.tsx +6 -11
- package/src/{pages-v2 → pages}/product-list/selected-facets.tsx +2 -2
- package/src/{pages-v2 → pages}/product-list/utils/search-for-category.ts +3 -3
- package/src/{pages-v2 → pages}/quickorder/context.ts +8 -2
- package/src/{pages-v2 → pages}/quickorder/order-upload.tsx +31 -10
- package/src/{pages-v2 → pages}/quickorder/provider.tsx +16 -17
- package/src/{pages-v2 → pages}/quickorder/quick-order-header.tsx +3 -3
- package/src/{pages-v2 → pages}/quickorder/quick-order-row.tsx +1 -1
- package/src/{pages-v2 → pages}/quickorder/quick-order-table.tsx +1 -1
- package/src/{pages-v2 → pages}/quickorder/quick-order.tsx +27 -21
- package/src/providers/nav-provider/index.tsx +1 -1
- package/src/providers/notifications/README.md +1 -1
- package/src/providers/notifications/notification-context.tsx +10 -4
- package/tsconfig.json +1 -2
- package/typedoc.js +1 -1
- package/src/components-v2/carousel-cards/carousel-card-1/index.ts +0 -1
- package/src/components-v2/categories/category-list-item/index.ts +0 -1
- package/src/components-v2/flex-box/index.ts +0 -5
- package/src/components-v2/navbar/category-based-menu/index.ts +0 -1
- package/src/components-v2/product-cards/product-card/index.ts +0 -1
- package/src/components-v2/product-cards/product-card-plp/index.ts +0 -1
- package/src/components-v2/product-cards/product-card-plp-list/index.ts +0 -1
- package/src/components-v2/product-cards/product-card-search/index.ts +0 -1
- package/src/pages-v2/checkout/checkout-alt-summary/index.ts +0 -1
- package/src/pages-v2/product-details/bopis/store-card/index.ts +0 -1
- package/src/{components-v2 → components}/BazaarCard.stories.tsx +0 -0
- package/src/{components-v2 → components}/BazaarCard.tsx +0 -0
- package/src/{components-v2 → components}/BazaarImage.tsx +0 -0
- package/src/{components-v2 → components}/BazaarMenu.stories.tsx +0 -0
- package/src/{components-v2 → components}/BazaarMenu.tsx +0 -0
- package/src/{components-v2 → components}/BazaarSwitch.stories.tsx +0 -0
- package/src/{components-v2 → components}/BazaarSwitch.tsx +0 -0
- package/src/{components-v2 → components}/BazaarTextField.stories.tsx +0 -0
- package/src/{components-v2 → components}/BorderShadowCard.stories.tsx +0 -0
- package/src/{components-v2 → components}/BoxShadowCard.tsx +0 -0
- package/src/{components-v2 → components}/DropZone.stories.tsx +0 -0
- package/src/{components-v2 → components}/HoverBox.stories.tsx +0 -0
- package/src/{components-v2 → components}/HoverBox.tsx +0 -0
- package/src/{components-v2 → components}/Image.tsx +0 -0
- package/src/{components-v2 → components}/LazyImage.tsx +0 -0
- package/src/{components-v2 → components}/Loading.stories.tsx +0 -0
- package/src/{components-v2 → components}/Loading.tsx +0 -0
- package/src/{components-v2 → components}/NoRecords.stories.tsx +0 -0
- package/src/{components-v2 → components}/README.md +0 -0
- package/src/{components-v2 → components}/SearchInput.stories.tsx +0 -0
- package/src/{components-v2 → components}/SearchInput.tsx +0 -0
- package/src/{components-v2 → components}/SiteLogo.stories.tsx +0 -0
- package/src/{components-v2 → components}/SnackbarProvider.tsx +0 -0
- package/src/{components-v2 → components}/Typography.stories.tsx +0 -0
- package/src/{components-v2 → components}/WhiteButton.stories.tsx +0 -0
- package/src/{components-v2 → components}/WhiteButton.tsx +0 -0
- package/src/{components-v2 → components}/accordion/AccordionHeader.stories.tsx +0 -0
- package/src/{components-v2 → components}/accordion/__tests__/accordion-header.test.tsx +0 -0
- package/src/{components-v2 → components}/carousel/Carousel.stories.tsx +0 -0
- package/src/{components-v2 → components}/carousel/__tests__/carousel.test.tsx +0 -0
- package/src/{components-v2 → components}/carousel/styles/index.ts +0 -0
- package/src/{components-v2 → components}/carousel-cards/carousel-card-1/CarouselCard1.stories.tsx +0 -0
- package/src/{components-v2 → components}/carousel-cards/carousel-card-1/__tests__/carousel-card-1.test.tsx +0 -0
- package/src/{components-v2 → components}/carousel-cards/carousel-card-1/styles.ts +0 -0
- package/src/{components-v2 → components}/categories/category-list/types.ts +0 -0
- package/src/{components-v2 → components}/categories/category-list-item/styles.ts +0 -0
- package/src/{components-v2 → components}/categories/mega-menu/styles.ts +0 -0
- package/src/{components-v2 → components}/categories/types.ts +0 -0
- package/src/{components-v2 → components}/flex-box/Flex.stories.tsx +0 -0
- package/src/{components-v2 → components}/flex-box/flex-between.tsx +0 -0
- package/src/{components-v2 → components}/flex-box/flex-box.tsx +0 -0
- package/src/{components-v2 → components}/flex-box/flex-row-center.tsx +0 -0
- package/src/{components-v2 → components}/header/Header.stories.tsx +0 -0
- package/src/{components-v2 → components}/header/hooks/use-header.ts +0 -0
- package/src/{components-v2 → components}/header/styles/index.ts +0 -0
- package/src/{components-v2 → components}/icons/__tests__/icons.test.tsx +1 -1
- package/src/{components-v2 → components}/mini-cart/__tests__/cart-item.test.tsx +0 -0
- package/src/{components-v2 → components}/mini-cart/__tests__/mini-cart.test.tsx +0 -0
- package/src/{components-v2 → components}/mini-cart/__tests__/test-cart-empty.json +0 -0
- package/src/{components-v2 → components}/mini-cart/__tests__/test-cart-with-item.json +0 -0
- package/src/{components-v2 → components}/mini-cart/components/bottom-actions.tsx +0 -0
- package/src/{components-v2 → components}/mobile-navigation/__tests__/mobile-navigation-bar.test.tsx +2 -2
- package/src/{components-v2 → components}/nav-link/NavLink.stories.tsx +0 -0
- package/src/{components-v2 → components}/nav-link/NavLink2.stories.tsx +0 -0
- package/src/{components-v2 → components}/nav-link/NavLink3.stories.tsx +0 -0
- package/src/{components-v2 → components}/navbar/category-based-menu/types.ts +0 -0
- package/src/{components-v2 → components}/navbar/utils/transform-nav.ts +0 -0
- package/src/{components-v2 → components}/product-cards/__tests__/product-cards.test.tsx +0 -0
- package/src/{components-v2 → components}/product-cards/discount-chip.tsx +0 -0
- package/src/{components-v2 → components}/product-cards/product-card/ProductCard.stories.tsx +0 -0
- package/src/{components-v2 → components}/product-cards/product-card-plp/ProductCardPlp.stories.tsx +0 -0
- package/src/{components-v2 → components}/product-cards/product-card-plp/styles/index.ts +0 -0
- package/src/{components-v2 → components}/product-cards/product-card-plp-list/components/tags.tsx +0 -0
- package/src/{components-v2 → components}/product-cards/product-card-search/styles/index.ts +0 -0
- package/src/{components-v2 → components}/product-dialog/ProductDialog.stories.tsx +0 -0
- package/src/{components-v2 → components}/product-dimensions/__mocks__/data.ts +0 -0
- package/src/{components-v2 → components}/product-dimensions/utils/has-selected-dimension.ts +0 -0
- package/src/{components-v2 → components}/products-view/compound/context.ts +0 -0
- package/src/{components-v2 → components}/progress/ProgressBar.stories.tsx +0 -0
- package/src/{components-v2 → components}/progress/__tests__/progress.test.tsx +0 -0
- package/src/{components-v2 → components}/scrollbar/styles.ts +0 -0
- package/src/{components-v2 → components}/search-bar/compound/context.ts +0 -0
- package/src/{components-v2 → components}/search-bar/compound/textfield-adornment-button.tsx +0 -0
- package/src/{components-v2 → components}/search-bar/hooks/use-click-outside.ts +0 -0
- package/src/{components-v2 → components}/search-bar/hooks/use-search.ts +0 -0
- package/src/{components-v2 → components}/search-bar/styles/index.ts +0 -0
- package/src/{components-v2 → components}/section/Section.stories.tsx +0 -0
- package/src/{components-v2 → components}/wishlist-dialogs/__tests__/wishlistDetailData.json +0 -0
- package/src/{components-v2 → components}/wishlist-dialogs/__tests__/wishlistsData.json +0 -0
- package/src/{components-v2 → components}/wishlist-dialogs/add-to-wishlist/AddToWishlist.stories.tsx +0 -0
- package/src/{components-v2 → components}/wishlist-dialogs/add-to-wishlist/compound/context.ts +0 -0
- package/src/{components-v2 → components}/wishlist-dialogs/add-to-wishlist/hooks/use-add-to-wishlist.ts +0 -0
- package/src/{components-v2 → components}/wishlist-dialogs/create-wishlist/CreateWishlistButton.stories.tsx +0 -0
- package/src/{pages-v2 → pages}/README.md +0 -0
- package/src/{pages-v2 → pages}/account/table-row.tsx +0 -0
- package/src/{pages-v2 → pages}/blog/pagination.tsx +0 -0
- package/src/{pages-v2 → pages}/cart/__tests__/cart-with-items.json +0 -0
- package/src/{pages-v2 → pages}/cart/__tests__/conutries.json +0 -0
- package/src/{pages-v2 → pages}/cart/__tests__/countries.json +0 -0
- package/src/{pages-v2 → pages}/cart/wrapper.tsx +0 -0
- package/src/{pages-v2 → pages}/checkout/checkout-alt-form/node.tsx +0 -0
- package/src/{pages-v2 → pages}/checkout/checkout-alt-form/steps/address/styles.ts +0 -0
- package/src/{pages-v2 → pages}/checkout/checkout-alt-form/steps/payment/safe-card-preview-data.tsx +0 -0
- package/src/{pages-v2 → pages}/checkout/checkout-alt-form/types.ts +0 -0
- package/src/{pages-v2 → pages}/product-details/bopis/search-header.tsx +0 -0
- package/src/{pages-v2 → pages}/product-details/bopis/store-card/styles.ts +0 -0
- package/src/{pages-v2 → pages}/product-details/bopis/store-card/utils/convertSecondsToTime.ts +0 -0
- package/src/{pages-v2 → pages}/product-details/bopis/store-card/utils/getDaysResources.ts +0 -0
- package/src/{pages-v2 → pages}/product-details/checkbox-label.tsx +0 -0
- package/src/{pages-v2 → pages}/product-details/product-intro/compound/context.ts +0 -0
- package/src/{pages-v2 → pages}/product-details/product-intro/utils.ts +0 -0
- package/src/{pages-v2 → pages}/product-details/types.ts +0 -0
- package/src/{pages-v2 → pages}/product-list/checkbox-label.tsx +0 -0
- package/src/{pages-v2 → pages}/product-list/facet.tsx +0 -0
- package/src/{pages-v2 → pages}/product-list/product-list-state.ts +0 -0
- package/src/{pages-v2 → pages}/product-list/product-rating.tsx +0 -0
- package/src/{pages-v2 → pages}/product-list/quick-view-dialog.tsx +4 -4
- package/src/{pages-v2 → pages}/product-list/range-filter.tsx +0 -0
- package/src/{pages-v2 → pages}/product-list/scrollbar.tsx +0 -0
- package/src/{pages-v2 → pages}/product-list/search-bar.tsx +0 -0
- package/src/{pages-v2 → pages}/product-list/side-nav.tsx +0 -0
- package/src/{pages-v2 → pages}/product-list/swatch.tsx +0 -0
- package/src/{pages-v2 → pages}/product-list/types.ts +0 -0
- package/src/{pages-v2 → pages}/product-list/use-product-list.ts +0 -0
- package/src/{pages-v2 → pages}/product-list/useCategoryFilter.tsx +0 -0
- package/src/{pages-v2 → pages}/product-list/utils/facet-helpers.ts +0 -0
- package/src/{pages-v2 → pages}/product-list/utils/generate-breadcrumbs.ts +0 -0
- package/src/{pages-v2 → pages}/product-list/utils/getCategoryFilterFromSlug.ts +0 -0
- package/src/{pages-v2 → pages}/product-list/utils/product-list-helper.ts +4 -4
- /package/src/{pages-v2 → pages}/product-list/utils/product-list-types.ts +0 -0
- /package/src/{pages-v2 → pages}/product-list/utils/sort-options.ts +0 -0
- /package/src/{pages-v2 → pages}/product-list/utils/use-previous-refiners.ts +0 -0
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
// TODO: use api manager types to remove type any
|
|
3
1
|
import createApiManager from "@evenicanpm/storefront-core/src/api-manager/index";
|
|
4
2
|
import type { DatasourceApis } from "@evenicanpm/storefront-core/src/api-manager/types/Datasource";
|
|
5
3
|
import { isServer, type QueryClient } from "@tanstack/query-core";
|
|
@@ -18,277 +16,130 @@ import signOut from "@/auth/signout";
|
|
|
18
16
|
const QUERY_ROUTE = "/api";
|
|
19
17
|
const mutex = new Mutex();
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
* @param queryKey a prefix to add to cache key
|
|
26
|
-
* @param route the route to the corresponding route handler
|
|
27
|
-
* @param apiManagerPath a tuple of two items, entity name and method
|
|
28
|
-
* @param options.disableProperty if these input properties are undefined then disable query
|
|
29
|
-
* @param options.enabled raw enabled for certain use cases
|
|
30
|
-
* @returns
|
|
31
|
-
*/
|
|
32
|
-
export const createQuery = <TInput, TOutput>(
|
|
33
|
-
apiManagerPath: ApiPath<keyof DatasourceApis>,
|
|
34
|
-
config?: {
|
|
35
|
-
queryKey?: string;
|
|
36
|
-
disableProperties?: Array<keyof TInput>;
|
|
37
|
-
},
|
|
38
|
-
) => {
|
|
39
|
-
/**
|
|
40
|
-
* Generates the configuration object for a query, including the query function, cache key, and enabled state.
|
|
41
|
-
*
|
|
42
|
-
* The query function (`queryFn`) is determined based on the execution environment (server or client):
|
|
43
|
-
* - On the server, it checks for token expiry, refreshes the token if needed, creates an API manager, and invokes the appropriate API function.
|
|
44
|
-
* - On the client, it checks for token expiry and either refreshes the token or performs a fetch operation.
|
|
45
|
-
*
|
|
46
|
-
* The `enabled` property is computed based on the presence and truthiness of specified properties in the input, if `disableProperties` are provided in options.
|
|
47
|
-
*
|
|
48
|
-
* @param input - Optional input parameters for the query and API function.
|
|
49
|
-
* @returns An object containing:
|
|
50
|
-
* - `queryKey`: The cache key for the query, built from the input.
|
|
51
|
-
* - `queryFn`: The asynchronous function to execute for the query.
|
|
52
|
-
* - `enabled`: A boolean indicating whether the query should be enabled.
|
|
53
|
-
*/
|
|
54
|
-
const getQueryData = (input?: TInput) => {
|
|
55
|
-
const queryFn = isServer
|
|
56
|
-
? /// Server ///
|
|
57
|
-
async () => {
|
|
58
|
-
const apiManager = await createApiManager();
|
|
59
|
-
const apiFunction = getApiFromPath(apiManager, apiManagerPath);
|
|
60
|
-
const result = await apiFunction(input);
|
|
61
|
-
return result;
|
|
62
|
-
}
|
|
63
|
-
: /// Client ///
|
|
64
|
-
async () => {
|
|
65
|
-
// Check if token is expired
|
|
66
|
-
const shouldRefreshToken = await checkTokenExpiry();
|
|
67
|
-
if (shouldRefreshToken) {
|
|
68
|
-
return await handleTokenRefreshClient(input);
|
|
69
|
-
} else {
|
|
70
|
-
return await doFetch(input, apiManagerPath);
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
// if disable props specified then use them to compute enabled
|
|
75
|
-
const enabled: boolean = config?.disableProperties
|
|
76
|
-
? config.disableProperties.every((prop) => !!input?.[prop])
|
|
77
|
-
: true;
|
|
78
|
-
|
|
79
|
-
const data = {
|
|
80
|
-
queryKey: buildCacheKey(input),
|
|
81
|
-
queryFn,
|
|
82
|
-
enabled,
|
|
83
|
-
};
|
|
84
|
-
return data;
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Sends a POST request to the specified route with the provided input and API manager path.
|
|
89
|
-
*
|
|
90
|
-
* @template TInput - The type of the input parameter.
|
|
91
|
-
* @param input - The input data to be sent in the request body. Can be undefined.
|
|
92
|
-
* @param route - The endpoint URL to which the request is sent.
|
|
93
|
-
* @param apiManagerPath - The API manager path used to identify the API endpoint.
|
|
94
|
-
* @returns A promise that resolves to the response of the fetch request.
|
|
95
|
-
*/
|
|
96
|
-
const doFetch = async (
|
|
97
|
-
input: TInput | undefined,
|
|
98
|
-
apiManagerPath: ApiPath<keyof DatasourceApis>,
|
|
99
|
-
additionalHeaders?: HeadersInit,
|
|
100
|
-
) => {
|
|
101
|
-
// Merge headers
|
|
102
|
-
const headers = new Headers(additionalHeaders);
|
|
103
|
-
// generic route handler (new) - will refactor all queries to use this
|
|
104
|
-
const result = await fetch(QUERY_ROUTE, {
|
|
105
|
-
method: "POST",
|
|
106
|
-
body: JSON.stringify({ input, apiManagerPath }),
|
|
107
|
-
headers,
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
if (result.status === 401) {
|
|
111
|
-
// If unauthenticated , sign out the user
|
|
112
|
-
signOut();
|
|
113
|
-
}
|
|
114
|
-
return await result.json();
|
|
115
|
-
};
|
|
19
|
+
export type ApiPath<T extends keyof DatasourceApis = keyof DatasourceApis> = [
|
|
20
|
+
T,
|
|
21
|
+
keyof DatasourceApis[T],
|
|
22
|
+
];
|
|
116
23
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
*/
|
|
121
|
-
const useData = (
|
|
122
|
-
input?: TInput,
|
|
123
|
-
options?: { enabled: boolean },
|
|
124
|
-
): UseQueryResult<TOutput> => {
|
|
125
|
-
return useQuery({ ...getQueryData(input), enabled: options?.enabled });
|
|
126
|
-
};
|
|
24
|
+
export type Query<TInput, TOutput> = ReturnType<
|
|
25
|
+
typeof createQuery<TInput, TOutput>
|
|
26
|
+
>;
|
|
127
27
|
|
|
128
|
-
|
|
129
|
-
* Client-side hook to call data from react query cache,
|
|
130
|
-
* used with suspense for suspense loading state handling
|
|
131
|
-
* @returns
|
|
132
|
-
*/
|
|
133
|
-
const useSuspenseData = (input?: TInput): UseSuspenseQueryResult<TOutput> => {
|
|
134
|
-
return useSuspenseQuery(getQueryData(input));
|
|
135
|
-
};
|
|
28
|
+
// --- Shared helpers (no closure dependencies) ---
|
|
136
29
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
30
|
+
const checkTokenExpiry = async (): Promise<boolean> => {
|
|
31
|
+
let token: string | undefined;
|
|
32
|
+
if (isServer) {
|
|
33
|
+
const session = (await manuallyRetrieveSessionCookie()) ?? undefined;
|
|
34
|
+
token = session?.accessToken;
|
|
35
|
+
} else {
|
|
36
|
+
const session = await getSession();
|
|
37
|
+
token = session?.accessToken;
|
|
38
|
+
}
|
|
39
|
+
const decoded = token && (jwt.decode(token) as { exp?: number } | null);
|
|
40
|
+
const currentTime = Math.floor(Date.now() / 1000);
|
|
41
|
+
return (
|
|
42
|
+
!!decoded && typeof decoded.exp === "number" && decoded.exp < currentTime
|
|
43
|
+
);
|
|
44
|
+
};
|
|
145
45
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
46
|
+
const doFetch = async <TInput>(
|
|
47
|
+
input: TInput | undefined,
|
|
48
|
+
apiManagerPath: ApiPath,
|
|
49
|
+
additionalHeaders?: HeadersInit,
|
|
50
|
+
) => {
|
|
51
|
+
const headers = new Headers(additionalHeaders);
|
|
52
|
+
const result = await fetch(QUERY_ROUTE, {
|
|
53
|
+
method: "POST",
|
|
54
|
+
body: JSON.stringify({ input, apiManagerPath }),
|
|
55
|
+
headers,
|
|
56
|
+
});
|
|
57
|
+
if (result.status === 401) {
|
|
58
|
+
signOut();
|
|
59
|
+
}
|
|
60
|
+
return result.json();
|
|
61
|
+
};
|
|
154
62
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
63
|
+
// Acquires a mutex before fetching so concurrent requests don't each trigger
|
|
64
|
+
// a token refresh simultaneously (double-check pattern after acquiring lock).
|
|
65
|
+
const withTokenRefresh = async <TInput>(
|
|
66
|
+
input: TInput | undefined,
|
|
67
|
+
apiManagerPath: ApiPath,
|
|
68
|
+
) => {
|
|
69
|
+
const release = await mutex.acquire();
|
|
70
|
+
try {
|
|
71
|
+
const headers = new Headers();
|
|
72
|
+
if (await checkTokenExpiry()) {
|
|
73
|
+
headers.append("should-refresh-token", "true");
|
|
74
|
+
}
|
|
75
|
+
return await doFetch(input, apiManagerPath, headers);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
console.error("Error fetching data:", error);
|
|
78
|
+
throw new Error("Failed to fetch data");
|
|
79
|
+
} finally {
|
|
80
|
+
release();
|
|
81
|
+
}
|
|
82
|
+
};
|
|
166
83
|
|
|
167
|
-
|
|
168
|
-
*
|
|
169
|
-
* @param queryClient react-query client
|
|
170
|
-
* @param data the data to set the query to
|
|
171
|
-
* @param input the input of the query that's used to generate cache key
|
|
172
|
-
* returns a promise of QueryResult for query
|
|
173
|
-
*/
|
|
174
|
-
const setQueryData = async (
|
|
175
|
-
queryClient: QueryClient,
|
|
176
|
-
data: TOutput,
|
|
177
|
-
input?: TInput,
|
|
178
|
-
) => {
|
|
179
|
-
const key = buildCacheKey(input);
|
|
180
|
-
return await queryClient.setQueryData(key, data);
|
|
181
|
-
};
|
|
84
|
+
// --- Factory ---
|
|
182
85
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
86
|
+
export const createQuery = <TInput, TOutput>(
|
|
87
|
+
apiManagerPath: ApiPath<keyof DatasourceApis>,
|
|
88
|
+
config?: {
|
|
89
|
+
queryKey?: string;
|
|
90
|
+
disableProperties?: Array<keyof TInput>;
|
|
91
|
+
},
|
|
92
|
+
) => {
|
|
188
93
|
const buildCacheKey = (input?: TInput) => {
|
|
189
94
|
const prefix = config?.queryKey ?? apiManagerPath;
|
|
190
95
|
return input ? [prefix, input] : [prefix];
|
|
191
96
|
};
|
|
192
97
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const decoded = token && (jwt.decode(token) as { exp?: number } | null);
|
|
213
|
-
|
|
214
|
-
const currentTime = Math.floor(Date.now() / 1000);
|
|
215
|
-
|
|
216
|
-
// Use this for testing - expires after 60 seconds (1 min) from issued-at time
|
|
217
|
-
// const isExpired = !!decoded && typeof decoded.iat === "number" && currentTime > decoded.iat + 60;
|
|
218
|
-
|
|
219
|
-
const isExpired =
|
|
220
|
-
!!decoded && typeof decoded.exp === "number" && decoded.exp < currentTime;
|
|
221
|
-
|
|
222
|
-
return isExpired;
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Handles fetching data with token refresh logic in a thread-safe manner.
|
|
227
|
-
*
|
|
228
|
-
* Acquires a mutex lock to ensure only one token refresh operation occurs at a time.
|
|
229
|
-
* Checks if the token is expired and, if so, adds a header to indicate that the token should be refreshed.
|
|
230
|
-
* Performs the fetch operation with the appropriate headers and returns the parsed JSON response.
|
|
231
|
-
* Releases the mutex lock after the operation completes, regardless of success or failure.
|
|
232
|
-
*
|
|
233
|
-
* @param input - The input data for the fetch operation, which may be undefined.
|
|
234
|
-
* @returns A promise that resolves to the parsed JSON response from the fetch operation.
|
|
235
|
-
* @throws An error if the fetch operation fails.
|
|
236
|
-
*/
|
|
237
|
-
const handleTokenRefreshClient = async (input: TInput | undefined) => {
|
|
238
|
-
const release = await mutex.acquire();
|
|
239
|
-
try {
|
|
240
|
-
// Check if token is expired again
|
|
241
|
-
const stillShouldRefreshToken = await checkTokenExpiry();
|
|
242
|
-
const headers = new Headers();
|
|
243
|
-
if (stillShouldRefreshToken) {
|
|
244
|
-
// Add refresh token header
|
|
245
|
-
headers.append("should-refresh-token", "true");
|
|
246
|
-
}
|
|
247
|
-
// Call do fetch with the headers
|
|
248
|
-
return await doFetch(input, apiManagerPath, headers);
|
|
249
|
-
} catch (error) {
|
|
250
|
-
// Handle API Error
|
|
251
|
-
console.error("Error fetching data:", error);
|
|
252
|
-
throw new Error("Failed to fetch data");
|
|
253
|
-
} finally {
|
|
254
|
-
release();
|
|
255
|
-
}
|
|
256
|
-
};
|
|
98
|
+
const getQueryOptions = (input?: TInput) => ({
|
|
99
|
+
queryKey: buildCacheKey(input),
|
|
100
|
+
queryFn: isServer
|
|
101
|
+
? async () => {
|
|
102
|
+
const apiManager = await createApiManager();
|
|
103
|
+
return getApiFromPath(apiManager, apiManagerPath)(input);
|
|
104
|
+
}
|
|
105
|
+
: async () => {
|
|
106
|
+
const isExpired = await checkTokenExpiry();
|
|
107
|
+
return isExpired
|
|
108
|
+
? withTokenRefresh(input, apiManagerPath)
|
|
109
|
+
: doFetch(input, apiManagerPath);
|
|
110
|
+
},
|
|
111
|
+
enabled: config?.disableProperties
|
|
112
|
+
? config.disableProperties.every((prop) => !!input?.[prop])
|
|
113
|
+
: true,
|
|
114
|
+
});
|
|
257
115
|
|
|
258
116
|
return {
|
|
259
|
-
useData
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
117
|
+
useData: (
|
|
118
|
+
input?: TInput,
|
|
119
|
+
options?: { enabled: boolean },
|
|
120
|
+
): UseQueryResult<TOutput> =>
|
|
121
|
+
useQuery({ ...getQueryOptions(input), enabled: options?.enabled }),
|
|
122
|
+
useSuspenseData: (input?: TInput): UseSuspenseQueryResult<TOutput> =>
|
|
123
|
+
useSuspenseQuery(getQueryOptions(input)),
|
|
124
|
+
fetchData: (queryClient: QueryClient, input?: TInput) =>
|
|
125
|
+
queryClient.fetchQuery(getQueryOptions(input)),
|
|
126
|
+
prefetchData: (queryClient: QueryClient, input?: TInput) =>
|
|
127
|
+
queryClient.prefetchQuery(getQueryOptions(input)),
|
|
128
|
+
getData: (queryClient: QueryClient): TOutput | undefined =>
|
|
129
|
+
queryClient.getQueryData(buildCacheKey()),
|
|
130
|
+
setQueryData: (queryClient: QueryClient, data: TOutput, input?: TInput) =>
|
|
131
|
+
queryClient.setQueryData(buildCacheKey(input), data),
|
|
264
132
|
buildCacheKey,
|
|
265
|
-
getData,
|
|
266
133
|
};
|
|
267
134
|
};
|
|
268
135
|
|
|
269
|
-
|
|
270
|
-
* A tuple type where api manager entity is first item and second item is method
|
|
271
|
-
* of first item
|
|
272
|
-
*/
|
|
273
|
-
export type ApiPath<T extends keyof DatasourceApis = keyof DatasourceApis> = [
|
|
274
|
-
T,
|
|
275
|
-
keyof DatasourceApis[T],
|
|
276
|
-
];
|
|
136
|
+
// --- Utilities ---
|
|
277
137
|
|
|
278
|
-
/// Utilities ///
|
|
279
|
-
/**
|
|
280
|
-
* Takes an apiManager and reaches into nested sub api's based on array path
|
|
281
|
-
* @param apiManager
|
|
282
|
-
* @param path array of path steps
|
|
283
|
-
* @returns the function at the specified path
|
|
284
|
-
*/
|
|
285
138
|
export function getApiFromPath<TInput, TOutput>(
|
|
286
|
-
apiManager:
|
|
139
|
+
apiManager: Awaited<ReturnType<typeof createApiManager>>,
|
|
287
140
|
path: ApiPath,
|
|
288
141
|
): (input?: TInput) => Promise<TOutput> {
|
|
289
142
|
const [entity, method] = path;
|
|
290
|
-
// Typescript is doing heavy lifting to ensure correct api path
|
|
291
|
-
// so safe to call method directly
|
|
292
143
|
const result = apiManager[entity][method];
|
|
293
144
|
|
|
294
145
|
if (process.env.NODE_ENV === "development") {
|
|
@@ -300,30 +151,19 @@ export function getApiFromPath<TInput, TOutput>(
|
|
|
300
151
|
});
|
|
301
152
|
}
|
|
302
153
|
|
|
303
|
-
// Function reference loses 'this' context.
|
|
304
|
-
// Re-bind for d365 classes.
|
|
154
|
+
// Function reference loses 'this' context — re-bind for d365 classes.
|
|
305
155
|
if (typeof result === "function") {
|
|
306
|
-
return result.bind(
|
|
156
|
+
return (result as (input?: TInput) => Promise<TOutput>).bind(
|
|
157
|
+
apiManager[entity],
|
|
158
|
+
);
|
|
307
159
|
}
|
|
308
160
|
return result;
|
|
309
161
|
}
|
|
310
162
|
|
|
311
|
-
/**
|
|
312
|
-
*
|
|
313
|
-
* @param key
|
|
314
|
-
* @param method
|
|
315
|
-
* @returns
|
|
316
|
-
*/
|
|
317
163
|
export function createApiPath<T extends keyof DatasourceApis>(
|
|
318
164
|
key: T,
|
|
319
165
|
method: keyof DatasourceApis[T],
|
|
320
166
|
) {
|
|
321
|
-
//
|
|
322
|
-
// using stricter type for type narrowing and intellisense
|
|
323
|
-
console.log([key, method]);
|
|
167
|
+
// re-cast to general ApiPath after using stricter type for intellisense
|
|
324
168
|
return [key, method] as ApiPath<keyof DatasourceApis>;
|
|
325
169
|
}
|
|
326
|
-
|
|
327
|
-
export type Query<TInput, TOutput> = ReturnType<
|
|
328
|
-
typeof createQuery<TInput, TOutput>
|
|
329
|
-
>;
|
|
@@ -111,9 +111,6 @@ export interface UserApi {
|
|
|
111
111
|
copyCartToWishlist(
|
|
112
112
|
input: userSchemas.CopyCartToWishlistInput,
|
|
113
113
|
): Promise<userSchemas.Wishlist>;
|
|
114
|
-
updateUser(user: userSchemas.User): Promise<userSchemas.User>;
|
|
115
|
-
getUser(): Promise<userSchemas.User | null>;
|
|
116
|
-
getUserCounts(userId: string): Promise<userSchemas.UserCounts>;
|
|
117
114
|
}
|
|
118
115
|
|
|
119
116
|
/**
|
package/src/auth/msal.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import azureADB2CProvider from "@/auth/providers/aadb2c-provider";
|
|
2
2
|
import authentikProvider from "@/auth/providers/authentik-provider";
|
|
3
|
-
import keycloakProvider from "@/auth/providers/keycloak-provider";
|
|
4
3
|
import createEntraExternalIdProvider from "@/auth/providers/entra-external-id-provider";
|
|
4
|
+
import keycloakProvider from "@/auth/providers/keycloak-provider";
|
|
5
5
|
|
|
6
6
|
export const getProviders = () => {
|
|
7
7
|
const azureProvider = azureADB2CProvider();
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// GLOBAL CUSTOM COMPONENT
|
|
4
|
-
import BazaarCard from "@evenicanpm/storefront-core/src/components
|
|
5
|
-
import { Carousel } from "@evenicanpm/storefront-core/src/components
|
|
6
|
-
import { Section } from "@evenicanpm/storefront-core/src/components
|
|
4
|
+
import BazaarCard from "@evenicanpm/storefront-core/src/components/BazaarCard";
|
|
5
|
+
import { Carousel } from "@evenicanpm/storefront-core/src/components/carousel/index";
|
|
6
|
+
import { Section } from "@evenicanpm/storefront-core/src/components/section";
|
|
7
7
|
import NextLink from "next/link";
|
|
8
|
-
import React from "react";
|
|
9
8
|
// LOCAL CUSTOM COMPONENT
|
|
10
9
|
import TopCategoriesCard from "@/cms/blocks/components/shared/top-categories-card";
|
|
11
10
|
// CUSTOM ICON COMPONENT
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Box, Container } from "@mui/material";
|
|
2
2
|
import Grid from "@mui/material/Grid2";
|
|
3
|
-
import React from "react";
|
|
4
3
|
|
|
5
4
|
// Local components
|
|
6
5
|
import CategoryCard from "@/cms/blocks/components/category-card";
|
|
@@ -26,7 +25,7 @@ const FeaturedCategories = (categoriesData: FeaturedCategoriesBlock) => {
|
|
|
26
25
|
size={3}
|
|
27
26
|
display="flex"
|
|
28
27
|
justifyContent="center"
|
|
29
|
-
key={
|
|
28
|
+
key={`category_index_${i}`}
|
|
30
29
|
>
|
|
31
30
|
<CategoryCard
|
|
32
31
|
name={category.name}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Box, Container } from "@mui/material";
|
|
2
2
|
import Grid from "@mui/material/Grid2";
|
|
3
|
-
import React from "react";
|
|
4
3
|
|
|
5
4
|
// Local components
|
|
6
5
|
import MediaCard from "@/cms/blocks/components/media-card";
|
|
@@ -23,7 +22,7 @@ const FeaturedProducts = (productsData: FeaturedProductsBlock) => {
|
|
|
23
22
|
size={3}
|
|
24
23
|
display="flex"
|
|
25
24
|
justifyContent="center"
|
|
26
|
-
key={
|
|
25
|
+
key={`product_index_${i}`}
|
|
27
26
|
>
|
|
28
27
|
<MediaCard
|
|
29
28
|
name={product?.description ?? ""}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// MUI
|
|
2
2
|
import { Box, Container } from "@mui/material";
|
|
3
3
|
import Grid from "@mui/material/Grid2";
|
|
4
|
-
import React from "react";
|
|
5
4
|
import type {
|
|
6
5
|
FooterBlock,
|
|
7
6
|
FooterResponse,
|
|
@@ -13,7 +12,7 @@ import Logo from "@/cms/blocks/components/footer/sections/footer-logo";
|
|
|
13
12
|
import cms from "@/cms/endpoints";
|
|
14
13
|
|
|
15
14
|
const getBlockComponent = (block: FooterBlock, index: number) => {
|
|
16
|
-
let Block;
|
|
15
|
+
let Block: typeof Links | typeof Logo | typeof Contact;
|
|
17
16
|
|
|
18
17
|
switch (block.__component) {
|
|
19
18
|
case "footer.links":
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import FlexBox from "@evenicanpm/storefront-core/src/components
|
|
1
|
+
import FlexBox from "@evenicanpm/storefront-core/src/components/flex-box/flex-box";
|
|
2
2
|
import { Box } from "@mui/material";
|
|
3
|
-
import
|
|
3
|
+
import { Fragment } from "react";
|
|
4
4
|
import { MdFacebook as Facebook } from "react-icons/md";
|
|
5
5
|
import { Link } from "react-router-dom";
|
|
6
6
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { Paragraph } from "@evenicanpm/storefront-core/src/components
|
|
1
|
+
import { Paragraph } from "@evenicanpm/storefront-core/src/components/Typography";
|
|
2
2
|
import Grid from "@mui/material/Grid2";
|
|
3
|
-
import React from "react";
|
|
4
3
|
import type { SocialLink } from "@/cms/blocks/components/footer/interfaces";
|
|
5
4
|
import SocialLinks from "@/cms/blocks/components/footer/sections/footer-social-links";
|
|
6
5
|
import { Heading } from "@/cms/blocks/components/footer/styles/index";
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import SiteLogo from "@evenicanpm/storefront-core/src/components
|
|
4
|
-
import { Paragraph } from "@evenicanpm/storefront-core/src/components
|
|
3
|
+
import SiteLogo from "@evenicanpm/storefront-core/src/components/site-logo";
|
|
4
|
+
import { Paragraph } from "@evenicanpm/storefront-core/src/components/Typography";
|
|
5
5
|
import Grid from "@mui/material/Grid2";
|
|
6
6
|
import useTheme from "@mui/material/styles/useTheme";
|
|
7
7
|
import useMediaQuery from "@mui/material/useMediaQuery";
|
|
8
|
-
import React from "react";
|
|
9
8
|
|
|
10
9
|
interface Props {
|
|
11
10
|
description: string;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// Custom Components
|
|
4
|
-
import FlexBox from "@evenicanpm/storefront-core/src/components
|
|
4
|
+
import FlexBox from "@evenicanpm/storefront-core/src/components/flex-box/flex-box";
|
|
5
5
|
import IconButton from "@mui/material/IconButton";
|
|
6
6
|
import styled from "@mui/material/styles/styled";
|
|
7
|
-
import React from "react";
|
|
8
7
|
import {
|
|
9
8
|
FaGoogle as Google,
|
|
10
9
|
FaInstagram as Instagram,
|
|
@@ -43,7 +42,12 @@ export default function SocialLinks({
|
|
|
43
42
|
return (
|
|
44
43
|
<FlexBox className="flex" mx={-0.625}>
|
|
45
44
|
{socials?.map(({ name, link }, i) => {
|
|
46
|
-
let Icon
|
|
45
|
+
let Icon:
|
|
46
|
+
| typeof Facebook
|
|
47
|
+
| typeof Instagram
|
|
48
|
+
| typeof Google
|
|
49
|
+
| typeof Twitter
|
|
50
|
+
| undefined;
|
|
47
51
|
|
|
48
52
|
switch (name) {
|
|
49
53
|
case "Facebook":
|
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
// This component works best with cutout product images
|
|
3
3
|
|
|
4
4
|
// GLOBAL CUSTOM COMPONENTS
|
|
5
|
-
import { Carousel } from "@evenicanpm/storefront-core/src/components
|
|
6
|
-
import CarouselCard1 from "@evenicanpm/storefront-core/src/components
|
|
5
|
+
import { Carousel } from "@evenicanpm/storefront-core/src/components/carousel/index";
|
|
6
|
+
import CarouselCard1 from "@evenicanpm/storefront-core/src/components/carousel-cards/carousel-card-1/index";
|
|
7
7
|
import { Box, Container } from "@mui/material";
|
|
8
|
-
import React from "react";
|
|
9
8
|
import type { HeroCarouselBlock, Slide } from "@/cms/blocks/interfaces";
|
|
10
9
|
import { getImageUrl } from "@/cms/endpoints";
|
|
11
10
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Box, Button, Container, Typography } from "@mui/material";
|
|
2
2
|
import Image from "next/image";
|
|
3
3
|
import NextLink from "next/link";
|
|
4
|
-
import React from "react";
|
|
5
4
|
import type { HeroSectionBlock } from "@/cms/blocks/interfaces";
|
|
6
5
|
import cmsEndPoints from "@/cms/endpoints";
|
|
7
6
|
|