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