@sonic-equipment/ui 184.0.0 → 185.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/cards/data-card/data-card.js +37 -20
- package/dist/cards/data-card/data-card.module.css.js +1 -1
- package/dist/country-selector/country-selector-dialog/country-selector-dialog.js +1 -5
- package/dist/exports.d.ts +20 -2
- package/dist/forms/form/form.d.ts +7 -3
- package/dist/forms/form/form.js +2 -2
- package/dist/forms/password-validation/password-validation.d.ts +4 -0
- package/dist/forms/password-validation/password-validation.js +32 -0
- package/dist/forms/select/select.d.ts +2 -1
- package/dist/forms/select/select.js +2 -2
- package/dist/index.js +21 -3
- package/dist/intl/translation-id.d.ts +1 -1
- package/dist/intl/use-formatted-message.js +2 -1
- package/dist/lists/menu-list/menu-list.d.ts +2 -1
- package/dist/lists/menu-list/menu-list.js +2 -2
- package/dist/lists/widget-grid/widget-grid.d.ts +5 -0
- package/dist/lists/widget-grid/widget-grid.js +9 -0
- package/dist/lists/widget-grid/widget-grid.module.css.js +3 -0
- package/dist/lists/widget-grid/widget.d.ts +6 -0
- package/dist/lists/widget-grid/widget.js +10 -0
- package/dist/modals/dialog/dialog.d.ts +5 -5
- package/dist/modals/dialog/dialog.js +18 -18
- package/dist/modals/dialog/dialog.module.css.js +1 -1
- package/dist/modals/recover-password/recover-password-dialog.js +1 -3
- package/dist/pages/account/components/create-account-form/create-account-form.js +2 -17
- package/dist/pages/account/create-account-page/create-account-page.js +4 -5
- package/dist/pages/account/layouts/sign-in-page-layout/sign-in-page-layout.js +1 -1
- package/dist/pages/account/sign-in-page/sign-in-page.js +2 -3
- package/dist/pages/checkout/shipping-page/hooks/use-patch-shipping-details.d.ts +1 -0
- package/dist/pages/components/page-container/page-container.js +1 -1
- package/dist/pages/my-sonic/actions/change-customer/change-customer-dialog.d.ts +4 -3
- package/dist/pages/my-sonic/actions/change-customer/change-customer-dialog.js +10 -4
- package/dist/pages/my-sonic/actions/change-customer/change-customer.d.ts +5 -2
- package/dist/pages/my-sonic/actions/change-customer/change-customer.js +16 -7
- package/dist/pages/my-sonic/actions/change-customer/change-customer.module.css.js +1 -1
- package/dist/pages/my-sonic/actions/change-customer/connected-change-customer-dialog.d.ts +7 -2
- package/dist/pages/my-sonic/actions/change-customer/connected-change-customer-dialog.js +9 -6
- package/dist/pages/my-sonic/actions/change-password/change-password-dialog.d.ts +10 -0
- package/dist/pages/my-sonic/actions/change-password/change-password-dialog.js +24 -0
- package/dist/pages/my-sonic/actions/change-password/change-password.d.ts +7 -0
- package/dist/pages/my-sonic/actions/change-password/change-password.js +35 -0
- package/dist/pages/my-sonic/actions/change-password/change-password.module.css.js +3 -0
- package/dist/pages/my-sonic/actions/change-password/connected-change-password-dialog.d.ts +5 -0
- package/dist/pages/my-sonic/actions/change-password/connected-change-password-dialog.js +39 -0
- package/dist/pages/my-sonic/actions/edit-user-info/connected-edit-user-info-dialog.d.ts +5 -0
- package/dist/pages/my-sonic/actions/edit-user-info/connected-edit-user-info-dialog.js +56 -0
- package/dist/pages/my-sonic/actions/edit-user-info/edit-user-info-dialog.d.ts +10 -0
- package/dist/pages/my-sonic/actions/edit-user-info/edit-user-info-dialog.js +15 -0
- package/dist/pages/my-sonic/actions/edit-user-info/edit-user-info.d.ts +11 -0
- package/dist/pages/my-sonic/actions/edit-user-info/edit-user-info.js +29 -0
- package/dist/pages/my-sonic/actions/edit-user-info/edit-user-info.module.css.js +3 -0
- package/dist/pages/my-sonic/layouts/my-sonic-layout/my-sonic-layout-aside.d.ts +4 -0
- package/dist/pages/my-sonic/layouts/my-sonic-layout/my-sonic-layout-aside.js +9 -0
- package/dist/pages/my-sonic/layouts/my-sonic-layout/my-sonic-layout-main.d.ts +4 -0
- package/dist/pages/my-sonic/layouts/my-sonic-layout/my-sonic-layout-main.js +9 -0
- package/dist/pages/my-sonic/layouts/my-sonic-layout/my-sonic-layout-page.d.ts +5 -0
- package/dist/pages/my-sonic/layouts/my-sonic-layout/my-sonic-layout-page.js +10 -0
- package/dist/pages/my-sonic/layouts/my-sonic-layout/my-sonic-layout-pre-aside.d.ts +4 -0
- package/dist/pages/my-sonic/layouts/my-sonic-layout/my-sonic-layout-pre-aside.js +9 -0
- package/dist/pages/my-sonic/layouts/my-sonic-layout/my-sonic-layout-title.d.ts +4 -0
- package/dist/pages/my-sonic/layouts/my-sonic-layout/my-sonic-layout-title.js +10 -0
- package/dist/pages/my-sonic/layouts/my-sonic-layout/my-sonic-layout.d.ts +5 -0
- package/dist/pages/my-sonic/layouts/my-sonic-layout/my-sonic-layout.js +10 -0
- package/dist/pages/my-sonic/layouts/my-sonic-layout/my-sonic-layout.module.css.js +3 -0
- package/dist/pages/my-sonic/navigation/connected-my-sonic-navigation.js +3 -4
- package/dist/pages/my-sonic/navigation/connected-my-sonic-navigation.module.css.js +3 -0
- package/dist/pages/my-sonic/navigation/my-sonic-desktop-navigation.d.ts +2 -1
- package/dist/pages/my-sonic/navigation/my-sonic-desktop-navigation.js +2 -2
- package/dist/pages/my-sonic/navigation/my-sonic-mobile-navigation.d.ts +2 -1
- package/dist/pages/my-sonic/navigation/my-sonic-mobile-navigation.js +2 -2
- package/dist/pages/my-sonic/widgets/connected-customer-information-widget.js +3 -3
- package/dist/pages/my-sonic/widgets/connected-user-account-widget.js +16 -5
- package/dist/shared/api/shared/hooks/use-awaitable-mutation.d.ts +1 -0
- package/dist/shared/api/shared/hooks/use-awaitable-mutation.js +6 -0
- package/dist/shared/api/storefront/hooks/{authentication → account}/use-create-account.d.ts +1 -1
- package/dist/shared/api/storefront/hooks/{authentication → account}/use-create-account.js +3 -1
- package/dist/shared/api/storefront/hooks/{authentication → account}/use-create-guest-account.js +3 -1
- package/dist/shared/api/storefront/hooks/account/use-fetch-current-account.d.ts +3 -0
- package/dist/shared/api/storefront/hooks/account/use-fetch-current-account.js +13 -0
- package/dist/shared/api/storefront/hooks/account/use-patch-current-account.d.ts +11 -0
- package/dist/shared/api/storefront/hooks/account/use-patch-current-account.js +20 -0
- package/dist/shared/api/storefront/hooks/authentication/use-patch-session.d.ts +1 -0
- package/dist/shared/api/storefront/hooks/authentication/use-patch-session.js +1 -1
- package/dist/shared/api/storefront/hooks/cart/use-patch-cart.d.ts +1 -0
- package/dist/shared/api/storefront/hooks/cart/use-place-order.d.ts +1 -0
- package/dist/shared/api/storefront/hooks/customer/use-patch-bill-to-address.d.ts +1 -0
- package/dist/shared/api/storefront/services/account-service.d.ts +31 -0
- package/dist/shared/api/storefront/services/account-service.js +84 -0
- package/dist/shared/api/storefront/services/authentication-service.d.ts +7 -26
- package/dist/shared/api/storefront/services/authentication-service.js +38 -65
- package/dist/styles.css +351 -240
- package/package.json +1 -1
- /package/dist/shared/api/storefront/hooks/{authentication → account}/use-create-guest-account.d.ts +0 -0
|
@@ -17,9 +17,7 @@ function RecoverPasswordDialog({ isOpen, onOpenChange, }) {
|
|
|
17
17
|
reset();
|
|
18
18
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
19
19
|
}, [isOpen]);
|
|
20
|
-
const onSubmit = (
|
|
21
|
-
const form = event.currentTarget;
|
|
22
|
-
const formData = new FormData(form);
|
|
20
|
+
const onSubmit = ({ formData }) => {
|
|
23
21
|
const email = formData.get('email')?.toString();
|
|
24
22
|
if (!email)
|
|
25
23
|
throw new Error('Email value is required');
|
|
@@ -7,12 +7,11 @@ 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 {
|
|
10
|
+
import { PasswordValidation } from '../../../../forms/password-validation/password-validation.js';
|
|
11
11
|
import { SwitchField } from '../../../../forms/switch-field/switch-field.js';
|
|
12
12
|
import { TextField } from '../../../../forms/text-field/text-field.js';
|
|
13
13
|
import { isCountryCode } from '../../../../intl/types.js';
|
|
14
14
|
import { useFormattedMessage } from '../../../../intl/use-formatted-message.js';
|
|
15
|
-
import { validatePassword } from '../../../../shared/model/account.js';
|
|
16
15
|
import { validateEmail } from '../../../../shared/model/address.js';
|
|
17
16
|
import { Heading } from '../../../../typography/heading/heading.js';
|
|
18
17
|
import styles from './create-account-form.module.css.js';
|
|
@@ -22,8 +21,6 @@ function CreateAccountForm({ errorType, isDisabled: _isDisabled = false, isPendi
|
|
|
22
21
|
const title = t('create account');
|
|
23
22
|
const isDisabled = isPendingCreateAccount || _isDisabled;
|
|
24
23
|
const [isPrivateAccount, setIsPrivateAccount] = useState(false);
|
|
25
|
-
const [password, setPassword] = useState('');
|
|
26
|
-
const [passwordConfirm, setPasswordConfirm] = useState('');
|
|
27
24
|
const [lastName, setLastName] = useState('');
|
|
28
25
|
const [companyName, setCompanyName] = useState('');
|
|
29
26
|
const errorMessages = {
|
|
@@ -64,13 +61,6 @@ function CreateAccountForm({ errorType, isDisabled: _isDisabled = false, isPendi
|
|
|
64
61
|
},
|
|
65
62
|
});
|
|
66
63
|
};
|
|
67
|
-
const isMismatchingPasswords = () => {
|
|
68
|
-
if (!passwordConfirm)
|
|
69
|
-
return;
|
|
70
|
-
if (passwordConfirm === password)
|
|
71
|
-
return false;
|
|
72
|
-
return true;
|
|
73
|
-
};
|
|
74
64
|
// form header
|
|
75
65
|
const header = (jsx(Heading, { "data-test-selector": "PageTitle", italic: true, size: "m", tag: "h1", uppercase: true, children: title }));
|
|
76
66
|
// form footer
|
|
@@ -79,12 +69,7 @@ function CreateAccountForm({ errorType, isDisabled: _isDisabled = false, isPendi
|
|
|
79
69
|
if (!value)
|
|
80
70
|
return value;
|
|
81
71
|
return (validateEmail(value) || t('Please enter a valid email address'));
|
|
82
|
-
} }) }), jsx(FormSegment, { children: jsx(
|
|
83
|
-
if (!value)
|
|
84
|
-
return;
|
|
85
|
-
return (validatePassword(value) ||
|
|
86
|
-
t('Password does not meet requirements'));
|
|
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') }) }) })] }));
|
|
72
|
+
} }) }), jsx(PasswordValidation, { isDisabled: isDisabled })] }), 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') }) }) })] }));
|
|
88
73
|
}
|
|
89
74
|
|
|
90
75
|
export { CreateAccountForm };
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import { useMemo } from 'react';
|
|
4
4
|
import { Button } from '../../../buttons/button/button.js';
|
|
5
5
|
import { FormattedMessage } from '../../../intl/formatted-message.js';
|
|
6
6
|
import { Dialog } from '../../../modals/dialog/dialog.js';
|
|
7
|
-
import { useCreateAccount } from '../../../shared/api/storefront/hooks/
|
|
7
|
+
import { useCreateAccount } from '../../../shared/api/storefront/hooks/account/use-create-account.js';
|
|
8
8
|
import { useFetchSession } from '../../../shared/api/storefront/hooks/authentication/use-fetch-session.js';
|
|
9
|
-
import { ExistingAccountError } from '../../../shared/api/storefront/services/
|
|
9
|
+
import { ExistingAccountError } from '../../../shared/api/storefront/services/account-service.js';
|
|
10
10
|
import { useNavigate } from '../../../shared/routing/use-navigate.js';
|
|
11
|
-
import { Page } from '../../components/page/page.js';
|
|
12
11
|
import { LoadingPage } from '../../loading-page/loading-page.js';
|
|
13
12
|
import { PATHS } from '../../paths.js';
|
|
14
13
|
import { CreateAccountForm } from '../components/create-account-form/create-account-form.js';
|
|
@@ -40,7 +39,7 @@ function CreateAccountPage({ returnUrl } = {}) {
|
|
|
40
39
|
navigate(continuePath, { reload: true });
|
|
41
40
|
return;
|
|
42
41
|
}
|
|
43
|
-
return (jsxs(
|
|
42
|
+
return (jsxs(Fragment, { children: [jsx(SignInPageLayout, { fullHeight: true, children: jsx(CreateAccountForm, { errorType: errorType, isDisabled: isDisabled, isPendingCreateAccount: isPendingCreateAccount, onSubmit: onSubmit }) }), jsx(Dialog, { footer: jsx(Button, { color: "primary", href: continuePath, route: { reload: true }, size: "md", withArrow: true, children: jsx(FormattedMessage, { id: "Continue" }) }), hasCloseButton: false, isDismissable: false, isKeyboardDismissDisabled: true, isOpen: isSuccess && !isReturnToShipping, title: "Account created", children: jsx("p", { children: jsx(FormattedMessage, { id: "Your new Sonic Equipment account was succesfully created. You should receive an email soon with further instructions on how to activate this account. If you do not receive this email, please contact Customer Support." }) }) }), jsx(Dialog, { footer: jsx(Button, { color: "primary", href: `${PATHS.SIGN_IN}${returnUrl ? `?returnUrl=${continuePath}` : ''}`, route: { reload: true }, size: "md", withArrow: true, children: jsx(FormattedMessage, { id: "Continue to sign in" }) }), hasCloseButton: false, isDismissable: false, isKeyboardDismissDisabled: true, isOpen: isExistingAccount, title: "Existing account", children: jsx("p", { children: jsx(FormattedMessage, { id: "The email address you entered is already associated with an existing account. Please sign in to this account or contact Customer Support." }) }) })] }));
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
export { CreateAccountPage };
|
|
@@ -8,7 +8,7 @@ import styles from './sign-in-page-layout.module.css.js';
|
|
|
8
8
|
|
|
9
9
|
function SignInPageLayout({ children, fullHeight, image = SIGN_IN_PAGE_BACKGROUND_IMAGE, }) {
|
|
10
10
|
const isLg = useIsBreakpoint('lg');
|
|
11
|
-
return (jsxs("div", { className: clsx(styles['sign-in-page-layout'], fullHeight && styles['full-height']), children: [jsx("
|
|
11
|
+
return (jsxs("div", { className: clsx(styles['sign-in-page-layout'], fullHeight && styles['full-height']), children: [jsx("section", { className: styles.main, children: children }), isLg && (jsx("div", { className: styles.side, children: jsx("div", { className: styles.image, children: jsx(Image, { image: image, title: "" }) }) }))] }));
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export { SignInPageLayout };
|
|
@@ -2,13 +2,12 @@
|
|
|
2
2
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import { useState, useMemo } from 'react';
|
|
4
4
|
import { RecoverPasswordDialog } from '../../../modals/recover-password/recover-password-dialog.js';
|
|
5
|
-
import { useCreateGuestAccount } from '../../../shared/api/storefront/hooks/
|
|
5
|
+
import { useCreateGuestAccount } from '../../../shared/api/storefront/hooks/account/use-create-guest-account.js';
|
|
6
6
|
import { useFetchSession } from '../../../shared/api/storefront/hooks/authentication/use-fetch-session.js';
|
|
7
7
|
import { useSignIn } from '../../../shared/api/storefront/hooks/authentication/use-sign-in.js';
|
|
8
8
|
import { isRequestError } from '../../../shared/fetch/request.js';
|
|
9
9
|
import { useDisclosure } from '../../../shared/hooks/use-disclosure.js';
|
|
10
10
|
import { useNavigate } from '../../../shared/routing/use-navigate.js';
|
|
11
|
-
import { Page } from '../../components/page/page.js';
|
|
12
11
|
import { PATHS } from '../../paths.js';
|
|
13
12
|
import { SignInForm } from '../components/sign-in-form/sign-in-form.js';
|
|
14
13
|
import { SignInPageLayout } from '../layouts/sign-in-page-layout/sign-in-page-layout.js';
|
|
@@ -57,7 +56,7 @@ function SignInPage({ returnUrl } = {}) {
|
|
|
57
56
|
const onRecoverPasswordDialogOpen = () => {
|
|
58
57
|
setRecoverPasswordDialogOpen(true);
|
|
59
58
|
};
|
|
60
|
-
return (jsxs(Fragment, { children: [jsx(
|
|
59
|
+
return (jsxs(Fragment, { children: [jsx(SignInPageLayout, { fullHeight: true, children: jsx(SignInForm, { allowGuestSignIn: allowGuestSignIn, createAccountPath: createAccountPath, errorType: errorType, initialEmail: session?.isGuest ? '' : session?.email, initialRememberMe: session?.rememberMe, isDisabled: !session || isSuccess, isPendingGuestSignIn: isPendingCreateGuest, isPendingUserSignIn: isPendingSignIn, onRecoverPasswordDialogOpen: onRecoverPasswordDialogOpen, onSubmit: onSubmit }) }), jsx(RecoverPasswordDialog, { isOpen: isRecoverPasswordDialogOpen, onOpenChange: isOpen => setRecoverPasswordDialogOpen(isOpen) })] }));
|
|
61
60
|
}
|
|
62
61
|
|
|
63
62
|
export { SignInPage };
|
|
@@ -4,7 +4,7 @@ import resetStyles from '../../../shared/reset.module.css.js';
|
|
|
4
4
|
import styles from './page-container.module.css.js';
|
|
5
5
|
|
|
6
6
|
function PageContainer({ breadcrumbSlot, children, className, 'data-test-selector': dataTestSelector, fluid, fullHeight, titleSlot, }) {
|
|
7
|
-
return (jsx("div", { className: clsx(styles['page-container'], resetStyles.reset, fullHeight && styles['full-height'], fluid && styles['fluid'], className), "data-test-selector": dataTestSelector, children: jsxs("
|
|
7
|
+
return (jsx("div", { className: clsx(styles['page-container'], resetStyles.reset, fullHeight && styles['full-height'], fluid && styles['fluid'], className), "data-test-selector": dataTestSelector, children: jsxs("div", { className: styles['page-main'], children: [breadcrumbSlot && (jsx("div", { className: styles.breadcrumb, children: breadcrumbSlot })), titleSlot && jsx("div", { className: styles.title, children: titleSlot }), jsx("div", { className: styles.content, children: children })] }) }));
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export { PageContainer };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { BillToCollectionModel } from '../../../../shared/api/storefront/model/storefront.model';
|
|
2
2
|
export interface ChangeCustomerDialogProps {
|
|
3
|
-
|
|
3
|
+
allowSetDefault?: boolean;
|
|
4
4
|
data?: BillToCollectionModel;
|
|
5
|
+
defaultCustomerId?: string;
|
|
5
6
|
error?: Error | null | unknown;
|
|
6
7
|
filter?: string;
|
|
7
8
|
hasErrorSubmitting?: boolean;
|
|
@@ -9,7 +10,7 @@ export interface ChangeCustomerDialogProps {
|
|
|
9
10
|
isOpen: boolean;
|
|
10
11
|
isUpdating?: boolean;
|
|
11
12
|
onClose: () => void;
|
|
12
|
-
onCustomerSelected: (id: string) => void;
|
|
13
|
+
onCustomerSelected: (id: string, setAsDefault: boolean) => void;
|
|
13
14
|
onFilterChanged?: (filter: string) => void;
|
|
14
15
|
}
|
|
15
|
-
export declare function ChangeCustomerDialog({
|
|
16
|
+
export declare function ChangeCustomerDialog({ allowSetDefault, data, defaultCustomerId, error, filter, hasErrorSubmitting, isLoading, isOpen, isUpdating, onClose, onCustomerSelected, onFilterChanged, }: ChangeCustomerDialogProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -8,17 +8,23 @@ import { Dialog } from '../../../../modals/dialog/dialog.js';
|
|
|
8
8
|
import { ChangeCustomer } from './change-customer.js';
|
|
9
9
|
import styles from './change-customer-dialog.module.css.js';
|
|
10
10
|
|
|
11
|
-
function ChangeCustomerDialog({
|
|
11
|
+
function ChangeCustomerDialog({ allowSetDefault = false, data, defaultCustomerId, error, filter, hasErrorSubmitting, isLoading, isOpen, isUpdating = false, onClose, onCustomerSelected, onFilterChanged, }) {
|
|
12
12
|
const t = useFormattedMessage();
|
|
13
13
|
const [hasCustomerSelected, setHasCustomerSelected] = useState(false);
|
|
14
14
|
const [selectedCustomerId, setSelectedCustomerId] = useState();
|
|
15
|
-
|
|
15
|
+
const [setAsDefault, setSetAsDefault] = useState(false);
|
|
16
|
+
if (!isOpen && setAsDefault)
|
|
17
|
+
setSetAsDefault(false);
|
|
18
|
+
if (!isOpen)
|
|
19
|
+
return null;
|
|
20
|
+
return (jsx(Dialog, { allowSubmit: !hasErrorSubmitting && hasCustomerSelected, className: styles['change-customer-dialog'], isOpen: isOpen, isSubmitting: isUpdating || hasErrorSubmitting, onOpenChange: isOpen => !isOpen && onClose(), onSubmit: () => selectedCustomerId &&
|
|
21
|
+
onCustomerSelected(selectedCustomerId, setAsDefault), 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, { allowSetDefault: allowSetDefault, className: styles.content, data: data, defaultCustomerId: defaultCustomerId, error: error, filter: filter, isLoading: isLoading, onCustomerSelected: id => {
|
|
16
22
|
setSelectedCustomerId(id);
|
|
17
|
-
onCustomerSelected(id);
|
|
23
|
+
onCustomerSelected(id, setAsDefault);
|
|
18
24
|
}, onCustomerSelectionChanged: id => {
|
|
19
25
|
setSelectedCustomerId(id);
|
|
20
26
|
setHasCustomerSelected(true);
|
|
21
|
-
}, onFilterChanged: onFilterChanged,
|
|
27
|
+
}, onFilterChanged: onFilterChanged, onSetAsDefaultChange: setSetAsDefault, setAsDefault: setAsDefault })) }));
|
|
22
28
|
}
|
|
23
29
|
|
|
24
30
|
export { ChangeCustomerDialog };
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { BillToCollectionModel } from '../../../../shared/api/storefront/model/storefront.model';
|
|
2
2
|
export interface ChangeCustomerProps {
|
|
3
|
+
allowSetDefault?: boolean;
|
|
3
4
|
className?: string;
|
|
4
5
|
data?: BillToCollectionModel;
|
|
6
|
+
defaultCustomerId?: string;
|
|
5
7
|
error?: Error | null | unknown;
|
|
6
8
|
filter?: string;
|
|
7
9
|
isLoading?: boolean;
|
|
8
10
|
onCustomerSelected?: (id: string) => void;
|
|
9
11
|
onCustomerSelectionChanged?: (id: string) => void;
|
|
10
12
|
onFilterChanged?: (filter: string) => void;
|
|
11
|
-
|
|
13
|
+
onSetAsDefaultChange?: (setAsDefault: boolean) => void;
|
|
14
|
+
setAsDefault?: boolean;
|
|
12
15
|
}
|
|
13
|
-
export declare function ChangeCustomer({ className, data, error, filter, isLoading, onCustomerSelected, onCustomerSelectionChanged, onFilterChanged,
|
|
16
|
+
export declare function ChangeCustomer({ allowSetDefault, className, data, defaultCustomerId, error, filter, isLoading, onCustomerSelected, onCustomerSelectionChanged: _onCustomerSelectionChanged, onFilterChanged, onSetAsDefaultChange, setAsDefault, }: ChangeCustomerProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { useRef, useMemo } from 'react';
|
|
3
|
+
import { useRef, useState, useCallback, useMemo } from 'react';
|
|
4
4
|
import { ListBox, ListBoxItem, Text } from 'react-aria-components';
|
|
5
5
|
import clsx from 'clsx';
|
|
6
|
+
import { Checkbox } from '../../../../forms/checkbox/checkbox.js';
|
|
6
7
|
import { SearchField } from '../../../../forms/search-field/search-field.js';
|
|
7
8
|
import { SolidRatingIcon } from '../../../../icons/solid/solid-rating-icon.js';
|
|
8
9
|
import { FormattedMessage } from '../../../../intl/formatted-message.js';
|
|
@@ -13,13 +14,18 @@ import { HighlightText } from '../../../../text/highlight-text/highlight-text.js
|
|
|
13
14
|
import styles from './change-customer.module.css.js';
|
|
14
15
|
|
|
15
16
|
const DEFAULT_PAGE_SIZE = 20;
|
|
16
|
-
function ChangeCustomer({ className, data, error, filter = '', isLoading = false, onCustomerSelected, onCustomerSelectionChanged, onFilterChanged,
|
|
17
|
+
function ChangeCustomer({ allowSetDefault = false, className, data, defaultCustomerId, error, filter = '', isLoading = false, onCustomerSelected, onCustomerSelectionChanged: _onCustomerSelectionChanged, onFilterChanged, onSetAsDefaultChange, setAsDefault = false, }) {
|
|
17
18
|
const t = useFormattedMessage();
|
|
18
19
|
const listBoxRef = useRef(null);
|
|
19
20
|
const hasMoreResults = !isLoading &&
|
|
20
21
|
data?.pagination &&
|
|
21
22
|
data.pagination.totalItemCount > DEFAULT_PAGE_SIZE;
|
|
22
|
-
const
|
|
23
|
+
const [hasSelectedIdChanged, setHasSelectedIdChanged] = useState(false);
|
|
24
|
+
const onCustomerSelectionChanged = useCallback((key) => {
|
|
25
|
+
setHasSelectedIdChanged(true);
|
|
26
|
+
return _onCustomerSelectionChanged?.(String(key));
|
|
27
|
+
}, [_onCustomerSelectionChanged]);
|
|
28
|
+
const [listBoxItems, rerenderKey] = useMemo(() => {
|
|
23
29
|
const listBoxItems = [...(data?.billTos || [])];
|
|
24
30
|
if (error instanceof UnauthorizedRequestError) {
|
|
25
31
|
listBoxItems.push({
|
|
@@ -42,13 +48,16 @@ function ChangeCustomer({ className, data, error, filter = '', isLoading = false
|
|
|
42
48
|
type: 'warning',
|
|
43
49
|
});
|
|
44
50
|
}
|
|
45
|
-
return
|
|
46
|
-
|
|
51
|
+
return [
|
|
52
|
+
listBoxItems,
|
|
53
|
+
Math.random().toString(36).slice(2, 15) + defaultCustomerId,
|
|
54
|
+
];
|
|
55
|
+
}, [data?.billTos, error, hasMoreResults, t, defaultCustomerId]);
|
|
47
56
|
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 }) => {
|
|
48
57
|
if (key === 'ArrowDown') {
|
|
49
58
|
listBoxRef.current?.focus();
|
|
50
59
|
}
|
|
51
|
-
}, 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
|
|
60
|
+
}, 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, textValue: listBoxItem.id, children: jsx(Message, { type: listBoxItem.type, children: jsx(Text, { slot: "description", children: listBoxItem.message }) }) }, "marker")) : (jsxs(ListBoxItem, { className: styles['list-box-item'], id: listBoxItem.id, textValue: 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}` }), defaultCustomerId === 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: [
|
|
52
61
|
[listBoxItem.firstName, listBoxItem.lastName].join(' '),
|
|
53
62
|
]
|
|
54
63
|
.filter(Boolean)
|
|
@@ -61,7 +70,7 @@ function ChangeCustomer({ className, data, error, filter = '', isLoading = false
|
|
|
61
70
|
.filter(Boolean)
|
|
62
71
|
.join(', ') }) }), jsx(HighlightText, { highlightText: filter, text: [listBoxItem.postalCode, listBoxItem.country?.name]
|
|
63
72
|
.filter(Boolean)
|
|
64
|
-
.join(', ') })] })] }, listBoxItem.id)) })] }));
|
|
73
|
+
.join(', ') })] })] }, `${listBoxItem.id}-${defaultCustomerId}`)) }, rerenderKey), allowSetDefault && (jsx(Checkbox, { isDisabled: !hasSelectedIdChanged, isSelected: setAsDefault, onChange: onSetAsDefaultChange, value: String(setAsDefault), children: jsx(FormattedMessage, { id: "Make this the default customer" }) }))] }));
|
|
65
74
|
}
|
|
66
75
|
|
|
67
76
|
export { ChangeCustomer };
|
|
@@ -1,3 +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"};
|
|
1
|
+
var styles = {"change-customer-container":"change-customer-module-2kOw4","list-box":"change-customer-module-StfiY","list-box-item":"change-customer-module-P7ouY","selected-icon":"change-customer-module-lxmBJ","company-name":"change-customer-module-DSVPN","company-name-text":"change-customer-module-4KQoq","customer-number":"change-customer-module-4p6ab"};
|
|
2
2
|
|
|
3
3
|
export { styles as default };
|
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export interface ConnectedChangeCustomerDialogProps {
|
|
2
|
+
allowSetDefault?: boolean;
|
|
3
|
+
isOpen: boolean;
|
|
4
|
+
onClose: () => void;
|
|
5
|
+
onCustomerSelected: (id: string, setAsDefault: boolean) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function ConnectedChangeCustomerDialog({ allowSetDefault, isOpen, onClose, onCustomerSelected, }: ConnectedChangeCustomerDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { useState } from 'react';
|
|
3
|
+
import { useState, useEffect } from 'react';
|
|
4
|
+
import { useFetchCurrentAccount } from '../../../../shared/api/storefront/hooks/account/use-fetch-current-account.js';
|
|
4
5
|
import { usePatchSession } from '../../../../shared/api/storefront/hooks/authentication/use-patch-session.js';
|
|
5
6
|
import { useFetchBillToAddresses } from '../../../../shared/api/storefront/hooks/customer/use-fetch-bill-to-addresses.js';
|
|
6
7
|
import { ChangeCustomerDialog } from './change-customer-dialog.js';
|
|
7
8
|
|
|
8
|
-
function ConnectedChangeCustomerDialog({
|
|
9
|
+
function ConnectedChangeCustomerDialog({ allowSetDefault = false, isOpen, onClose, onCustomerSelected, }) {
|
|
9
10
|
const [filter, setFilter] = useState('');
|
|
10
|
-
const {
|
|
11
|
+
const { data: account } = useFetchCurrentAccount();
|
|
12
|
+
const { error: errorMutation, isLoading: isMutating, mutate, reset, } = usePatchSession();
|
|
11
13
|
const { data, error, isFetching, isLoading } = useFetchBillToAddresses({
|
|
12
14
|
filter,
|
|
13
15
|
isEnabled: isOpen,
|
|
14
16
|
});
|
|
15
|
-
|
|
17
|
+
useEffect(() => reset(), [isOpen, reset]);
|
|
18
|
+
return (jsx(ChangeCustomerDialog, { allowSetDefault: allowSetDefault, data: data, defaultCustomerId: account?.defaultCustomerId || undefined, error: error, filter: filter, hasErrorSubmitting: Boolean(errorMutation), isLoading: isLoading || isFetching, isOpen: isOpen, isUpdating: isMutating, onClose: onClose, onCustomerSelected: async (id, setAsDefault) => {
|
|
16
19
|
id = `${id}`;
|
|
17
20
|
try {
|
|
18
21
|
await mutate({
|
|
19
22
|
session: {
|
|
20
23
|
billTo: {
|
|
21
24
|
id,
|
|
22
|
-
isDefault:
|
|
25
|
+
isDefault: setAsDefault,
|
|
23
26
|
},
|
|
24
27
|
billToId: id,
|
|
25
28
|
customerWasUpdated: false,
|
|
@@ -29,7 +32,7 @@ function ConnectedChangeCustomerDialog({ currentlySelectedCustomerId, isOpen, on
|
|
|
29
32
|
shipToId: id,
|
|
30
33
|
},
|
|
31
34
|
});
|
|
32
|
-
onCustomerSelected(id);
|
|
35
|
+
onCustomerSelected(id, setAsDefault);
|
|
33
36
|
}
|
|
34
37
|
catch {
|
|
35
38
|
// Handle error if needed
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface ChangePasswordDialogProps {
|
|
2
|
+
error?: Error | null | unknown;
|
|
3
|
+
isLoading?: boolean;
|
|
4
|
+
isOpen: boolean;
|
|
5
|
+
isUpdating?: boolean;
|
|
6
|
+
onClose: () => void;
|
|
7
|
+
onPasswordChanged: (currentPassword: string, newPassword: string) => void;
|
|
8
|
+
username: string | undefined;
|
|
9
|
+
}
|
|
10
|
+
export declare function ChangePasswordDialog({ error, isLoading, isOpen, isUpdating, onClose, onPasswordChanged, username, }: ChangePasswordDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { FormSegmentGroup } from '../../../../forms/form/form-segment-group.js';
|
|
3
|
+
import { useFormattedMessage } from '../../../../intl/use-formatted-message.js';
|
|
4
|
+
import { Dialog } from '../../../../modals/dialog/dialog.js';
|
|
5
|
+
import { UnauthorizedRequestError } from '../../../../shared/fetch/request.js';
|
|
6
|
+
import { ChangePassword } from './change-password.js';
|
|
7
|
+
|
|
8
|
+
function ChangePasswordDialog({ error, isLoading = false, isOpen, isUpdating = false, onClose, onPasswordChanged, username, }) {
|
|
9
|
+
const t = useFormattedMessage();
|
|
10
|
+
return (jsx(Dialog, { allowSubmit: Boolean(username) &&
|
|
11
|
+
!isLoading &&
|
|
12
|
+
!isUpdating &&
|
|
13
|
+
!(error instanceof UnauthorizedRequestError), isOpen: isOpen, onOpenChange: isOpen => !isOpen && onClose(), onSubmit: ({ formData }) => {
|
|
14
|
+
const currentPassword = formData.get('current-password')?.toString();
|
|
15
|
+
const newPassword = formData.get('new-password')?.toString();
|
|
16
|
+
if (!currentPassword)
|
|
17
|
+
throw new Error('current password is required');
|
|
18
|
+
if (!newPassword)
|
|
19
|
+
throw new Error('New password is required');
|
|
20
|
+
onPasswordChanged(currentPassword, newPassword);
|
|
21
|
+
}, title: t('Change password'), children: jsx(FormSegmentGroup, { children: jsx(ChangePassword, { error: error, isLoading: isLoading, isUpdating: isUpdating, username: username }) }) }));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { ChangePasswordDialog };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface ChangePasswordProps {
|
|
2
|
+
error?: Error | null | unknown;
|
|
3
|
+
isLoading?: boolean;
|
|
4
|
+
isUpdating?: boolean;
|
|
5
|
+
username: string | undefined;
|
|
6
|
+
}
|
|
7
|
+
export declare function ChangePassword({ error, isLoading, isUpdating, username, }: ChangePasswordProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { FormSegment } from '../../../../forms/form/form-segment.js';
|
|
3
|
+
import { PasswordField } from '../../../../forms/password-field/password-field.js';
|
|
4
|
+
import { PasswordValidation } from '../../../../forms/password-validation/password-validation.js';
|
|
5
|
+
import { useFormattedMessage } from '../../../../intl/use-formatted-message.js';
|
|
6
|
+
import { ProgressCircle } from '../../../../loading/progress-circle.js';
|
|
7
|
+
import { Message } from '../../../../message/message.js';
|
|
8
|
+
import { NonUniquePasswordError, InvalidPasswordError } from '../../../../shared/api/storefront/services/authentication-service.js';
|
|
9
|
+
import { UnauthorizedRequestError } from '../../../../shared/fetch/request.js';
|
|
10
|
+
import { validatePassword } from '../../../../shared/model/account.js';
|
|
11
|
+
import styles from './change-password.module.css.js';
|
|
12
|
+
|
|
13
|
+
function ChangePassword({ error, isLoading = false, isUpdating = false, username, }) {
|
|
14
|
+
const t = useFormattedMessage();
|
|
15
|
+
if (error instanceof UnauthorizedRequestError) {
|
|
16
|
+
return (jsx(FormSegment, { children: jsx(Message, { type: "danger", children: t('You are not authorized to perform this action') }) }));
|
|
17
|
+
}
|
|
18
|
+
if (isLoading) {
|
|
19
|
+
return (jsx("div", { className: styles['loading-panel'], children: jsx(ProgressCircle, { variant: "gray" }) }));
|
|
20
|
+
}
|
|
21
|
+
if (!username) {
|
|
22
|
+
return jsx(Message, { type: "danger", children: t('An unexpected error occured') });
|
|
23
|
+
}
|
|
24
|
+
return (jsxs(Fragment, { children: [jsxs(FormSegment, { children: [jsx("input", { autoComplete: "username", defaultValue: username, id: "username", name: "username", style: { display: 'none' }, type: "text" }), jsx(PasswordField, { autoComplete: "password", "data-test-selector": "current_password", isDisabled: isUpdating, isRequired: true, label: t('Password'), name: "current-password", validate: value => {
|
|
25
|
+
if (!value)
|
|
26
|
+
return;
|
|
27
|
+
return (validatePassword(value) ||
|
|
28
|
+
t('Password does not meet requirements'));
|
|
29
|
+
} })] }), jsx(PasswordValidation, { isDisabled: isUpdating }), error && (jsx(FormSegment, { children: jsx(Message, { className: styles['error-message'], type: "danger", children: error instanceof NonUniquePasswordError ||
|
|
30
|
+
error instanceof InvalidPasswordError
|
|
31
|
+
? t(error.message)
|
|
32
|
+
: t('An unexpected error occured') }) }))] }));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export { ChangePassword };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { FormattedMessage } from '../../../../intl/formatted-message.js';
|
|
3
|
+
import { logger } from '../../../../logging/logger.js';
|
|
4
|
+
import { useFetchCurrentAccount } from '../../../../shared/api/storefront/hooks/account/use-fetch-current-account.js';
|
|
5
|
+
import { usePatchSession } from '../../../../shared/api/storefront/hooks/authentication/use-patch-session.js';
|
|
6
|
+
import { useNavigate } from '../../../../shared/routing/use-navigate.js';
|
|
7
|
+
import { useToast } from '../../../../toast/use-toast.js';
|
|
8
|
+
import { PATHS } from '../../../paths.js';
|
|
9
|
+
import { ChangePasswordDialog } from './change-password-dialog.js';
|
|
10
|
+
|
|
11
|
+
function ConnectedChangePasswordDialog({ isOpen, onClose, }) {
|
|
12
|
+
const { error: errorPatchSession, isLoading: isUpdating, mutate: patchSession, } = usePatchSession();
|
|
13
|
+
const { addToast } = useToast();
|
|
14
|
+
const { navigate } = useNavigate();
|
|
15
|
+
const { data: account, error: errorFetchCurrentAccount, isLoading, } = useFetchCurrentAccount({
|
|
16
|
+
isEnabled: isOpen,
|
|
17
|
+
});
|
|
18
|
+
if (!isOpen)
|
|
19
|
+
return null;
|
|
20
|
+
return (jsx(ChangePasswordDialog, { error: errorFetchCurrentAccount || errorPatchSession, isLoading: isLoading, isOpen: isOpen, isUpdating: isUpdating, onClose: onClose, onPasswordChanged: async (currentPassword, newPassword) => {
|
|
21
|
+
logger.info(currentPassword, newPassword);
|
|
22
|
+
await patchSession({
|
|
23
|
+
session: {
|
|
24
|
+
email: account?.email,
|
|
25
|
+
newPassword,
|
|
26
|
+
password: currentPassword,
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
addToast({
|
|
30
|
+
body: (jsx(FormattedMessage, { id: "Password changed. Please sign in again." })),
|
|
31
|
+
isUserDismissable: false,
|
|
32
|
+
messageType: 'success',
|
|
33
|
+
});
|
|
34
|
+
onClose();
|
|
35
|
+
navigate(`${PATHS.SIGN_IN}${location?.pathname ? `?returnUrl=${encodeURIComponent(location.pathname + location.search)}` : ''}`);
|
|
36
|
+
}, username: account?.email }));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { ConnectedChangePasswordDialog };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { useState, useEffect } from 'react';
|
|
4
|
+
import { useFormattedMessage } from '../../../../intl/use-formatted-message.js';
|
|
5
|
+
import { useFetchCurrentAccount } from '../../../../shared/api/storefront/hooks/account/use-fetch-current-account.js';
|
|
6
|
+
import { usePatchCurrentAccount } from '../../../../shared/api/storefront/hooks/account/use-patch-current-account.js';
|
|
7
|
+
import { ExistingAccountError } from '../../../../shared/api/storefront/services/account-service.js';
|
|
8
|
+
import { EditUserInfoDialog } from './edit-user-info-dialog.js';
|
|
9
|
+
|
|
10
|
+
function ConnectedEditUserInfoDialog({ isOpen, onClose, }) {
|
|
11
|
+
const t = useFormattedMessage();
|
|
12
|
+
const [validationErrors, setValidationErrors] = useState({});
|
|
13
|
+
const { data: account, error, isLoading, } = useFetchCurrentAccount({
|
|
14
|
+
isEnabled: isOpen,
|
|
15
|
+
});
|
|
16
|
+
const { error: errorPatchCurrentAccount, isLoading: isMutating, mutate, reset, } = usePatchCurrentAccount();
|
|
17
|
+
useEffect(() => reset(), [isOpen, reset]);
|
|
18
|
+
if (!isOpen)
|
|
19
|
+
return null;
|
|
20
|
+
return (jsx(EditUserInfoDialog, { account: account, error: error || errorPatchCurrentAccount, isLoading: isLoading, isOpen: isOpen, isUpdating: isMutating, onOpenChange: isOpen => !isOpen && onClose?.(), onSubmit: async ({ formData }) => {
|
|
21
|
+
const email = formData.get('email')?.toString();
|
|
22
|
+
if (!email)
|
|
23
|
+
throw new Error('E-mail is required');
|
|
24
|
+
const lastName = formData.get('lastName')?.toString();
|
|
25
|
+
if (!lastName)
|
|
26
|
+
throw new Error('Last name is required');
|
|
27
|
+
const firstName = formData.get('firstName')?.toString();
|
|
28
|
+
if (!firstName)
|
|
29
|
+
throw new Error('First name is required');
|
|
30
|
+
try {
|
|
31
|
+
await mutate({
|
|
32
|
+
account: {
|
|
33
|
+
...account,
|
|
34
|
+
email,
|
|
35
|
+
firstName,
|
|
36
|
+
lastName,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
onClose?.();
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (error instanceof ExistingAccountError) {
|
|
43
|
+
setValidationErrors(errors => ({
|
|
44
|
+
...errors,
|
|
45
|
+
email: t('This email is already in use'),
|
|
46
|
+
}));
|
|
47
|
+
reset();
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}, validationErrors: validationErrors }));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { ConnectedEditUserInfoDialog };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { OnSubmitHandler, ValidationErrors } from '../../../../forms/form/form';
|
|
2
|
+
import { EditUserInfoProps } from './edit-user-info';
|
|
3
|
+
export interface EditUserInfoDialogProps extends EditUserInfoProps {
|
|
4
|
+
isOpen: boolean;
|
|
5
|
+
isUpdating?: boolean;
|
|
6
|
+
onOpenChange?: (isOpen: boolean) => void;
|
|
7
|
+
onSubmit?: OnSubmitHandler;
|
|
8
|
+
validationErrors?: ValidationErrors;
|
|
9
|
+
}
|
|
10
|
+
export declare function EditUserInfoDialog({ account, error, isLoading, isOpen, isUpdating, onOpenChange, onSubmit, validationErrors, }: EditUserInfoDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { useFormattedMessage } from '../../../../intl/use-formatted-message.js';
|
|
4
|
+
import { Dialog } from '../../../../modals/dialog/dialog.js';
|
|
5
|
+
import { UnauthorizedRequestError } from '../../../../shared/fetch/request.js';
|
|
6
|
+
import { EditUserInfo } from './edit-user-info.js';
|
|
7
|
+
|
|
8
|
+
function EditUserInfoDialog({ account, error, isLoading, isOpen = false, isUpdating = false, onOpenChange, onSubmit, validationErrors, }) {
|
|
9
|
+
const t = useFormattedMessage();
|
|
10
|
+
return (jsx(Dialog, { allowSubmit: !isLoading &&
|
|
11
|
+
!isUpdating &&
|
|
12
|
+
!(error instanceof UnauthorizedRequestError), isOpen: isOpen, isSubmitting: isUpdating, onOpenChange: onOpenChange, onSubmit: onSubmit, title: t('Edit Sonic account'), validationErrors: validationErrors, children: jsx(EditUserInfo, { account: account, error: error, isLoading: isLoading }) }));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { EditUserInfoDialog };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AccountModel } from '../../../../shared/api/storefront/model/storefront.model';
|
|
2
|
+
export interface EditUserInfoProps {
|
|
3
|
+
account: AccountModel | {
|
|
4
|
+
email: string;
|
|
5
|
+
firstName: string;
|
|
6
|
+
lastName: string;
|
|
7
|
+
} | undefined;
|
|
8
|
+
error?: Error | null | unknown;
|
|
9
|
+
isLoading?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function EditUserInfo({ account, error, isLoading, }: EditUserInfoProps): import("react/jsx-runtime").JSX.Element;
|