ente/packages/accounts/components/ChangeEmail.tsx
2023-11-10 13:13:09 +05:30

167 lines
6.4 KiB
TypeScript

import { Formik, FormikHelpers } from 'formik';
import React, { useRef, useState } from 'react';
import * as Yup from 'yup';
import SubmitButton from '@ente/shared/components/SubmitButton';
import { changeEmail, sendOTTForEmailChange } from '@ente/accounts/api/user';
import { getData, LS_KEYS, setData } from '@ente/shared/storage/localStorage';
import { Alert, Box, TextField } from '@mui/material';
import { VerticallyCentered } from '@ente/shared/components/Container';
import LinkButton from '@ente/shared/components/LinkButton';
import FormPaperFooter from '@ente/shared/components/Form/FormPaper/Footer';
import { sleep } from '@ente/shared/utils';
import { Trans } from 'react-i18next';
import { t } from 'i18next';
import { APP_HOMES } from '@ente/shared/apps/constants';
import { PageProps } from '@ente/shared/apps/types';
interface formValues {
email: string;
ott?: string;
}
function ChangeEmailForm({ appName, router }: PageProps) {
const [loading, setLoading] = useState(false);
const [ottInputVisible, setShowOttInputVisibility] = useState(false);
const ottInputRef = useRef(null);
const [email, setEmail] = useState(null);
const [showMessage, setShowMessage] = useState(false);
const [success, setSuccess] = useState(false);
const requestOTT = async (
{ email }: formValues,
{ setFieldError }: FormikHelpers<formValues>
) => {
try {
setLoading(true);
await sendOTTForEmailChange(email);
setEmail(email);
setShowOttInputVisibility(true);
setShowMessage(true);
setTimeout(() => {
ottInputRef.current?.focus();
}, 250);
} catch (e) {
setFieldError('email', t('EMAIl_ALREADY_OWNED'));
}
setLoading(false);
};
const requestEmailChange = async (
{ email, ott }: formValues,
{ setFieldError }: FormikHelpers<formValues>
) => {
try {
setLoading(true);
await changeEmail(email, ott);
setData(LS_KEYS.USER, { ...getData(LS_KEYS.USER), email });
setLoading(false);
setSuccess(true);
await sleep(1000);
goToApp();
} catch (e) {
setLoading(false);
setFieldError('ott', t('INCORRECT_CODE'));
}
};
const goToApp = () => {
router.push(APP_HOMES.get(appName));
};
return (
<Formik<formValues>
initialValues={{ email: '' }}
validationSchema={Yup.object().shape({
email: Yup.string()
.email(t('EMAIL_ERROR'))
.required(t('REQUIRED')),
ott: ottInputVisible && Yup.string().required(t('REQUIRED')),
})}
validateOnChange={false}
validateOnBlur={false}
onSubmit={!ottInputVisible ? requestOTT : requestEmailChange}>
{({ values, errors, handleChange, handleSubmit }) => (
<>
{showMessage && (
<Alert
color="success"
onClose={() => setShowMessage(false)}>
<Trans
i18nKey="EMAIL_SENT"
components={{
a: (
<Box
color="text.muted"
component={'span'}
/>
),
}}
values={{ email }}
/>
</Alert>
)}
<form noValidate onSubmit={handleSubmit}>
<VerticallyCentered>
<TextField
fullWidth
InputProps={{
readOnly: ottInputVisible,
}}
type="email"
label={t('ENTER_EMAIL')}
value={values.email}
onChange={handleChange('email')}
error={Boolean(errors.email)}
helperText={errors.email}
autoFocus
disabled={loading}
/>
{ottInputVisible && (
<TextField
fullWidth
type="text"
label={t('ENTER_OTT')}
value={values.ott}
onChange={handleChange('ott')}
error={Boolean(errors.ott)}
helperText={errors.ott}
disabled={loading}
/>
)}
<SubmitButton
success={success}
sx={{ mt: 2 }}
loading={loading}
buttonText={
!ottInputVisible
? t('SEND_OTT')
: t('VERIFY')
}
/>
</VerticallyCentered>
</form>
<FormPaperFooter
style={{
justifyContent: ottInputVisible && 'space-between',
}}>
{ottInputVisible && (
<LinkButton
onClick={() =>
setShowOttInputVisibility(false)
}>
{t('CHANGE_EMAIL')}?
</LinkButton>
)}
<LinkButton onClick={goToApp}>
{t('GO_BACK')}
</LinkButton>
</FormPaperFooter>
</>
)}
</Formik>
);
}
export default ChangeEmailForm;