diff options
author | Mo Tarbin <mhed.t91@gmail.com> | 2024-06-30 18:55:39 -0400 |
---|---|---|
committer | Mo Tarbin <mhed.t91@gmail.com> | 2024-06-30 18:55:39 -0400 |
commit | 2657469964e24ffbeb905024532120395f6e797c (patch) | |
tree | 2fe9db8a4ecfa92d854ca94f7586d81163c8bd25 /src/views/Authorization/Signup.jsx | |
download | donetick-frontend-2657469964e24ffbeb905024532120395f6e797c.tar.gz donetick-frontend-2657469964e24ffbeb905024532120395f6e797c.tar.bz2 donetick-frontend-2657469964e24ffbeb905024532120395f6e797c.zip |
move to Donetick Org, First commit frontend
Diffstat (limited to '')
-rw-r--r-- | src/views/Authorization/Signup.jsx | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/src/views/Authorization/Signup.jsx b/src/views/Authorization/Signup.jsx new file mode 100644 index 0000000..d83411f --- /dev/null +++ b/src/views/Authorization/Signup.jsx @@ -0,0 +1,243 @@ +import { + Box, + Button, + Container, + Divider, + FormControl, + FormHelperText, + Input, + Sheet, + Typography, +} from '@mui/joy' +import React from 'react' +import { useNavigate } from 'react-router-dom' +import Logo from '../../Logo' +import { login, signUp } from '../../utils/Fetcher' + +const SignupView = () => { + const [username, setUsername] = React.useState('') + const [password, setPassword] = React.useState('') + const Navigate = useNavigate() + const [displayName, setDisplayName] = React.useState('') + const [email, setEmail] = React.useState('') + const [usernameError, setUsernameError] = React.useState('') + const [passwordError, setPasswordError] = React.useState('') + const [emailError, setEmailError] = React.useState('') + const [displayNameError, setDisplayNameError] = React.useState('') + const [error, setError] = React.useState(null) + const handleLogin = (username, password) => { + login(username, password).then(response => { + if (response.status === 200) { + response.json().then(res => { + localStorage.setItem('ca_token', res.token) + localStorage.setItem('ca_expiration', res.expire) + setTimeout(() => { + // TODO: not sure if there is a race condition here + // but on first sign up it renavigates to login. + Navigate('/my/chores') + }, 500) + }) + } else { + console.log('Login failed', response) + // Navigate('/login') + } + }) + } + const handleSignUpValidation = () => { + // Reset errors before validation + setUsernameError(null) + setPasswordError(null) + setDisplayNameError(null) + setEmailError(null) + + let isValid = true + + if (!username.trim()) { + setUsernameError('Username is required') + isValid = false + } + if (username.length < 4) { + setUsernameError('Username must be at least 4 characters') + isValid = false + } + // if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { + // setEmailError('Invalid email address') + // isValid = false + // } + + if (password.length < 8) { + setPasswordError('Password must be at least 8 characters') + isValid = false + } + + if (!displayName.trim()) { + setDisplayNameError('Display name is required') + isValid = false + } + + // display name should only contain letters and spaces and numbers: + if (!/^[a-zA-Z0-9 ]+$/.test(displayName)) { + setDisplayNameError('Display name can only contain letters and numbers') + isValid = false + } + + // username should only contain letters , numbers , dot and dash: + if (!/^[a-zA-Z0-9.-]+$/.test(username)) { + setUsernameError( + 'Username can only contain letters, numbers, dot and dash', + ) + isValid = false + } + + return isValid + } + const handleSubmit = async e => { + e.preventDefault() + if (!handleSignUpValidation()) { + return + } + signUp(username, password, displayName, email).then(response => { + if (response.status === 201) { + handleLogin(username, password) + } else { + console.log('Signup failed') + setError('Signup failed') + } + }) + } + + return ( + <Container component='main' maxWidth='xs'> + <Box + sx={{ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + marginTop: 4, + }} + > + <Sheet + component='form' + sx={{ + mt: 1, + width: '100%', + display: 'flex', + flexDirection: 'column', + // alignItems: 'center', + padding: 2, + borderRadius: '8px', + boxShadow: 'md', + }} + > + <Box + sx={{ + display: 'flex', + alignItems: 'center', + flexDirection: 'column', + }} + > + <Logo /> + <Typography level='h2'> + Done + <span + style={{ + color: '#06b6d4', + }} + > + tick + </span> + </Typography> + <Typography level='body2'> + Create an account to get started! + </Typography> + </Box> + <Typography level='body2' alignSelf={'start'} mt={4}> + Username + </Typography> + <Input + margin='normal' + required + fullWidth + id='email' + label='Email Address' + name='email' + autoComplete='email' + autoFocus + value={username} + onChange={e => { + setUsernameError(null) + setUsername(e.target.value.trim()) + }} + /> + <FormControl error={usernameError}> + <FormHelperText c>{usernameError}</FormHelperText> + </FormControl> + {/* Error message display */} + <Typography level='body2' alignSelf={'start'}> + Password: + </Typography> + <Input + margin='normal' + required + fullWidth + name='password' + label='Password' + type='password' + id='password' + value={password} + onChange={e => { + setPasswordError(null) + setPassword(e.target.value) + }} + /> + <FormControl error={passwordError}> + <FormHelperText>{passwordError}</FormHelperText> + </FormControl> + <Typography level='body2' alignSelf={'start'}> + Display Name: + </Typography> + <Input + margin='normal' + required + fullWidth + name='displayName' + label='Display Name' + id='displayName' + value={displayName} + onChange={e => { + setDisplayNameError(null) + setDisplayName(e.target.value) + }} + /> + <FormControl error={displayNameError}> + <FormHelperText>{displayNameError}</FormHelperText> + </FormControl> + <Button + // type='submit' + size='lg' + fullWidth + variant='solid' + sx={{ mt: 3, mb: 1 }} + onClick={handleSubmit} + > + Sign Up + </Button> + <Divider> or </Divider> + <Button + size='lg' + onClick={() => { + Navigate('/login') + }} + fullWidth + variant='soft' + // sx={{ mt: 3, mb: 2 }} + > + Login + </Button> + </Sheet> + </Box> + </Container> + ) +} + +export default SignupView |