-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Expand file tree
/
Copy pathTwoFactorEmailModal.tsx
More file actions
120 lines (110 loc) · 3.19 KB
/
TwoFactorEmailModal.tsx
File metadata and controls
120 lines (110 loc) · 3.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import { Box, Button } from '@rocket.chat/fuselage';
import { FieldGroup, TextInput, Field, FieldLabel, FieldRow, FieldError } from '@rocket.chat/fuselage-forms';
import { GenericModal } from '@rocket.chat/ui-client';
import { useToastMessageDispatch } from '@rocket.chat/ui-contexts';
import { useEffect, type ReactElement } from 'react';
import { useForm, Controller } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import type { OnConfirm } from './TwoFactorModal';
import { Method } from './TwoFactorModal';
type TwoFactorEmailModalProps = {
onConfirm: OnConfirm;
onClose: () => void;
resendEmail?: () => Promise<null>;
invalidAttempt?: boolean;
};
type TwoFactorEmailFormData = {
code: string;
};
const TwoFactorEmailModal = ({ onConfirm, onClose, resendEmail, invalidAttempt }: TwoFactorEmailModalProps): ReactElement => {
const dispatchToastMessage = useToastMessageDispatch();
const { t } = useTranslation();
const {
control,
handleSubmit,
setError,
setValue,
clearErrors,
formState: { errors, isSubmitting },
} = useForm<TwoFactorEmailFormData>({
defaultValues: { code: '' },
});
useEffect(() => {
if (invalidAttempt) {
setError('code', {
type: 'manual',
message: t('code'),
});
}
}, [invalidAttempt, setError, t]);
const onClickResendCode = async (): Promise<void> => {
try {
if (!resendEmail) {
throw new Error('resendEmail is not defined');
}
await resendEmail();
dispatchToastMessage({ type: 'success', message: t('Email_sent') });
} catch (error) {
dispatchToastMessage({
type: 'error',
message: t('error-email-send-failed', { message: error }),
});
}
};
const onSubmit = handleSubmit(async ({ code }) => {
try {
await onConfirm(code, Method.EMAIL);
} catch (error) {
setError('code', {
type: 'manual',
message: t('Invalid_two_factor_code'),
});
setValue('code', '');
}
});
return (
<GenericModal
wrapperFunction={(props) => <Box is='form' onSubmit={onSubmit} {...props} />}
onCancel={onClose}
confirmText={t('Verify')}
title={t('Enter_authentication_code')}
onClose={onClose}
variant='warning'
confirmDisabled={isSubmitting}
tagline={t('Email_two-factor_authentication')}
icon={null}
>
<FieldGroup>
<Field>
<FieldLabel alignSelf='stretch'>{t('Enter_the_code_we_just_emailed_you')}</FieldLabel>
<FieldRow>
<Controller
name='code'
control={control}
rules={{ required: t('Required_field', { field: t('Code') }) }}
render={({ field: { onChange, ...fieldProps } }) => (
<TextInput
{...fieldProps}
onChange={(e) => {
clearErrors('code');
onChange(e);
}}
placeholder={t('Enter_code_here')}
autoComplete='one-time-code'
inputMode='numeric'
disabled={isSubmitting}
error={errors.code?.message}
/>
)}
/>
</FieldRow>
{errors.code && <FieldError>{errors.code.message}</FieldError>}
</Field>
</FieldGroup>
<Button display='flex' justifyContent='end' onClick={onClickResendCode} small mbs={24}>
{t('Cloud_resend_email')}
</Button>
</GenericModal>
);
};
export default TwoFactorEmailModal;