Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / applications / drive / src / app / components / modals / RenameModal.tsx
blob195e26078703ba762e48333c15abe757c855b483
1 import type { ChangeEvent, FocusEvent } from 'react';
2 import { useState } from 'react';
4 import { c } from 'ttag';
6 import { Button } from '@proton/atoms';
7 import type { ModalStateProps } from '@proton/components';
8 import {
9     Field,
10     InputFieldTwo,
11     Label,
12     ModalTwo,
13     ModalTwoContent,
14     ModalTwoFooter,
15     ModalTwoHeader,
16     PrimaryButton,
17     Row,
18     useModalTwoStatic,
19 } from '@proton/components';
20 import { useLoading } from '@proton/hooks';
21 import noop from '@proton/utils/noop';
23 import { formatLinkName, splitLinkName, validateLinkNameField } from '../../store';
25 interface Props {
26     onClose?: () => void;
27     onSubmit: (formattedName: string) => Promise<void>;
28     isFile: boolean;
29     name: string;
32 const RenameModal = ({ isFile, name: linkName, onClose, onSubmit, ...modalProps }: Props & ModalStateProps) => {
33     const [name, setName] = useState(linkName);
34     const [loading, withLoading] = useLoading();
35     const [autofocusDone, setAutofocusDone] = useState(false);
37     const selectNamePart = (e: FocusEvent<HTMLInputElement>) => {
38         if (autofocusDone) {
39             return;
40         }
41         setAutofocusDone(true);
42         const [namePart] = splitLinkName(linkName);
43         if (!namePart || !isFile) {
44             return e.target.select();
45         }
46         e.target.setSelectionRange(0, namePart.length);
47     };
49     const handleBlur = ({ target }: FocusEvent<HTMLInputElement>) => {
50         setName(formatLinkName(target.value));
51     };
53     const handleChange = ({ target }: ChangeEvent<HTMLInputElement>) => {
54         setName(target.value);
55     };
57     const handleSubmit = async (e: React.FormEvent) => {
58         e.preventDefault();
60         const formattedName = formatLinkName(name);
61         setName(formattedName);
63         await onSubmit(formattedName);
64         onClose?.();
65     };
67     const validationError = validateLinkNameField(name);
69     return (
70         <ModalTwo
71             as="form"
72             disableCloseOnEscape={loading}
73             onClose={onClose}
74             onSubmit={(e: React.FormEvent) => withLoading(handleSubmit(e)).catch(noop)}
75             size="large"
76             {...modalProps}
77         >
78             <ModalTwoHeader
79                 closeButtonProps={{ disabled: loading }}
80                 title={!isFile ? c('Title').t`Rename a folder` : c('Title').t`Rename a file`}
81             />
82             <ModalTwoContent>
83                 <Row className="my-4">
84                     <Label>{!isFile ? c('Label').t`Folder name` : c('Label').t`File name`}</Label>
85                     <Field>
86                         <InputFieldTwo
87                             id="link-name"
88                             value={name}
89                             autoFocus
90                             placeholder={c('Placeholder').t`New name`}
91                             onChange={handleChange}
92                             onBlur={handleBlur}
93                             onFocus={selectNamePart}
94                             error={validationError}
95                             required
96                             data-testid="input-rename"
97                         />
98                     </Field>
99                 </Row>
100             </ModalTwoContent>
101             <ModalTwoFooter>
102                 <Button type="button" onClick={onClose} disabled={loading}>
103                     {c('Action').t`Cancel`}
104                 </Button>
105                 <PrimaryButton type="submit" loading={loading}>
106                     {c('Action').t`Rename`}
107                 </PrimaryButton>
108             </ModalTwoFooter>
109         </ModalTwo>
110     );
113 export default RenameModal;
115 export const useRenameModal = () => {
116     return useModalTwoStatic(RenameModal);