@sonic-equipment/ui 132.0.0 → 133.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/address/address.d.ts +2 -13
  2. package/dist/buttons/add-to-cart-button/connected-add-to-cart-button.js +1 -1
  3. package/dist/buttons/button/button.js +2 -1
  4. package/dist/delivery-time/delivery-time.js +6 -5
  5. package/dist/display/info-display/info-display.d.ts +7 -0
  6. package/dist/display/info-display/info-display.js +8 -0
  7. package/dist/display/info-display/info-display.module.css.js +3 -0
  8. package/dist/exports.d.ts +13 -5
  9. package/dist/forms/input/input.d.ts +1 -0
  10. package/dist/forms/input/input.js +5 -3
  11. package/dist/forms/input/input.module.css.js +1 -1
  12. package/dist/forms/switch/switch.d.ts +2 -1
  13. package/dist/forms/switch/switch.js +2 -2
  14. package/dist/forms/text-field/password-reveal-toggle/password-reveal-toggle.d.ts +10 -0
  15. package/dist/forms/text-field/password-reveal-toggle/password-reveal-toggle.js +18 -0
  16. package/dist/forms/text-field/password-reveal-toggle/password-reveal-toggle.module.css.js +3 -0
  17. package/dist/forms/text-field/text-field.d.ts +3 -3
  18. package/dist/forms/text-field/text-field.js +9 -2
  19. package/dist/icons/stroke/stroke-dehashed-icon.js +7 -0
  20. package/dist/icons/stroke/stroke-hashed-icon.js +7 -0
  21. package/dist/index.js +14 -6
  22. package/dist/intl/translation-id.d.ts +1 -1
  23. package/dist/pages/checkout/cart-page/cart-page.js +6 -9
  24. package/dist/pages/checkout/cart-page/components/empty-cart-page.d.ts +1 -0
  25. package/dist/pages/checkout/cart-page/components/empty-cart-page.js +11 -0
  26. package/dist/pages/checkout/components/billing-and-invoice-information.d.ts +7 -0
  27. package/dist/pages/checkout/components/billing-and-invoice-information.js +12 -0
  28. package/dist/pages/checkout/components/billing-and-invoice-information.module.css.js +3 -0
  29. package/dist/pages/checkout/constants.d.ts +8 -0
  30. package/dist/pages/checkout/constants.js +10 -0
  31. package/dist/pages/checkout/layouts/checkout-page-layout/components/checkout-page-section.module.css.js +1 -1
  32. package/dist/pages/checkout/order-confirmation-page/order-confirmation-page.d.ts +4 -0
  33. package/dist/pages/checkout/order-confirmation-page/order-confirmation-page.js +115 -0
  34. package/dist/pages/checkout/order-confirmation-page/order-confirmation-page.module.css.js +3 -0
  35. package/dist/{checkout → pages/checkout/payment-page/components}/adyen-payment.js +5 -5
  36. package/dist/pages/checkout/payment-page/components/adyen-payment.module.css.js +3 -0
  37. package/dist/{checkout → pages/checkout/payment-page/components}/payment.d.ts +4 -2
  38. package/dist/{checkout → pages/checkout/payment-page/components}/payment.js +74 -44
  39. package/dist/pages/checkout/payment-page/components/payment.module.css.js +3 -0
  40. package/dist/pages/checkout/payment-page/payment-page.js +16 -10
  41. package/dist/{checkout → pages/checkout/payment-page/utils}/parse-amount.js +1 -1
  42. package/dist/pages/checkout/shipping-page/components/edit-address.js +8 -4
  43. package/dist/pages/checkout/shipping-page/hooks/use-patch-shipping-details.d.ts +12 -0
  44. package/dist/pages/checkout/shipping-page/hooks/use-patch-shipping-details.js +21 -0
  45. package/dist/pages/checkout/shipping-page/shipping-page.js +37 -51
  46. package/dist/pages/checkout/shipping-page/shipping-page.module.css.js +1 -1
  47. package/dist/pages/components/page/page.d.ts +3 -2
  48. package/dist/pages/components/page/page.js +3 -2
  49. package/dist/pages/components/page-meta-data/page-meta-data.d.ts +3 -4
  50. package/dist/pages/components/page-meta-data/page-meta-data.js +2 -2
  51. package/dist/pages/product/product-details-page/product-details-page.js +2 -10
  52. package/dist/pages/product/product-details-page/product-details.js +10 -4
  53. package/dist/pages/product/product-listing-page/product-listing-page-data-types.d.ts +1 -1
  54. package/dist/pages/product/product-listing-page/product-listing-page.js +2 -10
  55. package/dist/pages/product/product-listing-page/product-listing.js +8 -1
  56. package/dist/pages/product/search-result-page/search-results-page.js +4 -7
  57. package/dist/shared/api/bff/model/bff.model.d.ts +4 -4
  58. package/dist/shared/api/bff/services/bff-service.js +1 -4
  59. package/dist/shared/api/storefront/hooks/cart/use-fetch-cart-by-id.d.ts +8 -0
  60. package/dist/shared/api/storefront/hooks/cart/use-fetch-cart-by-id.js +20 -0
  61. package/dist/shared/api/storefront/hooks/cart/use-fetch-current-cart-count.d.ts +1 -1
  62. package/dist/shared/api/storefront/hooks/cart/use-fetch-current-cart-count.js +3 -3
  63. package/dist/shared/api/storefront/hooks/cart/use-fetch-current-cart.d.ts +2 -5
  64. package/dist/shared/api/storefront/hooks/cart/use-fetch-current-cart.js +3 -16
  65. package/dist/shared/api/storefront/hooks/cart/use-patch-cart.js +11 -8
  66. package/dist/shared/api/storefront/hooks/cart/use-place-order.js +2 -2
  67. package/dist/shared/model/address.d.ts +13 -0
  68. package/dist/shared/providers/react-query-container.d.ts +2 -1
  69. package/dist/shared/providers/react-query-container.js +2 -2
  70. package/dist/shared/utils/date.d.ts +2 -0
  71. package/dist/shared/utils/date.js +11 -1
  72. package/dist/styles.css +331 -261
  73. package/dist/tooltip/tooltip.js +10 -5
  74. package/package.json +1 -1
  75. package/dist/checkout/adyen-payment.module.css.js +0 -3
  76. package/dist/checkout/payment.module.css.js +0 -3
  77. /package/dist/{checkout → pages/checkout/payment-page/components}/adyen-payment.d.ts +0 -0
  78. /package/dist/{checkout → pages/checkout/payment-page/hooks}/use-get-adyen-redirect-result.d.ts +0 -0
  79. /package/dist/{checkout → pages/checkout/payment-page/hooks}/use-get-adyen-redirect-result.js +0 -0
  80. /package/dist/{checkout → pages/checkout/payment-page/hooks}/use-has-returned-from-adyen.d.ts +0 -0
  81. /package/dist/{checkout → pages/checkout/payment-page/hooks}/use-has-returned-from-adyen.js +0 -0
  82. /package/dist/{checkout → pages/checkout/payment-page/utils}/parse-amount.d.ts +0 -0
@@ -6,53 +6,36 @@ import { CartTotalsSummary } from '../../../cart-totals/cart-totals-summary.js';
6
6
  import { Select } from '../../../forms/select/select.js';
7
7
  import { FormattedMessage } from '../../../intl/formatted-message.js';
8
8
  import { useFormattedMessage } from '../../../intl/use-formatted-message.js';
9
- import { useAwaitableMutation } from '../../../shared/api/shared/hooks/use-awaitable-mutation.js';
10
9
  import { useFetchSession } from '../../../shared/api/storefront/hooks/authentication/use-fetch-session.js';
11
10
  import { useIsAuthenticated } from '../../../shared/api/storefront/hooks/authentication/use-is-authenticated.js';
12
11
  import { usePatchSession } from '../../../shared/api/storefront/hooks/authentication/use-patch-session.js';
13
12
  import { useFetchCurrentCart } from '../../../shared/api/storefront/hooks/cart/use-fetch-current-cart.js';
14
13
  import { useFetchFulfillmentMethodsForCurrentCart } from '../../../shared/api/storefront/hooks/customer/use-fetch-fulfillment-methods-for-current-cart.js';
15
14
  import { useFetchCountries } from '../../../shared/api/storefront/hooks/website/use-fetch-countries.js';
16
- import { patchCart } from '../../../shared/api/storefront/services/cart-service.js';
17
- import { patchBillToAddress } from '../../../shared/api/storefront/services/customer-service.js';
18
15
  import { useNavigate } from '../../../shared/routing/route-provider.js';
19
16
  import { hasNo } from '../../../shared/utils/types.js';
20
17
  import { Page } from '../../components/page/page.js';
21
18
  import { ErrorPage } from '../../error-page/error-page.js';
22
19
  import { LoadingPage } from '../../loading-page/loading-page.js';
20
+ import { CHECKOUT_PATHS } from '../constants.js';
23
21
  import { CheckoutPageLayout } from '../layouts/checkout-page-layout/checkout-page-layout.js';
24
22
  import { CheckoutPageSection } from '../layouts/checkout-page-layout/components/checkout-page-section.js';
25
23
  import { CheckoutPageSectionContent } from '../layouts/checkout-page-layout/components/checkout-page-section-content.js';
26
24
  import { EDIT_ADDRESS_FORM_ID, EditAddresses } from './components/edit-address.js';
27
25
  import { ReadOnlyAddresses } from './components/readonly-address.js';
26
+ import { usePatchShippingDetails } from './hooks/use-patch-shipping-details.js';
28
27
  import styles from './shipping-page.module.css.js';
29
28
 
30
- const REVIEW_AND_SUBMIT_PATH = '/CheckoutReviewAndSubmit';
31
- function usePatchCartAndBillingAddress() {
32
- return useAwaitableMutation({
33
- mutationFn: async ({ billTo, cart, notes, }) => {
34
- await Promise.all([
35
- billTo && patchBillToAddress({ billTo }),
36
- patchCart({ cart: { ...cart, notes } }),
37
- ].filter(Boolean));
38
- },
39
- onSuccess: ({ queryClient }) => {
40
- queryClient.removeQueries({ queryKey: ['customer'] });
41
- queryClient.removeQueries({ queryKey: ['carts'] });
42
- queryClient.removeQueries({ queryKey: ['session'] });
43
- },
44
- });
45
- }
46
29
  function ShippingPage() {
47
30
  const isAuthenticated = useIsAuthenticated();
48
- const { data: cart, error, isLoading: isLoadingCart, refetch: refetchCart, } = useFetchCurrentCart();
31
+ const { data: cart, error: errorFetchCart, isLoading: isLoadingCart, refetch: refetchCart, } = useFetchCurrentCart();
49
32
  const { data: countries, isLoading: isLoadingCountries } = useFetchCountries({
50
33
  enabled: hasNo(cart?.billTo?.address1),
51
34
  });
52
35
  const { data: session } = useFetchSession();
53
36
  const { data: fulfillmentMethods, isLoading: isLoadingFulfillmentMethods } = useFetchFulfillmentMethodsForCurrentCart();
54
37
  const { isLoading: isPatchingSession, mutate: patchSession } = usePatchSession();
55
- const { isError, isLoading: isPatching, isSuccess, mutate: patchCartAndBillingAddress, } = usePatchCartAndBillingAddress();
38
+ const { error: errorPatchBillingAddress, isError, isLoading: isPatching, isSuccess, mutate: patchShippingDetails, } = usePatchShippingDetails();
56
39
  const isLoading = isLoadingCart || isLoadingCountries || isLoadingFulfillmentMethods;
57
40
  const t = useFormattedMessage();
58
41
  const { isNavigating, navigate } = useNavigate();
@@ -72,13 +55,13 @@ function ShippingPage() {
72
55
  if (isAuthenticated === undefined)
73
56
  return;
74
57
  if (!isAuthenticated)
75
- return navigate('/signin?returnUrl=/CheckoutShipping');
58
+ return navigate(CHECKOUT_PATHS.CHECKOUT_SHIPPING_VIA_SIGNIN);
76
59
  if (hasNo(cart))
77
60
  return;
78
61
  if (hasNo(cart.cartLines) || cart.cartLines.length === 0)
79
- return navigate('/cart');
62
+ return navigate(CHECKOUT_PATHS.CART);
80
63
  if (hasNo(cart.billTo))
81
- return navigate('/signin?returnUrl=/CheckoutShipping');
64
+ return navigate(CHECKOUT_PATHS.CHECKOUT_SHIPPING_VIA_SIGNIN);
82
65
  }, [cart, navigate, isAuthenticated, isNavigating]);
83
66
  useEffect(() => {
84
67
  /* Guards for when the bill to address is saved and we should navigate to the next page */
@@ -92,10 +75,10 @@ function ShippingPage() {
92
75
  return location?.reload();
93
76
  if (hasNo(cart?.billTo?.address1))
94
77
  return;
95
- return navigate(REVIEW_AND_SUBMIT_PATH);
78
+ return navigate(CHECKOUT_PATHS.REVIEW_AND_SUBMIT);
96
79
  }, [isSuccess, cart, navigate, isNavigating, isPatching, isError]);
97
- if (error)
98
- return jsx(ErrorPage, { error: error });
80
+ if (errorFetchCart)
81
+ return jsx(ErrorPage, { error: errorFetchCart });
99
82
  if (isLoading || isNavigating || isError || isSuccess)
100
83
  return jsx(LoadingPage, {});
101
84
  if (!isAuthenticated ||
@@ -106,33 +89,36 @@ function ShippingPage() {
106
89
  (hasNo(cart.billTo.address1) && hasNo(countries)))
107
90
  return null;
108
91
  return (jsx(Page, { breadCrumb: [
109
- { href: '/', label: t('Home') },
110
- { href: '/CheckoutShipping', label: t('Shipping details') },
111
- ], title: t('Shipping details'), children: jsx(CheckoutPageLayout, { actions: {
92
+ { href: CHECKOUT_PATHS.HOME, label: t('Home') },
93
+ {
94
+ href: CHECKOUT_PATHS.CHECKOUT_SHIPPING,
95
+ label: t('Shipping details'),
96
+ },
97
+ ], title: t('Shipping details'), children: jsxs(CheckoutPageLayout, { actions: {
112
98
  primary: (jsx(Button, { withArrow: true, "data-test-selector": "checkoutShippingCartTotalContinueButton", form: EDIT_ADDRESS_FORM_ID, isDisabled: isPatching, isLoading: isPatching || isPatchingSession ? (jsx(FormattedMessage, { id: "Updating address" })) : undefined, type: "submit", children: jsx(FormattedMessage, { id: "Continue shopping" }) })),
113
99
  }, mobileSummary: jsx(CartTotalsSummary, { totalAmount: cart.orderGrandTotalDisplay }), overview: jsx(CartTotals, { fulfillmentMethod: fulfillmentMethods && fulfillmentMethods.length === 1
114
100
  ? cart.fulfillmentMethod
115
- : undefined, shippingCost: cart.shippingAndHandlingDisplay, subtotal: cart.orderSubTotalDisplay, tax: cart.totalTaxDisplay, total: cart.orderGrandTotalDisplay, vatPercentage: cart.cartLines[0]?.pricing?.vatRate }), children: jsxs(Fragment, { children: [fulfillmentMethods && fulfillmentMethods.length > 1 && (jsx(CheckoutPageSection, { hasBorder: true, title: t('Fulfillment method'), children: jsx(CheckoutPageSectionContent, { children: jsx("div", { className: styles['fulfillment-select-wrapper'], children: jsx(Select, { isRequired: true, showLabel: true, "data-test-selector": "fulfillmentMethodSelect", defaultSelectedOption: cart.fulfillmentMethod, isLoading: isLoadingFulfillmentMethods, label: t('Fulfillment method'), name: "fulfillmentMethod", onChange: async (value) => {
116
- await patchSession({
117
- session: {
118
- ...session,
119
- fulfillmentMethod: value,
120
- },
121
- });
122
- await refetchCart();
123
- }, options: fulfillmentMethodOptions || {}, variant: "solid" }) }) }) })), hasBillToAddress ? (jsx(ReadOnlyAddresses, { billTo: cart.billTo, isLoading: isPatching, isPickup: isPickup, notes: cart.notes, onSubmit: async ({ notes }) => {
124
- if (!cart.billTo)
125
- return;
126
- await patchCartAndBillingAddress({ cart, notes });
127
- }, shipTo: cart.shipTo })) : (jsx(EditAddresses, { countries: countries || [], isLoading: isPatching, isPickup: isPickup, onSubmit: async ({ address, notes }) => {
128
- if (!cart.billTo)
129
- return;
130
- await patchCartAndBillingAddress({
131
- billTo: { ...cart.billTo, ...address },
132
- cart,
133
- notes,
134
- });
135
- } }))] }) }) }));
101
+ : undefined, shippingCost: cart.shippingAndHandlingDisplay, subtotal: cart.orderSubTotalDisplay, tax: cart.totalTaxDisplay, total: cart.orderGrandTotalDisplay, vatPercentage: cart.cartLines[0]?.pricing?.vatRate }), children: [jsxs(Fragment, { children: [fulfillmentMethods && fulfillmentMethods.length > 1 && (jsx(CheckoutPageSection, { hasBorder: true, title: t('Fulfillment method'), children: jsx(CheckoutPageSectionContent, { children: jsx("div", { className: styles['fulfillment-select-wrapper'], children: jsx(Select, { isRequired: true, showLabel: true, "data-test-selector": "fulfillmentMethodSelect", defaultSelectedOption: cart.fulfillmentMethod, isLoading: isLoadingFulfillmentMethods, label: t('Fulfillment method'), name: "fulfillmentMethod", onChange: async (value) => {
102
+ await patchSession({
103
+ session: {
104
+ ...session,
105
+ fulfillmentMethod: value,
106
+ },
107
+ });
108
+ await refetchCart();
109
+ }, options: fulfillmentMethodOptions || {}, variant: "solid" }) }) }) })), hasBillToAddress ? (jsx(ReadOnlyAddresses, { billTo: cart.billTo, isLoading: isPatching, isPickup: isPickup, notes: cart.notes, onSubmit: async ({ notes }) => {
110
+ if (!cart.billTo)
111
+ return;
112
+ await patchShippingDetails({ cart, notes });
113
+ }, shipTo: cart.shipTo })) : (jsx(EditAddresses, { countries: countries || [], isLoading: isPatching, isPickup: isPickup, onSubmit: async ({ address, notes }) => {
114
+ if (!cart.billTo)
115
+ return;
116
+ await patchShippingDetails({
117
+ billTo: { ...cart.billTo, ...address },
118
+ cart,
119
+ notes,
120
+ });
121
+ } }))] }), Boolean(errorPatchBillingAddress) && (jsx("div", { className: styles['error-message'], children: jsx(FormattedMessage, { id: "An unexpected error occured" }) }))] }) }));
136
122
  }
137
123
 
138
124
  export { ShippingPage };
@@ -1,3 +1,3 @@
1
- var styles = {"fulfillment-select-wrapper":"shipping-page-module-v6oci"};
1
+ var styles = {"fulfillment-select-wrapper":"shipping-page-module-v6oci","error-message":"shipping-page-module-FK0yX"};
2
2
 
3
3
  export { styles as default };
@@ -1,9 +1,10 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { BreadcrumbLink } from '../../../breadcrumbs/breadcrumb';
3
- export interface PageProps {
3
+ import { PageMetaDataProps } from '../page-meta-data/page-meta-data';
4
+ export interface PageProps extends PageMetaDataProps {
4
5
  breadCrumb: BreadcrumbLink[];
5
6
  children: ReactNode;
6
7
  className?: string;
7
8
  title?: string;
8
9
  }
9
- export declare function Page({ breadCrumb, children, className, title }: PageProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function Page({ alternateLanguageUrls, breadCrumb, canonicalUrl, children, className, meta, openGraph, title, windowTitle, }: PageProps): import("react/jsx-runtime").JSX.Element;
@@ -4,13 +4,14 @@ import clsx from 'clsx';
4
4
  import { Breadcrumb } from '../../../breadcrumbs/breadcrumb.js';
5
5
  import { Heading } from '../../../typography/heading/heading.js';
6
6
  import { PageContainer } from '../page-container/page-container.js';
7
+ import { PageMetaData } from '../page-meta-data/page-meta-data.js';
7
8
  import styles from './page.module.css.js';
8
9
 
9
10
  function PageTitle({ children }) {
10
11
  return (jsx(Heading, { italic: true, uppercase: true, breakpoints: { lg: 'm', xxl: 'xl' }, className: styles.title, size: "s", tag: "h1", children: children }));
11
12
  }
12
- function Page({ breadCrumb, children, className, title }) {
13
- return (jsxs(PageContainer, { className: clsx(styles.page, className), children: [jsx("div", { className: styles.breadcrumb, children: jsx(Breadcrumb, { links: breadCrumb }) }), title && jsx(PageTitle, { children: title }), children] }));
13
+ function Page({ alternateLanguageUrls, breadCrumb, canonicalUrl, children, className, meta, openGraph, title, windowTitle, }) {
14
+ return (jsxs(PageContainer, { className: clsx(styles.page, className), children: [jsx(PageMetaData, { alternateLanguageUrls: alternateLanguageUrls, canonicalUrl: canonicalUrl, meta: meta, openGraph: openGraph, windowTitle: windowTitle }), jsx("div", { className: styles.breadcrumb, children: jsx(Breadcrumb, { links: breadCrumb }) }), title && jsx(PageTitle, { children: title }), children] }));
14
15
  }
15
16
 
16
17
  export { Page };
@@ -1,6 +1,6 @@
1
- interface PageMetaDataProps {
1
+ export interface PageMetaDataProps {
2
2
  alternateLanguageUrls?: Record<string, string> | null;
3
- canonicalUrl: string;
3
+ canonicalUrl?: string;
4
4
  meta?: {
5
5
  description: string;
6
6
  keywords: string;
@@ -10,7 +10,6 @@ interface PageMetaDataProps {
10
10
  title: string;
11
11
  url: string;
12
12
  };
13
- title: string;
13
+ windowTitle?: string;
14
14
  }
15
15
  export declare function PageMetaData(props: PageMetaDataProps): null;
16
- export {};
@@ -21,8 +21,8 @@ function removeElements(selector) {
21
21
  function PageMetaData(props) {
22
22
  if (typeof document === 'undefined')
23
23
  return null;
24
- if (props.title) {
25
- document.title = props.title;
24
+ if (props.windowTitle) {
25
+ document.title = props.windowTitle;
26
26
  }
27
27
  if (props.canonicalUrl) {
28
28
  addOrUpdateElement('link[rel="canonical"]', {
@@ -1,8 +1,7 @@
1
1
  "use client";
2
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { jsx } from 'react/jsx-runtime';
3
3
  import { useCultureCode } from '../../../intl/use-culture-code.js';
4
4
  import { useFetchProductDetailsPageData } from '../../../shared/api/bff/hooks/use-fetch-product-details-page-data.js';
5
- import { PageMetaData } from '../../components/page-meta-data/page-meta-data.js';
6
5
  import { ErrorPage } from '../../error-page/error-page.js';
7
6
  import { LoadingPage } from '../../loading-page/loading-page.js';
8
7
  import { ProductDetails } from './product-details.js';
@@ -17,14 +16,7 @@ function ProductDetailsPage({ pageUrl }) {
17
16
  return jsx(ErrorPage, { error: error });
18
17
  if (!data || isFetching)
19
18
  return jsx(LoadingPage, {});
20
- return (jsxs(Fragment, { children: [data.page && (jsx(PageMetaData, { alternateLanguageUrls: data.page.alternateLanguageUrls, canonicalUrl: data.page.canonicalPath, meta: {
21
- description: data.page.metaDescription,
22
- keywords: data.page.metaKeywords,
23
- }, openGraph: {
24
- image: data.page.openGraphImage,
25
- title: data.page.openGraphTitle,
26
- url: data.page.openGraphUrl,
27
- }, title: data.page.title })), jsx(ProductDetails, { data: data })] }));
19
+ return jsx(ProductDetails, { data: data });
28
20
  }
29
21
 
30
22
  export { ProductDetailsPage };
@@ -13,20 +13,26 @@ import { ProductDetailsPanel } from './components/product-details-panel/product-
13
13
  import { ProductDetailsRecentlyViewed } from './components/product-details-recently-viewed/product-details-recently-viewed.js';
14
14
 
15
15
  function ProductDetails({ data, priceComponent, recentlyViewedComponent, }) {
16
- const { breadCrumb, included, product, recentlyViewed, usps } = data;
16
+ const { breadCrumb, included, page, product, recentlyViewed, usps } = data;
17
17
  useDataLayer({
18
18
  event: {
19
19
  event: 'view_item',
20
20
  },
21
21
  product,
22
22
  });
23
- return (jsx(Page, { breadCrumb: breadCrumb, children: jsx(ProductDetailsPageLayout, { imageGallery: jsx(ProductDetailImages, { images: product.images }), included: included !== undefined &&
24
- included.length > 0 && (jsxs(Fragment, { children: [jsx(Heading, { size: "s", tag: "h2", children: jsx(FormattedMessage, { id: "Includes" }) }), jsx(CardCarousel, { allowExpandToGrid: true, hasOverflow: true, cards: included.map(product => (jsx(ConnectedProductCard, { href: product.href, id: product.productId, image: {
23
+ return (jsx(Page, { alternateLanguageUrls: page.alternateLanguageUrls, breadCrumb: breadCrumb, canonicalUrl: page.canonicalPath, meta: {
24
+ description: page.metaDescription,
25
+ keywords: page.metaKeywords,
26
+ }, openGraph: {
27
+ image: page.openGraphImage,
28
+ title: page.openGraphTitle,
29
+ url: page.openGraphUrl,
30
+ }, windowTitle: page.title, children: jsx(ProductDetailsPageLayout, { imageGallery: jsx(ProductDetailImages, { images: product.images }), included: included.length > 0 && (jsxs(Fragment, { children: [jsx(Heading, { size: "s", tag: "h2", children: jsx(FormattedMessage, { id: "Includes" }) }), jsx(CardCarousel, { allowExpandToGrid: true, hasOverflow: true, cards: included.map(product => (jsx(ConnectedProductCard, { href: product.href, id: product.productId, image: {
25
31
  fit: 'contain',
26
32
  image: product.image,
27
33
  title: product.image?.altText || product.title,
28
34
  }, price: product.price, sku: product.sku, tags: product.tags, title: product.title }, product.storefrontId))) })] })), productInformation: jsx(ProductDetailsPanel, { priceComponent: priceComponent, product: product }), recentlyViewed: recentlyViewedComponent ||
29
- (recentlyViewed !== undefined && recentlyViewed.length > 0 && (jsx(ProductDetailsRecentlyViewed, { recentlyViewed: recentlyViewed }))), usp: usps && jsx(ProductUSPCarousel, { usps: usps }) }) }));
35
+ (recentlyViewed.length > 0 && (jsx(ProductDetailsRecentlyViewed, { recentlyViewed: recentlyViewed }))), usp: usps && jsx(ProductUSPCarousel, { usps: usps }) }) }));
30
36
  }
31
37
 
32
38
  export { ProductDetails };
@@ -18,7 +18,7 @@ export interface ProductListingPageData {
18
18
  category: CategoryType | undefined;
19
19
  categoryPages: string;
20
20
  hierarchicalCategories: string[];
21
- page?: PageModel;
21
+ page: PageModel;
22
22
  promoBanners?: {
23
23
  top: PromoBannerType[] | undefined;
24
24
  };
@@ -1,10 +1,9 @@
1
1
  "use client";
2
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { jsx } from 'react/jsx-runtime';
3
3
  import { createSonicSearchClient } from '../../../algolia/algolia-sonic-searchclient.js';
4
4
  import { config } from '../../../config.js';
5
5
  import { useCultureCode } from '../../../intl/use-culture-code.js';
6
6
  import { useFetchProductListingPageData } from '../../../shared/api/bff/hooks/use-fetch-product-listing-page-data.js';
7
- import { PageMetaData } from '../../components/page-meta-data/page-meta-data.js';
8
7
  import { ErrorPage } from '../../error-page/error-page.js';
9
8
  import { LoadingPage } from '../../loading-page/loading-page.js';
10
9
  import { ProductListing } from './product-listing.js';
@@ -24,14 +23,7 @@ function ProductListingPage({ pageUrl, searchClient = defaultSearchClient, }) {
24
23
  return jsx(ErrorPage, { error: error });
25
24
  if (!data || isFetching)
26
25
  return jsx(LoadingPage, {});
27
- return (jsxs(Fragment, { children: [data.page && (jsx(PageMetaData, { alternateLanguageUrls: data.page.alternateLanguageUrls, canonicalUrl: data.page.canonicalPath, meta: {
28
- description: data.page.metaDescription,
29
- keywords: data.page.metaKeywords,
30
- }, openGraph: {
31
- image: data.page.openGraphImage,
32
- title: data.page.openGraphTitle,
33
- url: data.page.openGraphUrl,
34
- }, title: data.page.title })), jsx(ProductListing, { data: data, searchClient: searchClient })] }));
26
+ return jsx(ProductListing, { data: data, searchClient: searchClient });
35
27
  }
36
28
 
37
29
  export { ProductListingPage };
@@ -24,7 +24,14 @@ import styles from './product-listing-page.module.css.js';
24
24
  function ProductListing({ data, searchClient, }) {
25
25
  const languageCode = useLanguageCode();
26
26
  const category = data.breadCrumb.slice(1).map(breadCrumb => breadCrumb.label);
27
- return (jsx(AlgoliaProvider, { categoryPages: data.categoryPages, hierarchicalCategories: data.hierarchicalCategories, languageCode: languageCode, offlineSearchClient: offlineSearchClient, searchClient: searchClient, children: jsx(Page, { breadCrumb: data.breadCrumb, className: styles['product-listing'], title: [...category].pop(), children: jsx(ProductListingPageContent, { currentCategoryPath: data.hierarchicalCategories, promoBanners: data.promoBanners?.top }) }) }, data.categoryPages));
27
+ return (jsx(AlgoliaProvider, { categoryPages: data.categoryPages, hierarchicalCategories: data.hierarchicalCategories, languageCode: languageCode, offlineSearchClient: offlineSearchClient, searchClient: searchClient, children: jsx(Page, { alternateLanguageUrls: data.page.alternateLanguageUrls, breadCrumb: data.breadCrumb, canonicalUrl: data.page.canonicalPath, className: styles['product-listing'], meta: {
28
+ description: data.page.metaDescription,
29
+ keywords: data.page.metaKeywords,
30
+ }, openGraph: {
31
+ image: data.page.openGraphImage,
32
+ title: data.page.openGraphTitle,
33
+ url: data.page.openGraphUrl,
34
+ }, title: [...category].pop(), windowTitle: data.page.title, children: jsx(ProductListingPageContent, { currentCategoryPath: data.hierarchicalCategories, promoBanners: data.promoBanners?.top }) }) }, data.categoryPages));
28
35
  }
29
36
  function ProductListingPageContent({ currentCategoryPath, promoBanners, }) {
30
37
  const { hits, isLoading } = useAlgoliaHits();
@@ -14,7 +14,6 @@ import { scrollToTop } from '../../../shared/hooks/use-scroll-to.js';
14
14
  import { Sidebar } from '../../../sidebar/sidebar.js';
15
15
  import { ToggleSidebarButton } from '../../../sidebar/toggle-sidebar-button.js';
16
16
  import { Page } from '../../components/page/page.js';
17
- import { PageMetaData } from '../../components/page-meta-data/page-meta-data.js';
18
17
  import { LoadingPage } from '../../loading-page/loading-page.js';
19
18
  import { NoResults } from '../product-listing-page/no-results/no-results.js';
20
19
  import { SearchResultProductOverview } from './search-result-product-overview/search-result-product-overview.js';
@@ -28,13 +27,11 @@ function SearchResultsPage({ location, searchClient, }) {
28
27
  const keyword = Array.isArray(keywords) ? keywords.join(' ') : keywords;
29
28
  if (!keyword)
30
29
  return jsx("h1", { children: "No search results...." });
31
- return (jsxs(AlgoliaProvider, { languageCode: languageCode, query: keyword, searchClient: searchClient, children: [jsx(PageMetaData
30
+ return (jsx(AlgoliaProvider, { languageCode: languageCode, query: keyword, searchClient: searchClient, children: jsx(Page, { breadCrumb: [],
32
31
  // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc
33
- , {
34
- // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc
35
- canonicalUrl: typeof window === 'undefined' ? '' : window.location.href, title: t('Search') }), jsx(Page, { breadCrumb: [], className: styles['search-results'], title: t("'{0}' in all products", {
36
- replacementValues: { 0: keyword },
37
- }), children: jsx(SearchResultsPageContent, { keyword: keyword }) })] }));
32
+ canonicalUrl: typeof window === 'undefined' ? '' : window.location.href, className: styles['search-results'], title: t("'{0}' in all products", {
33
+ replacementValues: { 0: keyword },
34
+ }), windowTitle: `${t('Search')} - ${t('Sonic Equipment')}`, children: jsx(SearchResultsPageContent, { keyword: keyword }) }) }));
38
35
  }
39
36
  function SearchResultsPageContent({ keyword }) {
40
37
  const { hits, isLoading } = useAlgoliaHits();
@@ -142,10 +142,10 @@ export interface Usp {
142
142
  }
143
143
  export interface ProductDetailsPageDataResponse {
144
144
  breadCrumb: BreadCrumb[];
145
- included?: ProductSummary[];
146
- page?: PageModel;
145
+ included: ProductSummary[];
146
+ page: PageModel;
147
147
  product: ProductDetails;
148
- recentlyViewed?: ProductSummary[];
148
+ recentlyViewed: ProductSummary[];
149
149
  usps?: Usp[];
150
150
  }
151
151
  export interface ProductListingPageDataResponse {
@@ -156,7 +156,7 @@ export interface ProductListingPageDataResponse {
156
156
  categories: Category | null;
157
157
  categoryPages: string;
158
158
  hierarchicalCategories: string[];
159
- page?: PageModel;
159
+ page: PageModel;
160
160
  promoBanners: PromoBanners | null;
161
161
  }
162
162
  export {};
@@ -40,7 +40,7 @@ async function fetchProductListingPageData({ cultureCode, pageUrl, }) {
40
40
  url: `${config.BFF_API_URL}/plp/?pageUrl=${pageUrl}`,
41
41
  });
42
42
  return {
43
- breadCrumb: body.breadCrumb,
43
+ ...body,
44
44
  category: body.categories
45
45
  ? {
46
46
  href: body.categories.path,
@@ -53,9 +53,6 @@ async function fetchProductListingPageData({ cultureCode, pageUrl, }) {
53
53
  title: body.categories.shortDescription,
54
54
  }
55
55
  : undefined,
56
- categoryPages: body.categoryPages,
57
- hierarchicalCategories: body.hierarchicalCategories,
58
- page: body.page,
59
56
  promoBanners: body.promoBanners
60
57
  ? {
61
58
  top: body.promoBanners.top || undefined,
@@ -0,0 +1,8 @@
1
+ import { CartModel } from '../../model/storefront.model';
2
+ export interface UseFetchCartByIdArgs<T> {
3
+ enabled?: boolean;
4
+ forceRecalculation?: boolean;
5
+ id: string;
6
+ select?: (data: CartModel) => T;
7
+ }
8
+ export declare function useFetchCartById<T = CartModel>({ enabled, forceRecalculation, id, select, }: UseFetchCartByIdArgs<T>): import("@tanstack/react-query").UseQueryResult<T, Error>;
@@ -0,0 +1,20 @@
1
+ import { useQuery } from '@tanstack/react-query';
2
+ import { TIME } from '../../../../utils/time.js';
3
+ import { fetchCart } from '../../services/cart-service.js';
4
+
5
+ function useFetchCartById({ enabled = true, forceRecalculation = true, id, select, }) {
6
+ return useQuery({
7
+ enabled,
8
+ gcTime: 15 * TIME.MINUTE,
9
+ placeholderData: prev => prev,
10
+ queryFn: () => {
11
+ return fetchCart({ forceRecalculation, id });
12
+ },
13
+ queryKey: ['carts', id],
14
+ retry: 3,
15
+ select: select || (cartModel => cartModel),
16
+ staleTime: 15 * TIME.MINUTE,
17
+ });
18
+ }
19
+
20
+ export { useFetchCartById };
@@ -1 +1 @@
1
- export declare function useFetchCurrentCartCount(): number | undefined;
1
+ export declare function useFetchCurrentCartCount(): number;
@@ -1,8 +1,8 @@
1
- import { useFetchCurrentCartLines } from './use-fetch-current-cart-lines.js';
1
+ import { useFetchCurrentCart } from './use-fetch-current-cart.js';
2
2
 
3
3
  function useFetchCurrentCartCount() {
4
- const { data } = useFetchCurrentCartLines();
5
- return data?.reduce((acc, cartLine) => acc + (cartLine.qtyOrdered || 0), 0);
4
+ const { data } = useFetchCurrentCart();
5
+ return data?.totalCountDisplay || 0;
6
6
  }
7
7
 
8
8
  export { useFetchCurrentCartCount };
@@ -1,6 +1,3 @@
1
1
  import { CartModel } from '../../model/storefront.model';
2
- export declare function useFetchCurrentCart<T = CartModel>({ enabled, forceRecalculation, select, }?: {
3
- enabled?: boolean;
4
- forceRecalculation?: boolean;
5
- select?: (data: CartModel) => T;
6
- }): import("@tanstack/react-query").UseQueryResult<T, Error>;
2
+ import { UseFetchCartByIdArgs } from './use-fetch-cart-by-id';
3
+ export declare function useFetchCurrentCart<T = CartModel>(args?: Omit<UseFetchCartByIdArgs<T>, 'id'>): import("@tanstack/react-query").UseQueryResult<T, Error>;
@@ -1,20 +1,7 @@
1
- import { useQuery } from '@tanstack/react-query';
2
- import { TIME } from '../../../../utils/time.js';
3
- import { fetchCurrentCart } from '../../services/cart-service.js';
1
+ import { useFetchCartById } from './use-fetch-cart-by-id.js';
4
2
 
5
- function useFetchCurrentCart({ enabled = true, forceRecalculation = true, select, } = {}) {
6
- return useQuery({
7
- enabled,
8
- gcTime: 15 * TIME.MINUTE,
9
- placeholderData: prev => prev,
10
- queryFn: () => {
11
- return fetchCurrentCart({ forceRecalculation });
12
- },
13
- queryKey: ['carts', 'current'],
14
- retry: 3,
15
- select: select || (cartModel => cartModel),
16
- staleTime: 15 * TIME.MINUTE,
17
- });
3
+ function useFetchCurrentCart(args) {
4
+ return useFetchCartById({ ...args, id: 'current' });
18
5
  }
19
6
 
20
7
  export { useFetchCurrentCart };
@@ -1,17 +1,20 @@
1
+ import { useCallback } from 'react';
1
2
  import { useAwaitableMutation } from '../../../shared/hooks/use-awaitable-mutation.js';
2
3
  import { patchCart } from '../../services/cart-service.js';
3
4
 
4
5
  function usePatchCart({ skipInvalidation = false, } = {}) {
6
+ const onError = useCallback(({ args: [{ cart }], queryClient }) => {
7
+ queryClient.invalidateQueries({ queryKey: ['carts', cart.id] });
8
+ }, []);
9
+ const onSuccess = useCallback(({ args: [{ cart }], queryClient }) => {
10
+ if (skipInvalidation)
11
+ return;
12
+ queryClient.removeQueries({ queryKey: ['carts', cart.id] });
13
+ }, [skipInvalidation]);
5
14
  return useAwaitableMutation({
6
15
  mutationFn: patchCart,
7
- onError: ({ args: [{ cart }], queryClient }) => {
8
- queryClient.invalidateQueries({ queryKey: ['carts', cart.id] });
9
- },
10
- onSuccess: ({ args: [{ cart }], data: updatedCart, queryClient }) => {
11
- if (skipInvalidation)
12
- return;
13
- queryClient.setQueriesData({ exact: true, queryKey: ['carts', updatedCart.id] }, { ...updatedCart, cartLines: cart.cartLines });
14
- },
16
+ onError,
17
+ onSuccess,
15
18
  });
16
19
  }
17
20
 
@@ -4,10 +4,10 @@ import { placeOrder } from '../../services/cart-service.js';
4
4
 
5
5
  const usePlaceOrder = () => {
6
6
  const onComplete = useCallback(({ args: [{ cart }], queryClient }) => {
7
- queryClient.invalidateQueries({ queryKey: ['carts', cart.id] });
7
+ queryClient.removeQueries({ queryKey: ['carts', cart.id] });
8
8
  }, []);
9
9
  const onSuccess = useCallback(({ data: updatedCart, queryClient }) => {
10
- queryClient.setQueryData(['carts', updatedCart.id], updatedCart);
10
+ queryClient.removeQueries({ queryKey: ['carts', updatedCart.id] });
11
11
  }, []);
12
12
  return useAwaitableMutation({
13
13
  mutationFn: placeOrder,
@@ -1,2 +1,15 @@
1
1
  export declare const validatePhone: (value: string) => boolean;
2
2
  export declare const validateEmail: (value: string) => boolean;
3
+ export interface AddressType {
4
+ address1?: string;
5
+ address2?: string;
6
+ address3?: string;
7
+ city?: string;
8
+ companyName?: string;
9
+ country?: string;
10
+ email?: string;
11
+ firstName?: string;
12
+ lastName?: string;
13
+ phone?: string;
14
+ postalCode?: string;
15
+ }
@@ -1,4 +1,5 @@
1
1
  import { ReactNode } from 'react';
2
- export declare function ReactQueryContainer({ children }: {
2
+ export declare function ReactQueryContainer({ children, enableDevTools, }: {
3
3
  children: ReactNode;
4
+ enableDevTools?: boolean;
4
5
  }): import("react/jsx-runtime").JSX.Element;
@@ -15,8 +15,8 @@ const queryClient = new QueryClient({
15
15
  },
16
16
  },
17
17
  });
18
- function ReactQueryContainer({ children }) {
19
- return (jsxs(QueryClientProvider, { client: queryClient, children: [environment !== 'production' && (jsx(ReactQueryDevtools, { initialIsOpen: false })), children] }));
18
+ function ReactQueryContainer({ children, enableDevTools = environment !== 'production', }) {
19
+ return (jsxs(QueryClientProvider, { client: queryClient, children: [enableDevTools && jsx(ReactQueryDevtools, { initialIsOpen: false }), children] }));
20
20
  }
21
21
 
22
22
  export { ReactQueryContainer };
@@ -1,3 +1,4 @@
1
+ import { CultureCode } from '../../intl/types';
1
2
  export type DateUnit = 'day' | 'week' | 'month';
2
3
  export type DateUnitObject = {
3
4
  number: number;
@@ -9,3 +10,4 @@ export type DateThreshold = {
9
10
  };
10
11
  export declare function getDateUnitObject(date: Date): DateUnitObject;
11
12
  export declare function convertDateUnitToPluralOrSingle(unit: DateUnit, number: number): 'day' | 'days' | 'week' | 'weeks' | 'month' | 'months';
13
+ export declare function formatDateToLocaleString(date?: Date, cultureCode?: CultureCode): string;
@@ -54,5 +54,15 @@ function convertDateUnitToPluralOrSingle(unit, number) {
54
54
  return 'months';
55
55
  }
56
56
  }
57
+ function formatDateToLocaleString(date, cultureCode) {
58
+ if (!date || !cultureCode)
59
+ return '';
60
+ return date.toLocaleDateString(cultureCode, {
61
+ day: 'numeric',
62
+ month: 'long',
63
+ weekday: 'long',
64
+ year: 'numeric',
65
+ });
66
+ }
57
67
 
58
- export { convertDateUnitToPluralOrSingle, getDateUnitObject };
68
+ export { convertDateUnitToPluralOrSingle, formatDateToLocaleString, getDateUnitObject };