all repos — caroster @ e6df524bf4e90efcb82e2474df6c26952d86b7a4

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

frontend/pages/auth/login.tsx (view raw)

  1import {useTranslation} from 'react-i18next';
  2import Layout from '../../layouts/Centered';
  3import {
  4  Button,
  5  Card,
  6  CardContent,
  7  CardMedia,
  8  Container,
  9  Stack,
 10  TextField,
 11  Typography,
 12  FormHelperText,
 13} from '@mui/material';
 14import Logo from '../../components/Logo';
 15import {getSession} from 'next-auth/react';
 16import pageUtils from '../../lib/pageUtils';
 17import Cookies from 'cookies';
 18import {useState} from 'react';
 19import LoginGoogle from '../../containers/LoginGoogle';
 20import {useSendMagicLinkMutation} from '../../generated/graphql';
 21
 22interface Props {
 23  error?: string;
 24}
 25
 26const Login = (props: Props) => {
 27  const {error} = props;
 28  const {t, i18n} = useTranslation();
 29  const [email, setEmail] = useState('');
 30  const [sent, setSent] = useState(false);
 31  const [magicLinkError, setMagicLinkError] = useState<string>(null);
 32  const [sendMagicLink] = useSendMagicLinkMutation();
 33
 34  const handleSubmit = async (e: React.FormEvent<HTMLButtonElement>) => {
 35    try {
 36      setMagicLinkError(null);
 37      if (email) await sendMagicLink({variables: {email, lang: i18n.language}});
 38      setSent(true);
 39    } catch (error) {
 40      console.error(error);
 41      if (error.message === 'GoogleAccount') setMagicLinkError(error.message);
 42    }
 43  };
 44
 45  return (
 46    <Layout menuTitle={t('signin.title')} displayMenu={false}>
 47      <Container maxWidth="xs">
 48        <Card sx={{pt: 2, width: '100%'}}>
 49          <CardMedia component={Logo} />
 50
 51          <CardContent>
 52            <Stack spacing={2}>
 53              <Typography variant="h6" align="center">
 54                {t('signin.title')}
 55              </Typography>
 56              {(error || magicLinkError) && (
 57                <FormHelperText error sx={{textAlign: 'center'}}>
 58                  {t(errorsMap[error || magicLinkError])}
 59                </FormHelperText>
 60              )}
 61              {!sent && (
 62                <>
 63                  <TextField
 64                    label={t`signin.email`}
 65                    fullWidth
 66                    required
 67                    value={email}
 68                    onChange={e => setEmail(e.target.value)}
 69                    type="email"
 70                  />
 71                  <Button
 72                    fullWidth
 73                    color="primary"
 74                    variant="contained"
 75                    disabled={!email}
 76                    onClick={handleSubmit}
 77                  >
 78                    {t('signin.login')}
 79                  </Button>
 80                  <Typography align="center">{t('signin.or')}</Typography>
 81                  <LoginGoogle />
 82                </>
 83              )}
 84              {sent && (
 85                <Typography
 86                  variant="body2"
 87                  align="center"
 88                >{t`signin.check_email`}</Typography>
 89              )}
 90            </Stack>
 91          </CardContent>
 92        </Card>
 93      </Container>
 94    </Layout>
 95  );
 96};
 97
 98const errorsMap = {
 99  CredentialsSignin: 'signin.errors.CredentialsSignin',
100  GoogleAccount: 'signin.errors.GoogleAccount',
101};
102
103export const getServerSideProps = async (context: any) => {
104  const session = await getSession(context);
105
106  if (session)
107    return {
108      redirect: {
109        destination: '/',
110        permanent: false,
111      },
112    };
113  else
114    return pageUtils.getServerSideProps(async ctx => {
115      const error = ctx.query?.error || null;
116      const redirectPath = ctx.query?.redirectPath;
117
118      if (redirectPath) {
119        const cookies = new Cookies(ctx.req, ctx.res);
120        cookies.set('redirectPath', redirectPath);
121      }
122
123      return {props: {error}};
124    })(context);
125};
126
127export default Login;