@sonic-equipment/ui 134.0.0 → 136.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 (51) hide show
  1. package/dist/address/address.d.ts +5 -2
  2. package/dist/address/address.js +3 -2
  3. package/dist/algolia/algolia-initialization.js +2 -1
  4. package/dist/algolia/algolia-insights-provider.js +3 -3
  5. package/dist/algolia/algolia-searchclient-offline.js +3 -2
  6. package/dist/algolia/use-algolia-insights.js +24 -23
  7. package/dist/buttons/link/link.d.ts +2 -1
  8. package/dist/buttons/link/link.js +4 -2
  9. package/dist/collapsables/accordion/accordion-item.d.ts +2 -1
  10. package/dist/collapsables/accordion/accordion-item.js +13 -4
  11. package/dist/exports.d.ts +7 -0
  12. package/dist/footer/footer.d.ts +9 -0
  13. package/dist/footer/footer.js +14 -0
  14. package/dist/footer/footer.model.d.ts +18 -0
  15. package/dist/footer/footer.module.css.js +3 -0
  16. package/dist/header/hamburger-button/hamburger-button.d.ts +6 -0
  17. package/dist/header/hamburger-button/hamburger-button.js +14 -0
  18. package/dist/header/hamburger-button/hamburger-button.module.css.js +3 -0
  19. package/dist/header/header-layout/header-layout.d.ts +9 -0
  20. package/dist/header/header-layout/header-layout.js +8 -0
  21. package/dist/header/header-layout/header-layout.module.css.js +3 -0
  22. package/dist/header/sonic-logo/sonic-logo.d.ts +5 -0
  23. package/dist/header/sonic-logo/sonic-logo.js +11 -0
  24. package/dist/header/sonic-logo/sonic-logo.module.css.js +3 -0
  25. package/dist/index.js +7 -0
  26. package/dist/intl/translation-id.d.ts +1 -1
  27. package/dist/intl/utils.js +2 -1
  28. package/dist/logging/logger.d.ts +11 -0
  29. package/dist/logging/logger.js +22 -0
  30. package/dist/logging/use-log-error.d.ts +1 -0
  31. package/dist/logging/use-log-error.js +12 -0
  32. package/dist/notifications/announcements/announcement-provider.js +3 -6
  33. package/dist/pages/checkout/components/billing-and-invoice-information.js +1 -1
  34. package/dist/pages/checkout/order-confirmation-page/order-confirmation-page-content.js +1 -1
  35. package/dist/pages/checkout/payment-page/components/adyen-payment.js +34 -24
  36. package/dist/pages/checkout/payment-page/components/payment.js +29 -17
  37. package/dist/pages/checkout/payment-page/payment-page-content.js +1 -1
  38. package/dist/pages/checkout/shipping-page/components/edit-address.d.ts +3 -2
  39. package/dist/pages/checkout/shipping-page/components/edit-address.js +5 -5
  40. package/dist/pages/checkout/shipping-page/components/readonly-address.js +25 -1
  41. package/dist/pages/checkout/shipping-page/shipping-page-content.d.ts +2 -1
  42. package/dist/pages/checkout/shipping-page/shipping-page-content.js +2 -2
  43. package/dist/pages/checkout/shipping-page/shipping-page.js +3 -2
  44. package/dist/pages/product/search-result-page/search-results-page.js +1 -1
  45. package/dist/shared/ga/data-layer.js +3 -2
  46. package/dist/shared/providers/global-state-provider.js +3 -5
  47. package/dist/shared/utils/debug.d.ts +2 -0
  48. package/dist/shared/utils/debug.js +21 -0
  49. package/dist/shared/utils/environment.js +4 -2
  50. package/dist/styles.css +242 -3
  51. package/package.json +1 -1
@@ -0,0 +1,12 @@
1
+ import { useEffect } from 'react';
2
+ import { logger } from './logger.js';
3
+
4
+ function useLogError(error) {
5
+ return useEffect(() => {
6
+ if (!error)
7
+ return;
8
+ logger.error(error);
9
+ }, [error]);
10
+ }
11
+
12
+ export { useLogError };
@@ -1,8 +1,9 @@
1
1
  "use client";
2
2
  import { jsx } from 'react/jsx-runtime';
3
- import { useRef, useEffect } from 'react';
3
+ import { useRef } from 'react';
4
4
  import { TransitionGroup, CSSTransition } from 'react-transition-group';
5
5
  import { useCultureCode } from '../../intl/use-culture-code.js';
6
+ import { useLogError } from '../../logging/use-log-error.js';
6
7
  import { useFetchAnnouncements } from '../../shared/api/bff/hooks/use-fetch-announcements.js';
7
8
  import { useLocalStorage } from '../../shared/hooks/use-local-storage.js';
8
9
  import { ConnectedAnnouncement } from './connected-announcement.js';
@@ -14,11 +15,7 @@ function AnnouncementProvider() {
14
15
  const { data: announcements, error } = useFetchAnnouncements({
15
16
  cultureCode,
16
17
  });
17
- useEffect(() => {
18
- if (!error)
19
- return;
20
- console.error(error);
21
- }, [error]);
18
+ useLogError(error);
22
19
  const [dismissedIds, setDismissedIds] = useLocalStorage('dismissedAnnouncementIds', []);
23
20
  const filteredAnnouncements = announcements?.filter(({ id }) => !dismissedIds.includes(id));
24
21
  return (jsx(TransitionGroup, { className: styles['announcement-provider'], children: filteredAnnouncements?.map(announcement => (jsx(CSSTransition, { classNames: {
@@ -6,7 +6,7 @@ import styles from './billing-and-invoice-information.module.css.js';
6
6
 
7
7
  function BillingAndInvoiceInformation({ billToAddress, shipToAddress, }) {
8
8
  const t = useFormattedMessage();
9
- return (jsxs("div", { className: styles['billing-and-invoice-information'], children: [jsx("section", { className: styles.section, children: jsx(InfoDisplay, { id: "billing-address", label: t('Billing address'), value: jsx(Address, { ...billToAddress }) }) }), jsx("section", { className: styles.section, children: jsx(InfoDisplay, { id: "shipping-address", label: t('Shipping address'), value: jsx(Address, { ...shipToAddress }) }) })] }));
9
+ return (jsxs("div", { className: styles['billing-and-invoice-information'], children: [jsx("section", { className: styles.section, children: jsx(InfoDisplay, { id: "billing-address", label: t('Billing address'), value: jsx(Address, { address: billToAddress, "data-test-selector": "orderConfirmationBillingInformation" }) }) }), jsx("section", { className: styles.section, children: jsx(InfoDisplay, { id: "shipping-address", label: t('Shipping address'), value: jsx(Address, { address: shipToAddress, "data-test-selector": "orderConfirmationShippingInformation" }) }) })] }));
10
10
  }
11
11
 
12
12
  export { BillingAndInvoiceInformation };
@@ -40,7 +40,7 @@ function OrderConfirmationPageContent({ cart, }) {
40
40
  },
41
41
  });
42
42
  return (jsx(Page, { breadCrumb: [{ href: CHECKOUT_PATHS.HOME, label: t('Home') }], title: t('Order confirmation'), children: jsx(CheckoutPageLayout, { actions: {
43
- primary: (jsx(RouteButton, { withArrow: true, "data-test-selector": "checkoutShippingCartTotalContinueButton", href: "/", children: jsx(FormattedMessage, { id: "Continue shopping" }) })),
43
+ primary: (jsx(RouteButton, { withArrow: true, "data-test-selector": "checkoutReviewAndSubmit_continueShopping", href: "/", children: jsx(FormattedMessage, { id: "Continue shopping" }) })),
44
44
  secondary: (jsxs(Fragment, { children: [cart.canSaveOrder && (jsx(RouteButton, { color: "secondary", onClick: () => {
45
45
  saveCartForLater.mutate({ cart });
46
46
  }, variant: "outline", children: jsx(FormattedMessage, { id: "Save order" }) })), jsx(PrintButton, {})] })),
@@ -42,34 +42,44 @@ function AdyenPayment({ amount, cartId, countryCode, currencyCode, customerId, d
42
42
  if (!state.details.redirectResult) {
43
43
  return onError(new Error('No redirectResult'), null);
44
44
  }
45
- const result = await getAdyenPaymentDetails({
46
- redirectResult: state.details.redirectResult,
47
- });
48
- if (amount.toFixed(2).replaceAll(/[,.]/gi, '') !== adyenAmount)
49
- return onError(new Error('Invalid amount'), result);
50
- if (customerId !== adyenCustomerId)
51
- return onError(new Error('Invalid customer'), result);
52
- return handlePaymentResponse(result, onComplete, onError);
45
+ try {
46
+ const result = await getAdyenPaymentDetails({
47
+ redirectResult: state.details.redirectResult,
48
+ });
49
+ if (amount.toFixed(2).replaceAll(/[,.]/gi, '') !== adyenAmount)
50
+ return onError(new Error('Invalid amount'), result);
51
+ if (customerId !== adyenCustomerId)
52
+ return onError(new Error('Invalid customer'), result);
53
+ return handlePaymentResponse(result, onComplete, onError);
54
+ }
55
+ catch (error) {
56
+ return onError(error, null);
57
+ }
53
58
  }),
54
59
  onSubmit: (async (state, _component) => {
55
- dropinDivRef.current?.classList.add(styles.loading);
56
- if (state.data.paymentMethod.type === 'paybybank') {
57
- state.data.countryCode = countryCode;
58
- }
59
- const result = await postAdyenPayment({
60
- currencyCode,
61
- data: state.data,
62
- orderAmount,
63
- returnUrl,
64
- webOrderNumber: adyenSession.webOrderNumber,
65
- });
66
- if (result.action) {
67
- if (result.action.type === 'redirect') {
68
- return handleRedirectPaymentAction(result);
60
+ try {
61
+ dropinDivRef.current?.classList.add(styles.loading);
62
+ if (state.data.paymentMethod.type === 'paybybank') {
63
+ state.data.countryCode = countryCode;
64
+ }
65
+ const result = await postAdyenPayment({
66
+ currencyCode,
67
+ data: state.data,
68
+ orderAmount,
69
+ returnUrl,
70
+ webOrderNumber: adyenSession.webOrderNumber,
71
+ });
72
+ if (result.action) {
73
+ if (result.action.type === 'redirect') {
74
+ return handleRedirectPaymentAction(result);
75
+ }
76
+ return onError(new Error('Invalid payment response'), result);
69
77
  }
70
- return onError(new Error('Invalid payment response'), result);
78
+ return handlePaymentResponse(result, onComplete, onError);
79
+ }
80
+ catch (error) {
81
+ return onError(error, null);
71
82
  }
72
- return handlePaymentResponse(result, onComplete, onError);
73
83
  }),
74
84
  session: {
75
85
  ...adyenSession,
@@ -12,7 +12,9 @@ import { TextField } from '../../../../forms/text-field/text-field.js';
12
12
  import { InfoIconTooltip } from '../../../../info-icon-tooltip/info-icon-tooltip.js';
13
13
  import { FormattedMessage } from '../../../../intl/formatted-message.js';
14
14
  import { useFormattedMessage } from '../../../../intl/use-formatted-message.js';
15
+ import { logger } from '../../../../logging/logger.js';
15
16
  import { usePatchSession } from '../../../../shared/api/storefront/hooks/authentication/use-patch-session.js';
17
+ import { useInvalidateCurrentCart } from '../../../../shared/api/storefront/hooks/cart/use-invalidate-current-cart.js';
16
18
  import { usePatchCart } from '../../../../shared/api/storefront/hooks/cart/use-patch-cart.js';
17
19
  import { usePlaceOrder } from '../../../../shared/api/storefront/hooks/cart/use-place-order.js';
18
20
  import { useInvalidateAdyen } from '../../../../shared/api/storefront/hooks/payment/use-invalidate-adyen.js';
@@ -27,10 +29,13 @@ import styles from './payment.module.css.js';
27
29
 
28
30
  function Payment({ atp, cart: _cart, form, onError: _onError, onPaymentComplete, onProcessing, onValidating, }) {
29
31
  const { createEcommerceEvent, dataLayer } = useDataLayer();
30
- const { isLoading: isPatchingCart, mutate: patchCart } = usePatchCart();
32
+ const { isLoading: isPatchingCart, mutate: patchCart } = usePatchCart({
33
+ skipInvalidation: true,
34
+ });
31
35
  const { isLoading: isPatchingSession } = usePatchSession();
32
36
  const { isLoading: isPlacingCart, mutate: placeOrder } = usePlaceOrder();
33
37
  const { sendPurchaseEventFromPaymentPage } = useAlgoliaInsights();
38
+ const invalidateCurrentCart = useInvalidateCurrentCart();
34
39
  const dropinRef = useRef(null);
35
40
  const [paymentError, setPaymentError] = useState();
36
41
  const [apiError, setAPIError] = useState();
@@ -151,7 +156,7 @@ function Payment({ atp, cart: _cart, form, onError: _onError, onPaymentComplete,
151
156
  if (isAdyenPayment) {
152
157
  /* Adyen Payment */
153
158
  if (!dropinRef.current) {
154
- console.warn('Adyen Dropin not ready');
159
+ logger.warn('Adyen Dropin not ready');
155
160
  return;
156
161
  }
157
162
  dropinRef.current.showValidation();
@@ -168,20 +173,26 @@ function Payment({ atp, cart: _cart, form, onError: _onError, onPaymentComplete,
168
173
  requestedDeliveryDate: formData.get('deliveryDate')?.toString(),
169
174
  };
170
175
  try {
171
- cartRef.current = await patchCart({
172
- cart: updatedCart,
173
- });
174
- }
175
- catch (error) {
176
- console.error(error);
177
- setAPIError(error);
178
- }
179
- try {
180
- dropinRef.current.submit();
176
+ try {
177
+ cartRef.current = await patchCart({
178
+ cart: updatedCart,
179
+ });
180
+ }
181
+ catch (error) {
182
+ setAPIError(error);
183
+ throw error;
184
+ }
185
+ try {
186
+ dropinRef.current.submit();
187
+ }
188
+ catch (error) {
189
+ setPaymentError(error);
190
+ throw error;
191
+ }
181
192
  }
182
193
  catch (error) {
183
- console.error(error);
184
- setPaymentError(error);
194
+ logger.error(error);
195
+ invalidateCurrentCart();
185
196
  }
186
197
  }
187
198
  else {
@@ -196,8 +207,9 @@ function Payment({ atp, cart: _cart, form, onError: _onError, onPaymentComplete,
196
207
  return onPaymentComplete({ cartId: cart.trackId });
197
208
  }
198
209
  catch (error) {
199
- console.error(error);
210
+ logger.error(error);
200
211
  setPaymentError(error);
212
+ invalidateCurrentCart();
201
213
  }
202
214
  }
203
215
  }
@@ -224,7 +236,7 @@ function Payment({ atp, cart: _cart, form, onError: _onError, onPaymentComplete,
224
236
  return onPaymentComplete({ cartId: cart.trackId });
225
237
  }
226
238
  catch (error) {
227
- console.error(error);
239
+ logger.error(error);
228
240
  setAPIError(error);
229
241
  }
230
242
  }, [onPaymentComplete, onPlaceOrderCompleted, placeOrder]);
@@ -232,7 +244,7 @@ function Payment({ atp, cart: _cart, form, onError: _onError, onPaymentComplete,
232
244
  invalidateAdyen();
233
245
  // invalidateCurrentCart()
234
246
  setPaymentError(error);
235
- console.error(error);
247
+ logger.error(error);
236
248
  _onError?.(error, result);
237
249
  }, [_onError, invalidateAdyen]);
238
250
  return (jsxs(Form, { className: styles['payment-form'], "data-test-selector": "paymentForm", id: form, onSubmit: e => {
@@ -22,7 +22,7 @@ function PaymentPageContent({ atp, cart, formId, hasAtp, isProcessing, isValidat
22
22
  label: t('Review and payment'),
23
23
  },
24
24
  ], title: t('Review and payment'), children: jsxs(CheckoutPageLayout, { actions: {
25
- primary: (jsx(Button, { withArrow: true, "data-test-selector": "checkoutShippingCartTotalContinueButton", form: formId, isDisabled: isProcessing, isLoading: isProcessing ? (jsx(FormattedMessage, { id: "Processing" })) : isValidating ? (jsx(FormattedMessage, { id: "Validating" })) : (false), type: "submit", children: jsx(FormattedMessage, { id: "Pay" }) })),
25
+ primary: (jsx(Button, { withArrow: true, "data-test-selector": "checkoutReviewAndSubmit_placeOrder", form: formId, isDisabled: isProcessing, isLoading: isProcessing ? (jsx(FormattedMessage, { id: "Processing" })) : isValidating ? (jsx(FormattedMessage, { id: "Validating" })) : (false), type: "submit", children: jsx(FormattedMessage, { id: "Pay" }) })),
26
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
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, onPaymentComplete: onPaymentComplete, onProcessing: setIsProcessing, onValidating: setIsValidating }) }) }), 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
28
  fit: 'contain',
@@ -1,4 +1,4 @@
1
- import { CountryModel } from '../../../../shared/api/storefront/model/storefront.model';
1
+ import { BillToModel, CountryModel } from '../../../../shared/api/storefront/model/storefront.model';
2
2
  export declare const EDIT_ADDRESS_FORM_ID = "billToForm";
3
3
  interface Address {
4
4
  address1: string;
@@ -13,7 +13,8 @@ interface Address {
13
13
  phone: string;
14
14
  postalCode: string;
15
15
  }
16
- export declare function EditAddresses({ countries, isLoading, isPickup, onSubmit, }: {
16
+ export declare function EditAddresses({ billTo, countries, isLoading, isPickup, onSubmit, }: {
17
+ billTo: BillToModel | undefined | null;
17
18
  countries: CountryModel[];
18
19
  isLoading: boolean;
19
20
  isPickup: boolean;
@@ -15,10 +15,10 @@ import { SonicAddress } from './sonic-address.js';
15
15
  import styles from './edit-address.module.css.js';
16
16
 
17
17
  const EDIT_ADDRESS_FORM_ID = 'billToForm';
18
- function EditAddresses({ countries, isLoading, isPickup, onSubmit, }) {
18
+ function EditAddresses({ billTo, countries, isLoading, isPickup, onSubmit, }) {
19
19
  const t = useFormattedMessage();
20
- const [companyName, setCompanyName] = useState('');
21
- const [lastName, setLastName] = useState('');
20
+ const [companyName, setCompanyName] = useState(billTo?.companyName || '');
21
+ const [lastName, setLastName] = useState(billTo?.lastName || '');
22
22
  const { data: cart } = useFetchCurrentCart();
23
23
  return (jsxs(Fragment, { children: [jsx(CheckoutPageSection, { title: jsx(FormattedMessage, { id: "Billing address" }), children: jsx(CheckoutPageSectionContent, { children: jsxs(Form, { className: styles.form, "data-test-selector": "billToAddressForm", id: EDIT_ADDRESS_FORM_ID, onSubmit: e => {
24
24
  e.preventDefault();
@@ -43,7 +43,7 @@ function EditAddresses({ countries, isLoading, isPickup, onSubmit, }) {
43
43
  },
44
44
  notes: formData.get('notes')?.toString() || '',
45
45
  });
46
- }, children: [jsx(TextField, { isDisabled: isLoading, label: t('First name'), name: "firstName", showLabel: true }), jsx(TextField, { isDisabled: isLoading, isRequired: !companyName, label: t('Last name'), minLength: 3, name: "lastName", onChange: setLastName, showLabel: true, value: lastName }, `lastname-${Boolean(companyName)}`), jsx(TextField, { isDisabled: isLoading, label: t('Company name'), name: "companyName", onChange: setCompanyName, showLabel: true, value: companyName }), jsx(TextField, { isDisabled: isLoading, label: t('Attention'), name: "attention", showLabel: true }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { isRequired: true, isDisabled: isLoading, label: `${t('Address')} 1`, maxLength: 30, minLength: 3, name: "address1", showLabel: true }) }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { isDisabled: isLoading, label: `${t('Address')} 2`, maxLength: 30, minLength: 3, name: "address2", showLabel: true }) }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { isDisabled: isLoading, label: `${t('Address')} 3`, maxLength: 30, minLength: 3, name: "address3", showLabel: true }) }), jsx(TextField, { isRequired: true, isDisabled: isLoading, label: t('Postal Code'), maxLength: 10, minLength: 4, name: "postalCode", showLabel: true }), jsx(TextField, { isRequired: true, isDisabled: isLoading, label: t('City'), maxLength: 30, minLength: 3, name: "city", showLabel: true }), jsx("div", { className: styles['span-2'], children: jsx(CountrySelect, { isRequired: true, countries: countries, "data-test-selector": "countrySelect", isDisabled: isLoading, name: "countrySelect" }) }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { isRequired: true, isDisabled: isLoading, label: t('Phone'), name: "phone", showLabel: true, validate: value => {
46
+ }, children: [jsx(TextField, { defaultValue: billTo?.firstName, isDisabled: isLoading, label: t('First name'), name: "firstName", showLabel: true }), jsx(TextField, { isDisabled: isLoading, isRequired: !companyName, label: t('Last name'), minLength: 3, name: "lastName", onChange: setLastName, showLabel: true, value: lastName }, `lastname-${Boolean(companyName)}`), jsx(TextField, { defaultValue: billTo?.companyName, isDisabled: isLoading, label: t('Company name'), name: "companyName", onChange: setCompanyName, showLabel: true, value: companyName }), jsx(TextField, { defaultValue: billTo?.attention, isDisabled: isLoading, label: t('Attention'), name: "attention", showLabel: true }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { isRequired: true, defaultValue: billTo?.address1, isDisabled: isLoading, label: `${t('Address')} 1`, maxLength: 30, minLength: 3, name: "address1", showLabel: true }) }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { defaultValue: billTo?.address2, isDisabled: isLoading, label: `${t('Address')} 2`, maxLength: 30, minLength: 3, name: "address2", showLabel: true }) }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { defaultValue: billTo?.address3, isDisabled: isLoading, label: `${t('Address')} 3`, maxLength: 30, minLength: 3, name: "address3", showLabel: true }) }), jsx(TextField, { isRequired: true, defaultValue: billTo?.postalCode, isDisabled: isLoading, label: t('Postal Code'), maxLength: 10, minLength: 4, name: "postalCode", showLabel: true }), jsx(TextField, { isRequired: true, defaultValue: billTo?.city, isDisabled: isLoading, label: t('City'), maxLength: 30, minLength: 3, name: "city", showLabel: true }), jsx("div", { className: styles['span-2'], children: jsx(CountrySelect, { isRequired: true, countries: countries, "data-test-selector": "countrySelect", isDisabled: isLoading, name: "countrySelect", selectedCountry: countries.find(country => country.id === billTo?.country?.id) }) }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { isRequired: true, defaultValue: billTo?.phone, isDisabled: isLoading, label: t('Phone'), name: "phone", showLabel: true, validate: value => {
47
47
  if (!value)
48
48
  return value;
49
49
  return (validatePhone(value) ||
@@ -53,7 +53,7 @@ function EditAddresses({ countries, isLoading, isPickup, onSubmit, }) {
53
53
  return value;
54
54
  return (validateEmail(value) ||
55
55
  t('Please enter a valid e-mail address'));
56
- } }) }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { isDisabled: isLoading, isMultiline: true, label: t('Add order notes'), name: "notes", rows: 3, showLabel: true }) })] }) }) }), jsx(CheckoutPageSection, { title: jsx(FormattedMessage, { id: isPickup ? 'Pickup address' : 'Shipping address' }), children: jsx(CheckoutPageSectionContent, { children: jsx(Fragment, { children: isPickup ? (jsx(SonicAddress, {})) : (jsxs("div", { className: styles['use-invoice-checkbox'], children: [jsx(Checkbox, { "data-test-selector": "checkboxUseBillingAddress", isDisabled: true, isSelected: true, children: jsx(FormattedMessage, { id: "Use billing address" }) }), jsx(InfoIconTooltip, { variant: "stroke", children: t('Changing your address is currently not possible. Please contact customer support to change your address.') })] })) }) }) })] }));
56
+ } }) }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { defaultValue: cart?.notes, isDisabled: isLoading, isMultiline: true, label: t('Add order notes'), name: "notes", rows: 3, showLabel: true }) })] }) }) }), jsx(CheckoutPageSection, { title: jsx(FormattedMessage, { id: isPickup ? 'Pickup address' : 'Shipping address' }), children: jsx(CheckoutPageSectionContent, { children: jsx(Fragment, { children: isPickup ? (jsx(SonicAddress, {})) : (jsxs("div", { className: styles['use-invoice-checkbox'], children: [jsx(Checkbox, { "data-test-selector": "checkboxUseBillingAddress", isDisabled: true, isSelected: true, children: jsx(FormattedMessage, { id: "Use billing address" }) }), jsx(InfoIconTooltip, { variant: "stroke", children: t('Changing your address is currently not possible. Please contact customer support to change your address.') })] })) }) }) })] }));
57
57
  }
58
58
 
59
59
  export { EDIT_ADDRESS_FORM_ID, EditAddresses };
@@ -22,7 +22,31 @@ function ReadOnlyAddresses({ billTo, isLoading, isPickup, notes, onSubmit, shipT
22
22
  onSubmit({
23
23
  notes: formData.get('notes')?.toString() || '',
24
24
  });
25
- }, children: [jsxs(CheckoutPageSection, { title: jsx(FormattedMessage, { id: "Billing address" }), children: [jsx(CheckoutPageSectionLink, { children: jsxs(RouteLink, { color: "secondary", href: ACCOUNT_ADDRESSES_PATH, isDisabled: isLoading, children: [jsx(FormattedMessage, { id: "Edit billing address" }), " >"] }) }), jsxs(CheckoutPageSectionContent, { children: [billTo && (jsx(Address, { address1: billTo.address1, address2: billTo.address2, address3: billTo.address3, city: billTo.city, companyName: billTo.companyName, country: billTo.country?.name, email: billTo.email, firstName: billTo.firstName, lastName: billTo.lastName, phone: billTo.phone, postalCode: billTo.postalCode })), jsx("div", { className: styles.notes, children: jsx(TextField, { defaultValue: notes, isDisabled: isLoading, isMultiline: true, label: t('Add order notes'), name: "notes", rows: 3, showLabel: true }) })] })] }), jsxs(CheckoutPageSection, { title: jsx(FormattedMessage, { id: isPickup ? 'Pickup address' : 'Shipping address' }), children: [!isPickup && (jsx(CheckoutPageSectionLink, { children: jsxs(RouteLink, { color: "secondary", href: ACCOUNT_ADDRESSES_PATH, isDisabled: isLoading, children: [jsx(FormattedMessage, { id: "Edit shipping address" }), " >"] }) })), jsx(CheckoutPageSectionContent, { children: isPickup ? (jsx(SonicAddress, {})) : (jsxs(Fragment, { children: [jsx(Checkbox, { className: styles['use-invoice-checkbox'], "data-test-selector": "checkboxUseBillingAddress", isDisabled: true, isSelected: true, children: jsx(FormattedMessage, { id: "Use billing address" }) }), shipTo && (jsx(Address, { address1: shipTo.address1, address2: shipTo.address2, address3: shipTo.address3, city: shipTo.city, companyName: shipTo.companyName, country: shipTo.country?.name, email: shipTo.email, firstName: shipTo.firstName, lastName: shipTo.lastName, phone: shipTo.phone, postalCode: shipTo.postalCode }))] })) })] })] }));
25
+ }, children: [jsxs(CheckoutPageSection, { title: jsx(FormattedMessage, { id: "Billing address" }), children: [jsx(CheckoutPageSectionLink, { children: jsxs(RouteLink, { color: "secondary", href: ACCOUNT_ADDRESSES_PATH, isDisabled: isLoading, children: [jsx(FormattedMessage, { id: "Edit billing address" }), " >"] }) }), jsxs(CheckoutPageSectionContent, { children: [billTo && (jsx(Address, { address: {
26
+ address1: billTo.address1,
27
+ address2: billTo.address2,
28
+ address3: billTo.address3,
29
+ city: billTo.city,
30
+ companyName: billTo.companyName,
31
+ country: billTo.country?.name,
32
+ email: billTo.email,
33
+ firstName: billTo.firstName,
34
+ lastName: billTo.lastName,
35
+ phone: billTo.phone,
36
+ postalCode: billTo.postalCode,
37
+ } })), jsx("div", { className: styles.notes, children: jsx(TextField, { defaultValue: notes, isDisabled: isLoading, isMultiline: true, label: t('Add order notes'), name: "notes", rows: 3, showLabel: true }) })] })] }), jsxs(CheckoutPageSection, { title: jsx(FormattedMessage, { id: isPickup ? 'Pickup address' : 'Shipping address' }), children: [!isPickup && (jsx(CheckoutPageSectionLink, { children: jsxs(RouteLink, { color: "secondary", href: ACCOUNT_ADDRESSES_PATH, isDisabled: isLoading, children: [jsx(FormattedMessage, { id: "Edit shipping address" }), " >"] }) })), jsx(CheckoutPageSectionContent, { children: isPickup ? (jsx(SonicAddress, {})) : (jsxs(Fragment, { children: [jsx(Checkbox, { className: styles['use-invoice-checkbox'], "data-test-selector": "checkboxUseBillingAddress", isDisabled: true, isSelected: true, children: jsx(FormattedMessage, { id: "Use billing address" }) }), shipTo && (jsx(Address, { address: {
38
+ address1: shipTo.address1,
39
+ address2: shipTo.address2,
40
+ address3: shipTo.address3,
41
+ city: shipTo.city,
42
+ companyName: shipTo.companyName,
43
+ country: shipTo.country?.name,
44
+ email: shipTo.email,
45
+ firstName: shipTo.firstName,
46
+ lastName: shipTo.lastName,
47
+ phone: shipTo.phone,
48
+ postalCode: shipTo.postalCode,
49
+ } }))] })) })] })] }));
26
50
  }
27
51
 
28
52
  export { ReadOnlyAddresses };
@@ -5,10 +5,11 @@ export interface ShippingPageContentProps {
5
5
  editAddress: ReactNode;
6
6
  errorPatchBillingAddress?: unknown;
7
7
  fulfillmentMethods: string[] | undefined;
8
+ isGuest: boolean;
8
9
  isLoadingFulfillmentMethods: boolean;
9
10
  isPatching: boolean;
10
11
  isPatchingSession: boolean;
11
12
  onChangeFulfillmentMethod: (value: string) => void;
12
13
  readOnlyAddress: ReactNode;
13
14
  }
14
- export declare function ShippingPageContent({ cart, editAddress, errorPatchBillingAddress, fulfillmentMethods, isLoadingFulfillmentMethods, isPatching, isPatchingSession, onChangeFulfillmentMethod, readOnlyAddress, }: ShippingPageContentProps): import("react/jsx-runtime").JSX.Element;
15
+ export declare function ShippingPageContent({ cart, editAddress, errorPatchBillingAddress, fulfillmentMethods, isGuest, isLoadingFulfillmentMethods, isPatching, isPatchingSession, onChangeFulfillmentMethod, readOnlyAddress, }: ShippingPageContentProps): import("react/jsx-runtime").JSX.Element;
@@ -14,7 +14,7 @@ import { CheckoutPageSectionContent } from '../layouts/checkout-page-layout/comp
14
14
  import { EDIT_ADDRESS_FORM_ID } from './components/edit-address.js';
15
15
  import styles from './shipping-page.module.css.js';
16
16
 
17
- function ShippingPageContent({ cart, editAddress, errorPatchBillingAddress, fulfillmentMethods, isLoadingFulfillmentMethods, isPatching, isPatchingSession, onChangeFulfillmentMethod, readOnlyAddress, }) {
17
+ function ShippingPageContent({ cart, editAddress, errorPatchBillingAddress, fulfillmentMethods, isGuest, isLoadingFulfillmentMethods, isPatching, isPatchingSession, onChangeFulfillmentMethod, readOnlyAddress, }) {
18
18
  const t = useFormattedMessage();
19
19
  const fulfillmentMethodOptions = fulfillmentMethods?.reduce((acc, method) => ({
20
20
  ...acc,
@@ -34,7 +34,7 @@ function ShippingPageContent({ cart, editAddress, errorPatchBillingAddress, fulf
34
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" }) })),
35
35
  }, mobileSummary: jsx(CartTotalsSummary, { totalAmount: cart.orderGrandTotalDisplay }), overview: jsx(CartTotals, { fulfillmentMethod: fulfillmentMethods && fulfillmentMethods.length === 1
36
36
  ? cart.fulfillmentMethod
37
- : 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 ? readOnlyAddress : editAddress] }), Boolean(errorPatchBillingAddress) && (jsx("div", { className: styles['error-message'], children: jsx(FormattedMessage, { id: "An unexpected error occured" }) }))] }) }));
37
+ : 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" }) }))] }) }));
38
38
  }
39
39
 
40
40
  export { ShippingPageContent };
@@ -75,13 +75,14 @@ function ShippingPage() {
75
75
  if (isLoading || isNavigating || isError || isSuccess)
76
76
  return jsx(LoadingPage, {});
77
77
  if (!isAuthenticated ||
78
+ hasNo(session) ||
78
79
  hasNo(cart) ||
79
80
  hasNo(cart.cartLines) ||
80
81
  cart.cartLines.length === 0 ||
81
82
  hasNo(cart.billTo) ||
82
83
  (hasNo(cart.billTo.address1) && hasNo(countries)))
83
84
  return null;
84
- return (jsx(ShippingPageContent, { cart: cart, editAddress: jsx(EditAddresses, { countries: countries || [], isLoading: isPatching, isPickup: isPickup, onSubmit: async ({ address, notes }) => {
85
+ return (jsx(ShippingPageContent, { cart: cart, editAddress: jsx(EditAddresses, { billTo: cart.billTo, countries: countries || [], isLoading: isPatching, isPickup: isPickup, onSubmit: async ({ address, notes }) => {
85
86
  if (!cart.billTo)
86
87
  return;
87
88
  await patchShippingDetails({
@@ -93,7 +94,7 @@ function ShippingPage() {
93
94
  cart,
94
95
  event: { event: 'add_shipping_info' },
95
96
  }));
96
- } }), errorPatchBillingAddress: errorPatchBillingAddress, fulfillmentMethods: fulfillmentMethods, isLoadingFulfillmentMethods: isLoadingFulfillmentMethods, isPatching: isPatching, isPatchingSession: isPatchingSession, onChangeFulfillmentMethod: async (value) => {
97
+ } }), errorPatchBillingAddress: errorPatchBillingAddress, fulfillmentMethods: fulfillmentMethods, isGuest: session.isGuest, isLoadingFulfillmentMethods: isLoadingFulfillmentMethods, isPatching: isPatching, isPatchingSession: isPatchingSession, onChangeFulfillmentMethod: async (value) => {
97
98
  await patchSession({
98
99
  session: {
99
100
  ...session,
@@ -37,7 +37,7 @@ function SearchResultsPageContent({ keyword }) {
37
37
  const { hits, isLoading } = useAlgoliaHits();
38
38
  const hasHits = hits.length > 0;
39
39
  const t = useFormattedMessage();
40
- return (jsxs(Fragment, { children: [isLoading !== false && !hasHits && jsx(LoadingPage, {}), isLoading === false && !hasHits && (jsx(NoResults, { content: jsxs("p", { children: [jsx(FormattedMessage, { id: "You could try checking the spelling of your search query" }), jsx("br", {}), jsx(FormattedMessage, { id: "Try another search" }), jsx("br", {}), jsx(FormattedMessage, { id: "Are you looking for information about our service? Please visit our customer support page" })] }), title: t("Unfortnately, We found no articles for your search '{0}'", {
40
+ return (jsxs(Fragment, { children: [isLoading !== false && !hasHits && jsx(LoadingPage, {}), isLoading === false && !hasHits && (jsx(NoResults, { content: jsxs(Fragment, { children: [jsx(FormattedMessage, { id: "You could try checking the spelling of your search query" }), jsx("br", {}), jsx(FormattedMessage, { id: "Try another search" }), jsx("br", {}), jsx(FormattedMessage, { id: "Are you looking for information about our service? Please visit our customer support page" })] }), title: t("Unfortnately, We found no articles for your search '{0}'", {
41
41
  replacementValues: { 0: keyword },
42
42
  }) })), jsxs("div", { style: {
43
43
  display: hasHits ? undefined : 'none',
@@ -1,8 +1,9 @@
1
+ import { logger } from '../../logging/logger.js';
2
+
1
3
  const _dataLayer = [];
2
4
  _dataLayer.push = (function (_push) {
3
5
  return (...items) => {
4
- // eslint-disable-next-line no-console
5
- console.log('dataLayer.push', items.length === 1 ? items[0] : items);
6
+ logger.info('dataLayer.push', items.length === 1 ? items[0] : items);
6
7
  return _push(...items);
7
8
  };
8
9
  })(_dataLayer.push.bind(_dataLayer));
@@ -73,11 +73,9 @@ function useGlobalState(key, initialState) {
73
73
  state.removeEventListener('stateChanged', updateState);
74
74
  };
75
75
  }, [state]);
76
- function updateGlobalState(valueOrFn) {
77
- state.value =
78
- valueOrFn instanceof Function ? valueOrFn(state.value) : valueOrFn;
79
- }
80
- return [rerenderState, useCallback(updateGlobalState, [updateGlobalState])];
76
+ const setGlobalState = useCallback((valueOrFn) => (state.value =
77
+ valueOrFn instanceof Function ? valueOrFn(state.value) : valueOrFn), [state]);
78
+ return [rerenderState, setGlobalState];
81
79
  }
82
80
 
83
81
  export { GlobalStateProvider, GlobalStateProviderContext, useGlobalState };
@@ -0,0 +1,2 @@
1
+ export declare function trackPropertyChange(name: string, value: unknown): void;
2
+ export declare function trackPropertyChange(obj: Record<string, unknown>): void;
@@ -0,0 +1,21 @@
1
+ import { logger } from '../../logging/logger.js';
2
+
3
+ const prevState = {};
4
+ function trackPropertyChange(name, value) {
5
+ if (typeof name === 'string') {
6
+ if (value === prevState[name]) {
7
+ logger.info(name, value === prevState[name]);
8
+ }
9
+ else {
10
+ logger.warn(name, value === prevState[name]);
11
+ }
12
+ prevState[name] = value;
13
+ }
14
+ else {
15
+ for (const [key, value] of Object.entries(name)) {
16
+ trackPropertyChange(key, value);
17
+ }
18
+ }
19
+ }
20
+
21
+ export { trackPropertyChange };
@@ -1,3 +1,5 @@
1
+ import { logger } from '../../logging/logger.js';
2
+
1
3
  const environments = [
2
4
  'marketingLocal',
3
5
  'sandbox',
@@ -26,7 +28,7 @@ function getEnvironment() {
26
28
  }
27
29
  else if (typeof window === 'undefined') {
28
30
  environmentUrl = 'production';
29
- console.error('Unable to detect environment url');
31
+ logger.error('Unable to detect environment url');
30
32
  }
31
33
  else {
32
34
  environmentUrl = `${window.location.hostname}:${window.location.port}`;
@@ -52,7 +54,7 @@ function getEnvironment() {
52
54
  }
53
55
  else {
54
56
  environment = 'production';
55
- console.error(`Environment not detected for url ${environmentUrl}. Defaulting to production.`);
57
+ logger.error(`Environment not detected for url ${environmentUrl}. Defaulting to production.`);
56
58
  }
57
59
  return environment;
58
60
  }