2024-07-29 00:40:35 +02:00

133 lines
4.0 KiB
TypeScript

import { Box, Button, TextField } from '@mui/material';
import { useForm } from '@tanstack/react-form';
import { useRouter } from '@tanstack/react-router';
import { FC, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useApi } from '../../../api/Api';
import { Login } from '../../../types/User';
import ErrorComponent from '../../Error/ErrorComponent';
interface Props {
handleClose: () => void;
}
const LoginForm: FC<Props> = ({ handleClose }) => {
const [error, setError] = useState();
const { t } = useTranslation();
const router = useRouter();
const Api = useApi();
const form = useForm<Login>({
defaultValues: {
email: '',
password: '',
},
onSubmit: async ({ value }) => {
try {
await Api.logIn(value.email, value.password);
router.invalidate();
handleClose();
//eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (_error: any) {
setError(_error);
}
},
});
return (
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
form.handleSubmit();
}}
onKeyDown={(event) => {
if (event.key === 'Tab') {
event.stopPropagation();
}
}}
noValidate
>
<Box sx={{ display: 'grid', gap: 2, padding: 1 }}>
<form.Field
name="email"
validators={{
onChange: ({ value }) => (!value ? t('Email required') : undefined),
onChangeAsyncDebounceMs: 250,
onChangeAsync: async ({ value }) => {
return !value && t('Email required');
},
}}
children={(field) => {
return (
<>
<TextField
variant="outlined"
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
size="small"
label={t('Email')}
required
error={field.state.meta.isTouched && field.state.meta.errors.length > 0}
helperText={field.state.meta.isTouched ? field.state.meta.errors.join(',') : ''}
type="email"
autoComplete="email"
inputMode="email"
fullWidth
/>
</>
);
}}
/>
<form.Field
name="password"
validators={{
onChange: ({ value }) => (!value ? t('Password required') : undefined),
onChangeAsyncDebounceMs: 250,
onChangeAsync: async ({ value }) => {
return !value && t('Password required');
},
}}
children={(field) => {
return (
<>
<TextField
variant="outlined"
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
size="small"
label={t('Password')}
required
error={field.state.meta.isTouched && field.state.meta.errors.length > 0}
helperText={field.state.meta.isTouched ? field.state.meta.errors.join(',') : ''}
type="password"
autoComplete="current-password"
fullWidth
/>
</>
);
}}
/>
<form.Subscribe
selector={(state) => [state.canSubmit, state.isSubmitting]}
children={([canSubmit]) => (
<>
<Button type="submit" disabled={!canSubmit} variant="contained">
{t('Log in')}
</Button>
</>
)}
/>
{error && <ErrorComponent error={error} context="login" />}
</Box>
</form>
);
};
export default LoginForm;