@sonic-equipment/ui 178.0.0 → 180.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.
- package/dist/algolia/algolia-active-filters.js +4 -0
- package/dist/config.js +4 -7
- package/dist/country-select/country-select.d.ts +1 -0
- package/dist/exports.d.ts +19 -9
- package/dist/forms/input/input.d.ts +1 -0
- package/dist/forms/input/input.js +4 -4
- package/dist/forms/input/input.module.css.js +1 -1
- package/dist/forms/password-field/password-field.d.ts +2 -0
- package/dist/forms/password-field/password-field.js +15 -0
- package/dist/forms/search-field/search-field.d.ts +5 -0
- package/dist/forms/search-field/search-field.js +19 -0
- package/dist/forms/text-field/text-field.d.ts +25 -24
- package/dist/forms/text-field/text-field.js +7 -14
- package/dist/forms/textarea/textarea.d.ts +1 -0
- package/dist/forms/textarea/textarea.js +2 -2
- package/dist/forms/textarea/textarea.module.css.js +1 -1
- package/dist/global-search/search-highlight/highlight.d.ts +1 -0
- package/dist/header/buttons/account/connected-account-button.js +1 -1
- package/dist/icons/solid/solid-rating-icon.js +7 -0
- package/dist/index.js +20 -10
- package/dist/intl/translation-id.d.ts +1 -1
- package/dist/modals/dialog/dialog.d.ts +5 -1
- package/dist/modals/dialog/dialog.js +10 -4
- package/dist/navigation/mobile-navigation/mobile-navigation.js +1 -1
- package/dist/observers/intersection-observer.d.ts +9 -1
- package/dist/observers/intersection-observer.js +6 -3
- package/dist/pages/account/components/create-account-form/create-account-form.js +3 -2
- package/dist/pages/account/components/sign-in-form/sign-in-form.js +2 -1
- package/dist/pages/my-sonic/actions/change-customer/change-customer-dialog.d.ts +15 -0
- package/dist/pages/my-sonic/actions/change-customer/change-customer-dialog.js +23 -0
- package/dist/pages/my-sonic/actions/change-customer/change-customer-dialog.module.css.js +3 -0
- package/dist/pages/my-sonic/actions/change-customer/change-customer.d.ts +13 -0
- package/dist/pages/my-sonic/actions/change-customer/change-customer.js +66 -0
- package/dist/pages/my-sonic/actions/change-customer/change-customer.module.css.js +3 -0
- package/dist/pages/my-sonic/actions/change-customer/connected-change-customer-dialog.d.ts +2 -0
- package/dist/pages/my-sonic/actions/change-customer/connected-change-customer-dialog.js +39 -0
- package/dist/pages/my-sonic/navigation/connected-my-sonic-navigation.d.ts +1 -0
- package/dist/pages/{my-account/navigation/connected-my-account-navigation.js → my-sonic/navigation/connected-my-sonic-navigation.js} +5 -5
- package/dist/pages/my-sonic/navigation/my-sonic-desktop-navigation.d.ts +6 -0
- package/dist/pages/my-sonic/navigation/my-sonic-desktop-navigation.js +19 -0
- package/dist/pages/my-sonic/navigation/my-sonic-desktop-navigation.module.css.js +3 -0
- package/dist/pages/{my-account/navigation/my-account-mobile-navigation.d.ts → my-sonic/navigation/my-sonic-mobile-navigation.d.ts} +1 -1
- package/dist/pages/my-sonic/navigation/my-sonic-mobile-navigation.js +22 -0
- package/dist/pages/my-sonic/navigation/my-sonic-navigation-items.d.ts +18 -0
- package/dist/pages/my-sonic/navigation/my-sonic-navigation-items.js +29 -0
- package/dist/pages/my-sonic/widgets/connected-customer-information-widget.d.ts +1 -0
- package/dist/pages/my-sonic/widgets/connected-customer-information-widget.js +56 -0
- package/dist/pages/product/layouts/product-details-page-layout/product-details-page-layout.d.ts +2 -2
- package/dist/pages/product/layouts/product-details-page-layout/product-details-page-layout.js +3 -2
- package/dist/pages/product/layouts/product-details-page-layout/product-details-page-layout.module.css.js +1 -1
- package/dist/pages/product/product-details-page/components/product-details-recently-viewed-section/product-details-recently-viewed-section.d.ts +1 -0
- package/dist/pages/product/product-details-page/components/product-details-recently-viewed-section/product-details-recently-viewed-section.js +24 -0
- package/dist/pages/product/product-details-page/components/product-details-recently-viewed-section/product-details-recently-viewed-section.module.css.js +3 -0
- package/dist/pages/product/product-details-page/product-details.d.ts +1 -2
- package/dist/pages/product/product-details-page/product-details.js +4 -5
- package/dist/shared/api/bff/hooks/use-fetch-product-details-page-data.js +6 -2
- package/dist/shared/api/bff/hooks/use-fetch-recently-viewed-products.d.ts +4 -0
- package/dist/shared/api/bff/hooks/use-fetch-recently-viewed-products.js +15 -0
- package/dist/shared/api/bff/model/bff.model.d.ts +0 -1
- package/dist/shared/api/bff/services/bff-service.d.ts +4 -1
- package/dist/shared/api/bff/services/bff-service.js +11 -1
- package/dist/shared/api/storefront/hooks/authentication/use-patch-session.d.ts +12 -1
- package/dist/shared/api/storefront/hooks/customer/use-fetch-bill-to-addresses.d.ts +4 -1
- package/dist/shared/api/storefront/hooks/customer/use-fetch-bill-to-addresses.js +5 -6
- package/dist/shared/api/storefront/hooks/product/use-mark-product-as-viewed.d.ts +2 -0
- package/dist/shared/api/storefront/hooks/product/use-mark-product-as-viewed.js +17 -0
- package/dist/shared/api/storefront/model/storefront.model.d.ts +4 -1
- package/dist/shared/api/storefront/services/customer-service.d.ts +5 -1
- package/dist/shared/api/storefront/services/customer-service.js +3 -3
- package/dist/shared/api/storefront/services/product-service.d.ts +4 -0
- package/dist/shared/api/storefront/services/product-service.js +10 -0
- package/dist/shared/feature-flags/use-feature-flags.d.ts +0 -3
- package/dist/shared/feature-flags/use-feature-flags.js +0 -3
- package/dist/shared/fetch/request.d.ts +1 -1
- package/dist/shared/ga/google-analytics-provider.d.ts +1 -1
- package/dist/shared/hooks/use-intersection-observer.d.ts +2 -1
- package/dist/shared/hooks/use-intersection-observer.js +3 -2
- package/dist/styles.css +228 -101
- package/dist/text/highlight-text/highlight-text.d.ts +10 -0
- package/dist/text/highlight-text/highlight-text.js +19 -0
- package/dist/text/highlight-text/highlight-text.module.css.js +3 -0
- package/dist/typography/heading/heading.d.ts +3 -1
- package/dist/typography/heading/heading.js +2 -1
- package/package.json +2 -1
- package/dist/icons/solid/solid-dashboard-icon.js +0 -7
- package/dist/pages/my-account/navigation/connected-my-account-navigation.d.ts +0 -1
- package/dist/pages/my-account/navigation/my-account-desktop-navigation.d.ts +0 -6
- package/dist/pages/my-account/navigation/my-account-desktop-navigation.js +0 -17
- package/dist/pages/my-account/navigation/my-account-desktop-navigation.module.css.js +0 -3
- package/dist/pages/my-account/navigation/my-account-mobile-navigation.js +0 -25
- package/dist/pages/my-account/widgets/connected-company-information-widget.d.ts +0 -1
- package/dist/pages/my-account/widgets/connected-company-information-widget.js +0 -43
- package/dist/pages/product/product-details-page/components/product-details-recently-viewed/product-details-recently-viewed.d.ts +0 -4
- package/dist/pages/product/product-details-page/components/product-details-recently-viewed/product-details-recently-viewed.js +0 -15
- /package/dist/pages/{my-account → my-sonic}/widgets/components/address-data-card.d.ts +0 -0
- /package/dist/pages/{my-account → my-sonic}/widgets/components/address-data-card.js +0 -0
- /package/dist/pages/{my-account → my-sonic}/widgets/connected-bill-to-address-widget.d.ts +0 -0
- /package/dist/pages/{my-account → my-sonic}/widgets/connected-bill-to-address-widget.js +0 -0
- /package/dist/pages/{my-account → my-sonic}/widgets/connected-ship-to-address-widget.d.ts +0 -0
- /package/dist/pages/{my-account → my-sonic}/widgets/connected-ship-to-address-widget.js +0 -0
- /package/dist/pages/{my-account → my-sonic}/widgets/connected-user-account-widget.d.ts +0 -0
- /package/dist/pages/{my-account → my-sonic}/widgets/connected-user-account-widget.js +0 -0
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
interface IntersectionObserverProps {
|
|
3
|
+
/** The content to render when the observer is intersecting */
|
|
3
4
|
children: ReactNode;
|
|
5
|
+
/** Options for the IntersectionObserver */
|
|
6
|
+
intersectionObserverInit?: IntersectionObserverInit;
|
|
7
|
+
/** Whether the observer is disabled */
|
|
4
8
|
isDisabled?: boolean;
|
|
9
|
+
/** Whether the observer is a placeholder.
|
|
10
|
+
* Once intersected the observer is replaced by its children */
|
|
11
|
+
isPlaceholder?: boolean;
|
|
12
|
+
/** Callback when the intersection state changes */
|
|
5
13
|
onIntersectingChange?: (isIntersecting: boolean) => void;
|
|
6
14
|
}
|
|
7
|
-
export declare function IntersectionObserverComponent({ children, isDisabled, onIntersectingChange, }: IntersectionObserverProps): string | number | boolean | import("react/jsx-runtime").JSX.Element | Iterable<ReactNode> | null | undefined;
|
|
15
|
+
export declare function IntersectionObserverComponent({ children, intersectionObserverInit, isDisabled, isPlaceholder, onIntersectingChange, }: IntersectionObserverProps): string | number | boolean | import("react/jsx-runtime").JSX.Element | Iterable<ReactNode> | null | undefined;
|
|
8
16
|
export {};
|
|
@@ -3,17 +3,20 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
3
3
|
import { useRef } from 'react';
|
|
4
4
|
import { useIntersectionObserver } from '../shared/hooks/use-intersection-observer.js';
|
|
5
5
|
|
|
6
|
-
function IntersectionObserverComponent({ children, isDisabled, onIntersectingChange, }) {
|
|
6
|
+
function IntersectionObserverComponent({ children, intersectionObserverInit, isDisabled, isPlaceholder = false, onIntersectingChange, }) {
|
|
7
7
|
const topRef = useRef(null);
|
|
8
8
|
const bottomRef = useRef(null);
|
|
9
|
-
useIntersectionObserver({
|
|
9
|
+
const { isIntersecting } = useIntersectionObserver({
|
|
10
|
+
intersectionObserverInit,
|
|
10
11
|
isDisabled,
|
|
11
12
|
observables: [{ ref: topRef }, { ref: bottomRef }],
|
|
12
13
|
onIntersectingChange,
|
|
13
14
|
});
|
|
14
15
|
if (isDisabled)
|
|
15
16
|
return children;
|
|
16
|
-
|
|
17
|
+
if (isIntersecting && isPlaceholder)
|
|
18
|
+
return children;
|
|
19
|
+
return (jsxs("div", { "data-intersecting": isIntersecting, style: { display: 'contents' }, children: [jsx("div", { ref: topRef, "aria-hidden": true, "data-role": "top of intersection observer" }), isIntersecting && children, jsx("div", { ref: bottomRef, "aria-hidden": true, "data-role": "bottom of intersection observer" })] }));
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
export { IntersectionObserverComponent };
|
|
@@ -7,6 +7,7 @@ import { useCountries } from '../../../../country-select/hooks/use-countries.js'
|
|
|
7
7
|
import { Form } from '../../../../forms/form/form.js';
|
|
8
8
|
import { FormSegment } from '../../../../forms/form/form-segment.js';
|
|
9
9
|
import { FormSegmentGroup } from '../../../../forms/form/form-segment-group.js';
|
|
10
|
+
import { PasswordField } from '../../../../forms/password-field/password-field.js';
|
|
10
11
|
import { SwitchField } from '../../../../forms/switch-field/switch-field.js';
|
|
11
12
|
import { TextField } from '../../../../forms/text-field/text-field.js';
|
|
12
13
|
import { isCountryCode } from '../../../../intl/types.js';
|
|
@@ -78,12 +79,12 @@ function CreateAccountForm({ errorType, isDisabled: _isDisabled = false, isPendi
|
|
|
78
79
|
if (!value)
|
|
79
80
|
return value;
|
|
80
81
|
return (validateEmail(value) || t('Please enter a valid email address'));
|
|
81
|
-
} }) }), jsx(FormSegment, { children: jsx(
|
|
82
|
+
} }) }), jsx(FormSegment, { children: jsx(PasswordField, { autoComplete: "new-password", "data-test-selector": "createAccount_password", info: "Password must be at least 8 characters long, include at least one number, at least one lowercase character, at least one uppercase character and at least one non-alphanumeric character.", isDisabled: isDisabled, isRequired: true, label: t('Password'), name: "password", onChange: setPassword, validate: value => {
|
|
82
83
|
if (!value)
|
|
83
84
|
return;
|
|
84
85
|
return (validatePassword(value) ||
|
|
85
86
|
t('Password does not meet requirements'));
|
|
86
|
-
} }) }), jsx(FormSegment, { children: jsx(
|
|
87
|
+
} }) }), jsx(FormSegment, { children: jsx(PasswordField, { autoComplete: "new-password", customErrorMessage: "Passwords do not match", "data-test-selector": "createAccount_passwordConfirm", isDisabled: isDisabled, isInvalid: isMismatchingPasswords(), isRequired: true, label: t('Confirm password'), onChange: setPasswordConfirm, value: passwordConfirm }) })] }), jsxs(FormSegmentGroup, { children: [jsx(FormSegment, { children: jsx(SwitchField, { isDisabled: isDisabled, isSelected: isPrivateAccount, name: "isPrivateAccount", onChange: setIsPrivateAccount, children: t('Private account') }) }), jsx(FormSegment, { children: jsx(TextField, { autoComplete: "organization", "data-test-selector": "createAccount_companyName", isDisabled: isDisabled, isRequired: !isPrivateAccount, label: t('Company name'), name: "companyName", onChange: setCompanyName, value: companyName }, `companyName-${Boolean(isPrivateAccount)}`) }), jsx(FormSegment, { children: jsx(TextField, { autoComplete: "given-name", "data-test-selector": "createAccount_firstName", isDisabled: isDisabled, label: t('First name'), name: "firstName" }) }), jsx(FormSegment, { children: jsx(TextField, { autoComplete: "family-name", "data-test-selector": "createAccount_lastName", isDisabled: isDisabled, isRequired: isPrivateAccount, label: t('Last name'), name: "lastName", onChange: setLastName, value: lastName }, `lastname-${Boolean(isPrivateAccount)}`) }), jsx(FormSegment, { children: jsx(CountrySelect, { isRequired: true, countries: countries || [], "data-test-selector": "createAccount_countrySelect", defaultSelectedCountry: defaultSelectedCountry, isDisabled: isLoadingCountries || isDisabled, isLoading: isLoadingCountries, name: "countrySelect" }, defaultSelectedCountry?.id) })] }), jsx(FormSegmentGroup, { children: jsx(FormSegment, { children: jsx(SwitchField, { isDisabled: isDisabled, name: "isSubscribed", children: t('Sign me up for newsletters and product updates') }) }) })] }));
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
export { CreateAccountForm };
|
|
@@ -5,6 +5,7 @@ import { Link } from '../../../../buttons/link/link.js';
|
|
|
5
5
|
import { Form } from '../../../../forms/form/form.js';
|
|
6
6
|
import { FormSegment } from '../../../../forms/form/form-segment.js';
|
|
7
7
|
import { FormSegmentGroup } from '../../../../forms/form/form-segment-group.js';
|
|
8
|
+
import { PasswordField } from '../../../../forms/password-field/password-field.js';
|
|
8
9
|
import { SwitchField } from '../../../../forms/switch-field/switch-field.js';
|
|
9
10
|
import { TextField } from '../../../../forms/text-field/text-field.js';
|
|
10
11
|
import { useFormattedMessage } from '../../../../intl/use-formatted-message.js';
|
|
@@ -64,7 +65,7 @@ function SignInForm({ allowGuestSignIn = false, createAccountPath, errorType, in
|
|
|
64
65
|
if (!value)
|
|
65
66
|
return value;
|
|
66
67
|
return (validateEmail(value) || t('Please enter a valid email address'));
|
|
67
|
-
} }) }), jsx(FormSegment, { children: jsx(
|
|
68
|
+
} }) }), jsx(FormSegment, { children: jsx(PasswordField, { autoComplete: "current-password", "data-test-selector": "signIn_password", isDisabled: isDisabled, isRequired: true, label: t('Password'), name: "password", showLabel: true }) })] }) }));
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
export { SignInForm };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BillToCollectionModel } from '../../../../shared/api/storefront/model/storefront.model';
|
|
2
|
+
export interface ChangeCustomerDialogProps {
|
|
3
|
+
currentlySelectedCustomerId?: string;
|
|
4
|
+
data?: BillToCollectionModel;
|
|
5
|
+
error?: Error | null | unknown;
|
|
6
|
+
filter?: string;
|
|
7
|
+
hasErrorSubmitting?: boolean;
|
|
8
|
+
isLoading?: boolean;
|
|
9
|
+
isOpen: boolean;
|
|
10
|
+
isUpdating?: boolean;
|
|
11
|
+
onClose: () => void;
|
|
12
|
+
onCustomerSelected: (id: string) => void;
|
|
13
|
+
onFilterChanged?: (filter: string) => void;
|
|
14
|
+
}
|
|
15
|
+
export declare function ChangeCustomerDialog({ currentlySelectedCustomerId, data, error, filter, hasErrorSubmitting, isLoading, isOpen, isUpdating, onClose, onCustomerSelected, onFilterChanged, }: ChangeCustomerDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { FormattedMessage } from '../../../../intl/formatted-message.js';
|
|
4
|
+
import { useFormattedMessage } from '../../../../intl/use-formatted-message.js';
|
|
5
|
+
import { Message } from '../../../../message/message.js';
|
|
6
|
+
import { Dialog } from '../../../../modals/dialog/dialog.js';
|
|
7
|
+
import { ChangeCustomer } from './change-customer.js';
|
|
8
|
+
import styles from './change-customer-dialog.module.css.js';
|
|
9
|
+
|
|
10
|
+
function ChangeCustomerDialog({ currentlySelectedCustomerId, data, error, filter, hasErrorSubmitting, isLoading, isOpen, isUpdating = false, onClose, onCustomerSelected, onFilterChanged, }) {
|
|
11
|
+
const t = useFormattedMessage();
|
|
12
|
+
const [hasCustomerSelected, setHasCustomerSelected] = useState(false);
|
|
13
|
+
const [selectedCustomerId, setSelectedCustomerId] = useState();
|
|
14
|
+
return (jsx(Dialog, { allowSubmit: !hasErrorSubmitting && hasCustomerSelected, className: styles['change-customer-dialog'], isOpen: isOpen, isSubmitting: isUpdating || hasErrorSubmitting, onOpenChange: isOpen => !isOpen && onClose(), onSubmit: () => selectedCustomerId && onCustomerSelected(selectedCustomerId), title: t('Change customer'), children: hasErrorSubmitting ? (jsx(Message, { className: styles.error, type: "danger", children: jsx(FormattedMessage, { id: "An error occurred while changing the customer." }) })) : (jsx(ChangeCustomer, { className: styles.content, data: data, error: error, filter: filter, isLoading: isLoading, onCustomerSelected: id => {
|
|
15
|
+
setSelectedCustomerId(id);
|
|
16
|
+
onCustomerSelected(id);
|
|
17
|
+
}, onCustomerSelectionChanged: id => {
|
|
18
|
+
setSelectedCustomerId(id);
|
|
19
|
+
setHasCustomerSelected(true);
|
|
20
|
+
}, onFilterChanged: onFilterChanged, selectedId: currentlySelectedCustomerId })) }));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { ChangeCustomerDialog };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BillToCollectionModel } from '../../../../shared/api/storefront/model/storefront.model';
|
|
2
|
+
export interface ChangeCustomerProps {
|
|
3
|
+
className?: string;
|
|
4
|
+
data?: BillToCollectionModel;
|
|
5
|
+
error?: Error | null | unknown;
|
|
6
|
+
filter?: string;
|
|
7
|
+
isLoading?: boolean;
|
|
8
|
+
onCustomerSelected?: (id: string) => void;
|
|
9
|
+
onCustomerSelectionChanged?: (id: string) => void;
|
|
10
|
+
onFilterChanged?: (filter: string) => void;
|
|
11
|
+
selectedId?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function ChangeCustomer({ className, data, error, filter, isLoading, onCustomerSelected, onCustomerSelectionChanged, onFilterChanged, selectedId, }: ChangeCustomerProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useRef, useMemo } from 'react';
|
|
3
|
+
import { ListBox, ListBoxItem, Text } from 'react-aria-components';
|
|
4
|
+
import clsx from 'clsx';
|
|
5
|
+
import { SearchField } from '../../../../forms/search-field/search-field.js';
|
|
6
|
+
import { SolidRatingIcon } from '../../../../icons/solid/solid-rating-icon.js';
|
|
7
|
+
import { FormattedMessage } from '../../../../intl/formatted-message.js';
|
|
8
|
+
import { useFormattedMessage } from '../../../../intl/use-formatted-message.js';
|
|
9
|
+
import { Message } from '../../../../message/message.js';
|
|
10
|
+
import { UnauthorizedRequestError } from '../../../../shared/fetch/request.js';
|
|
11
|
+
import { HighlightText } from '../../../../text/highlight-text/highlight-text.js';
|
|
12
|
+
import styles from './change-customer.module.css.js';
|
|
13
|
+
|
|
14
|
+
const DEFAULT_PAGE_SIZE = 20;
|
|
15
|
+
function ChangeCustomer({ className, data, error, filter = '', isLoading = false, onCustomerSelected, onCustomerSelectionChanged, onFilterChanged, selectedId, }) {
|
|
16
|
+
const t = useFormattedMessage();
|
|
17
|
+
const listBoxRef = useRef(null);
|
|
18
|
+
const hasMoreResults = !isLoading &&
|
|
19
|
+
data?.pagination &&
|
|
20
|
+
data.pagination.totalItemCount > DEFAULT_PAGE_SIZE;
|
|
21
|
+
const listBoxItems = useMemo(() => {
|
|
22
|
+
const listBoxItems = [...(data?.billTos || [])];
|
|
23
|
+
if (error instanceof UnauthorizedRequestError) {
|
|
24
|
+
listBoxItems.push({
|
|
25
|
+
id: 'message',
|
|
26
|
+
message: t('You are not authorized to view customers. Please log in or contact support.'),
|
|
27
|
+
type: 'danger',
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
else if (error) {
|
|
31
|
+
listBoxItems.push({
|
|
32
|
+
id: 'message',
|
|
33
|
+
message: t('An error occurred while fetching customers. Please try again later.'),
|
|
34
|
+
type: 'danger',
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
else if (hasMoreResults) {
|
|
38
|
+
listBoxItems.push({
|
|
39
|
+
id: 'message',
|
|
40
|
+
message: t('There are more customers, please refine your search if needed.'),
|
|
41
|
+
type: 'warning',
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return listBoxItems;
|
|
45
|
+
}, [data?.billTos, error, hasMoreResults, t]);
|
|
46
|
+
return (jsxs("div", { className: clsx(styles['change-customer-container'], className), children: [jsx(SearchField, { autoFocus: true, isDebounced: true, "aria-controls": "filtered-customer-results-list", isLoading: isLoading, label: t('Search for a customer'), onChange: onFilterChanged, onKeyUp: ({ key }) => {
|
|
47
|
+
if (key === 'ArrowDown') {
|
|
48
|
+
listBoxRef.current?.focus();
|
|
49
|
+
}
|
|
50
|
+
}, placeholder: t('Search for a customer'), showLabel: false, size: "md", value: filter, variant: "outline" }), jsx(ListBox, { ref: listBoxRef, "aria-label": "List of customers", "aria-live": "polite", className: styles['list-box'], id: "filtered-customer-results-list", items: listBoxItems, onAction: key => onCustomerSelected?.(String(key)), onSelectionChange: keys => onCustomerSelectionChanged?.(String([...keys][0])), renderEmptyState: () => !isLoading && (jsx(Message, { type: "info", children: jsx(FormattedMessage, { id: "No results found. Please refine your search." }) })), selectionBehavior: "replace", selectionMode: "single", children: listBoxItem => 'type' in listBoxItem ? (jsx(ListBoxItem, { isDisabled: true, children: jsx(Message, { type: listBoxItem.type, children: listBoxItem.message }) }, "marker")) : (jsxs(ListBoxItem, { className: styles['list-box-item'], id: listBoxItem.id, children: [jsxs(Text, { slot: "label", children: [jsxs("div", { className: styles['company-name'], children: [jsx(HighlightText, { className: styles['company-name-text'], highlightText: filter, text: `${listBoxItem.companyName}` }), selectedId === listBoxItem.id && (jsx(SolidRatingIcon, { className: styles['selected-icon'] }))] }), jsx(HighlightText, { className: styles['customer-number'], highlightText: filter, text: `${listBoxItem.customerNumber}` })] }), jsxs(Text, { slot: "description", children: [jsx("div", { children: jsx(HighlightText, { highlightText: filter, text: [
|
|
51
|
+
[listBoxItem.firstName, listBoxItem.lastName].join(' '),
|
|
52
|
+
]
|
|
53
|
+
.filter(Boolean)
|
|
54
|
+
.join(', ') }) }), jsx("div", { children: jsx(HighlightText, { highlightText: filter, text: [
|
|
55
|
+
listBoxItem.address1,
|
|
56
|
+
listBoxItem.address2,
|
|
57
|
+
listBoxItem.address3,
|
|
58
|
+
listBoxItem.address4,
|
|
59
|
+
]
|
|
60
|
+
.filter(Boolean)
|
|
61
|
+
.join(', ') }) }), jsx(HighlightText, { highlightText: filter, text: [listBoxItem.postalCode, listBoxItem.country?.name]
|
|
62
|
+
.filter(Boolean)
|
|
63
|
+
.join(', ') })] })] }, listBoxItem.id)) })] }));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { ChangeCustomer };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
var styles = {"change-customer-container":"change-customer-module-2kOw4","list-box":"change-customer-module-StfiY","list-box-item":"change-customer-module-P7ouY","company-name":"change-customer-module-DSVPN","company-name-text":"change-customer-module-4KQoq","customer-number":"change-customer-module-4p6ab"};
|
|
2
|
+
|
|
3
|
+
export { styles as default };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { usePatchSession } from '../../../../shared/api/storefront/hooks/authentication/use-patch-session.js';
|
|
4
|
+
import { useFetchBillToAddresses } from '../../../../shared/api/storefront/hooks/customer/use-fetch-bill-to-addresses.js';
|
|
5
|
+
import { ChangeCustomerDialog } from './change-customer-dialog.js';
|
|
6
|
+
|
|
7
|
+
function ConnectedChangeCustomerDialog({ currentlySelectedCustomerId, isOpen, onClose, onCustomerSelected, }) {
|
|
8
|
+
const [filter, setFilter] = useState('');
|
|
9
|
+
const { error: errorMutation, isLoading: isMutating, mutate, } = usePatchSession();
|
|
10
|
+
const { data, error, isFetching, isLoading } = useFetchBillToAddresses({
|
|
11
|
+
filter,
|
|
12
|
+
isEnabled: isOpen,
|
|
13
|
+
});
|
|
14
|
+
return (jsx(ChangeCustomerDialog, { currentlySelectedCustomerId: currentlySelectedCustomerId, data: data, error: error, filter: filter, hasErrorSubmitting: Boolean(errorMutation), isLoading: isLoading || isFetching, isOpen: isOpen, isUpdating: isMutating, onClose: onClose, onCustomerSelected: async (id) => {
|
|
15
|
+
id = `${id}`;
|
|
16
|
+
try {
|
|
17
|
+
await mutate({
|
|
18
|
+
session: {
|
|
19
|
+
billTo: {
|
|
20
|
+
id,
|
|
21
|
+
isDefault: false,
|
|
22
|
+
},
|
|
23
|
+
billToId: id,
|
|
24
|
+
customerWasUpdated: false,
|
|
25
|
+
fulfillmentMethod: 'Ship',
|
|
26
|
+
pickUpWarehouse: null,
|
|
27
|
+
shipTo: { id },
|
|
28
|
+
shipToId: id,
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
onCustomerSelected(id);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Handle error if needed
|
|
35
|
+
}
|
|
36
|
+
}, onFilterChanged: setFilter }));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { ConnectedChangeCustomerDialog };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ConnectedMySonicNavigation(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -6,10 +6,10 @@ import { useIsBreakpoint } from '../../../shared/hooks/use-is-breakpoint.js';
|
|
|
6
6
|
import { useLocation } from '../../../shared/routing/use-location.js';
|
|
7
7
|
import { useNavigate } from '../../../shared/routing/use-navigate.js';
|
|
8
8
|
import { PATHS } from '../../paths.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { MySonicDesktopNavigation } from './my-sonic-desktop-navigation.js';
|
|
10
|
+
import { MySonicMobileNavigation } from './my-sonic-mobile-navigation.js';
|
|
11
11
|
|
|
12
|
-
function
|
|
12
|
+
function ConnectedMySonicNavigation() {
|
|
13
13
|
const isXl = useIsBreakpoint('xl');
|
|
14
14
|
const { pathname } = useLocation();
|
|
15
15
|
const { navigate } = useNavigate();
|
|
@@ -21,7 +21,7 @@ function ConnectedMyAccountNavigation() {
|
|
|
21
21
|
navigate(PATHS.HOME, { reload: true });
|
|
22
22
|
},
|
|
23
23
|
});
|
|
24
|
-
return (jsx("div", { style: { display: 'grid' }, children: isXl ? (jsx(
|
|
24
|
+
return (jsx("div", { style: { display: 'grid' }, children: isXl ? (jsx(MySonicDesktopNavigation, { currentPath: pathname, onLogout: mutate })) : (jsx(MySonicMobileNavigation, { currentPath: pathname, onLogout: mutate })) }));
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export {
|
|
27
|
+
export { ConnectedMySonicNavigation };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { FormattedMessage } from '../../../intl/formatted-message.js';
|
|
3
|
+
import { MenuList } from '../../../lists/menu-list/menu-list.js';
|
|
4
|
+
import { MenuListItem } from '../../../lists/menu-list/menu-list-item.js';
|
|
5
|
+
import { mySonicNavigationItems } from './my-sonic-navigation-items.js';
|
|
6
|
+
import styles from './my-sonic-desktop-navigation.module.css.js';
|
|
7
|
+
|
|
8
|
+
function MySonicDesktopNavigation({ currentPath, onLogout, }) {
|
|
9
|
+
return (jsx(MenuList, { children: mySonicNavigationItems.map(item => (jsx(MenuListItem, { hasChildren: true, badge: jsx(item.Icon, {}), ...(item.type === 'action'
|
|
10
|
+
? item.action === 'logout'
|
|
11
|
+
? { onClick: onLogout }
|
|
12
|
+
: {}
|
|
13
|
+
: {
|
|
14
|
+
href: item.path,
|
|
15
|
+
isSelected: currentPath?.toLowerCase() === item.path,
|
|
16
|
+
}), children: jsx("span", { className: styles['menu-list-item'], children: jsx(FormattedMessage, { id: item.label }) }) }, item.label))) }));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { MySonicDesktopNavigation };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Select } from '../../../forms/select/select.js';
|
|
3
|
+
import { useFormattedMessage } from '../../../intl/use-formatted-message.js';
|
|
4
|
+
import { useNavigate } from '../../../shared/routing/use-navigate.js';
|
|
5
|
+
import { mySonicNavigationItems } from './my-sonic-navigation-items.js';
|
|
6
|
+
|
|
7
|
+
function MySonicMobileNavigation({ currentPath, onLogout, }) {
|
|
8
|
+
const { navigate } = useNavigate();
|
|
9
|
+
const t = useFormattedMessage();
|
|
10
|
+
return (jsx(Select, { label: t('Navigate to...'), onChange: option => {
|
|
11
|
+
if (option === 'logout')
|
|
12
|
+
return onLogout();
|
|
13
|
+
return navigate(option);
|
|
14
|
+
}, options: mySonicNavigationItems.reduce((options, item) => ({
|
|
15
|
+
...options,
|
|
16
|
+
...(item.type === 'link'
|
|
17
|
+
? { [item.path]: t(item.label) }
|
|
18
|
+
: { [item.action]: t(item.label) }),
|
|
19
|
+
}), {}), selectedOption: currentPath?.toLowerCase() }));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { MySonicMobileNavigation };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ComponentType } from 'react';
|
|
2
|
+
import { TranslationId } from '../../../intl/translation-id';
|
|
3
|
+
interface MySonicNavigationItemBase {
|
|
4
|
+
Icon: ComponentType;
|
|
5
|
+
label: TranslationId;
|
|
6
|
+
type: 'link' | 'action';
|
|
7
|
+
}
|
|
8
|
+
interface MySonicNavigationLink extends MySonicNavigationItemBase {
|
|
9
|
+
path: Lowercase<string>;
|
|
10
|
+
type: 'link';
|
|
11
|
+
}
|
|
12
|
+
interface MySonicNavigationAction extends MySonicNavigationItemBase {
|
|
13
|
+
action: string;
|
|
14
|
+
type: 'action';
|
|
15
|
+
}
|
|
16
|
+
type MySonicNavigationItem = MySonicNavigationLink | MySonicNavigationAction;
|
|
17
|
+
export declare const mySonicNavigationItems: MySonicNavigationItem[];
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { SolidCartIcon } from '../../../icons/solid/solid-cart-icon.js';
|
|
2
|
+
import { SolidFavoriteIcon } from '../../../icons/solid/solid-favorite-icon.js';
|
|
3
|
+
import { SolidLoginIcon } from '../../../icons/solid/solid-login-icon.js';
|
|
4
|
+
import { SolidLogOutIcon } from '../../../icons/solid/solid-logout-icon.js';
|
|
5
|
+
import { PATHS } from '../../paths.js';
|
|
6
|
+
|
|
7
|
+
const mySonicNavigationItems = [
|
|
8
|
+
{
|
|
9
|
+
Icon: SolidLoginIcon,
|
|
10
|
+
label: 'Account',
|
|
11
|
+
path: PATHS.ACCOUNT_SETTINGS.toLowerCase(),
|
|
12
|
+
type: 'link',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
Icon: SolidFavoriteIcon,
|
|
16
|
+
label: 'Favorites',
|
|
17
|
+
path: PATHS.ACCOUNT_MY_LISTS.toLowerCase(),
|
|
18
|
+
type: 'link',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
Icon: SolidCartIcon,
|
|
22
|
+
label: 'Orders',
|
|
23
|
+
path: PATHS.ACCOUNT_ORDERS.toLowerCase(),
|
|
24
|
+
type: 'link',
|
|
25
|
+
},
|
|
26
|
+
{ Icon: SolidLogOutIcon, action: 'logout', label: 'Log out', type: 'action' },
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
export { mySonicNavigationItems };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ConnectedCustomerInformationWidget(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Button } from '../../../buttons/button/button.js';
|
|
4
|
+
import { DataCard } from '../../../cards/data-card/data-card.js';
|
|
5
|
+
import { FormattedMessage } from '../../../intl/formatted-message.js';
|
|
6
|
+
import { useFetchBillToAddresses } from '../../../shared/api/storefront/hooks/customer/use-fetch-bill-to-addresses.js';
|
|
7
|
+
import { useFetchCurrentBillToAddress } from '../../../shared/api/storefront/hooks/customer/use-fetch-current-bill-to-address.js';
|
|
8
|
+
import { ConnectedChangeCustomerDialog } from '../actions/change-customer/connected-change-customer-dialog.js';
|
|
9
|
+
|
|
10
|
+
function ConnectedCustomerInformationWidget() {
|
|
11
|
+
const [isOpenChangeCustomerDialog, setIsOpenChangeCustomerDialog] = useState(false);
|
|
12
|
+
const { data: billToAddress, error: fetchBillToAddressError, isLoading: isLoadingFetchCurrentBillToAddress, } = useFetchCurrentBillToAddress();
|
|
13
|
+
const { data: billToAddresses, error: fetchBillToAddressesError, isLoading: isLoadingFetchBillToAddresses, } = useFetchBillToAddresses();
|
|
14
|
+
const hasBillToAddresses = Boolean(billToAddresses?.pagination?.totalItemCount);
|
|
15
|
+
const data = billToAddress
|
|
16
|
+
? [
|
|
17
|
+
{
|
|
18
|
+
key: 'company-name',
|
|
19
|
+
label: 'Company name',
|
|
20
|
+
value: billToAddress.companyName,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
key: 'coc-number',
|
|
24
|
+
label: 'CoC number',
|
|
25
|
+
value: billToAddress.properties.cocRegistration,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
key: 'billing',
|
|
29
|
+
label: 'Billing',
|
|
30
|
+
value: [
|
|
31
|
+
billToAddress.address1,
|
|
32
|
+
billToAddress.address2,
|
|
33
|
+
billToAddress.address3,
|
|
34
|
+
billToAddress.address4,
|
|
35
|
+
billToAddress.postalCode,
|
|
36
|
+
billToAddress.city,
|
|
37
|
+
billToAddress.country?.abbreviation,
|
|
38
|
+
]
|
|
39
|
+
.filter(Boolean)
|
|
40
|
+
.join(', ') || null,
|
|
41
|
+
},
|
|
42
|
+
]
|
|
43
|
+
: [];
|
|
44
|
+
function onChangeCustomer() {
|
|
45
|
+
setIsOpenChangeCustomerDialog(true);
|
|
46
|
+
}
|
|
47
|
+
return (jsxs(Fragment, { children: [jsx(DataCard, { actions: hasBillToAddresses
|
|
48
|
+
? [
|
|
49
|
+
jsx(Button, { color: "secondary", onClick: onChangeCustomer, size: "sm", variant: "outline", children: jsx(FormattedMessage, { id: "Select other customer" }) }, "edit"),
|
|
50
|
+
]
|
|
51
|
+
: undefined, data: data, "data-test-selector": "customer-information-widget", isLoading: isLoadingFetchCurrentBillToAddress || isLoadingFetchBillToAddresses, showError: fetchBillToAddressError || fetchBillToAddressesError, title: "Selected customer" }), hasBillToAddresses && (jsx(ConnectedChangeCustomerDialog, { isOpen: isOpenChangeCustomerDialog, onClose: () => setIsOpenChangeCustomerDialog(false), onCustomerSelected: () => {
|
|
52
|
+
window?.location.reload();
|
|
53
|
+
} }, billToAddress?.id))] }));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { ConnectedCustomerInformationWidget };
|
package/dist/pages/product/layouts/product-details-page-layout/product-details-page-layout.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ interface ProductDetailsPageLayoutProps {
|
|
|
2
2
|
imageGallery?: React.ReactNode;
|
|
3
3
|
included?: React.ReactNode;
|
|
4
4
|
productInformation?: React.ReactNode;
|
|
5
|
-
|
|
5
|
+
recentlyViewedSection?: React.ReactNode;
|
|
6
6
|
usp?: React.ReactNode;
|
|
7
7
|
}
|
|
8
|
-
export declare function ProductDetailsPageLayout({ imageGallery, included, productInformation,
|
|
8
|
+
export declare function ProductDetailsPageLayout({ imageGallery, included, productInformation, recentlyViewedSection, usp, }: ProductDetailsPageLayoutProps): import("react/jsx-runtime").JSX.Element;
|
|
9
9
|
export {};
|
package/dist/pages/product/layouts/product-details-page-layout/product-details-page-layout.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { IntersectionObserverComponent } from '../../../../observers/intersection-observer.js';
|
|
2
3
|
import styles from './product-details-page-layout.module.css.js';
|
|
3
4
|
|
|
4
|
-
function ProductDetailsPageLayout({ imageGallery, included, productInformation,
|
|
5
|
-
return (jsxs("div", { className: styles['product-details-page-layout'], children: [jsxs("section", { className: styles.top, children: [jsx("div", { className: styles['image-gallery'], children: imageGallery }), jsx("div", { className: styles['product-information'], "data-test-selector": "productInformation", children: productInformation })] }), jsx("section", { className: styles.usp, "data-test-selector": "usp", children: usp }), jsx("section", { className: styles.included, "data-test-selector": "included", children: included }), jsx(
|
|
5
|
+
function ProductDetailsPageLayout({ imageGallery, included, productInformation, recentlyViewedSection, usp, }) {
|
|
6
|
+
return (jsxs("div", { className: styles['product-details-page-layout'], children: [jsxs("section", { className: styles.top, children: [jsx("div", { className: styles['image-gallery'], children: imageGallery }), jsx("div", { className: styles['product-information'], "data-test-selector": "productInformation", children: productInformation })] }), usp && (jsx("section", { className: styles.usp, "data-test-selector": "usp", children: usp })), included && (jsx("section", { className: styles.included, "data-test-selector": "included", children: included })), jsx(IntersectionObserverComponent, { isPlaceholder: true, intersectionObserverInit: { rootMargin: '400px' }, children: recentlyViewedSection })] }));
|
|
6
7
|
}
|
|
7
8
|
|
|
8
9
|
export { ProductDetailsPageLayout };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var styles = {"product-details-page-layout":"product-details-page-layout-module-pPtZX","top":"product-details-page-layout-module-KCKLZ","image-gallery":"product-details-page-layout-module-0uf92","product-information":"product-details-page-layout-module-3-19O","
|
|
1
|
+
var styles = {"product-details-page-layout":"product-details-page-layout-module-pPtZX","top":"product-details-page-layout-module-KCKLZ","image-gallery":"product-details-page-layout-module-0uf92","product-information":"product-details-page-layout-module-3-19O","included":"product-details-page-layout-module-lfAgH","usp":"product-details-page-layout-module-e8ZNQ"};
|
|
2
2
|
|
|
3
3
|
export { styles as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ProductDetailsRecentlyViewedSection(): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { ConnectedProductCard } from '../../../../../cards/product-card/connected-product-card.js';
|
|
3
|
+
import { CardCarousel } from '../../../../../carousel/card-carousel/card-carousel.js';
|
|
4
|
+
import { FormattedMessage } from '../../../../../intl/formatted-message.js';
|
|
5
|
+
import { useCultureCode } from '../../../../../intl/use-culture-code.js';
|
|
6
|
+
import { useFetchRecentlyViewedProducts } from '../../../../../shared/api/bff/hooks/use-fetch-recently-viewed-products.js';
|
|
7
|
+
import { Heading } from '../../../../../typography/heading/heading.js';
|
|
8
|
+
import styles from './product-details-recently-viewed-section.module.css.js';
|
|
9
|
+
|
|
10
|
+
function ProductDetailsRecentlyViewedSection() {
|
|
11
|
+
const cultureCode = useCultureCode();
|
|
12
|
+
const { data: products, isLoading } = useFetchRecentlyViewedProducts({
|
|
13
|
+
cultureCode,
|
|
14
|
+
});
|
|
15
|
+
if (isLoading || !products || products.length === 0)
|
|
16
|
+
return null;
|
|
17
|
+
return (jsxs("section", { className: styles['recently-viewed'], "data-test-selector": "recentlyViewed", children: [jsx(Heading, { size: "s", tag: "h2", children: jsx(FormattedMessage, { id: "Recently viewed" }) }), jsx(CardCarousel, { hasOverflow: true, cards: products.map(product => (jsx(ConnectedProductCard, { href: product.href, id: product.productId, image: {
|
|
18
|
+
fit: 'contain',
|
|
19
|
+
image: product.image,
|
|
20
|
+
title: product.image?.altText || product.title,
|
|
21
|
+
}, price: product.price, sku: product.sku, tags: product.tags, title: product.title }, product.productId))) })] }));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { ProductDetailsRecentlyViewedSection };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ProductDetailsPageDataResponse } from '../../../shared/api/bff/model/bff.model';
|
|
2
|
-
export declare function ProductDetails({ data, priceComponent,
|
|
2
|
+
export declare function ProductDetails({ data, priceComponent, }: {
|
|
3
3
|
data: ProductDetailsPageDataResponse;
|
|
4
4
|
priceComponent?: React.ReactNode;
|
|
5
|
-
recentlyViewedComponent?: React.ReactNode;
|
|
6
5
|
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -10,10 +10,10 @@ import { Page } from '../../components/page/page.js';
|
|
|
10
10
|
import { ProductDetailsPageLayout } from '../layouts/product-details-page-layout/product-details-page-layout.js';
|
|
11
11
|
import { ProductDetailImages } from './components/product-details-images/product-detail-images.js';
|
|
12
12
|
import { ProductDetailsPanel } from './components/product-details-panel/product-details-panel.js';
|
|
13
|
-
import {
|
|
13
|
+
import { ProductDetailsRecentlyViewedSection } from './components/product-details-recently-viewed-section/product-details-recently-viewed-section.js';
|
|
14
14
|
|
|
15
|
-
function ProductDetails({ data, priceComponent,
|
|
16
|
-
const { breadCrumb, included, page, product,
|
|
15
|
+
function ProductDetails({ data, priceComponent, }) {
|
|
16
|
+
const { breadCrumb, included, page, product, usps } = data;
|
|
17
17
|
useDataLayer({
|
|
18
18
|
event: {
|
|
19
19
|
event: 'view_item',
|
|
@@ -31,8 +31,7 @@ function ProductDetails({ data, priceComponent, recentlyViewedComponent, }) {
|
|
|
31
31
|
fit: 'contain',
|
|
32
32
|
image: product.image,
|
|
33
33
|
title: product.image?.altText || product.title,
|
|
34
|
-
}, price: product.price, sku: product.sku, tags: product.tags, title: product.title }, product.storefrontId))) })] })), productInformation: jsx(ProductDetailsPanel, { priceComponent: priceComponent, product: product }),
|
|
35
|
-
(recentlyViewed.length > 0 && (jsx(ProductDetailsRecentlyViewed, { recentlyViewed: recentlyViewed }))), usp: usps && jsx(ProductUSPCarousel, { usps: usps }) }) }));
|
|
34
|
+
}, price: product.price, sku: product.sku, tags: product.tags, title: product.title }, product.storefrontId))) })] })), productInformation: jsx(ProductDetailsPanel, { priceComponent: priceComponent, product: product }), recentlyViewedSection: jsx(ProductDetailsRecentlyViewedSection, {}), usp: usps && usps.length > 0 && jsx(ProductUSPCarousel, { usps: usps }) }) }));
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
export { ProductDetails };
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import { useQuery } from '@tanstack/react-query';
|
|
1
|
+
import { useQueryClient, useQuery } from '@tanstack/react-query';
|
|
2
2
|
import { TIME } from '../../../utils/time.js';
|
|
3
3
|
import { fetchProductDetailsPageData } from '../services/bff-service.js';
|
|
4
4
|
|
|
5
5
|
function useFetchProductDetailsPageData(args) {
|
|
6
|
+
const queryClient = useQueryClient();
|
|
6
7
|
return useQuery({
|
|
7
8
|
gcTime: 1 * TIME.DAY,
|
|
8
|
-
queryFn: () =>
|
|
9
|
+
queryFn: () => {
|
|
10
|
+
queryClient.removeQueries({ queryKey: ['products', 'recently-viewed'] });
|
|
11
|
+
return fetchProductDetailsPageData(args);
|
|
12
|
+
},
|
|
9
13
|
queryKey: ['product-details-page-data', args.pageUrl, args.cultureCode],
|
|
10
14
|
staleTime: 1 * TIME.DAY,
|
|
11
15
|
});
|