diff options
author | ilyayudovin <46264063+ilyayudovin@users.noreply.github.com> | 2020-08-29 23:39:15 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-29 23:39:15 +0300 |
commit | 96f1c8f86fc973ca66c8725a86b6cf277adb9c72 (patch) | |
tree | 866380704610aa2807777c21b3971dd71a020617 /src/containers | |
parent | 890141100a2e9b942a6ef2de15620fa5a01ba581 (diff) | |
parent | 3c4f51295ec4ccbed37d2faf8fd751608fc48843 (diff) | |
download | which-ui-96f1c8f86fc973ca66c8725a86b6cf277adb9c72.tar.gz |
Merge pull request #97 from which-ecosystem/validSignUp
fix input validation errors
Diffstat (limited to 'src/containers')
-rw-r--r-- | src/containers/Login/Login.tsx | 99 | ||||
-rw-r--r-- | src/containers/Registration/Registration.tsx | 170 |
2 files changed, 147 insertions, 122 deletions
diff --git a/src/containers/Login/Login.tsx b/src/containers/Login/Login.tsx index bec0db5..3d58c63 100644 --- a/src/containers/Login/Login.tsx +++ b/src/containers/Login/Login.tsx @@ -1,14 +1,24 @@ -import React, { useState, useRef } from 'react'; +import React, { useState } from 'react'; import { useHistory } from 'react-router-dom'; +import { Formik, Form, Field } from 'formik'; import { makeStyles } from '@material-ui/core/styles'; import { TextField, Button, FormControlLabel, - Switch + Switch, + InputAdornment, + IconButton } from '@material-ui/core'; +import { Visibility, VisibilityOff } from '@material-ui/icons'; import { useAuth } from '../../hooks/useAuth'; +interface Fields { + username: string; + password: string; + remember: boolean; +} + const useStyles = makeStyles(theme => ({ root: { '& > *': { @@ -37,54 +47,71 @@ const useStyles = makeStyles(theme => ({ const Login: React.FC = () => { const [error, setError] = useState<boolean>(false); - const [remember, setRemember] = useState<boolean>(true); + const [showPassword, setShowPassword] = useState<boolean>(false); const classes = useStyles(); - const nameRef = useRef<HTMLInputElement>(); - const passwordRef = useRef<HTMLInputElement>(); const { login } = useAuth(); const history = useHistory(); - const handleCheck = () => { - setRemember(!remember); - }; - - const handleSubmit = async () => { - const name = nameRef.current?.value?.toLowerCase(); - const password = passwordRef.current?.value; - if (name && password) { - login(name, password, remember).then(success => { - if (success) history.push(`/profile/${name}`); + const handleSubmit = async ({ username, password, remember }: Fields) => { + if (username && password) { + login(username, password, remember).then(success => { + if (success) history.push(`/profile/${username}`); else setError(true); }); - } + } else setError(true); }; - const handleRegistration = () => { history.push('/registration'); }; + const toggleShowPassword = () => { + setShowPassword(prevState => !prevState); + }; + return ( <> <div className={classes.formHeader}>Sign In</div> - <form className={classes.root} noValidate autoComplete="off"> - <TextField - inputRef={nameRef} - error={error} - label="Login" - /> - <TextField - inputRef={passwordRef} - error={error} - helperText={error && 'Invalid credentials'} - label="Password" - type="password" - /> - <FormControlLabel - control={<Switch color="primary" onClick={handleCheck} checked={remember} size="small" />} - label="Remember me" - /> - <Button variant="contained" onClick={handleSubmit}>submit</Button> - </form> + <Formik + initialValues={{ username: '', password: '', remember: true }} + onSubmit={handleSubmit} + > + {({ values, isSubmitting }) => ( + <Form className={classes.root} autoComplete="off"> + <Field + name="username" + label="Login" + value={values.username} + error={error} + as={TextField} + /> + <Field + name="password" + label="Password" + as={TextField} + value={values.password} + error={error} + helperText={error && 'Invalid credentials'} + type={showPassword ? 'text' : 'password'} + InputProps={{ + endAdornment: ( + <InputAdornment position="end"> + <IconButton size="small" onClick={toggleShowPassword}> + {showPassword ? <Visibility /> : <VisibilityOff />} + </IconButton> + </InputAdornment> + ) + }} + /> + <Field + name="remember" + label="Remember me" + as={FormControlLabel} + control={<Switch color="primary" checked={values.remember} size="small" />} + /> + <Button variant="contained" type="submit" disabled={isSubmitting}>submit</Button> + </Form> + )} + </Formik> <div className={classes.formTransfer}> <div>{'Don\'t have an account?'}</div> <span diff --git a/src/containers/Registration/Registration.tsx b/src/containers/Registration/Registration.tsx index 9bcea8e..a3aedb3 100644 --- a/src/containers/Registration/Registration.tsx +++ b/src/containers/Registration/Registration.tsx @@ -1,13 +1,35 @@ -import React, { useState, useRef } from 'react'; +import React, { useState } from 'react'; import { useHistory } from 'react-router-dom'; +import { Formik, Form, Field } from 'formik'; +import * as Yup from 'yup'; import { makeStyles } from '@material-ui/core/styles'; -import TextField from '@material-ui/core/TextField'; -import Button from '@material-ui/core/Button'; -import CheckCircleIcon from '@material-ui/icons/CheckCircle'; -import InputAdornment from '@material-ui/core/InputAdornment'; +import { + TextField, + Button, + InputAdornment, + IconButton +} from '@material-ui/core'; +import { Visibility, VisibilityOff } from '@material-ui/icons'; import { post } from '../../requests'; import { useAuth } from '../../hooks/useAuth'; +interface Fields { + username: string; + email: string; + password: string; +} + +const validationSchema = Yup.object({ + username: Yup.string() + .lowercase('Must be lowercase') + .required('This field is required'), + email: Yup.string() + .email('Invalid email address') + .required('This field is required'), + password: Yup.string() + .min(6, 'Should be at least 6 characters') + .required('This field is required') +}); const useStyles = makeStyles(theme => ({ root: { @@ -35,102 +57,78 @@ const useStyles = makeStyles(theme => ({ } })); -const inputStyle = { WebkitBoxShadow: '0 0 0 1000px snow inset' }; - - const Registration: React.FC = () => { - const errorOutputs = { - usernameError: 'Username is required', - emailError: 'Invalid email address', - passwordError: 'Should be at least 6 characters' - }; - const [errorPassword, setErrorPassword] = useState<boolean>(false); - const [errorEmail, setErrorEmail] = useState<boolean>(false); - const [errorUsername, setErrorUsername] = useState<boolean>(false); - const classes = useStyles(); - const usernameRef = useRef<HTMLInputElement>(); - const emailRef = useRef<HTMLInputElement>(); - const passwordRef = useRef<HTMLInputElement>(); const { login } = useAuth(); const history = useHistory(); - - const handleSubmit = () => { - const username = usernameRef.current?.value?.toLowerCase(); - const password = passwordRef.current?.value; - const email = emailRef.current?.value; - if (username && password) { - post('/users', { username, password, email }) - .then(() => login(username, password)) - .then(() => history.push(`/profile/${username}`)); - } - }; + const [showPassword, setShowPassword] = useState<boolean>(false); const handleLogin = () => { history.push('/login'); }; - const handleLoginChange = (e: React.ChangeEvent<HTMLInputElement>) => { - setErrorUsername(e.currentTarget.value.length === 0); + const handleSubmit = ({ username, email, password }: Fields) => { + post('/users', { username, email, password }) + .then(() => login(username, password)) + .then(() => history.push(`/profile/${username}`)); }; - const handleEmailChange = (e: React.ChangeEvent<HTMLInputElement>) => { - setErrorEmail(!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(e.currentTarget.value)); - }; - const handlePasswordChange = (e: React.ChangeEvent<HTMLInputElement>) => { - setErrorPassword(e.currentTarget.value.length < 6); + + const toggleShowPassword = () => { + setShowPassword(prevState => !prevState); }; return ( <> <div className={classes.formHeader}>Sign Up</div> - <form className={classes.root} noValidate autoComplete="off"> - <TextField - inputRef={usernameRef} - label="Username" - error={errorUsername} - helperText={errorUsername && errorOutputs.usernameError} - required - onChange={handleLoginChange} - inputProps={{ style: inputStyle }} - /> - <TextField - inputRef={emailRef} - label="Email" - error={errorEmail} - helperText={errorEmail && errorOutputs.emailError} - onChange={handleEmailChange} - InputProps={errorEmail ? {} : { - endAdornment: ( - <InputAdornment position="end"> - <CheckCircleIcon color="primary" /> - </InputAdornment> - ), - inputProps: { - style: inputStyle - } - }} - /> - <TextField - inputRef={passwordRef} - label="Password" - type="password" - required - error={errorPassword} - helperText={errorPassword && errorOutputs.passwordError} - onChange={handlePasswordChange} - InputProps={errorPassword ? {} : { - endAdornment: ( - <InputAdornment position="end"> - <CheckCircleIcon color="primary" /> - </InputAdornment> - ), - inputProps: { - style: inputStyle - } - }} - /> - <Button variant="contained" onClick={handleSubmit}>submit</Button> - </form> + <Formik + initialValues={{ username: '', email: '', password: '' }} + validationSchema={validationSchema} + onSubmit={handleSubmit} + > + {({ values, errors, touched, isSubmitting }) => ( + <Form className={classes.root} autoComplete="off"> + <Field + id="username" + name="username" + label="Username" + value={values.username.toLowerCase()} + error={touched.username && !!errors.username} + helperText={touched.username && errors.username} + required + as={TextField} + /> + <Field + name="email" + label="Email" + value={values.email} + error={touched.email && !!errors.email} + helperText={touched.email && errors.email} + required + as={TextField} + /> + <Field + name="password" + label="Password" + value={values.password} + error={touched.password && !!errors.password} + helperText={touched.password && errors.password} + required + type={showPassword ? 'text' : 'password'} + as={TextField} + InputProps={{ + endAdornment: ( + <InputAdornment position="end"> + <IconButton size="small" onClick={toggleShowPassword}> + {showPassword ? <Visibility /> : <VisibilityOff />} + </IconButton> + </InputAdornment> + ) + }} + /> + <Button variant="contained" type="submit" disabled={isSubmitting}>submit</Button> + </Form> + )} + </Formik> <div className={classes.formTransfer}> <div>Already have an account?</div> <span |