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: '/dashboard',
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 px: 2,
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 }}
79 >
80 <TextField
81 label={t('signin.email')}
82 fullWidth
83 required={true}
84 InputLabelProps={{required: false}}
85 margin="dense"
86 value={email}
87 onChange={({target: {value = ''}}) => setEmail(value)}
88 id="SignInEmail"
89 name="email"
90 type="email"
91 error={!!error}
92 />
93 <TextField
94 label={t('signin.password')}
95 fullWidth
96 InputLabelProps={{required: false}}
97 required={true}
98 margin="dense"
99 value={password}
100 onChange={({target: {value = ''}}) => setPassword(value)}
101 id="SignInEmail"
102 name="password"
103 type="password"
104 error={!!error}
105 />
106 </Box>
107
108 <Box sx={spaceAround}>
109 <NextLink href="/auth/lost-password" passHref>
110 <Link>
111 <Typography align="center" variant="body2">
112 {t('lost_password.message')}
113 </Typography>
114 </Link>
115 </NextLink>
116 </Box>
117 <Box
118 sx={{
119 display: 'flex',
120 flexDirection: 'column',
121 alignItems: 'center',
122 width: '100%',
123 pb: 1
124 }}
125 >
126 <Button
127 color="primary"
128 variant="contained"
129 fullWidth
130 type="submit"
131 disabled={!canSubmit}
132 aria-disabled={!canSubmit}
133 id="SignInSubmit"
134 >
135 {t('signin.login')}
136 </Button>
137 <Box sx={spaceAround}>
138 <Typography>{t('signin.or')}</Typography>
139 </Box>
140 <LoginGoogle />
141 </Box>
142 </CardContent>
143 <Divider />
144 <CardActions
145 sx={{
146 flexDirection: 'column',
147 justifyContent: 'center',
148 marginBottom: theme.spacing(2),
149 textAlign: 'center',
150 px: 2,
151 }}
152 >
153 <Typography align="center" variant="body2" sx={{pt: 2}}>
154 {t('signin.no_account')}
155 </Typography>
156 <NextLink href="/auth/register" passHref>
157 <Button size="small" id="SignInRegister">
158 {t('signin.register')}
159 </Button>
160 </NextLink>
161 </CardActions>
162 </form>
163 );
164};
165
166export default SignIn;