frontend/containers/SignInForm/index.tsx (view raw)
1import {useState, useMemo} from 'react';
2import NextLink from 'next/link';
3import TextField from '@mui/material/TextField';
4import Button from '@mui/material/Button';
5import Link from '@mui/material/Link';
6import Typography from '@mui/material/Typography';
7import CardContent from '@mui/material/CardContent';
8import FormHelperText from '@mui/material/FormHelperText';
9import CardActions from '@mui/material/CardActions';
10import Divider from '@mui/material/Divider';
11import Box from '@mui/material/Box';
12import {useTheme} from '@mui/material/styles';
13import {useTranslation} from 'react-i18next';
14import {signIn} from 'next-auth/react';
15import useAddToEvents from '../../hooks/useAddToEvents';
16import LoginGoogle from '../LoginGoogle';
17
18interface Props {
19 error?: string;
20}
21
22const SignIn = (props: Props) => {
23 const {error} = props;
24 const {t} = useTranslation();
25 const theme = useTheme();
26 const [email, setEmail] = useState('');
27 const [password, setPassword] = useState('');
28 const {saveStoredEvents} = useAddToEvents();
29
30 const canSubmit = useMemo(
31 () => [email, password].filter(s => s.length < 4).length === 0,
32 [email, password]
33 );
34
35 const onSubmit = async e => {
36 e.preventDefault?.();
37 try {
38 await signIn('credentials', {
39 email,
40 password,
41 callbackUrl: '/',
42 });
43 saveStoredEvents(); // TODO Check it's correctly executed after sign-in
44 } catch (error) {
45 console.error(error);
46 }
47
48 return false;
49 };
50
51 const spaceAround = {
52 width: '100%',
53 textAlign: 'center',
54 margin: theme.spacing(2, 0),
55 };
56
57 return (
58 <form onSubmit={onSubmit}>
59 <CardContent
60 sx={{
61 display: 'flex',
62 flexDirection: 'column',
63 padding: theme.spacing(0, 6),
64 }}
65 >
66 <Typography variant="h6" align="center">
67 {t('signin.title')}
68 </Typography>
69 {error && (
70 <FormHelperText error={true}>
71 {t(`signin.errors.${error}`)}
72 </FormHelperText>
73 )}
74 <Box
75 sx={{
76 display: 'flex',
77 flexDirection: 'column',
78 padding: {sm: theme.spacing(0, 6), xs: 0},
79 }}
80 >
81 <TextField
82 label={t('signin.email')}
83 fullWidth
84 required={true}
85 InputLabelProps={{required: false}}
86 margin="dense"
87 value={email}
88 onChange={({target: {value = ''}}) => setEmail(value)}
89 id="SignInEmail"
90 name="email"
91 type="email"
92 error={!!error}
93 />
94 <TextField
95 label={t('signin.password')}
96 fullWidth
97 InputLabelProps={{required: false}}
98 required={true}
99 margin="dense"
100 value={password}
101 onChange={({target: {value = ''}}) => setPassword(value)}
102 id="SignInEmail"
103 name="password"
104 type="password"
105 error={!!error}
106 />
107 </Box>
108
109 <Box sx={spaceAround}>
110 <NextLink href="/auth/lost-password" passHref>
111 <Link>
112 <Typography align="center" variant="body2">
113 {t('lost_password.message')}
114 </Typography>
115 </Link>
116 </NextLink>
117 </Box>
118 <Box
119 sx={{
120 display: 'flex',
121 flexDirection: 'column',
122 alignItems: 'center',
123 width: '100%',
124 padding: {md: theme.spacing(0, 16), sm: theme.spacing(0, 6)},
125 }}
126 >
127 <Button
128 color="primary"
129 variant="contained"
130 fullWidth
131 type="submit"
132 disabled={!canSubmit}
133 aria-disabled={!canSubmit}
134 id="SignInSubmit"
135 >
136 {t('signin.login')}
137 </Button>
138 <Box sx={spaceAround}>
139 <Typography>{t('signin.or')}</Typography>
140 </Box>
141 <LoginGoogle />
142 </Box>
143 <Box sx={spaceAround}>
144 <Divider />
145 </Box>
146 <Typography align="center" variant="body2">
147 {t('signin.no_account')}
148 </Typography>
149 </CardContent>
150 <CardActions
151 sx={{
152 justifyContent: 'center',
153 marginBottom: theme.spacing(2),
154 textAlign: 'center',
155 }}
156 >
157 <NextLink href="/auth/register" passHref>
158 <Button size="small" id="SignInRegister">
159 {t('signin.register')}
160 </Button>
161 </NextLink>
162 </CardActions>
163 </form>
164 );
165};
166
167export default SignIn;