Merge branch 'DRVDOC-1260' into 'main'
[ProtonMail-WebClient.git] / packages / components / containers / addresses / EditInternalAddressModal.tsx
blob4eef6f2f79d20b8e79833bce9d33821737477b0d
1 import type { FormEvent } from 'react';
2 import { useState } from 'react';
4 import { c } from 'ttag';
6 import { useGetOrganizationKey } from '@proton/account/organizationKey/hooks';
7 import { useGetUserKeys } from '@proton/account/userKeys/hooks';
8 import { Button } from '@proton/atoms';
9 import type { ModalProps } from '@proton/components/components/modalTwo/Modal';
10 import Modal from '@proton/components/components/modalTwo/Modal';
11 import ModalContent from '@proton/components/components/modalTwo/ModalContent';
12 import ModalFooter from '@proton/components/components/modalTwo/ModalFooter';
13 import ModalHeader from '@proton/components/components/modalTwo/ModalHeader';
14 import InputFieldTwo from '@proton/components/components/v2/field/InputField';
15 import useFormErrors from '@proton/components/components/v2/useFormErrors';
16 import useApi from '@proton/components/hooks/useApi';
17 import useEventManager from '@proton/components/hooks/useEventManager';
18 import useNotifications from '@proton/components/hooks/useNotifications';
19 import { useLoading } from '@proton/hooks';
20 import { renameInternalAddress, updateAddress } from '@proton/shared/lib/api/addresses';
21 import { CANONICALIZE_SCHEME, canonicalizeEmail, getEmailParts } from '@proton/shared/lib/helpers/email';
22 import { emailValidator, requiredValidator } from '@proton/shared/lib/helpers/formValidators';
23 import type { Address } from '@proton/shared/lib/interfaces';
24 import { getRenamedAddressKeys } from '@proton/shared/lib/keys';
25 import noop from '@proton/utils/noop';
27 interface Props extends ModalProps<'form'> {
28     address: Address;
31 const EditInternalAddressModal = ({ address, ...rest }: Props) => {
32     const [initialEmail] = useState(address.Email);
33     const [[initialLocalEmail, domain]] = useState(getEmailParts(initialEmail));
34     const [initialDisplayName] = useState(address.DisplayName);
36     const [displayName, setDisplayName] = useState(initialDisplayName);
37     const [localEmail, setEmail] = useState(initialLocalEmail);
38     const newEmail = `${localEmail}@${domain}`;
39     const getUserKeys = useGetUserKeys();
40     const getOrganizationKey = useGetOrganizationKey();
41     const { createNotification } = useNotifications();
42     const { onFormSubmit, validator } = useFormErrors();
43     const [submitting, withLoading] = useLoading();
44     const api = useApi();
45     const { call } = useEventManager();
47     const handleSubmit = async () => {
48         if (localEmail !== initialLocalEmail) {
49             const userKeys = await getUserKeys();
50             const organizationKey = await getOrganizationKey();
51             await api(
52                 renameInternalAddress(address.ID, {
53                     Local: localEmail,
54                     AddressKeys: await getRenamedAddressKeys({
55                         userKeys,
56                         addressKeys: address.Keys,
57                         organizationKey: organizationKey?.privateKey ? organizationKey : undefined,
58                         email: newEmail,
59                     }),
60                 })
61             );
62         }
63         if (displayName !== initialDisplayName) {
64             await api(
65                 updateAddress(address.ID, {
66                     DisplayName: displayName,
67                     Signature: address.Signature,
68                 })
69             ).catch(noop);
70         }
71         await call();
72         createNotification({ text: c('Success').t`Email address updated` });
73         rest.onClose?.();
74     };
76     const handleClose = submitting ? undefined : rest.onClose;
78     return (
79         <Modal
80             as="form"
81             size="small"
82             {...rest}
83             onSubmit={(event: FormEvent) => {
84                 event.preventDefault();
85                 event.stopPropagation();
86                 if (!onFormSubmit()) {
87                     return;
88                 }
89                 withLoading(handleSubmit());
90             }}
91             onClose={handleClose}
92             noValidate
93         >
94             <ModalHeader title={c('Title').t`Edit email address`} />
95             <ModalContent>
96                 <div className="color-weak mb-4">{c('loc_nightly_Info')
97                     .t`You can change capitalization or punctuation to edit your email address.`}</div>
98                 <InputFieldTwo
99                     type="email"
100                     autoComplete="email"
101                     id="email"
102                     autoFocus
103                     value={localEmail}
104                     suffix={
105                         <span className="text-ellipsis" title={`@${domain}`}>
106                             @{domain}
107                         </span>
108                     }
109                     onValue={setEmail}
110                     error={validator([
111                         requiredValidator(localEmail),
112                         emailValidator(newEmail),
113                         (() => {
114                             if (
115                                 canonicalizeEmail(newEmail, CANONICALIZE_SCHEME.PROTON) !==
116                                 canonicalizeEmail(initialEmail, CANONICALIZE_SCHEME.PROTON)
117                             ) {
118                                 return c('loc_nightly_Error')
119                                     .t`Only capitalization and punctuation (periods, hyphens, and underscores) can be changed for this address`;
120                             }
121                             return '';
122                         })(),
123                     ])}
124                     label={c('Label').t`Address`}
125                 />
126                 <InputFieldTwo
127                     id="displayName"
128                     value={displayName}
129                     onValue={setDisplayName}
130                     label={c('Label').t`Display name`}
131                 />
132             </ModalContent>
133             <ModalFooter>
134                 <Button onClick={handleClose} disabled={submitting}>{c('Action').t`Cancel`}</Button>
135                 <Button color="norm" type="submit" loading={submitting}>{c('Action').t`Save`}</Button>
136             </ModalFooter>
137         </Modal>
138     );
141 export default EditInternalAddressModal;