all repos — caroster @ 3010fd5066be948e41801643efc745089461e26a

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

frontend/containers/SignInForm/index.tsx (view raw)

  1import {useState, useMemo, useEffect} from 'react';
  2import {useRouter} from 'next/router';
  3import RouterLink from 'next/link';
  4import {makeStyles} from '@material-ui/core/styles';
  5import TextField from '@material-ui/core/TextField';
  6import Button from '@material-ui/core/Button';
  7import Link from '@material-ui/core/Link';
  8import Typography from '@material-ui/core/Typography';
  9import CardContent from '@material-ui/core/CardContent';
 10import CircularProgress from '@material-ui/core/CircularProgress';
 11import FormHelperText from '@material-ui/core/FormHelperText';
 12import CardActions from '@material-ui/core/CardActions';
 13import {useTranslation} from 'react-i18next';
 14import useToastsStore from '../../stores/useToastStore';
 15import useLoginWithProvider from '../../hooks/useLoginWithProvider';
 16import useLoginForm from '../../hooks/useLoginForm';
 17import useAddToEvents from '../../hooks/useAddToEvents';
 18
 19const SignIn = () => {
 20  const {t} = useTranslation();
 21  const router = useRouter();
 22  const {loginWithProvider} = useLoginWithProvider();
 23  const [error, setError] = useState('');
 24  const [email, setEmail] = useState('');
 25  const [password, setPassword] = useState('');
 26  const addToast = useToastsStore(s => s.addToast);
 27  const {login, loading} = useLoginForm(email, password);
 28  const {saveStoredEvents} = useAddToEvents();
 29  const classes = useStyles();
 30
 31  const canSubmit = useMemo(
 32    () => [email, password].filter(s => s.length < 4).length === 0,
 33    [email, password]
 34  );
 35
 36  const onSubmit = async e => {
 37    e.preventDefault?.();
 38    try {
 39      await login();
 40      saveStoredEvents();
 41      router.push('/');
 42    } catch (error) {
 43      handleAuthError(error);
 44    }
 45
 46    return false;
 47  };
 48
 49  useEffect(() => {
 50    const authWithGoogle = async search => {
 51      try {
 52        await loginWithProvider('google', search);
 53      } catch (error) {
 54        handleAuthError(error);
 55      }
 56    };
 57
 58    const search = getURLSearch(router);
 59    if (search) authWithGoogle(search);
 60  }, [router.route]); // eslint-disable-line react-hooks/exhaustive-deps
 61
 62  const handleAuthError = error => {
 63    const strapiError = error.message;
 64    console.error({strapiError});
 65    if (strapiError === 'Invalid identifier or password') {
 66      setError(t('signin.errors'));
 67      addToast(t('signin.errors'));
 68    } else if (strapiError === 'Auth.form.error.confirmed') {
 69      setError(t('signin.unconfirmed'));
 70      addToast(t('signin.unconfirmed'));
 71    }
 72  };
 73
 74  return (
 75    <form onSubmit={onSubmit}>
 76      <CardContent className={classes.content}>
 77        <Typography variant="h6">{t('signin.title')}</Typography>
 78        {error && <FormHelperText error={true}>{error}</FormHelperText>}
 79        <TextField
 80          label={t('signin.email')}
 81          fullWidth
 82          required={true}
 83          margin="dense"
 84          value={email}
 85          onChange={({target: {value = ''}}) => setEmail(value)}
 86          id="SignInEmail"
 87          name="email"
 88          type="email"
 89          error={!!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        />
103        <RouterLink href="/auth/lost-password">
104          <Link>
105            <Typography align="center" variant="body2">
106              {t('lost_password.message')}
107            </Typography>
108          </Link>
109        </RouterLink>
110      </CardContent>
111      <CardActions className={classes.actions} align="center">
112        <Button size="small" id="SignInRegister" href="/auth/register">
113          {t('signin.register')}
114        </Button>
115        <Button
116          color="primary"
117          variant="contained"
118          type="submit"
119          disabled={!canSubmit}
120          aria-disabled={!canSubmit}
121          id="SignInSubmit"
122          endIcon={
123            loading && <CircularProgress className={classes.loader} size={20} />
124          }
125        >
126          {t('signin.login')}
127        </Button>
128      </CardActions>
129    </form>
130  );
131};
132
133const getURLSearch = router => router.asPath.replace(router.route, '');
134
135const useStyles = makeStyles(theme => ({
136  content: {
137    display: 'flex',
138    flexDirection: 'column',
139  },
140  loader: {
141    marginLeft: '14px',
142    color: theme.palette.background.paper,
143  },
144  actions: {
145    justifyContent: 'center',
146    marginBottom: theme.spacing(2),
147  },
148}));
149export default SignIn;