all repos — caroster @ 4a54c6a4bbd827770897a0aa72b8408835752d25

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

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

  1import {useState, useMemo} from 'react';
  2import NextLink from 'next/link';
  3import TextField from '@mui/material/TextField';
  4import Button from '@mui/material/Button';
  5import Typography from '@mui/material/Typography';
  6import CardContent from '@mui/material/CardContent';
  7import FormHelperText from '@mui/material/FormHelperText';
  8import CardActions from '@mui/material/CardActions';
  9import Divider from '@mui/material/Divider';
 10import Box from '@mui/material/Box';
 11import {useTheme} from '@mui/material/styles';
 12import {useTranslation} from 'react-i18next';
 13import {signIn} from 'next-auth/react';
 14import useAddToEvents from '../../hooks/useAddToEvents';
 15import LoginGoogle from '../LoginGoogle';
 16
 17interface Props {
 18  error?: string;
 19}
 20
 21const errorsMap = {
 22  CredentialsSignin: 'signin.errors.CredentialsSignin',
 23  EmailNotConfirmed: 'signin.errors.EmailNotConfirmed',
 24};
 25
 26const SignIn = (props: Props) => {
 27  const {error} = props;
 28  const {t} = useTranslation();
 29  const theme = useTheme();
 30  const [email, setEmail] = useState('');
 31  const [password, setPassword] = useState('');
 32  const {saveStoredEvents} = useAddToEvents();
 33
 34  const canSubmit = useMemo(
 35    () => [email, password].filter(s => s.length < 4).length === 0,
 36    [email, password]
 37  );
 38
 39  const onSubmit = async e => {
 40    e.preventDefault?.();
 41    try {
 42      await signIn('credentials', {
 43        email,
 44        password,
 45        callbackUrl: '/dashboard',
 46      });
 47      saveStoredEvents();
 48    } catch (error) {
 49      console.error(error);
 50    }
 51
 52    return false;
 53  };
 54
 55  const spaceAround = {
 56    width: '100%',
 57    textAlign: 'center',
 58    margin: theme.spacing(2, 0),
 59  };
 60
 61  return (
 62    <form onSubmit={onSubmit}>
 63      <CardContent
 64        sx={{
 65          display: 'flex',
 66          flexDirection: 'column',
 67          px: 2,
 68        }}
 69      >
 70        <Typography variant="h6" align="center">
 71          {t('signin.title')}
 72        </Typography>
 73        {error && (
 74          <FormHelperText error sx={{textAlign: 'center'}}>
 75            {t(errorsMap[error])}
 76          </FormHelperText>
 77        )}
 78        <Box
 79          sx={{
 80            display: 'flex',
 81            flexDirection: 'column',
 82          }}
 83        >
 84          <TextField
 85            label={t('signin.email')}
 86            fullWidth
 87            required={true}
 88            InputLabelProps={{required: false}}
 89            margin="dense"
 90            value={email}
 91            onChange={({target: {value = ''}}) => setEmail(value)}
 92            name="email"
 93            type="email"
 94            error={!!error}
 95          />
 96          <TextField
 97            label={t('signin.password')}
 98            fullWidth
 99            InputLabelProps={{required: false}}
100            required={true}
101            margin="dense"
102            value={password}
103            onChange={({target: {value = ''}}) => setPassword(value)}
104            id="SignInEmail"
105            name="password"
106            type="password"
107            error={!!error}
108          />
109        </Box>
110
111        <Box sx={spaceAround}>
112          <NextLink href="/auth/lost-password" passHref>
113            <Typography
114              align="center"
115              variant="body2"
116              color="primary"
117              sx={{
118                textDecoration: 'underline',
119                textDecorationColor: 'primary',
120              }}
121            >
122              {t('lost_password.message')}
123            </Typography>
124          </NextLink>
125        </Box>
126        <Box
127          sx={{
128            display: 'flex',
129            flexDirection: 'column',
130            alignItems: 'center',
131            width: '100%',
132            pb: 1,
133          }}
134        >
135          <Button
136            color="primary"
137            variant="contained"
138            fullWidth
139            type="submit"
140            disabled={!canSubmit}
141            aria-disabled={!canSubmit}
142          >
143            {t('signin.login')}
144          </Button>
145          <Box sx={spaceAround}>
146            <Typography>{t('signin.or')}</Typography>
147          </Box>
148          <LoginGoogle />
149        </Box>
150      </CardContent>
151      <Divider />
152      <CardActions
153        sx={{
154          flexDirection: 'column',
155          justifyContent: 'center',
156          marginBottom: theme.spacing(2),
157          textAlign: 'center',
158          px: 2,
159        }}
160      >
161        <Typography align="center" variant="body2" sx={{pt: 2}}>
162          {t('signin.no_account')}
163        </Typography>
164        <NextLink href="/auth/register" passHref>
165          <Button size="small">{t('signin.register')}</Button>
166        </NextLink>
167      </CardActions>
168    </form>
169  );
170};
171
172export default SignIn;