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