@sonic-equipment/ui 260.0.6 → 260.0.8
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/dist/country-language-selector/connected-country-language-selector.js +90 -91
- package/dist/country-select/hooks/use-countries.js +5 -3
- package/dist/lists/orderline-list/orderline-list.js +4 -1
- package/dist/modals/modal/modal.d.ts +1 -1
- package/dist/modals/modal/modal.js +1 -20
- package/dist/pages/checkout/payment-page/components/payment.js +19 -18
- package/dist/pages/checkout/shipping-page/shipping-page-content.js +3 -2
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
-
import { useState, useEffect } from 'react';
|
|
3
|
+
import { useState, useMemo, useCallback, useEffect } from 'react';
|
|
4
4
|
import { useCookie } from '../cookies/use-cookie.js';
|
|
5
5
|
import { useCountriesLanguages } from '../country-selector/use-countries-languages.js';
|
|
6
6
|
import { isCountryLanguageCode } from '../intl/types.js';
|
|
@@ -32,100 +32,99 @@ function ConnectedCountryLanguageSelector({ className, countries: _countries, is
|
|
|
32
32
|
const [isOpen, setIsOpen] = useState(_isOpen ?? !CLSelectorCookie?.includes('closed=true'));
|
|
33
33
|
const { countries } = useCountriesLanguages({});
|
|
34
34
|
const router = useRouter();
|
|
35
|
-
|
|
36
|
-
const menuOptions = {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
// stop if countryCode is not included in _countries prop
|
|
48
|
-
if (_countries && !_countries.includes(country.abbreviation)) {
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
const languageCodes = country.languages
|
|
52
|
-
.map(({ languageCode }) => languageCode.toLowerCase())
|
|
53
|
-
.sort();
|
|
54
|
-
// group label to sort on
|
|
55
|
-
const groupLabel = t(`clselector.country.${countryCode}.${languageCodes[0]}`);
|
|
56
|
-
// group reactNode to display
|
|
57
|
-
const groupReactNode = languageCodes.flatMap((languageCode, index) => {
|
|
58
|
-
const translation = t(`clselector.country.${countryCode}.${languageCode}`);
|
|
59
|
-
return index === 0
|
|
60
|
-
? [
|
|
61
|
-
jsx("span", { lang: languageCode, children: translation }, languageCode),
|
|
62
|
-
]
|
|
63
|
-
: [
|
|
64
|
-
'/',
|
|
65
|
-
jsx("span", { lang: languageCode, children: translation }, languageCode),
|
|
66
|
-
];
|
|
67
|
-
});
|
|
68
|
-
languageCodes.forEach(languageCode => {
|
|
69
|
-
const optionKey = `${languageCode}-${countryCode}`;
|
|
70
|
-
const optionCountryLabel = `clselector.country.${countryCode}.${languageCode}`;
|
|
71
|
-
const optionLanguageLabel = `clselector.language.${languageCode}.${languageCode}`;
|
|
72
|
-
// add option key to group's options
|
|
73
|
-
options.push(optionKey);
|
|
74
|
-
const { alternativeHrefs, pathname } = router.url;
|
|
75
|
-
let path;
|
|
76
|
-
if (alternativeHrefs && alternativeHrefs[optionKey]) {
|
|
77
|
-
path = `/${optionKey}${alternativeHrefs[optionKey]}`;
|
|
78
|
-
}
|
|
79
|
-
else if (!alternativeHrefs ||
|
|
80
|
-
Object.keys(alternativeHrefs).length === 0) {
|
|
81
|
-
const currentCountryLanguage = pathname.split('/')[1]?.toLowerCase();
|
|
82
|
-
path = isCountryLanguageCode(currentCountryLanguage)
|
|
83
|
-
? pathname
|
|
84
|
-
.toLowerCase()
|
|
85
|
-
.replace(`${currentCountryLanguage}`, `${optionKey}`)
|
|
86
|
-
: `/${optionKey}${pathname}`;
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
path = `/${optionKey}`;
|
|
35
|
+
const { alternativeHrefs, pathname } = router.url;
|
|
36
|
+
const { defaultSelectedOption, menuOptionGroups, menuOptions, optionData } = useMemo(() => {
|
|
37
|
+
const menuOptions = {
|
|
38
|
+
other: t('Choose your country or region…'),
|
|
39
|
+
};
|
|
40
|
+
const menuOptionGroups = [];
|
|
41
|
+
const optionData = [];
|
|
42
|
+
countries?.forEach(country => {
|
|
43
|
+
const options = [];
|
|
44
|
+
const countryCode = country.abbreviation.toLowerCase();
|
|
45
|
+
if (_countries && !_countries.includes(country.abbreviation)) {
|
|
46
|
+
return;
|
|
90
47
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
48
|
+
const languageCodes = country.languages
|
|
49
|
+
.map(({ languageCode }) => languageCode.toLowerCase())
|
|
50
|
+
.sort();
|
|
51
|
+
const groupLabel = t(`clselector.country.${countryCode}.${languageCodes[0]}`);
|
|
52
|
+
const groupReactNode = languageCodes.flatMap((languageCode, index) => {
|
|
53
|
+
const translation = t(`clselector.country.${countryCode}.${languageCode}`);
|
|
54
|
+
return index === 0
|
|
55
|
+
? [
|
|
56
|
+
jsx("span", { lang: languageCode, children: translation }, languageCode),
|
|
57
|
+
]
|
|
58
|
+
: [
|
|
59
|
+
'/',
|
|
60
|
+
jsx("span", { lang: languageCode, children: translation }, languageCode),
|
|
61
|
+
];
|
|
62
|
+
});
|
|
63
|
+
languageCodes.forEach(languageCode => {
|
|
64
|
+
const optionKey = `${languageCode}-${countryCode}`;
|
|
65
|
+
const optionCountryLabel = `clselector.country.${countryCode}.${languageCode}`;
|
|
66
|
+
const optionLanguageLabel = `clselector.language.${languageCode}.${languageCode}`;
|
|
67
|
+
options.push(optionKey);
|
|
68
|
+
let path;
|
|
69
|
+
if (alternativeHrefs && alternativeHrefs[optionKey]) {
|
|
70
|
+
path = `/${optionKey}${alternativeHrefs[optionKey]}`;
|
|
71
|
+
}
|
|
72
|
+
else if (!alternativeHrefs ||
|
|
73
|
+
Object.keys(alternativeHrefs).length === 0) {
|
|
74
|
+
const currentCountryLanguage = pathname.split('/')[1]?.toLowerCase();
|
|
75
|
+
path = isCountryLanguageCode(currentCountryLanguage)
|
|
76
|
+
? pathname
|
|
77
|
+
.toLowerCase()
|
|
78
|
+
.replace(`${currentCountryLanguage}`, `${optionKey}`)
|
|
79
|
+
: `/${optionKey}${pathname}`;
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
path = `/${optionKey}`;
|
|
83
|
+
}
|
|
84
|
+
menuOptions[optionKey] =
|
|
85
|
+
environment === 'next-production' ? (jsx("span", { lang: languageCode, children: `${t(optionCountryLabel)} - ${t(optionLanguageLabel)}` })) : (jsxs("span", { lang: languageCode, children: [`${t(optionCountryLabel)} - ${t(optionLanguageLabel)}`, jsx("code", { style: { fontSize: '12px' }, children: path })] }));
|
|
86
|
+
optionData.push({
|
|
87
|
+
country: countryCode,
|
|
88
|
+
key: optionKey,
|
|
89
|
+
language: languageCode,
|
|
90
|
+
path,
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
menuOptionGroups.push({
|
|
94
|
+
key: countryCode,
|
|
95
|
+
label: groupLabel,
|
|
96
|
+
options,
|
|
97
|
+
reactNode: groupReactNode,
|
|
102
98
|
});
|
|
103
99
|
});
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
100
|
+
menuOptionGroups.sort((a, b) => a.label.localeCompare(b.label));
|
|
101
|
+
const defaultSelectedLanguageCountry = selectedLanguage && selectedCountry
|
|
102
|
+
? `${selectedLanguage.toLowerCase()}-${selectedCountry.toLowerCase()}`
|
|
103
|
+
: undefined;
|
|
104
|
+
const defaultSelectedOption = defaultSelectedLanguageCountry &&
|
|
105
|
+
Object.keys(menuOptions).includes(defaultSelectedLanguageCountry)
|
|
106
|
+
? defaultSelectedLanguageCountry
|
|
107
|
+
: undefined;
|
|
108
|
+
return {
|
|
109
|
+
defaultSelectedOption,
|
|
110
|
+
menuOptionGroups,
|
|
111
|
+
menuOptions,
|
|
112
|
+
optionData,
|
|
113
|
+
};
|
|
114
|
+
}, [
|
|
115
|
+
_countries,
|
|
116
|
+
alternativeHrefs,
|
|
117
|
+
countries,
|
|
118
|
+
pathname,
|
|
119
|
+
selectedCountry,
|
|
120
|
+
selectedLanguage,
|
|
121
|
+
t,
|
|
122
|
+
]);
|
|
123
|
+
const handleClose = useCallback(() => {
|
|
124
124
|
setIsOpen(false);
|
|
125
125
|
setCLSelectorCookie('closed=true');
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
const handleSubmit = (selectedOption) => {
|
|
126
|
+
}, [setCLSelectorCookie]);
|
|
127
|
+
const handleSubmit = useCallback((selectedOption) => {
|
|
129
128
|
setIsOpen(false);
|
|
130
129
|
if (selectedOption === 'other') {
|
|
131
130
|
setCLSelectorCookie('closed=true');
|
|
@@ -141,7 +140,7 @@ function ConnectedCountryLanguageSelector({ className, countries: _countries, is
|
|
|
141
140
|
setCLSelectorCookie(`closed=true;language=${language};country=${country}`);
|
|
142
141
|
navigate(path, { ignoreLocalePrefix: true, reload: true });
|
|
143
142
|
}
|
|
144
|
-
};
|
|
143
|
+
}, [navigate, optionData, setCLSelectorCookie]);
|
|
145
144
|
// react to CountryLanguageSelectorButton clicked
|
|
146
145
|
useEffect(() => {
|
|
147
146
|
if (showSelector) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useMemo } from 'react';
|
|
2
|
+
import { useMemo, useEffect } from 'react';
|
|
3
3
|
import { useCookie } from '../../cookies/use-cookie.js';
|
|
4
4
|
import { isCountryCode, isCultureCode, isLanguageCode } from '../../intl/types.js';
|
|
5
5
|
import { useFetchCountriesWithLanguages } from '../../shared/api/storefront/hooks/website/use-fetch-countries-with-languages.js';
|
|
@@ -39,8 +39,10 @@ function useCountries({ enabled = true, } = {}) {
|
|
|
39
39
|
});
|
|
40
40
|
return countries;
|
|
41
41
|
}, [apiCountries, sessionCountries]);
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (countries !== sessionCountries)
|
|
44
|
+
setSessionCountries(countries);
|
|
45
|
+
}, [countries, sessionCountries, setSessionCountries]);
|
|
44
46
|
const currentCountry = countries?.find(country => country.id === currentCountryId);
|
|
45
47
|
return {
|
|
46
48
|
countries,
|
|
@@ -23,7 +23,10 @@ function OrderLineList({ children, onRemoveAll }) {
|
|
|
23
23
|
// eslint-disable-next-line @eslint-react/no-children-map
|
|
24
24
|
Children.map(children, (child, index) => (
|
|
25
25
|
// eslint-disable-next-line @eslint-react/no-array-index-key
|
|
26
|
-
jsx("li", { className: styles.item, children: child }, index))) })] }), onRemoveAll && (jsx(ConfirmationDialog, { isOpen: isOpen, onCancel: close, onConfirm:
|
|
26
|
+
jsx("li", { className: styles.item, children: child }, index))) })] }), onRemoveAll && (jsx(ConfirmationDialog, { isOpen: isOpen, onCancel: close, onConfirm: () => {
|
|
27
|
+
close();
|
|
28
|
+
onRemoveAll();
|
|
29
|
+
}, title: t('Are you sure you want to remove all items from your cart?') }))] }));
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
export { OrderLineList };
|
|
@@ -15,4 +15,4 @@ export interface ModalProps {
|
|
|
15
15
|
onOpenChange?: (isOpen: boolean) => void;
|
|
16
16
|
shouldCloseOnInteractOutside?: boolean;
|
|
17
17
|
}
|
|
18
|
-
export declare function Modal({ children, className, hasCloseButton, isDismissable, isFullScreen, isKeyboardDismissDisabled, isOpen, onOpenChange, shouldCloseOnInteractOutside, }: ModalProps): import("react/jsx-runtime").JSX.Element
|
|
18
|
+
export declare function Modal({ children, className, hasCloseButton, isDismissable, isFullScreen, isKeyboardDismissDisabled, isOpen, onOpenChange, shouldCloseOnInteractOutside, }: ModalProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -7,28 +7,9 @@ import { useFormattedMessage } from '../../intl/use-formatted-message.js';
|
|
|
7
7
|
import resetStyles from '../../shared/reset.module.css.js';
|
|
8
8
|
import styles from './modal.module.css.js';
|
|
9
9
|
|
|
10
|
-
const getDocument = () => typeof window === 'undefined' ? undefined : window.document;
|
|
11
10
|
function Modal({ children, className, hasCloseButton, isDismissable, isFullScreen, isKeyboardDismissDisabled, isOpen, onOpenChange, shouldCloseOnInteractOutside = true, }) {
|
|
12
11
|
const t = useFormattedMessage();
|
|
13
|
-
|
|
14
|
-
if (!document)
|
|
15
|
-
return;
|
|
16
|
-
return (jsx(ModalOverlay, { ref: ref => {
|
|
17
|
-
ref?.addEventListener('click', e => {
|
|
18
|
-
if ((!e.target || ref.contains(e.target)) &&
|
|
19
|
-
ref !== e.target)
|
|
20
|
-
return;
|
|
21
|
-
e.preventDefault();
|
|
22
|
-
e.stopPropagation();
|
|
23
|
-
});
|
|
24
|
-
ref?.addEventListener('touchend', e => {
|
|
25
|
-
if ((!e.target || ref.contains(e.target)) &&
|
|
26
|
-
ref !== e.target)
|
|
27
|
-
return;
|
|
28
|
-
e.preventDefault();
|
|
29
|
-
e.stopPropagation();
|
|
30
|
-
});
|
|
31
|
-
}, className: clsx(styles['modal-overlay'], resetStyles.reset, typeof className === 'string' ? className : className?.overlay), isDismissable: isDismissable, isKeyboardDismissDisabled: isKeyboardDismissDisabled, isOpen: isOpen, onOpenChange: onOpenChange, shouldCloseOnInteractOutside: () => shouldCloseOnInteractOutside, UNSTABLE_portalContainer: document.body, children: jsxs(Modal$1, { className: clsx(styles.modal, {
|
|
12
|
+
return (jsx(ModalOverlay, { className: clsx(styles['modal-overlay'], resetStyles.reset, typeof className === 'string' ? className : className?.overlay), isDismissable: isDismissable, isKeyboardDismissDisabled: isKeyboardDismissDisabled, isOpen: isOpen, onOpenChange: onOpenChange, shouldCloseOnInteractOutside: () => shouldCloseOnInteractOutside, children: jsxs(Modal$1, { className: clsx(styles.modal, {
|
|
32
13
|
[styles['is-full-screen']]: isFullScreen,
|
|
33
14
|
}, typeof className === 'string' ? undefined : className?.modal), children: [hasCloseButton && (jsx(IconButton, { className: styles.close, icon: "Close", isDisabled: !isDismissable, label: t('Close'), onClick: () => onOpenChange?.(false), theme: "secondary" })), jsx("div", { className: clsx(styles.content, typeof className === 'string' ? className : className?.content), children: children })] }) }));
|
|
34
15
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { useRef, useState, useEffect, useCallback } from 'react';
|
|
3
|
+
import { useRef, useState, useEffect, useMemo, useCallback } from 'react';
|
|
4
4
|
import { Form } from 'react-aria-components';
|
|
5
5
|
import { useAlgoliaInsights } from '../../../../algolia/use-algolia-insights.js';
|
|
6
6
|
import { Accordion } from '../../../../collapsables/accordion/accordion.js';
|
|
@@ -57,16 +57,29 @@ function Payment({ atp, cart: _cart, form, isProcessing, onError: _onError, onPa
|
|
|
57
57
|
cartRef.current = _cart;
|
|
58
58
|
}, [_cart]);
|
|
59
59
|
const [validationErrors, setValidationErrors] = useState({});
|
|
60
|
-
const atpSelectOptions = atp
|
|
60
|
+
const atpSelectOptions = useMemo(() => atp
|
|
61
61
|
.filter(atp => Boolean(atp.date))
|
|
62
62
|
.reduce((acc, atp) => ({
|
|
63
63
|
...acc,
|
|
64
64
|
[atp.date || '']: atp.displayDate,
|
|
65
|
-
}), {});
|
|
66
|
-
const paymentMethodOptions = cart.paymentOptions?.paymentMethods?.reduce((acc, method) => {
|
|
65
|
+
}), {}), [atp]);
|
|
66
|
+
const paymentMethodOptions = useMemo(() => cart.paymentOptions?.paymentMethods?.reduce((acc, method) => {
|
|
67
67
|
acc[method.name] = t(`paymentMethod.${method.description}`);
|
|
68
68
|
return acc;
|
|
69
|
-
}, {});
|
|
69
|
+
}, {}), [cart.paymentOptions?.paymentMethods, t]);
|
|
70
|
+
const industryOptions = useMemo(() => ({
|
|
71
|
+
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
|
72
|
+
PP: t('industry.PP'),
|
|
73
|
+
AU: t('industry.AU'),
|
|
74
|
+
MC: t('industry.MC'),
|
|
75
|
+
BC: t('industry.BC'),
|
|
76
|
+
TR: t('industry.TR'),
|
|
77
|
+
AG: t('industry.AG'),
|
|
78
|
+
AV: t('industry.AV'),
|
|
79
|
+
MA: t('industry.MA'),
|
|
80
|
+
OT: t('industry.OT'),
|
|
81
|
+
/* eslint-enable sort-keys-fix/sort-keys-fix */
|
|
82
|
+
}), [t]);
|
|
70
83
|
const onPlaceOrderCompleted = useCallback(({ cart, payment_type }) => {
|
|
71
84
|
dataLayer.push(createEcommerceEvent({
|
|
72
85
|
cart,
|
|
@@ -231,19 +244,7 @@ function Payment({ atp, cart: _cart, form, isProcessing, onError: _onError, onPa
|
|
|
231
244
|
setAsSoonAsPossible(checked);
|
|
232
245
|
if (checked)
|
|
233
246
|
setDeliveryDate('');
|
|
234
|
-
}, children: t('As soon as possible') }), jsx(InfoIconTooltip, { size: "sm", variant: "stroke", children: t('Selecting As Soon As Possible will enable us to send the products to you as they become available.') })] })] })), jsx(Select, { isRequired: true, showLabel: true, "data-test-selector": "industrySelect", defaultSelectedOption: cart.properties.industry, isDisabled: isDisabled, label: t('Industry'), name: "industry", options: {
|
|
235
|
-
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
|
236
|
-
PP: t('industry.PP'),
|
|
237
|
-
AU: t('industry.AU'),
|
|
238
|
-
MC: t('industry.MC'),
|
|
239
|
-
BC: t('industry.BC'),
|
|
240
|
-
TR: t('industry.TR'),
|
|
241
|
-
AG: t('industry.AG'),
|
|
242
|
-
AV: t('industry.AV'),
|
|
243
|
-
MA: t('industry.MA'),
|
|
244
|
-
OT: t('industry.OT'),
|
|
245
|
-
/* eslint-enable sort-keys-fix/sort-keys-fix */
|
|
246
|
-
}, placeholder: t('Select an industry'), variant: "solid" }), jsx(TextField, { showLabel: true, defaultValue: cart.customerVatNumber, isDisabled: isDisabled, label: t('VAT Number'), minLength: 8, name: "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: isProductionEnvironment ? 'live' : 'test', isDisabled: isDisabled, onComplete: onComplete, onError: onError, orderAmount: cart.orderGrandTotal, returnUrl:
|
|
247
|
+
}, children: t('As soon as possible') }), jsx(InfoIconTooltip, { size: "sm", variant: "stroke", children: t('Selecting As Soon As Possible will enable us to send the products to you as they become available.') })] })] })), jsx(Select, { isRequired: true, showLabel: true, "data-test-selector": "industrySelect", defaultSelectedOption: cart.properties.industry || 'AU', isDisabled: isDisabled, label: t('Industry'), name: "industry", options: industryOptions, placeholder: t('Select an industry'), variant: "solid" }), jsx(TextField, { showLabel: true, defaultValue: cart.customerVatNumber, isDisabled: isDisabled, label: t('VAT Number'), minLength: 8, name: "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: isProductionEnvironment ? 'live' : 'test', isDisabled: isDisabled, onComplete: onComplete, onError: onError, orderAmount: cart.orderGrandTotal, returnUrl:
|
|
247
248
|
/* eslint-disable ssr-friendly/no-dom-globals-in-react-fc */
|
|
248
249
|
typeof window === 'undefined'
|
|
249
250
|
? ''
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
|
+
import { useMemo } from 'react';
|
|
3
4
|
import { Button } from '../../../buttons/button/button.js';
|
|
4
5
|
import { CartTotals } from '../../../cart-totals/cart-totals.js';
|
|
5
6
|
import { CartTotalsSummary } from '../../../cart-totals/cart-totals-summary.js';
|
|
@@ -18,10 +19,10 @@ import styles from './shipping-page.module.css.js';
|
|
|
18
19
|
function ShippingPageContent({ cart, editAddress, errorPatchBillingAddress, fulfillmentMethods, isGuest, isLoadingFulfillmentMethods, isPatching, isPatchingSession, onChangeFulfillmentMethod, readOnlyAddress, }) {
|
|
19
20
|
const t = useFormattedMessage();
|
|
20
21
|
const paths = usePaths();
|
|
21
|
-
const fulfillmentMethodOptions = fulfillmentMethods?.reduce((acc, method) => ({
|
|
22
|
+
const fulfillmentMethodOptions = useMemo(() => fulfillmentMethods?.reduce((acc, method) => ({
|
|
22
23
|
...acc,
|
|
23
24
|
[method]: t(`fulfillmentmethod.${method}`),
|
|
24
|
-
}), {});
|
|
25
|
+
}), {}), [fulfillmentMethods, t]);
|
|
25
26
|
const hasBillToAddress = Boolean(cart.billTo?.address1);
|
|
26
27
|
const currencyCode = getCurrencyCodeBySymbol(cart.currencySymbol);
|
|
27
28
|
if (!currencyCode)
|