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