@sonic-equipment/ui 147.0.0 → 149.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 (80) hide show
  1. package/dist/address-info-display/address-info-display.js +1 -2
  2. package/dist/algolia/algolia-hit-type.d.ts +2 -0
  3. package/dist/algolia/algolia-results-count.js +8 -0
  4. package/dist/algolia/constants/index.d.ts +1 -0
  5. package/dist/algolia/constants/index.js +3 -0
  6. package/dist/algolia/use-algolia-insights.js +3 -3
  7. package/dist/cards/orderline-card/orderline-card.js +2 -2
  8. package/dist/cards/orderline-card/orderline-card.module.css.js +1 -1
  9. package/dist/cards/product-card/product-card.js +3 -2
  10. package/dist/cards/product-card/product-card.module.css.js +1 -1
  11. package/dist/cart-totals/cart-totals-summary.d.ts +4 -2
  12. package/dist/cart-totals/cart-totals-summary.js +3 -2
  13. package/dist/cart-totals/cart-totals.d.ts +7 -5
  14. package/dist/cart-totals/cart-totals.js +3 -2
  15. package/dist/country-selector/connected-country-selector.js +2 -2
  16. package/dist/delivery-time/delivery-time.js +2 -2
  17. package/dist/display/price/price.d.ts +18 -0
  18. package/dist/display/price/price.js +30 -0
  19. package/dist/display/price/price.module.css.js +3 -0
  20. package/dist/display/product-sku/product-sku.d.ts +2 -1
  21. package/dist/display/product-sku/product-sku.js +3 -2
  22. package/dist/exports.d.ts +5 -2
  23. package/dist/global-search/search-result-panel/sections/with-results.js +1 -0
  24. package/dist/index.js +9 -6
  25. package/dist/intl/intl-context.d.ts +10 -4
  26. package/dist/intl/intl-context.js +4 -0
  27. package/dist/intl/intl-provider.d.ts +4 -2
  28. package/dist/intl/intl-provider.js +18 -4
  29. package/dist/intl/missing-translation-provider.js +3 -2
  30. package/dist/intl/translation-id.d.ts +1 -1
  31. package/dist/intl/types.d.ts +2 -0
  32. package/dist/intl/types.js +6 -1
  33. package/dist/intl/use-country-code.d.ts +3 -0
  34. package/dist/intl/use-country-code.js +15 -0
  35. package/dist/intl/use-culture-code.d.ts +2 -1
  36. package/dist/intl/use-culture-code.js +5 -4
  37. package/dist/intl/use-currency-code.d.ts +4 -0
  38. package/dist/intl/use-currency-code.js +15 -0
  39. package/dist/intl/use-formatted-message.js +2 -3
  40. package/dist/intl/use-intl.d.ts +1 -0
  41. package/dist/intl/use-intl.js +9 -0
  42. package/dist/intl/use-language-code.js +2 -3
  43. package/dist/pages/checkout/cart-page/cart-page.js +6 -1
  44. package/dist/pages/checkout/order-confirmation-page/order-confirmation-page-content.js +6 -1
  45. package/dist/pages/checkout/payment-page/components/adyen-payment.d.ts +3 -2
  46. package/dist/pages/checkout/payment-page/components/payment.js +69 -40
  47. package/dist/pages/checkout/payment-page/payment-page-content.js +7 -2
  48. package/dist/pages/checkout/payment-page/utils/parse-amount.d.ts +2 -1
  49. package/dist/pages/checkout/shipping-page/components/edit-address-form.js +2 -2
  50. package/dist/pages/checkout/shipping-page/shipping-page-content.js +6 -2
  51. package/dist/pages/product/components/product-overview.d.ts +8 -0
  52. package/dist/pages/product/components/product-overview.js +20 -0
  53. package/dist/pages/product/product-details-page/components/product-details-panel/product-details-panel.js +2 -2
  54. package/dist/pages/product/product-details-page/components/product-details-panel/product-details-panel.module.css.js +1 -1
  55. package/dist/pages/product/product-listing-page/product-listing-product-overview/product-listing-product-overview.js +3 -6
  56. package/dist/pages/product/search-result-page/search-result-product-overview/search-result-product-overview.js +3 -6
  57. package/dist/shared/api/bff/model/bff.model.d.ts +3 -0
  58. package/dist/shared/api/storefront/hooks/cart/use-place-order.d.ts +1 -1
  59. package/dist/shared/api/storefront/model/storefront.model.d.ts +4 -0
  60. package/dist/shared/api/storefront/services/cart-service.d.ts +1 -1
  61. package/dist/shared/api/storefront/services/cart-service.js +1 -1
  62. package/dist/shared/api/storefront/services/finance-service.d.ts +1 -1
  63. package/dist/shared/ga/use-data-layer.js +4 -4
  64. package/dist/shared/model/currency.d.ts +8 -1
  65. package/dist/shared/model/currency.js +28 -30
  66. package/dist/shared/model/hit.d.ts +2 -0
  67. package/dist/shared/model/hit.js +1 -0
  68. package/dist/shared/model/price.d.ts +5 -2
  69. package/dist/shared/utils/price.d.ts +19 -5
  70. package/dist/shared/utils/price.js +36 -7
  71. package/dist/shared/utils/string.d.ts +0 -1
  72. package/dist/shared/utils/string.js +1 -4
  73. package/dist/styles.css +467 -278
  74. package/package.json +1 -1
  75. package/dist/display/product-price/product-price.d.ts +0 -7
  76. package/dist/display/product-price/product-price.js +0 -19
  77. package/dist/display/product-price/product-price.module.css.js +0 -3
  78. package/dist/display/product-price/product-total-price.d.ts +0 -7
  79. package/dist/display/product-price/product-total-price.js +0 -16
  80. package/dist/display/product-price/product-total-price.module.css.js +0 -3
@@ -3,6 +3,11 @@ function isCountryCode(value) {
3
3
  return false;
4
4
  return /^[A-Z]{2}$/.test(value);
5
5
  }
6
+ function isCurrencyCode(value) {
7
+ if (typeof value !== 'string')
8
+ return false;
9
+ return /^[A-Z]{3}$/.test(value);
10
+ }
6
11
  function isLanguageCode(value) {
7
12
  if (typeof value !== 'string')
8
13
  return false;
@@ -14,4 +19,4 @@ function isCultureCode(value) {
14
19
  return /^[a-z]{2}-[A-Z]{2}$/.test(value);
15
20
  }
16
21
 
17
- export { isCountryCode, isCultureCode, isLanguageCode };
22
+ export { isCountryCode, isCultureCode, isCurrencyCode, isLanguageCode };
@@ -0,0 +1,3 @@
1
+ import { UpdateCountryCode } from './intl-context';
2
+ export declare function useCountryCode(): string;
3
+ export declare function useUpdateCountryCode(): UpdateCountryCode;
@@ -0,0 +1,15 @@
1
+ "use client";
2
+ import { useIntl } from './use-intl.js';
3
+
4
+ function useCountryCode() {
5
+ const { countryCode } = useIntl();
6
+ return countryCode;
7
+ }
8
+ function useUpdateCountryCode() {
9
+ const { updateCountryCode } = useIntl();
10
+ if (!updateCountryCode)
11
+ throw new Error('updateCountryCode is not defined');
12
+ return updateCountryCode;
13
+ }
14
+
15
+ export { useCountryCode, useUpdateCountryCode };
@@ -1,3 +1,4 @@
1
+ import { UpdateCultureCode } from './intl-context';
1
2
  import { CultureCode } from './types';
2
3
  export declare function useCultureCode(): CultureCode;
3
- export declare function useUpdateCultureCode(): (cultureCode: CultureCode) => void;
4
+ export declare function useUpdateCultureCode(): UpdateCultureCode;
@@ -1,13 +1,14 @@
1
1
  "use client";
2
- import { useContext } from 'react';
3
- import { IntlContext } from './intl-context.js';
2
+ import { useIntl } from './use-intl.js';
4
3
 
5
4
  function useCultureCode() {
6
- const { cultureCode } = useContext(IntlContext);
5
+ const { cultureCode } = useIntl();
7
6
  return cultureCode;
8
7
  }
9
8
  function useUpdateCultureCode() {
10
- const { updateCultureCode } = useContext(IntlContext);
9
+ const { updateCultureCode } = useIntl();
10
+ if (!updateCultureCode)
11
+ throw new Error('updateCultureCode is not defined');
11
12
  return updateCultureCode;
12
13
  }
13
14
 
@@ -0,0 +1,4 @@
1
+ import { UpdateCurrencyCode } from './intl-context';
2
+ import { CurrencyCode } from './types';
3
+ export declare function useCurrencyCode(): CurrencyCode;
4
+ export declare function useUpdateCurrencyCode(): UpdateCurrencyCode;
@@ -0,0 +1,15 @@
1
+ "use client";
2
+ import { useIntl } from './use-intl.js';
3
+
4
+ function useCurrencyCode() {
5
+ const { currencyCode } = useIntl();
6
+ return currencyCode;
7
+ }
8
+ function useUpdateCurrencyCode() {
9
+ const { updateCurrencyCode } = useIntl();
10
+ if (!updateCurrencyCode)
11
+ throw new Error('updateCurrencyCode is not defined');
12
+ return updateCurrencyCode;
13
+ }
14
+
15
+ export { useCurrencyCode, useUpdateCurrencyCode };
@@ -1,9 +1,8 @@
1
1
  "use client";
2
- import { useContext } from 'react';
3
- import { IntlContext } from './intl-context.js';
2
+ import { useIntl } from './use-intl.js';
4
3
 
5
4
  function useFormattedMessage() {
6
- const { formattedMessage } = useContext(IntlContext);
5
+ const { formattedMessage } = useIntl();
7
6
  const formatFunction = (id, options) => formattedMessage(id, options);
8
7
  function pluralize(translationIdOrPrefix, translationIdOrCount, count) {
9
8
  return formatFunction((typeof translationIdOrCount === 'number'
@@ -0,0 +1 @@
1
+ export declare function useIntl(): import("./intl-context").IntlContextType;
@@ -0,0 +1,9 @@
1
+ "use client";
2
+ import { useContext } from 'react';
3
+ import { IntlContext } from './intl-context.js';
4
+
5
+ function useIntl() {
6
+ return useContext(IntlContext);
7
+ }
8
+
9
+ export { useIntl };
@@ -1,10 +1,9 @@
1
1
  "use client";
2
- import { useContext } from 'react';
3
- import { IntlContext } from './intl-context.js';
2
+ import { useIntl } from './use-intl.js';
4
3
  import { getLanguageCodeFromCultureCode } from './utils.js';
5
4
 
6
5
  function useLanguageCode() {
7
- const { cultureCode } = useContext(IntlContext);
6
+ const { cultureCode } = useIntl();
8
7
  return getLanguageCodeFromCultureCode(cultureCode);
9
8
  }
10
9
 
@@ -17,6 +17,7 @@ import { RouteButton } from '../../../shared/routing/route-button.js';
17
17
  import { useToast } from '../../../toast/use-toast.js';
18
18
  import { useFetchCurrentCartLinesWithAtp } from '../../../shared/api/storefront/hooks/cart/use-fetch-current-cart-lines-with-atp.js';
19
19
  import { useFetchCurrentCartWithAtp } from '../../../shared/api/storefront/hooks/cart/use-fetch-current-cart-with-atp.js';
20
+ import { getCurrencyCodeBySymbol } from '../../../shared/model/currency.js';
20
21
  import { PATHS } from '../../paths.js';
21
22
  import { EmptyCart } from './components/empty-cart-page.js';
22
23
 
@@ -74,6 +75,9 @@ function CartContent({ cartLines }) {
74
75
  const isAuthenticated = useIsAuthenticated();
75
76
  if (!currentCart)
76
77
  return null;
78
+ const currencyCode = getCurrencyCodeBySymbol(currentCart.currencySymbol);
79
+ if (!currencyCode)
80
+ throw new Error(`Currency code not found for symbol ${currentCart.currencySymbol}`);
77
81
  return (jsx(CheckoutPageLayout, { actions: {
78
82
  primary: (jsx(RouteButton, { withArrow: true, "data-test-selector": "checkoutShippingCartTotalContinueButton", href: "/CheckoutShipping", children: jsx(FormattedMessage, { id: "Continue shopping" }) })),
79
83
  secondary: (jsx(RouteButton, { color: "secondary", href: isAuthenticated ? undefined : PATHS.SIGN_IN, onClick: () => {
@@ -81,7 +85,7 @@ function CartContent({ cartLines }) {
81
85
  return;
82
86
  saveCartForLater.mutate({ cart: currentCart });
83
87
  }, variant: "outline", children: jsx(FormattedMessage, { id: "Save order" }) })),
84
- }, mobileSummary: jsx(CartTotalsSummary, { totalAmount: currentCart.orderGrandTotalDisplay }), overview: jsx(CartTotals, { shippingCost: currentCart.shippingAndHandlingDisplay, subtotal: currentCart.orderSubTotalDisplay, tax: currentCart.totalTaxDisplay, total: currentCart.orderGrandTotalDisplay, vatPercentage: cartLines[0]?.pricing?.vatRate || 0 }), children: jsx(OrderLineList, { onRemoveAll: () => deleteCurrentCart.mutate(), children: cartLines.map(cartLine => (jsx(ConnectedOrderLineCard, { deliveryDate: cartLine.atp?.date, href: cartLine.productUri, image: {
88
+ }, mobileSummary: jsx(CartTotalsSummary, { currencyCode: currencyCode, totalAmount: currentCart.orderGrandTotal }), overview: jsx(CartTotals, { currencyCode: currencyCode, shippingCost: currentCart.shippingAndHandling, subtotal: currentCart.orderSubTotal, tax: currentCart.totalTax, total: currentCart.orderGrandTotal, vatPercentage: cartLines[0]?.pricing?.vatRate || 0 }), children: jsx(OrderLineList, { onRemoveAll: () => deleteCurrentCart.mutate(), children: cartLines.map(cartLine => (jsx(ConnectedOrderLineCard, { deliveryDate: cartLine.atp?.date, href: cartLine.productUri, image: {
85
89
  fit: 'contain',
86
90
  image: {
87
91
  '1': cartLine.smallImagePath,
@@ -91,6 +95,7 @@ function CartContent({ cartLines }) {
91
95
  },
92
96
  title: cartLine.altText,
93
97
  }, isReadonly: false, onRemove: () => deleteCartLine.mutate({ cartLineId: cartLine.id }), orderLineId: cartLine.id, price: {
98
+ currencyCode,
94
99
  originalTotalPrice: cartLine.pricing?.extendedUnitNetPrice || 0,
95
100
  pricePerUnit: cartLine.pricing?.unitNetPrice || 0,
96
101
  totalPrice: cartLine.pricing?.extendedUnitNetPrice || 0,
@@ -8,6 +8,7 @@ import { useCultureCode } from '../../../intl/use-culture-code.js';
8
8
  import { useFormattedMessage } from '../../../intl/use-formatted-message.js';
9
9
  import { OrderLineList } from '../../../lists/orderline-list/orderline-list.js';
10
10
  import { useSaveCartForLater } from '../../../shared/api/storefront/hooks/cart/use-save-cart-for-later.js';
11
+ import { getCurrencyCodeBySymbol } from '../../../shared/model/currency.js';
11
12
  import { RouteButton } from '../../../shared/routing/route-button.js';
12
13
  import { formatDateToLocaleString } from '../../../shared/utils/date.js';
13
14
  import { useToast } from '../../../toast/use-toast.js';
@@ -39,6 +40,9 @@ function OrderConfirmationPageContent({ cart, }) {
39
40
  });
40
41
  },
41
42
  });
43
+ const currencyCode = getCurrencyCodeBySymbol(cart.currencySymbol);
44
+ if (!currencyCode)
45
+ throw new Error(`Currency code not found for symbol ${cart.currencySymbol}`);
42
46
  return (jsx(Page, { breadcrumb: [
43
47
  { href: PATHS.HOME, label: t('Home') },
44
48
  {
@@ -50,7 +54,7 @@ function OrderConfirmationPageContent({ cart, }) {
50
54
  secondary: (jsxs(Fragment, { children: [cart.canSaveOrder && (jsx(RouteButton, { color: "secondary", onClick: () => {
51
55
  saveCartForLater.mutate({ cart });
52
56
  }, variant: "outline", children: jsx(FormattedMessage, { id: "Save order" }) })), jsx(PrintButton, {})] })),
53
- }, overview: jsx(CartTotals, { fulfillmentMethod: t(`fulfillmentmethod.${cart.fulfillmentMethod}`), orderNumber: cart.orderNumber, shippingCost: cart.shippingAndHandlingDisplay, subtotal: cart.orderSubTotalDisplay, tax: cart.totalTaxDisplay, total: cart.orderGrandTotalDisplay, vatPercentage: cart.cartLines?.[0]?.pricing?.vatRate }), children: jsxs("div", { children: [jsx(CheckoutPageSection, { hasBorder: false, title: t('General'), children: jsx(CheckoutPageSectionContent, { children: jsxs("div", { className: styles['general-order-info'], children: [cart.orderDate && (jsx(InfoDisplay, { id: "order-date", label: t('Order date'), value: formatDateToLocaleString(new Date(cart.orderDate), cultureCode) })), cart.requestedDeliveryDateDisplay && (jsx(InfoDisplay, { id: "requested-delivery-date", label: t('Requested delivery date'), value: formatDateToLocaleString(new Date(cart.requestedDeliveryDateDisplay.toString()), cultureCode) })), cart.poNumber && (jsx(InfoDisplay, { id: "po-number", label: t('PO Number'), value: cart.poNumber }))] }) }) }), jsx(CheckoutPageSection, { hasBorder: false, title: t('Billing and shipping information'), children: jsx(CheckoutPageSectionContent, { children: jsx(BillingAndInvoiceInformation, { billToAddress: {
57
+ }, overview: jsx(CartTotals, { currencyCode: currencyCode, fulfillmentMethod: t(`fulfillmentmethod.${cart.fulfillmentMethod}`), orderNumber: cart.orderNumber, shippingCost: cart.shippingAndHandling, subtotal: cart.orderSubTotal, tax: cart.totalTax, total: cart.orderGrandTotal, vatPercentage: cart.cartLines?.[0]?.pricing?.vatRate }), children: jsxs("div", { children: [jsx(CheckoutPageSection, { hasBorder: false, title: t('General'), children: jsx(CheckoutPageSectionContent, { children: jsxs("div", { className: styles['general-order-info'], children: [cart.orderDate && (jsx(InfoDisplay, { id: "order-date", label: t('Order date'), value: formatDateToLocaleString(new Date(cart.orderDate), cultureCode) })), cart.requestedDeliveryDateDisplay && (jsx(InfoDisplay, { id: "requested-delivery-date", label: t('Requested delivery date'), value: formatDateToLocaleString(new Date(cart.requestedDeliveryDateDisplay.toString()), cultureCode) })), cart.poNumber && (jsx(InfoDisplay, { id: "po-number", label: t('PO Number'), value: cart.poNumber }))] }) }) }), jsx(CheckoutPageSection, { hasBorder: false, title: t('Billing and shipping information'), children: jsx(CheckoutPageSectionContent, { children: jsx(BillingAndInvoiceInformation, { billToAddress: {
54
58
  address1: cart.billTo?.address1,
55
59
  address2: cart.billTo?.address2,
56
60
  address3: cart.billTo?.address3,
@@ -80,6 +84,7 @@ function OrderConfirmationPageContent({ cart, }) {
80
84
  },
81
85
  title: cartLine.altText,
82
86
  }, isReadonly: true, price: {
87
+ currencyCode,
83
88
  originalTotalPrice: cartLine.pricing?.extendedUnitNetPrice || 0,
84
89
  pricePerUnit: cartLine.pricing?.unitNetPrice || 0,
85
90
  totalPrice: cartLine.pricing?.extendedUnitNetPrice || 0,
@@ -1,12 +1,13 @@
1
1
  import { MutableRefObject } from 'react';
2
2
  import Dropin from '@adyen/adyen-web/dist/types/components/Dropin';
3
3
  import { AdyenPaymentModel } from 'shared/api/storefront/model/storefront.model';
4
+ import { CountryCode, CurrencyCode } from '../../../../intl/types';
4
5
  import '@adyen/adyen-web/dist/adyen.css';
5
6
  interface AdyenPaymentProps {
6
7
  amount: number;
7
8
  cartId: string;
8
- countryCode: string;
9
- currencyCode: string;
9
+ countryCode: CountryCode;
10
+ currencyCode: CurrencyCode;
10
11
  customerId: string;
11
12
  dropinRef: MutableRefObject<Dropin | null>;
12
13
  environment: 'test' | 'live' | 'live-us' | 'live-au' | 'live-apse' | 'live-in';
@@ -10,6 +10,7 @@ import { Select } from '../../../../forms/select/select.js';
10
10
  import { TextField } from '../../../../forms/text-field/text-field.js';
11
11
  import { InfoIconTooltip } from '../../../../info-icon-tooltip/info-icon-tooltip.js';
12
12
  import { FormattedMessage } from '../../../../intl/formatted-message.js';
13
+ import { isCountryCode } from '../../../../intl/types.js';
13
14
  import { useFormattedMessage } from '../../../../intl/use-formatted-message.js';
14
15
  import { logger } from '../../../../logging/logger.js';
15
16
  import { useInvalidateCurrentCart } from '../../../../shared/api/storefront/hooks/cart/use-invalidate-current-cart.js';
@@ -18,7 +19,7 @@ import { usePlaceOrder } from '../../../../shared/api/storefront/hooks/cart/use-
18
19
  import { useInvalidateAdyen } from '../../../../shared/api/storefront/hooks/payment/use-invalidate-adyen.js';
19
20
  import { validateVATNumber } from '../../../../shared/api/storefront/services/finance-service.js';
20
21
  import { useDataLayer } from '../../../../shared/ga/use-data-layer.js';
21
- import { currencySymbolToISO } from '../../../../shared/model/currency.js';
22
+ import { getCurrencyCodeBySymbol } from '../../../../shared/model/currency.js';
22
23
  import { environment } from '../../../../shared/utils/environment.js';
23
24
  import { BillingAndInvoiceInformation } from '../../components/billing-and-invoice-information.js';
24
25
  import { useHasReturnedFromAdyen } from '../hooks/use-has-returned-from-adyen.js';
@@ -42,8 +43,10 @@ function Payment({ atp, cart: _cart, form, isProcessing, onError: _onError, onPa
42
43
  const [asSoonAsPossible, setAsSoonAsPossible] = useState(!hasAtp);
43
44
  const [deliveryDate, setDeliveryDate] = useState(cart.requestedDeliveryDateDisplay?.toString() || '');
44
45
  const [selectedPaymentMethod, setSelectedPaymentMethod] = useState(cart.paymentOptions?.paymentMethods?.[0]?.name || 'ADY');
45
- const countryCode = _cart.billTo?.country?.abbreviation;
46
- const currencyCode = currencySymbolToISO[cart.currencySymbol];
46
+ if (!isCountryCode(_cart.billTo?.country?.abbreviation))
47
+ throw new Error(`Country code not found for cart with country abbreviation: ${_cart.billTo?.country?.abbreviation}`);
48
+ const countryCode = _cart.billTo.country.abbreviation;
49
+ const currencyCode = getCurrencyCodeBySymbol(cart.currencySymbol);
47
50
  const lastVATNumber = useRef(cart.customerVatNumber);
48
51
  if (!currencyCode)
49
52
  throw new Error(`Currency code not found for cart with currency symbol: ${cart.currencySymbol}`);
@@ -57,6 +60,7 @@ function Payment({ atp, cart: _cart, form, isProcessing, onError: _onError, onPa
57
60
  cartRef.current = _cart;
58
61
  }, [_cart]);
59
62
  const [validationErrors, setValidationErrors] = useState({});
63
+ const [customerVatNumber, setCustomerVatNumber] = useState(cart.customerVatNumber);
60
64
  const atpSelectOptions = atp
61
65
  .filter(atp => Boolean(atp.date))
62
66
  .reduce((acc, atp) => ({
@@ -69,13 +73,17 @@ function Payment({ atp, cart: _cart, form, isProcessing, onError: _onError, onPa
69
73
  }, {});
70
74
  const validateVAT = useCallback(async (value) => {
71
75
  if (!value) {
72
- setValidationErrors({});
76
+ setValidationErrors(errors => {
77
+ const result = { ...errors };
78
+ delete result.customerVatNumber;
79
+ return result;
80
+ });
73
81
  return true;
74
82
  }
75
83
  if (value.length < 8) {
76
84
  setValidationErrors({
77
85
  ...validationErrors,
78
- vatNumber: t('validation.tooShort'),
86
+ customerVatNumber: t('validation.tooShort'),
79
87
  });
80
88
  return false;
81
89
  }
@@ -85,30 +93,50 @@ function Payment({ atp, cart: _cart, form, isProcessing, onError: _onError, onPa
85
93
  onValidatingVAT(true);
86
94
  const response = await validateVATNumber({ vatNumber: value });
87
95
  lastVATNumber.current = value;
88
- if (!response.isValid) {
89
- setValidationErrors({
90
- ...validationErrors,
91
- vatNumber: t('validation.invalid'),
96
+ if (response.isValid) {
97
+ setValidationErrors(validationErrors => {
98
+ const result = { ...validationErrors };
99
+ delete result.customerVatNumber;
100
+ return result;
92
101
  });
102
+ return true;
103
+ }
104
+ else {
105
+ setValidationErrors(validationErrors => ({
106
+ ...validationErrors,
107
+ customerVatNumber: t('validation.invalid'),
108
+ }));
93
109
  return false;
94
110
  }
95
- setValidationErrors(prev => {
96
- delete prev.vatNumber;
97
- return prev;
98
- });
99
- return true;
100
111
  }
101
112
  catch {
102
- setValidationErrors({
103
- ...validationErrors,
104
- vatNumber: t('validation.invalid'),
113
+ // When an error occurs, we don't want to show the error message
114
+ // because it might be a temporary issue with the service.
115
+ // The customer can not do anything about it, so we just remove the error message.
116
+ setValidationErrors(validationErrors => {
117
+ const result = { ...validationErrors };
118
+ delete result.customerVatNumber;
119
+ return result;
105
120
  });
106
- return false;
121
+ return true;
107
122
  }
108
123
  finally {
109
124
  onValidatingVAT(false);
110
125
  }
111
126
  }, [onValidatingVAT, t, validationErrors]);
127
+ useEffect(() => {
128
+ /* When a customer has an existing VAT that is
129
+ * not valid (e.g. invalid, undetermined, or failure),
130
+ * then trigger a client side validation. */
131
+ if (!cart.customerVatNumber)
132
+ return;
133
+ if (cart.properties.customerVatNumberStatus === 'valid')
134
+ return;
135
+ onValidatingVAT(true);
136
+ lastVATNumber.current = '';
137
+ validateVAT(cart.customerVatNumber);
138
+ // eslint-disable-next-line react-hooks/exhaustive-deps
139
+ }, []);
112
140
  const onPlaceOrderCompleted = useCallback(({ cart, payment_type }) => {
113
141
  dataLayer.push(createEcommerceEvent({
114
142
  cart,
@@ -127,7 +155,7 @@ function Payment({ atp, cart: _cart, form, isProcessing, onError: _onError, onPa
127
155
  event: 'purchase',
128
156
  },
129
157
  }), {
130
- currency: currencySymbolToISO[cart.currencySymbol],
158
+ currency: getCurrencyCodeBySymbol(cart.currencySymbol),
131
159
  event: 'transactionComplete',
132
160
  transactionAffiliation: cart.billTo?.companyName,
133
161
  transactionId: cart.orderNumber,
@@ -147,10 +175,16 @@ function Payment({ atp, cart: _cart, form, isProcessing, onError: _onError, onPa
147
175
  const formData = new FormData(e.currentTarget);
148
176
  const cart = cartRef.current;
149
177
  setValidationErrors(prev => prev); // NOTE: This makes sure the form is revalidated on submit
150
- const vatNumber = formData.get('vatNumber')?.toString();
151
- if (vatNumber &&
152
- lastVATNumber.current !== vatNumber &&
153
- !(await validateVAT(vatNumber)))
178
+ cart.customerVatNumber = formData.get('customerVatNumber')?.toString();
179
+ cart.poNumber = formData.get('poNumber')?.toString();
180
+ cart.properties = {
181
+ ...cart.properties,
182
+ industry: formData.get('industry')?.toString() || '',
183
+ };
184
+ cart.requestedDeliveryDate = formData.get('deliveryDate')?.toString();
185
+ if (cart.customerVatNumber &&
186
+ lastVATNumber.current !== cart.customerVatNumber &&
187
+ !(await validateVAT(cart.customerVatNumber)))
154
188
  return;
155
189
  if (Object.keys(validationErrors).length > 0)
156
190
  return;
@@ -167,18 +201,15 @@ function Payment({ atp, cart: _cart, form, isProcessing, onError: _onError, onPa
167
201
  try {
168
202
  try {
169
203
  cartRef.current = await patchCart({
170
- cart: {
171
- ...cart,
172
- customerVatNumber: formData.get('vatNumber')?.toString(),
173
- poNumber: formData.get('poNumber')?.toString(),
174
- properties: {
175
- ...cart.properties,
176
- industry: formData.get('industry')?.toString() || '',
177
- },
178
- requestedDeliveryDate: formData.get('deliveryDate')?.toString(),
179
- },
204
+ cart,
180
205
  forceRecalculation: false,
181
206
  });
207
+ if (cartRef.current.properties.customerVatNumberStatus === 'invalid') {
208
+ return setValidationErrors({
209
+ ...validationErrors,
210
+ customerVatNumber: t('validation.invalid'),
211
+ });
212
+ }
182
213
  }
183
214
  catch (error) {
184
215
  setAPIError(error);
@@ -205,12 +236,12 @@ function Payment({ atp, cart: _cart, form, isProcessing, onError: _onError, onPa
205
236
  const cart = cartRef.current;
206
237
  try {
207
238
  onProcessing(true);
208
- await placeOrder({ cart });
239
+ cartRef.current = await placeOrder({ cart });
209
240
  onPlaceOrderCompleted({
210
- cart,
211
- payment_type: cart.paymentMethod?.name || '',
241
+ cart: cartRef.current,
242
+ payment_type: cartRef.current.paymentMethod?.name || '',
212
243
  });
213
- return onPaymentComplete({ cartId: cart.trackId });
244
+ return onPaymentComplete({ cartId: cartRef.current.trackId });
214
245
  }
215
246
  catch (error) {
216
247
  logger.error(error);
@@ -279,9 +310,7 @@ function Payment({ atp, cart: _cart, form, isProcessing, onError: _onError, onPa
279
310
  MA: 'Maritime',
280
311
  OT: 'Other',
281
312
  /* eslint-enable sort-keys-fix/sort-keys-fix */
282
- }, variant: "solid" }), jsx(TextField, { showLabel: true, defaultValue: cart.customerVatNumber, isDisabled: isDisabled, label: t('VAT Number'), name: "vatNumber", onBlur: e => validateVAT(e.target.value), validate: () => validationErrors.vatNumber ?? true }), jsx(TextField, { showLabel: true, defaultValue: cart.poNumber, isDisabled: isDisabled, isRequired: cart.requiresPoNumber, label: t('PO Number'), name: "poNumber" }), paymentMethodOptions && Object.keys(paymentMethodOptions).length > 1 && (jsx(Select, { "data-test-selector": "paymentMethodSelect", defaultSelectedOption: cart.paymentOptions?.paymentMethods?.[0]?.name || 'ADY', isDisabled: isDisabled, label: t('Payment method'), name: "paymentMethod", onChange: setSelectedPaymentMethod, options: paymentMethodOptions, selectedOption: selectedPaymentMethod, variant: "solid" })), isAdyenPayment && cart.billTo && (jsx(AdyenPayment, { amount: cart.orderGrandTotal, cartId: cart.trackId, countryCode: countryCode, currencyCode: currencyCode, customerId: cart.billTo.id, dropinRef: dropinRef,
283
- // TODO: Use the correct Adyen environment before going live
284
- environment: environment === 'production' ? 'live' : 'test', isDisabled: isDisabled, onComplete: onComplete, onError: onError, orderAmount: cart.orderGrandTotal, returnUrl:
313
+ }, variant: "solid" }), jsx(TextField, { showLabel: true, isDisabled: isDisabled, label: t('VAT Number'), name: "customerVatNumber", onBlur: e => validateVAT(e.target.value), onChange: setCustomerVatNumber, validate: () => validationErrors.customerVatNumber ?? true, value: customerVatNumber }, `vat${Boolean(validationErrors.customerVatNumber)}`), jsx(TextField, { showLabel: true, defaultValue: cart.poNumber, isDisabled: isDisabled, isRequired: cart.requiresPoNumber, label: t('PO Number'), name: "poNumber" }), paymentMethodOptions && Object.keys(paymentMethodOptions).length > 1 && (jsx(Select, { "data-test-selector": "paymentMethodSelect", defaultSelectedOption: cart.paymentOptions?.paymentMethods?.[0]?.name || 'ADY', isDisabled: isDisabled, label: t('Payment method'), name: "paymentMethod", onChange: setSelectedPaymentMethod, options: paymentMethodOptions, selectedOption: selectedPaymentMethod, variant: "solid" })), isAdyenPayment && cart.billTo && (jsx(AdyenPayment, { amount: cart.orderGrandTotal, cartId: cart.trackId, countryCode: countryCode, currencyCode: currencyCode, customerId: cart.billTo.id, dropinRef: dropinRef, environment: environment === 'production' ? 'live' : 'test', isDisabled: isDisabled, onComplete: onComplete, onError: onError, orderAmount: cart.orderGrandTotal, returnUrl:
285
314
  /* eslint-disable ssr-friendly/no-dom-globals-in-react-fc */
286
315
  typeof window === 'undefined'
287
316
  ? ''
@@ -6,6 +6,7 @@ import { CartTotalsSummary } from '../../../cart-totals/cart-totals-summary.js';
6
6
  import { FormattedMessage } from '../../../intl/formatted-message.js';
7
7
  import { useFormattedMessage } from '../../../intl/use-formatted-message.js';
8
8
  import { OrderLineList } from '../../../lists/orderline-list/orderline-list.js';
9
+ import { getCurrencyCodeBySymbol } from '../../../shared/model/currency.js';
9
10
  import { Page } from '../../components/page/page.js';
10
11
  import { PATHS } from '../../paths.js';
11
12
  import { CheckoutPageLayout } from '../layouts/checkout-page-layout/checkout-page-layout.js';
@@ -15,6 +16,9 @@ import { Payment } from './components/payment.js';
15
16
 
16
17
  function PaymentPageContent({ atp, cart, formId, hasAtp, isProcessing, isValidatingVAT, onPaymentComplete, setIsProcessing, setIsValidatingVAT, }) {
17
18
  const t = useFormattedMessage();
19
+ const currencyCode = getCurrencyCodeBySymbol(cart.currencySymbol);
20
+ if (!currencyCode)
21
+ throw new Error(`Currency code not found for symbol ${cart.currencySymbol}`);
18
22
  return (jsx(Page, { breadcrumb: [
19
23
  { href: PATHS.HOME, label: t('Home') },
20
24
  {
@@ -23,8 +27,8 @@ function PaymentPageContent({ atp, cart, formId, hasAtp, isProcessing, isValidat
23
27
  },
24
28
  ], title: t('Review and payment'), children: jsxs(CheckoutPageLayout, { actions: {
25
29
  primary: (jsx(Button, { withArrow: true, "data-test-selector": "checkoutReviewAndSubmit_placeOrder", form: formId, isDisabled: isProcessing, isLoading: isProcessing ? (jsx(FormattedMessage, { id: "Processing" })) : isValidatingVAT ? (jsx(FormattedMessage, { id: "Validating" })) : (false), type: "submit", children: jsx(FormattedMessage, { id: "Pay" }) })),
26
- }, mobileSummary: jsx(CartTotalsSummary, { totalAmount: cart.orderGrandTotalDisplay }), overview: jsx(CartTotals, { deliveryDate: hasAtp ? undefined : cart.requestedDeliveryDate, fulfillmentMethod: cart.fulfillmentMethod, isPayByInvoice: (cart.paymentOptions?.paymentMethods?.length || 1) <= 1 &&
27
- cart.paymentMethod?.name === 'PBI', shippingCost: cart.shippingAndHandlingDisplay, subtotal: cart.orderSubTotalDisplay, tax: cart.totalTaxDisplay, total: cart.orderGrandTotalDisplay, vatPercentage: cart.cartLines?.[0]?.pricing?.vatRate || 0 }), children: [jsx(CheckoutPageSection, { hasBorder: false, title: jsx(FormattedMessage, { id: "Payment" }), children: jsx(CheckoutPageSectionContent, { children: jsx(Payment, { atp: atp, cart: cart, form: formId, isProcessing: isProcessing, onPaymentComplete: onPaymentComplete, onProcessing: setIsProcessing, onValidatingVAT: setIsValidatingVAT }) }) }), jsx(CheckoutPageSection, { hasBorder: false, title: jsx(FormattedMessage, { id: "Order" }), children: jsx(CheckoutPageSectionContent, { stretch: true, children: jsx(OrderLineList, { children: cart.cartLines?.map(cartLine => (jsx(OrderLineCard, { deliveryDate: cartLine.atp?.date, href: cartLine.productUri, image: {
30
+ }, mobileSummary: jsx(CartTotalsSummary, { currencyCode: currencyCode, totalAmount: cart.orderGrandTotal }), overview: jsx(CartTotals, { currencyCode: currencyCode, deliveryDate: hasAtp ? undefined : cart.requestedDeliveryDate, fulfillmentMethod: cart.fulfillmentMethod, isPayByInvoice: (cart.paymentOptions?.paymentMethods?.length || 1) <= 1 &&
31
+ cart.paymentMethod?.name === 'PBI', shippingCost: cart.shippingAndHandling, subtotal: cart.orderSubTotal, tax: cart.totalTax, total: cart.orderGrandTotal, vatPercentage: cart.cartLines?.[0]?.pricing?.vatRate || 0 }), children: [jsx(CheckoutPageSection, { hasBorder: false, title: jsx(FormattedMessage, { id: "Payment" }), children: jsx(CheckoutPageSectionContent, { children: jsx(Payment, { atp: atp, cart: cart, form: formId, isProcessing: isProcessing, onPaymentComplete: onPaymentComplete, onProcessing: setIsProcessing, onValidatingVAT: setIsValidatingVAT }) }) }), jsx(CheckoutPageSection, { hasBorder: false, title: jsx(FormattedMessage, { id: "Order" }), children: jsx(CheckoutPageSectionContent, { stretch: true, children: jsx(OrderLineList, { children: cart.cartLines?.map(cartLine => (jsx(OrderLineCard, { deliveryDate: cartLine.atp?.date, href: cartLine.productUri, image: {
28
32
  fit: 'contain',
29
33
  image: {
30
34
  '1': cartLine.smallImagePath,
@@ -34,6 +38,7 @@ function PaymentPageContent({ atp, cart, formId, hasAtp, isProcessing, isValidat
34
38
  },
35
39
  title: cartLine.altText,
36
40
  }, isReadonly: true, price: {
41
+ currencyCode,
37
42
  originalTotalPrice: cartLine.pricing?.extendedUnitNetPrice || 0,
38
43
  pricePerUnit: cartLine.pricing?.unitNetPrice || 0,
39
44
  totalPrice: cartLine.pricing?.extendedUnitNetPrice || 0,
@@ -1,2 +1,3 @@
1
1
  import { PaymentAmountExtended } from '@adyen/adyen-web/dist/types/types';
2
- export declare function parseAmount(amount: string | number, countryCode: string): PaymentAmountExtended;
2
+ import { CountryCode } from '../../../../intl/types';
3
+ export declare function parseAmount(amount: string | number, countryCode: CountryCode): PaymentAmountExtended;
@@ -36,12 +36,12 @@ function EditAddressesForm({ billTo, countries, currentCountry, isLoading, isPic
36
36
  address2: formData.get('address2')?.toString() || '',
37
37
  address3: formData.get('address3')?.toString() || '',
38
38
  attention: formData.get('attention')?.toString() || '',
39
- city: formData.get('address1')?.toString() || '',
39
+ city: formData.get('city')?.toString() || '',
40
40
  companyName: formData.get('companyName')?.toString() || '',
41
41
  country,
42
42
  email: formData.get('email')?.toString() || '',
43
43
  firstName: formData.get('firstName')?.toString() || '',
44
- lastName: formData.get('address1')?.toString() || '',
44
+ lastName: formData.get('lastName')?.toString() || '',
45
45
  phone: formData.get('phone')?.toString() || '',
46
46
  postalCode: formData.get('postalCode')?.toString() || '',
47
47
  },
@@ -5,6 +5,7 @@ import { CartTotalsSummary } from '../../../cart-totals/cart-totals-summary.js';
5
5
  import { Select } from '../../../forms/select/select.js';
6
6
  import { FormattedMessage } from '../../../intl/formatted-message.js';
7
7
  import { useFormattedMessage } from '../../../intl/use-formatted-message.js';
8
+ import { getCurrencyCodeBySymbol } from '../../../shared/model/currency.js';
8
9
  import { Page } from '../../components/page/page.js';
9
10
  import { PATHS } from '../../paths.js';
10
11
  import { CheckoutPageLayout } from '../layouts/checkout-page-layout/checkout-page-layout.js';
@@ -20,6 +21,9 @@ function ShippingPageContent({ cart, editAddress, errorPatchBillingAddress, fulf
20
21
  [method]: t(`fulfillmentMethod.${method}`),
21
22
  }), {});
22
23
  const hasBillToAddress = Boolean(cart.billTo?.address1);
24
+ const currencyCode = getCurrencyCodeBySymbol(cart.currencySymbol);
25
+ if (!currencyCode)
26
+ throw new Error(`Currency code not found for symbol ${cart.currencySymbol}`);
23
27
  return (jsx(Page, { breadcrumb: [
24
28
  { href: PATHS.HOME, label: t('Home') },
25
29
  {
@@ -28,9 +32,9 @@ function ShippingPageContent({ cart, editAddress, errorPatchBillingAddress, fulf
28
32
  },
29
33
  ], title: t('Shipping details'), children: jsxs(CheckoutPageLayout, { actions: {
30
34
  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" }) })),
31
- }, mobileSummary: jsx(CartTotalsSummary, { totalAmount: cart.orderGrandTotalDisplay }), overview: jsx(CartTotals, { fulfillmentMethod: fulfillmentMethods && fulfillmentMethods.length === 1
35
+ }, mobileSummary: jsx(CartTotalsSummary, { currencyCode: currencyCode, totalAmount: cart.orderGrandTotal }), overview: jsx(CartTotals, { currencyCode: currencyCode, fulfillmentMethod: fulfillmentMethods && fulfillmentMethods.length === 1
32
36
  ? cart.fulfillmentMethod
33
- : 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: onChangeFulfillmentMethod, options: fulfillmentMethodOptions || {}, variant: "solid" }) }) }) })), hasBillToAddress && !isGuest ? readOnlyAddress : editAddress] }), Boolean(errorPatchBillingAddress) && (jsx("div", { className: styles['error-message'], children: jsx(FormattedMessage, { id: "An unexpected error occured" }) }))] }) }));
37
+ : undefined, shippingCost: cart.shippingAndHandling, subtotal: cart.orderSubTotal, tax: cart.totalTax, total: cart.orderGrandTotal, 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: onChangeFulfillmentMethod, options: fulfillmentMethodOptions || {}, variant: "solid" }) }) }) })), hasBillToAddress && !isGuest ? readOnlyAddress : editAddress] }), Boolean(errorPatchBillingAddress) && (jsx("div", { className: styles['error-message'], children: jsx(FormattedMessage, { id: "An unexpected error occured" }) }))] }) }));
34
38
  }
35
39
 
36
40
  export { ShippingPageContent };
@@ -0,0 +1,8 @@
1
+ import { ProductHit } from '../../../shared/model/hit';
2
+ interface ProductOverviewProps {
3
+ ProductHitCard: React.ComponentType<{
4
+ hit: ProductHit;
5
+ }>;
6
+ }
7
+ export declare function ProductOverview({ ProductHitCard }: ProductOverviewProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,20 @@
1
+ "use client";
2
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
+ import { usePagination } from 'react-instantsearch';
4
+ import { MAX_QUERY_RESULTS } from '../../../algolia/constants/index.js';
5
+ import { useAlgoliaHits } from '../../../algolia/use-algolia-hits.js';
6
+ import { FormattedMessage } from '../../../intl/formatted-message.js';
7
+ import { ProductOverviewGrid } from '../../../lists/product-overview-grid/product-overview-grid.js';
8
+ import { Message } from '../../../message/message.js';
9
+ import { PromoCard } from '../../../promos/promo-card/promo-card.js';
10
+ import { isProductHit } from '../../../shared/model/hit.js';
11
+
12
+ function ProductOverview({ ProductHitCard }) {
13
+ const { hits, isLoading } = useAlgoliaHits();
14
+ const { currentRefinement, nbHits, nbPages } = usePagination();
15
+ const currentPage = currentRefinement + 1;
16
+ const isLastPage = currentPage === nbPages;
17
+ return (jsxs(Fragment, { children: [isLastPage && nbHits > MAX_QUERY_RESULTS && (jsx(Message, { type: "info", children: jsx(FormattedMessage, { id: "You have reached the end of the results, but there may be more articles available. Adjust your filters or search to discover more!" }) })), jsx(ProductOverviewGrid, { isLoading: isLoading, children: hits.map(hit => isProductHit(hit) ? (jsx(ProductHitCard, { hit: hit }, hit.id)) : (jsx(PromoCard, { href: hit.href, image: hit.image }, hit.id))) })] }));
18
+ }
19
+
20
+ export { ProductOverview };
@@ -4,7 +4,7 @@ import { ConnectedFavoriteButton } from '../../../../../buttons/favorite/connect
4
4
  import { Accordion } from '../../../../../collapsables/accordion/accordion.js';
5
5
  import { AccordionItem } from '../../../../../collapsables/accordion/accordion-item.js';
6
6
  import { ShowAll } from '../../../../../collapsables/show-all/show-all.js';
7
- import { ProductPrice } from '../../../../../display/product-price/product-price.js';
7
+ import { Price } from '../../../../../display/price/price.js';
8
8
  import { ProductSku } from '../../../../../display/product-sku/product-sku.js';
9
9
  import { FormattedMessage } from '../../../../../intl/formatted-message.js';
10
10
  import { DownloadDocumentList } from '../../../../../lists/download-document-list/download-document-list.js';
@@ -15,7 +15,7 @@ import styles from './product-details-panel.module.css.js';
15
15
 
16
16
  function ProductDetailsPanel({ priceComponent, product, }) {
17
17
  const { sendAddToCartFromProductDetailsPageEvent, sendAddToWishListFromProductDetailsPageEvent, } = useAlgoliaInsights();
18
- return (jsxs("div", { className: styles['product-details-panel'], children: [jsxs("div", { className: styles.heading, children: [jsx(Heading, { italic: true, size: "xs", tag: "h1", children: product.productTitle }), jsx(ProductSku, { sku: product.productNumber })] }), jsxs("div", { className: styles['price-action-container'], children: [priceComponent || (jsx(ProductPrice, { "data-test": "productPrice_unitNetPrice", isVatIncluded: product.isVatIncluded, originalPrice: product.originalPrice, price: product.price })), jsxs("div", { className: styles['action-container'], children: [product.canAddToCart && (jsx(ConnectedAddToCartButton, { onAddToCart: ({ cartLine }) => {
18
+ return (jsxs("div", { className: styles['product-details-panel'], children: [jsxs("div", { className: styles.heading, children: [jsx(Heading, { italic: true, size: "xs", tag: "h1", children: product.productTitle }), jsx(ProductSku, { sku: product.productNumber })] }), jsxs("div", { className: styles['price-action-container'], children: [priceComponent || (jsx(Price, { className: styles.price, currencyCode: product.currencyCode, "data-test": "productPrice_unitNetPrice", isVatIncluded: product.isVatIncluded, originalPrice: product.originalPrice, price: product.price, variant: "sonic" })), jsxs("div", { className: styles['action-container'], children: [product.canAddToCart && (jsx(ConnectedAddToCartButton, { onAddToCart: ({ cartLine }) => {
19
19
  sendAddToCartFromProductDetailsPageEvent({
20
20
  cartLine,
21
21
  });
@@ -1,3 +1,3 @@
1
- var styles = {"product-details-panel":"product-details-panel-module-MXfPm","heading":"product-details-panel-module-rtZYR","price-action-container":"product-details-panel-module-wHZCr","action-container":"product-details-panel-module-QLafW","description":"product-details-panel-module-9L-Nm","feature-list":"product-details-panel-module-NC2nx"};
1
+ var styles = {"product-details-panel":"product-details-panel-module-MXfPm","heading":"product-details-panel-module-rtZYR","price-action-container":"product-details-panel-module-wHZCr","price":"product-details-panel-module-dI2JL","action-container":"product-details-panel-module-QLafW","description":"product-details-panel-module-9L-Nm","feature-list":"product-details-panel-module-NC2nx"};
2
2
 
3
3
  export { styles as default };
@@ -1,11 +1,8 @@
1
1
  "use client";
2
2
  import { jsx } from 'react/jsx-runtime';
3
- import { useAlgoliaHits } from '../../../../algolia/use-algolia-hits.js';
4
3
  import { useAlgoliaInsights } from '../../../../algolia/use-algolia-insights.js';
5
4
  import { ConnectedProductCard } from '../../../../cards/product-card/connected-product-card.js';
6
- import { ProductOverviewGrid } from '../../../../lists/product-overview-grid/product-overview-grid.js';
7
- import { PromoCard } from '../../../../promos/promo-card/promo-card.js';
8
- import { isProductHit } from '../../../../shared/model/hit.js';
5
+ import { ProductOverview } from '../../components/product-overview.js';
9
6
 
10
7
  function ProductHitCard({ hit }) {
11
8
  const { sendAddToCartFromProductListPageEvent, sendAddToWishListFromProductListPageEvent, sendProductClickFromProductListPageEvent, } = useAlgoliaInsights();
@@ -22,14 +19,14 @@ function ProductHitCard({ hit }) {
22
19
  objectId: hit.objectId,
23
20
  position: hit.position,
24
21
  }), price: {
22
+ currencyCode: hit.currencyCode,
25
23
  isVatIncluded: hit.isVatIncluded,
26
24
  originalPrice: hit.originalPrice,
27
25
  price: hit.price,
28
26
  }, sku: hit.id, tags: hit.labels, title: hit.name }, hit.storefrontId));
29
27
  }
30
28
  function ProductListingProductOverview() {
31
- const { hits, isLoading } = useAlgoliaHits();
32
- return (jsx(ProductOverviewGrid, { isLoading: isLoading, children: hits.map(hit => isProductHit(hit) ? (jsx(ProductHitCard, { hit: hit }, hit.id)) : (jsx(PromoCard, { href: hit.href, image: hit.image }, hit.id))) }));
29
+ return jsx(ProductOverview, { ProductHitCard: ProductHitCard });
33
30
  }
34
31
 
35
32
  export { ProductListingProductOverview };