all repos — caroster @ v0.9.0

[Octree] Group carpool to your event https://caroster.io

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 {user} = 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 (user?.confirmed) router.replace('/confirm');
 30    else if (user) router.replace('/dashboard');
 31  }, [user]);
 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}&nbsp;
 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;