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