frontend/containers/SignInForm/index.tsx (view raw)
1import {useState, useMemo} from 'react';
2import RouterLink 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 useToastsStore from '../../stores/useToastStore';
14import useAddToEvents from '../../hooks/useAddToEvents';
15import useRedirectUrlStore from '../../stores/useRedirectUrl';
16
17const SignIn = () => {
18 const {t} = useTranslation();
19 const [error, setError] = useState('');
20 const [email, setEmail] = useState('');
21 const [password, setPassword] = useState('');
22 const addToast = useToastsStore(s => s.addToast);
23 const {saveStoredEvents} = useAddToEvents();
24 const classes = useStyles();
25 const getRedirectUrl = useRedirectUrlStore(s => s.getRedirectUrl);
26
27 const canSubmit = useMemo(
28 () => [email, password].filter(s => s.length < 4).length === 0,
29 [email, password]
30 );
31
32 const onSubmit = async e => {
33 e.preventDefault?.();
34 try {
35 const callbackUrl = getRedirectUrl() || '/';
36 await signIn('credentials', {
37 email,
38 password,
39 callbackUrl,
40 });
41 saveStoredEvents(); // TODO Check it's correctly executed after sign-in
42 } catch (error) {
43 handleAuthError(error);
44 }
45
46 return false;
47 };
48
49 const handleAuthError = error => {
50 const strapiError = error.message;
51 console.error({strapiError});
52 if (strapiError === 'Invalid identifier or password') {
53 setError(t('signin.errors'));
54 addToast(t('signin.errors'));
55 } else if (strapiError === 'Auth.form.error.confirmed') {
56 setError(t('signin.unconfirmed'));
57 addToast(t('signin.unconfirmed'));
58 }
59 };
60
61 return (
62 <form onSubmit={onSubmit}>
63 <CardContent className={classes.content}>
64 <Typography variant="h6">{t('signin.title')}</Typography>
65 {error && <FormHelperText error={true}>{error}</FormHelperText>}
66 <TextField
67 label={t('signin.email')}
68 fullWidth
69 required={true}
70 margin="dense"
71 value={email}
72 onChange={({target: {value = ''}}) => setEmail(value)}
73 id="SignInEmail"
74 name="email"
75 type="email"
76 error={!!error}
77 />
78 <TextField
79 label={t('signin.password')}
80 fullWidth
81 required={true}
82 margin="dense"
83 value={password}
84 onChange={({target: {value = ''}}) => setPassword(value)}
85 id="SignInEmail"
86 name="password"
87 type="password"
88 error={!!error}
89 />
90 <RouterLink href="/auth/lost-password">
91 <Link>
92 <Typography align="center" variant="body2">
93 {t('lost_password.message')}
94 </Typography>
95 </Link>
96 </RouterLink>
97 </CardContent>
98 <CardActions className={classes.actions} align="center">
99 <Button size="small" id="SignInRegister" href="/auth/register">
100 {t('signin.register')}
101 </Button>
102 <Button
103 color="primary"
104 variant="contained"
105 type="submit"
106 disabled={!canSubmit}
107 aria-disabled={!canSubmit}
108 id="SignInSubmit"
109 >
110 {t('signin.login')}
111 </Button>
112 </CardActions>
113 </form>
114 );
115};
116
117const useStyles = makeStyles(theme => ({
118 content: {
119 display: 'flex',
120 flexDirection: 'column',
121 },
122 actions: {
123 justifyContent: 'center',
124 marginBottom: theme.spacing(2),
125 },
126}));
127export default SignIn;