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