frontend/containers/SignUpForm/index.js (view raw)
1import {useState, useMemo} from 'react';
2import {useTranslation} from 'react-i18next';
3import TextField from '@material-ui/core/TextField';
4import {useRouter} from 'next/router';
5import Button from '@material-ui/core/Button';
6import CardContent from '@material-ui/core/CardContent';
7import CardActions from '@material-ui/core/CardActions';
8import Typography from '@material-ui/core/Typography';
9import CircularProgress from '@material-ui/core/CircularProgress';
10import {makeStyles} from '@material-ui/core/styles';
11import useToastsStore from '../../stores/useToastStore';
12import {useRegisterMutation} from '../../generated/graphql';
13import useAuthStore from '../../stores/useAuthStore';
14import useAddToEvents from '../../hooks/useAddToEvents';
15
16const SignUp = () => {
17 const {t} = useTranslation();
18 const classes = useStyles();
19 const addToast = useToastsStore(s => s.addToast);
20 const router = useRouter();
21 const setToken = useAuthStore(s => s.setToken);
22 const setUser = useAuthStore(s => s.setUser);
23 const [isLoading, setIsLoading] = useState(false);
24 const [error, setError] = useState('');
25 const [firstName, setFirstName] = useState('');
26 const [lastName, setLastName] = useState('');
27 const [email, setEmail] = useState('');
28 const [password, setPassword] = useState('');
29 const [register] = useRegisterMutation();
30 const {saveStoredEvents} = useAddToEvents();
31
32 const canSubmit = useMemo(
33 () =>
34 [firstName, lastName, email, password].filter(s => s.length < 2)
35 .length === 0,
36 [firstName, lastName, email, password]
37 );
38
39 const onSubmit = async e => {
40 e.preventDefault?.();
41 if (isLoading) return;
42 setIsLoading(true);
43 try {
44 const {data} = await register({
45 variables: {
46 email,
47 password,
48 username: `${firstName} ${lastName}`,
49 },
50 });
51 setToken(data.register.jwt);
52 setUser(data.register.user);
53 saveStoredEvents();
54 router.push('/dashboard');
55 } catch (error) {
56 const strapiError = getStrapiError(error);
57 console.error({strapiError});
58 if (strapiError === 'Auth.form.error.email.taken')
59 setError(t('signup.errors.email_taken'));
60 else addToast(t(`generic.errors.unknown`));
61 }
62 setIsLoading(false);
63 return false;
64 };
65
66 return (
67 <form onSubmit={onSubmit}>
68 <CardContent className={classes.content}>
69 <Typography variant="h6">{t('signup.title')}</Typography>
70 <TextField
71 label={t('signup.firstName')}
72 fullWidth
73 autoFocus
74 margin="dense"
75 value={firstName}
76 required={true}
77 onChange={({target: {value = ''}}) => setFirstName(value)}
78 id="SignUpFirstName"
79 name="firstName"
80 />
81 <TextField
82 label={t('signup.lastName')}
83 fullWidth
84 required={true}
85 margin="dense"
86 value={lastName}
87 onChange={({target: {value = ''}}) => setLastName(value)}
88 id="SignUpLastName"
89 name="lastName"
90 />
91 <TextField
92 label={t('signup.email')}
93 fullWidth
94 required={true}
95 error={!!error}
96 helperText={error}
97 margin="dense"
98 value={email}
99 onChange={({target: {value = ''}}) => setEmail(value)}
100 id="SignUpEmail"
101 name="email"
102 type="email"
103 />
104 <TextField
105 label={t('signup.password')}
106 fullWidth
107 gutterBottom
108 required={true}
109 margin="dense"
110 value={password}
111 onChange={({target: {value = ''}}) => setPassword(value)}
112 id="SignUpEmail"
113 name="password"
114 type="password"
115 />
116 </CardContent>
117 <CardActions className={classes.actions}>
118 <Button id="SignUpLogin" href="/auth/login" variant="text">
119 {t('signup.login')}
120 </Button>
121 <Button
122 color="primary"
123 variant="contained"
124 type="submit"
125 disabled={!canSubmit}
126 className={classes.button}
127 aria-disabled={!canSubmit}
128 id="SignUpSubmit"
129 iconEnd={
130 isLoading && (
131 <CircularProgress
132 class={classes.loader}
133 size={20}
134 color="secondary"
135 />
136 )
137 }
138 >
139 {t('signup.submit')}
140 </Button>
141 </CardActions>
142 </form>
143 );
144};
145
146const getStrapiError = error => {
147 if (error.message?.[0]?.messages?.[0]) return error.message[0].messages[0].id;
148 return error?.graphQLErrors?.[0].extensions.exception.data.message[0]
149 .messages[0].id;
150};
151
152const useStyles = makeStyles(theme => ({
153 content: {
154 display: 'flex',
155 flexDirection: 'column',
156 alignItems: 'center',
157 },
158 loader: {
159 marginLeft: '14px',
160 color: theme.palette.background.paper,
161 },
162 actions: {
163 justifyContent: 'center',
164 marginBottom: theme.spacing(2),
165 },
166 button: {
167 margin: theme.spacing(1),
168 },
169}));
170export default SignUp;