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 {Trans, useTranslation} from 'next-i18next';
13import {useRouter} from 'next/router';
14import useToastsStore from '../../stores/useToastStore';
15import SignUpActions from './SignupActions';
16import {useRegisterMutation} from '../../generated/graphql';
17import useSettings from '../../hooks/useSettings';
18import moment from 'moment';
19
20const SignUp = () => {
21 const {t, i18n} = useTranslation();
22 const theme = useTheme();
23 const addToast = useToastsStore(s => s.addToast);
24 const router = useRouter();
25 const [isLoading, setIsLoading] = useState(false);
26 const [error, setError] = useState('');
27 const [firstName, setFirstName] = useState('');
28 const [lastName, setLastName] = useState('');
29 const [email, setEmail] = useState('');
30 const [password, setPassword] = useState('');
31 const [newsletterConsent, setNewsletterConsent] = useState(false);
32 const [tosConsent, setTosConsent] = useState(false);
33 const [register] = useRegisterMutation();
34 const settings = useSettings();
35
36 const canSubmit = useMemo(
37 () =>
38 [firstName, lastName, email, password].filter(s => s.length < 2)
39 .length === 0 && tosConsent,
40 [firstName, lastName, email, password, tosConsent]
41 );
42
43 const onSubmit = async e => {
44 e.preventDefault?.();
45 if (isLoading) return;
46 setIsLoading(true);
47 const tosAcceptationDate = tosConsent ? moment().toISOString() : null;
48 try {
49 const lang = i18n.language;
50 await register({
51 variables: {
52 user: {
53 username: email,
54 email,
55 password,
56 firstName,
57 lastName,
58 newsletterConsent,
59 tosAcceptationDate,
60 lang,
61 },
62 },
63 });
64 router.push('/auth/confirm');
65 } catch (error) {
66 const strapiError = error.message;
67 console.error({strapiError});
68 if (strapiError === 'Email or Username are already taken')
69 setError(t('signup.errors.email_taken'));
70 else addToast(t(`generic.errors.unknown`));
71 }
72 setIsLoading(false);
73 return false;
74 };
75
76 const contentSx = {
77 display: 'flex',
78 flexDirection: 'column',
79 alignItems: 'center',
80 width: '100%',
81 padding: theme.spacing(0, 4),
82 };
83
84 return (
85 <form onSubmit={onSubmit}>
86 <CardContent sx={contentSx}>
87 <Typography
88 variant="h6"
89 align="center"
90 sx={{
91 whiteSpace: 'pre-line',
92 paddingBottom: theme.spacing(4),
93 }}
94 >
95 {t('signup.createForm')}
96 </Typography>
97 <Box sx={contentSx}>
98 <TextField
99 label={t('signup.firstName')}
100 fullWidth
101 autoFocus
102 margin="dense"
103 value={firstName}
104 InputLabelProps={{required: false}}
105 required={true}
106 onChange={({target: {value = ''}}) => setFirstName(value)}
107 id="SignUpFirstName"
108 name="firstName"
109 />
110 <TextField
111 label={t('signup.lastName')}
112 fullWidth
113 InputLabelProps={{required: false}}
114 required={true}
115 margin="dense"
116 value={lastName}
117 onChange={({target: {value = ''}}) => setLastName(value)}
118 id="SignUpLastName"
119 name="lastName"
120 />
121 <TextField
122 label={t('signup.email')}
123 fullWidth
124 InputLabelProps={{required: false}}
125 required={true}
126 error={!!error}
127 helperText={error}
128 margin="dense"
129 value={email}
130 onChange={({target: {value = ''}}) => setEmail(value)}
131 id="SignUpEmail"
132 name="email"
133 type="email"
134 />
135 <TextField
136 label={t('signup.password')}
137 fullWidth
138 InputLabelProps={{required: false}}
139 required={true}
140 margin="dense"
141 value={password}
142 onChange={({target: {value = ''}}) => setPassword(value)}
143 id="SignUpEmail"
144 name="password"
145 type="password"
146 />
147 </Box>
148 <FormControlLabel
149 sx={{
150 width: '100%',
151 mt: 2,
152 px: 5.5,
153 }}
154 componentsProps={{typography: {align: 'left', variant: 'body2'}}}
155 control={
156 <Checkbox
157 sx={{p: 0, mr: 2}}
158 color="primary"
159 value={newsletterConsent}
160 onChange={({target: {checked = false}}) =>
161 setNewsletterConsent(checked)
162 }
163 />
164 }
165 label={t('signup.newsletter.consent')}
166 />
167 <FormControlLabel
168 sx={{width: '100%', mt: 2, px: 5.5}}
169 componentsProps={{typography: {align: 'left', variant: 'body2'}}}
170 label={
171 <Trans
172 i18nKey="signup.tos.consent"
173 components={{
174 'tos-link': <a href={settings.tos_link} target="_blank" />,
175 'data-privacy-link': (
176 <a href={settings.data_policy_link} target="_blank" />
177 ),
178 }}
179 />
180 }
181 control={
182 <Checkbox
183 sx={{p: 0, mr: 2}}
184 value={tosConsent}
185 onChange={e => setTosConsent(e.target.checked)}
186 />
187 }
188 />
189
190 <Box sx={contentSx} mt={2}>
191 <Button
192 color="primary"
193 variant="contained"
194 fullWidth
195 type="submit"
196 disabled={!canSubmit}
197 sx={{margin: theme.spacing(1)}}
198 aria-disabled={!canSubmit}
199 id="SignUpSubmit"
200 endIcon={
201 isLoading && (
202 <CircularProgress
203 sx={{
204 marginLeft: '14px',
205 color: theme.palette.background.paper,
206 }}
207 size={20}
208 color="secondary"
209 />
210 )
211 }
212 >
213 {t('signup.submit')}
214 </Button>
215 </Box>
216 <Box
217 sx={{width: '100%', textAlign: 'center', margin: theme.spacing(2, 0)}}
218 >
219 <Divider />
220 </Box>
221 <Typography align="center" variant="body2">
222 {t('signup.account_already')}
223 </Typography>
224 </CardContent>
225 <SignUpActions />
226 </form>
227 );
228};
229
230export default SignUp;