frontend/containers/MailSignUpForm/index.tsx (view raw)
1import {useState, useMemo} from 'react';
2import Box from '@mui/material/Box';
3import Divider from '@mui/material/Divider';
4import Checkbox from '@mui/material/Checkbox';
5import FormControlLabel from '@mui/material/FormControlLabel';
6import TextField from '@mui/material/TextField';
7import Button from '@mui/material/Button';
8import CardContent from '@mui/material/CardContent';
9import Typography from '@mui/material/Typography';
10import CircularProgress from '@mui/material/CircularProgress';
11import {useTheme} from '@mui/material/styles';
12import {useTranslation} from 'react-i18next';
13import {useRouter} from 'next/router';
14import useToastsStore from '../../stores/useToastStore';
15import SignUpActions from './SignupActions';
16import {useRegisterMutation} from '../../generated/graphql';
17
18const SignUp = () => {
19 const {t, i18n} = useTranslation();
20 const theme = useTheme();
21 const addToast = useToastsStore(s => s.addToast);
22 const router = useRouter();
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 [newsletterConsent, setNewsletterConsent] = useState(false);
30 const [register] = useRegisterMutation();
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 lang = i18n.language;
45 await register({
46 variables: {
47 user: {
48 username: email,
49 email,
50 password,
51 firstName,
52 lastName,
53 newsletterConsent,
54 lang,
55 },
56 },
57 });
58 router.push('/auth/confirm');
59 } catch (error) {
60 const strapiError = error.message;
61 console.error({strapiError});
62 if (strapiError === 'Email or Username are already taken')
63 setError(t('signup.errors.email_taken'));
64 else addToast(t(`generic.errors.unknown`));
65 }
66 setIsLoading(false);
67 return false;
68 };
69
70 const contentSx = {
71 display: 'flex',
72 flexDirection: 'column',
73 alignItems: 'center',
74 width: '100%',
75 padding: theme.spacing(0, 4),
76 };
77
78 return (
79 <form onSubmit={onSubmit}>
80 <CardContent sx={contentSx}>
81 <Typography
82 variant="h6"
83 align="center"
84 sx={{
85 whiteSpace: 'pre-line',
86 paddingBottom: theme.spacing(4),
87 }}
88 >
89 {t('signup.createForm')}
90 </Typography>
91 <Box sx={contentSx}>
92 <TextField
93 label={t('signup.firstName')}
94 fullWidth
95 autoFocus
96 margin="dense"
97 value={firstName}
98 InputLabelProps={{required: false}}
99 required={true}
100 onChange={({target: {value = ''}}) => setFirstName(value)}
101 id="SignUpFirstName"
102 name="firstName"
103 />
104 <TextField
105 label={t('signup.lastName')}
106 fullWidth
107 InputLabelProps={{required: false}}
108 required={true}
109 margin="dense"
110 value={lastName}
111 onChange={({target: {value = ''}}) => setLastName(value)}
112 id="SignUpLastName"
113 name="lastName"
114 />
115 <TextField
116 label={t('signup.email')}
117 fullWidth
118 InputLabelProps={{required: false}}
119 required={true}
120 error={!!error}
121 helperText={error}
122 margin="dense"
123 value={email}
124 onChange={({target: {value = ''}}) => setEmail(value)}
125 id="SignUpEmail"
126 name="email"
127 type="email"
128 />
129 <TextField
130 label={t('signup.password')}
131 fullWidth
132 InputLabelProps={{required: false}}
133 required={true}
134 margin="dense"
135 value={password}
136 onChange={({target: {value = ''}}) => setPassword(value)}
137 id="SignUpEmail"
138 name="password"
139 type="password"
140 />
141 </Box>
142 <FormControlLabel
143 sx={{width: '100%', margin: theme.spacing(2, 0), padding: theme.spacing(0, 4)}}
144 componentsProps={{typography: {align: 'left', variant: 'body2'}}}
145 control={
146 <Checkbox
147 sx={{padding: 0, marginRight: theme.spacing(2)}}
148 color="primary"
149 value={newsletterConsent}
150 onChange={({target: {checked = false}}) =>
151 setNewsletterConsent(checked)
152 }
153 />
154 }
155 label={t('signup.newsletter.consent')}
156 />
157
158 <Box sx={contentSx}>
159 <Button
160 color="primary"
161 variant="contained"
162 fullWidth
163 type="submit"
164 disabled={!canSubmit}
165 sx={{margin: theme.spacing(1)}}
166 aria-disabled={!canSubmit}
167 id="SignUpSubmit"
168 endIcon={
169 isLoading && (
170 <CircularProgress
171 sx={{
172 marginLeft: '14px',
173 color: theme.palette.background.paper,
174 }}
175 size={20}
176 color="secondary"
177 />
178 )
179 }
180 >
181 {t('signup.submit')}
182 </Button>
183 </Box>
184 <Box
185 sx={{width: '100%', textAlign: 'center', margin: theme.spacing(2, 0)}}
186 >
187 <Divider />
188 </Box>
189 <Typography align="center" variant="body2">
190 {t('signup.account_already')}
191 </Typography>
192 </CardContent>
193 <SignUpActions />
194 </form>
195 );
196};
197
198export default SignUp;