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;