app/src/containers/LostPassword/index.js (view raw)
1import React, {useCallback, useState} from 'react';
2import {Redirect} from 'react-router-dom';
3import {useTranslation} from 'react-i18next';
4import {useAuth} from 'strapi-react-context';
5import TextField from '@material-ui/core/TextField';
6import Button from '@material-ui/core/Button';
7
8import CardContent from '@material-ui/core/CardContent';
9import Card from '@material-ui/core/Card';
10import CircularProgress from '@material-ui/core/CircularProgress';
11import CardActions from '@material-ui/core/CardActions';
12import Link from '@material-ui/core/Link';
13import {useToast} from '../../contexts/Toast';
14import {makeStyles} from '@material-ui/core/styles';
15import LostPasswordSuccess from './Success';
16
17const LostPassword = () => {
18 const {t} = useTranslation();
19 const classes = useStyles();
20
21 const {token, authState, sendPasswordReset} = useAuth();
22 const [isLoading, setIsLoading] = useState(false);
23 const [error, setError] = useState('');
24 const [email, setEmail] = useState('');
25 const [isSent, setIsSent] = useState(false);
26 const {addToast} = useToast();
27
28 const canSubmit = () => email.length < 4;
29
30 const onSubmit = useCallback(
31 async evt => {
32 if (evt.preventDefault) evt.preventDefault();
33 if (isLoading) {
34 return;
35 }
36 setIsLoading(true);
37 try {
38 await sendPasswordReset(email);
39 setIsSent(true);
40 } catch (error) {
41 if (error.kind === 'bad_data') {
42 addToast(t('lost_password.error'));
43 setError(t('lost_password.error'));
44 } else {
45 addToast(t('generic.errors.unknown'));
46 }
47 }
48 setIsLoading(false);
49 return false;
50 },
51 [sendPasswordReset, email, isLoading, addToast, t]
52 );
53
54 if (token) {
55 return <Redirect to="/dashboard" />;
56 }
57 if (authState && authState.user && !authState.user.confirmed) {
58 return <Redirect to="/confirm" />;
59 }
60
61 if (!isLoading && isSent) {
62 return <LostPasswordSuccess email={email} />;
63 }
64
65 return (
66 <form onSubmit={onSubmit}>
67 <Card>
68 <CardContent>
69 <TextField
70 label={t('lost_password.email')}
71 fullWidth
72 required={true}
73 margin="dense"
74 value={email}
75 onChange={({target: {value = ''}}) => setEmail(value)}
76 id="LostPasswordEmail"
77 name="email"
78 type="email"
79 error={!!error}
80 helperText={
81 error && (
82 <>
83 {error}
84 <Link href="/register">
85 {t('lost_password.actions.register')}
86 </Link>
87 </>
88 )
89 }
90 />
91 </CardContent>
92 <CardActions className={classes.actions}>
93 <Button id="LostPasswordRegister" href="/login">
94 {t('lost_password.actions.cancel')}
95 </Button>
96
97 <Button
98 color="primary"
99 variant="contained"
100 type="submit"
101 disabled={!canSubmit}
102 aria-disabled={!canSubmit}
103 id="LostPasswordSubmit"
104 >
105 {t('lost_password.actions.send')}
106 {isLoading && (
107 <CircularProgress
108 className={classes.loader}
109 color="primary"
110 size={20}
111 />
112 )}
113 </Button>
114 </CardActions>
115 </Card>
116 </form>
117 );
118};
119
120const useStyles = makeStyles(theme => ({
121 loader: {
122 marginLeft: theme.spacing(4),
123 },
124 actions: {
125 marginTop: theme.spacing(2),
126 justifyContent: 'flex-end',
127 },
128}));
129export default LostPassword;