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