app/src/containers/SignInForm/index.js (view raw)
1import React, {useCallback, useState, useMemo, useEffect} from 'react';
2import {Redirect, Link as RouterLink} from 'react-router-dom';
3import {useTranslation} from 'react-i18next';
4import {useAuth} from 'strapi-react-context';
5import TextField from '@material-ui/core/TextField';
6import {useLocation} from 'react-router-dom';
7import Button from '@material-ui/core/Button';
8import Link from '@material-ui/core/Link';
9import Typography from '@material-ui/core/Typography';
10import CardContent from '@material-ui/core/CardContent';
11import CircularProgress from '@material-ui/core/CircularProgress';
12import FormHelperText from '@material-ui/core/FormHelperText';
13import CardActions from '@material-ui/core/CardActions';
14import {makeStyles} from '@material-ui/core/styles';
15import {useToast} from '../../contexts/Toast';
16
17const SignIn = () => {
18 const {t} = useTranslation();
19 const classes = useStyles();
20 const location = useLocation();
21 const {login, token, authState, loginWithProvider} = useAuth();
22 const [isLoading, setIsLoading] = useState(false);
23 const [error, setError] = useState('');
24 const [email, setEmail] = useState('');
25 const [password, setPassword] = useState('');
26 const {addToast} = useToast();
27
28 const canSubmit = useMemo(
29 () => [email, password].filter(s => s.length < 4).length === 0,
30 [email, password]
31 );
32
33 const onSubmit = useCallback(
34 async evt => {
35 if (evt.preventDefault) evt.preventDefault();
36 if (isLoading) {
37 return;
38 }
39 setIsLoading(true);
40 try {
41 await login(email, password);
42 // TODO add to my event if saved in local storage
43 // TODO remove from local storage.
44 } catch (error) {
45 console.log('ERROR', {error});
46 if (error.kind === 'bad_data') {
47 setError(t('signin.errors'));
48 addToast(t('signin.errors'));
49 }
50 }
51
52 setIsLoading(false);
53 return false;
54 },
55 [email, password, login, isLoading, addToast, t]
56 );
57
58 // If an access token is given in URL params, login with auth provider
59 useEffect(() => {
60 const authWithGoogle = async search => {
61 try {
62 await loginWithProvider('google', search);
63 } catch (error) {
64 console.log('ERROR', {error});
65 addToast(t('signin.errors'));
66 }
67 };
68
69 if (location.search) authWithGoogle(location.search);
70 }, [location.search]); // eslint-disable-line react-hooks/exhaustive-deps
71
72 if (token) return <Redirect to="/dashboard" />;
73 if (authState?.user && !authState.user.confirmed)
74 return <Redirect to="/confirm" />;
75
76 return (
77 <form onSubmit={onSubmit}>
78 <CardContent className={classes.content}>
79 <Typography variant="h6">{t('signin.title')}</Typography>
80 {error && <FormHelperText error={true}>{error}</FormHelperText>}
81 <TextField
82 label={t('signin.email')}
83 fullWidth
84 required={true}
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 required={true}
97 margin="dense"
98 value={password}
99 onChange={({target: {value = ''}}) => setPassword(value)}
100 id="SignInEmail"
101 name="password"
102 type="password"
103 error={!!error}
104 gutterBottom
105 />
106 <RouterLink to="/reset-password" component={Link}>
107 <Typography align="center" variant="body2">
108 {t('lost_password.message')}
109 </Typography>
110 </RouterLink>
111 </CardContent>
112 <CardActions className={classes.actions} align="center">
113 <Button id="SignInRegister" href="/register" size="small">
114 {t('signin.register')}
115 </Button>
116 <Button
117 color="primary"
118 variant="contained"
119 type="submit"
120 disabled={!canSubmit}
121 aria-disabled={!canSubmit}
122 id="SignInSubmit"
123 endIcon={
124 isLoading && (
125 <CircularProgress className={classes.loader} size={20} />
126 )
127 }
128 >
129 {t('signin.login')}
130 </Button>
131 </CardActions>
132 </form>
133 );
134};
135
136const useStyles = makeStyles(theme => ({
137 content: {
138 display: 'flex',
139 flexDirection: 'column',
140 alignItems: 'center',
141 },
142 loader: {
143 marginLeft: '14px',
144 color: theme.palette.background.paper,
145 },
146 actions: {
147 justifyContent: 'center',
148 marginBottom: theme.spacing(2),
149 },
150}));
151export default SignIn;