From fa133c40edb633c63d37619682ba0771d4481ed9 Mon Sep 17 00:00:00 2001
From: ilyayudovin <ilyayudovin123@gmail.com>
Date: Fri, 28 Aug 2020 02:24:00 +0300
Subject: fix input validation errors

---
 src/containers/Registration/Registration.tsx | 103 ++++++++++++++++-----------
 1 file changed, 63 insertions(+), 40 deletions(-)

(limited to 'src/containers/Registration/Registration.tsx')

diff --git a/src/containers/Registration/Registration.tsx b/src/containers/Registration/Registration.tsx
index 9bcea8e..7d2a758 100644
--- a/src/containers/Registration/Registration.tsx
+++ b/src/containers/Registration/Registration.tsx
@@ -1,10 +1,13 @@
 import React, { useState, useRef } from 'react';
 import { useHistory } from 'react-router-dom';
 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 { CheckCircle, Visibility, VisibilityOff } from '@material-ui/icons';
 import { post } from '../../requests';
 import { useAuth } from '../../hooks/useAuth';
 
@@ -35,18 +38,20 @@ const useStyles = makeStyles(theme => ({
   }
 }));
 
-const inputStyle = { WebkitBoxShadow: '0 0 0 1000px snow inset' };
-
+interface ValidationStates {
+  validUsername: boolean | undefined;
+  validEmail: boolean | undefined;
+  validPassword: boolean | undefined;
+  showPassword: boolean;
+}
 
 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 [values, setValues] = useState<ValidationStates>({
+    validUsername: undefined,
+    validEmail: undefined,
+    validPassword: undefined,
+    showPassword: false
+  });
 
   const classes = useStyles();
   const usernameRef = useRef<HTMLInputElement>();
@@ -55,11 +60,15 @@ const Registration: React.FC = () => {
   const { login } = useAuth();
   const history = useHistory();
 
+  const checkFromValidation = () => {
+    return values.validUsername && values.validEmail && values.validPassword;
+  };
+
   const handleSubmit = () => {
     const username = usernameRef.current?.value?.toLowerCase();
     const password = passwordRef.current?.value;
     const email = emailRef.current?.value;
-    if (username && password) {
+    if (username && password && checkFromValidation()) {
       post('/users', { username, password, email })
         .then(() => login(username, password))
         .then(() => history.push(`/profile/${username}`));
@@ -70,14 +79,20 @@ const Registration: React.FC = () => {
     history.push('/login');
   };
 
-  const handleLoginChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-    setErrorUsername(e.currentTarget.value.length === 0);
+  const handleClickShowPassword = () => {
+    setValues({ ...values, showPassword: !values.showPassword });
+  };
+  const handleMouseDownPassword = (event: React.MouseEvent<HTMLButtonElement>) => {
+    event.preventDefault();
+  };
+  const handleUsernameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+    setValues({ ...values, validUsername: e.currentTarget.value.length > 0 });
   };
   const handleEmailChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-    setErrorEmail(!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(e.currentTarget.value));
+    setValues({ ...values, validEmail: /^[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);
+    setValues({ ...values, validPassword: e.currentTarget.value.length > 6 });
   };
 
   return (
@@ -87,46 +102,54 @@ const Registration: React.FC = () => {
         <TextField
           inputRef={usernameRef}
           label="Username"
-          error={errorUsername}
-          helperText={errorUsername && errorOutputs.usernameError}
+          error={!values.validUsername}
+          helperText={!values.validUsername && 'This field is required'}
           required
-          onChange={handleLoginChange}
-          inputProps={{ style: inputStyle }}
+          onChange={handleUsernameChange}
+          InputProps={{
+            endAdornment: (
+              <InputAdornment position="end">
+                {values.validUsername && values.validUsername !== undefined && <CheckCircle color="primary" />}
+              </InputAdornment>
+            )
+          }}
         />
         <TextField
           inputRef={emailRef}
           label="Email"
-          error={errorEmail}
-          helperText={errorEmail && errorOutputs.emailError}
+          error={!values.validEmail}
+          helperText={!values.validEmail && 'Invalid email address'}
           onChange={handleEmailChange}
-          InputProps={errorEmail ? {} : {
+          InputProps={{
             endAdornment: (
               <InputAdornment position="end">
-                <CheckCircleIcon color="primary" />
+                {values.validEmail && values.validEmail !== undefined && <CheckCircle color="primary" />}
               </InputAdornment>
-            ),
-            inputProps: {
-              style: inputStyle
-            }
+            )
           }}
         />
         <TextField
           inputRef={passwordRef}
           label="Password"
-          type="password"
           required
-          error={errorPassword}
-          helperText={errorPassword && errorOutputs.passwordError}
+          error={!values.validPassword}
+          helperText={!values.validPassword && 'Should be at least 6 characters'}
+          type={values.showPassword ? 'text' : 'password'}
           onChange={handlePasswordChange}
-          InputProps={errorPassword ? {} : {
+          InputProps={{
             endAdornment: (
               <InputAdornment position="end">
-                <CheckCircleIcon color="primary" />
+                <IconButton
+                  size="small"
+                  aria-label="toggle password visibility"
+                  onClick={handleClickShowPassword}
+                  onMouseDown={handleMouseDownPassword}
+                >
+                  {values.showPassword ? <Visibility /> : <VisibilityOff />}
+                </IconButton>
+                {values.validPassword && values.validPassword !== undefined && <CheckCircle color="primary" />}
               </InputAdornment>
-            ),
-            inputProps: {
-              style: inputStyle
-            }
+            )
           }}
         />
         <Button variant="contained" onClick={handleSubmit}>submit</Button>
-- 
cgit v1.2.3


From 4bbebc183e75e287e28d5b4369699d1bc40c0cd1 Mon Sep 17 00:00:00 2001
From: ilyayudovin <ilyayudovin123@gmail.com>
Date: Fri, 28 Aug 2020 18:40:23 +0300
Subject: feat: submit Form on button click

---
 src/containers/Registration/Registration.tsx | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

(limited to 'src/containers/Registration/Registration.tsx')

diff --git a/src/containers/Registration/Registration.tsx b/src/containers/Registration/Registration.tsx
index 7d2a758..20bc283 100644
--- a/src/containers/Registration/Registration.tsx
+++ b/src/containers/Registration/Registration.tsx
@@ -1,4 +1,4 @@
-import React, { useState, useRef } from 'react';
+import React, {useState, useRef, FormEvent} from 'react';
 import { useHistory } from 'react-router-dom';
 import { makeStyles } from '@material-ui/core/styles';
 import {
@@ -64,11 +64,13 @@ const Registration: React.FC = () => {
     return values.validUsername && values.validEmail && values.validPassword;
   };
 
-  const handleSubmit = () => {
+  const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
+    event.preventDefault();
     const username = usernameRef.current?.value?.toLowerCase();
     const password = passwordRef.current?.value;
     const email = emailRef.current?.value;
     if (username && password && checkFromValidation()) {
+      console.log('yes');
       post('/users', { username, password, email })
         .then(() => login(username, password))
         .then(() => history.push(`/profile/${username}`));
@@ -98,7 +100,7 @@ const Registration: React.FC = () => {
   return (
     <>
       <div className={classes.formHeader}>Sign Up</div>
-      <form className={classes.root} noValidate autoComplete="off">
+      <form className={classes.root} noValidate autoComplete="off" onSubmit={handleSubmit}>
         <TextField
           inputRef={usernameRef}
           label="Username"
@@ -152,7 +154,7 @@ const Registration: React.FC = () => {
             )
           }}
         />
-        <Button variant="contained" onClick={handleSubmit}>submit</Button>
+        <Button variant="contained" type="submit" >submit</Button>
       </form>
       <div className={classes.formTransfer}>
         <div>Already have an account?</div>
-- 
cgit v1.2.3


From b7be53c172869679cdfa65a44591c7bd9c5b9302 Mon Sep 17 00:00:00 2001
From: ilyayudovin <ilyayudovin123@gmail.com>
Date: Fri, 28 Aug 2020 18:46:47 +0300
Subject: separate validation state into 2 states and remove CheckCircle icon

---
 src/containers/Registration/Registration.tsx | 27 ++++++---------------------
 1 file changed, 6 insertions(+), 21 deletions(-)

(limited to 'src/containers/Registration/Registration.tsx')

diff --git a/src/containers/Registration/Registration.tsx b/src/containers/Registration/Registration.tsx
index 20bc283..0746deb 100644
--- a/src/containers/Registration/Registration.tsx
+++ b/src/containers/Registration/Registration.tsx
@@ -38,20 +38,19 @@ const useStyles = makeStyles(theme => ({
   }
 }));
 
-interface ValidationStates {
+interface errors {
   validUsername: boolean | undefined;
   validEmail: boolean | undefined;
   validPassword: boolean | undefined;
-  showPassword: boolean;
 }
 
 const Registration: React.FC = () => {
-  const [values, setValues] = useState<ValidationStates>({
+  const [values, setValues] = useState<errors>({
     validUsername: undefined,
     validEmail: undefined,
     validPassword: undefined,
-    showPassword: false
   });
+  const [showPassword, setShowPassword] = useState<boolean>(false);
 
   const classes = useStyles();
   const usernameRef = useRef<HTMLInputElement>();
@@ -82,7 +81,7 @@ const Registration: React.FC = () => {
   };
 
   const handleClickShowPassword = () => {
-    setValues({ ...values, showPassword: !values.showPassword });
+    setShowPassword(prevState => !prevState);
   };
   const handleMouseDownPassword = (event: React.MouseEvent<HTMLButtonElement>) => {
     event.preventDefault();
@@ -108,13 +107,6 @@ const Registration: React.FC = () => {
           helperText={!values.validUsername && 'This field is required'}
           required
           onChange={handleUsernameChange}
-          InputProps={{
-            endAdornment: (
-              <InputAdornment position="end">
-                {values.validUsername && values.validUsername !== undefined && <CheckCircle color="primary" />}
-              </InputAdornment>
-            )
-          }}
         />
         <TextField
           inputRef={emailRef}
@@ -122,13 +114,6 @@ const Registration: React.FC = () => {
           error={!values.validEmail}
           helperText={!values.validEmail && 'Invalid email address'}
           onChange={handleEmailChange}
-          InputProps={{
-            endAdornment: (
-              <InputAdornment position="end">
-                {values.validEmail && values.validEmail !== undefined && <CheckCircle color="primary" />}
-              </InputAdornment>
-            )
-          }}
         />
         <TextField
           inputRef={passwordRef}
@@ -136,7 +121,7 @@ const Registration: React.FC = () => {
           required
           error={!values.validPassword}
           helperText={!values.validPassword && 'Should be at least 6 characters'}
-          type={values.showPassword ? 'text' : 'password'}
+          type={showPassword ? 'text' : 'password'}
           onChange={handlePasswordChange}
           InputProps={{
             endAdornment: (
@@ -147,7 +132,7 @@ const Registration: React.FC = () => {
                   onClick={handleClickShowPassword}
                   onMouseDown={handleMouseDownPassword}
                 >
-                  {values.showPassword ? <Visibility /> : <VisibilityOff />}
+                  {showPassword ? <Visibility /> : <VisibilityOff />}
                 </IconButton>
                 {values.validPassword && values.validPassword !== undefined && <CheckCircle color="primary" />}
               </InputAdornment>
-- 
cgit v1.2.3


From 9c571fa6e99d3c5e271c5763d86bf4cdd702aebb Mon Sep 17 00:00:00 2001
From: ilyayudovin <ilyayudovin123@gmail.com>
Date: Fri, 28 Aug 2020 18:47:40 +0300
Subject: change state name

---
 src/containers/Registration/Registration.tsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/containers/Registration/Registration.tsx')

diff --git a/src/containers/Registration/Registration.tsx b/src/containers/Registration/Registration.tsx
index 0746deb..47b5947 100644
--- a/src/containers/Registration/Registration.tsx
+++ b/src/containers/Registration/Registration.tsx
@@ -38,14 +38,14 @@ const useStyles = makeStyles(theme => ({
   }
 }));
 
-interface errors {
+interface ErrorStates {
   validUsername: boolean | undefined;
   validEmail: boolean | undefined;
   validPassword: boolean | undefined;
 }
 
 const Registration: React.FC = () => {
-  const [values, setValues] = useState<errors>({
+  const [values, setValues] = useState<ErrorStates>({
     validUsername: undefined,
     validEmail: undefined,
     validPassword: undefined,
-- 
cgit v1.2.3


From da1854e8fd34245e2e9e4fd941320f08b1cc40e1 Mon Sep 17 00:00:00 2001
From: ilyayudovin <ilyayudovin123@gmail.com>
Date: Fri, 28 Aug 2020 18:55:34 +0300
Subject: add useMemo for check validity of the form

---
 src/containers/Registration/Registration.tsx | 41 ++++++++++++++--------------
 1 file changed, 20 insertions(+), 21 deletions(-)

(limited to 'src/containers/Registration/Registration.tsx')

diff --git a/src/containers/Registration/Registration.tsx b/src/containers/Registration/Registration.tsx
index 47b5947..3269f6e 100644
--- a/src/containers/Registration/Registration.tsx
+++ b/src/containers/Registration/Registration.tsx
@@ -1,4 +1,4 @@
-import React, {useState, useRef, FormEvent} from 'react';
+import React, {useState, useRef, FormEvent, useMemo} from 'react';
 import { useHistory } from 'react-router-dom';
 import { makeStyles } from '@material-ui/core/styles';
 import {
@@ -39,16 +39,16 @@ const useStyles = makeStyles(theme => ({
 }));
 
 interface ErrorStates {
-  validUsername: boolean | undefined;
-  validEmail: boolean | undefined;
-  validPassword: boolean | undefined;
+  username: boolean | undefined;
+  email: boolean | undefined;
+  password: boolean | undefined;
 }
 
 const Registration: React.FC = () => {
   const [values, setValues] = useState<ErrorStates>({
-    validUsername: undefined,
-    validEmail: undefined,
-    validPassword: undefined,
+    username: undefined,
+    email: undefined,
+    password: undefined,
   });
   const [showPassword, setShowPassword] = useState<boolean>(false);
 
@@ -59,16 +59,16 @@ const Registration: React.FC = () => {
   const { login } = useAuth();
   const history = useHistory();
 
-  const checkFromValidation = () => {
-    return values.validUsername && values.validEmail && values.validPassword;
-  };
+  const isValid = useMemo(() => {
+    return values.username && values.email && values.password;
+  },[values]);
 
   const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
     event.preventDefault();
     const username = usernameRef.current?.value?.toLowerCase();
     const password = passwordRef.current?.value;
     const email = emailRef.current?.value;
-    if (username && password && checkFromValidation()) {
+    if (username && password && isValid) {
       console.log('yes');
       post('/users', { username, password, email })
         .then(() => login(username, password))
@@ -87,13 +87,13 @@ const Registration: React.FC = () => {
     event.preventDefault();
   };
   const handleUsernameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-    setValues({ ...values, validUsername: e.currentTarget.value.length > 0 });
+    setValues({ ...values, username: e.currentTarget.value.length > 0 });
   };
   const handleEmailChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-    setValues({ ...values, validEmail: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(e.currentTarget.value) });
+    setValues({ ...values, email: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(e.currentTarget.value) });
   };
   const handlePasswordChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-    setValues({ ...values, validPassword: e.currentTarget.value.length > 6 });
+    setValues({ ...values, password: e.currentTarget.value.length > 6 });
   };
 
   return (
@@ -103,24 +103,24 @@ const Registration: React.FC = () => {
         <TextField
           inputRef={usernameRef}
           label="Username"
-          error={!values.validUsername}
-          helperText={!values.validUsername && 'This field is required'}
+          error={!values.username}
+          helperText={!values.username && 'This field is required'}
           required
           onChange={handleUsernameChange}
         />
         <TextField
           inputRef={emailRef}
           label="Email"
-          error={!values.validEmail}
-          helperText={!values.validEmail && 'Invalid email address'}
+          error={!values.email}
+          helperText={!values.email && 'Invalid email address'}
           onChange={handleEmailChange}
         />
         <TextField
           inputRef={passwordRef}
           label="Password"
           required
-          error={!values.validPassword}
-          helperText={!values.validPassword && 'Should be at least 6 characters'}
+          error={!values.password}
+          helperText={!values.password && 'Should be at least 6 characters'}
           type={showPassword ? 'text' : 'password'}
           onChange={handlePasswordChange}
           InputProps={{
@@ -134,7 +134,6 @@ const Registration: React.FC = () => {
                 >
                   {showPassword ? <Visibility /> : <VisibilityOff />}
                 </IconButton>
-                {values.validPassword && values.validPassword !== undefined && <CheckCircle color="primary" />}
               </InputAdornment>
             )
           }}
-- 
cgit v1.2.3


From 987c4ecc67dc3cd41d0db04727c942efe35d5c82 Mon Sep 17 00:00:00 2001
From: ilyayudovin <ilyayudovin123@gmail.com>
Date: Fri, 28 Aug 2020 19:21:11 +0300
Subject: change onChange to onBlur event

---
 src/containers/Registration/Registration.tsx | 28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)

(limited to 'src/containers/Registration/Registration.tsx')

diff --git a/src/containers/Registration/Registration.tsx b/src/containers/Registration/Registration.tsx
index 3269f6e..e250397 100644
--- a/src/containers/Registration/Registration.tsx
+++ b/src/containers/Registration/Registration.tsx
@@ -79,21 +79,29 @@ const Registration: React.FC = () => {
   const handleLogin = () => {
     history.push('/login');
   };
-
   const handleClickShowPassword = () => {
     setShowPassword(prevState => !prevState);
   };
   const handleMouseDownPassword = (event: React.MouseEvent<HTMLButtonElement>) => {
     event.preventDefault();
   };
-  const handleUsernameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-    setValues({ ...values, username: e.currentTarget.value.length > 0 });
+  const handleUsernameChange = (e: React.FocusEvent<HTMLInputElement>) => {
+    setValues({
+      ...values,
+      username: e.currentTarget.value.length > 0
+    });
   };
-  const handleEmailChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-    setValues({ ...values, email: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(e.currentTarget.value) });
+  const handleEmailChange = (e: React.FocusEvent<HTMLInputElement>) => {
+    setValues({
+      ...values,
+      email: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(e.currentTarget.value)
+    });
   };
-  const handlePasswordChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-    setValues({ ...values, password: e.currentTarget.value.length > 6 });
+  const handlePasswordChange = (e: React.FocusEvent<HTMLInputElement>) => {
+    setValues({
+      ...values,
+      password: e.currentTarget.value.length > 6
+    });
   };
 
   return (
@@ -106,14 +114,14 @@ const Registration: React.FC = () => {
           error={!values.username}
           helperText={!values.username && 'This field is required'}
           required
-          onChange={handleUsernameChange}
+          onBlur={handleUsernameChange}
         />
         <TextField
           inputRef={emailRef}
           label="Email"
           error={!values.email}
           helperText={!values.email && 'Invalid email address'}
-          onChange={handleEmailChange}
+          onBlur={handleEmailChange}
         />
         <TextField
           inputRef={passwordRef}
@@ -122,7 +130,7 @@ const Registration: React.FC = () => {
           error={!values.password}
           helperText={!values.password && 'Should be at least 6 characters'}
           type={showPassword ? 'text' : 'password'}
-          onChange={handlePasswordChange}
+          onBlur={handlePasswordChange}
           InputProps={{
             endAdornment: (
               <InputAdornment position="end">
-- 
cgit v1.2.3


From be765bb98e19fdc755418cdf4d2eb19d0aa15ecd Mon Sep 17 00:00:00 2001
From: ilyayudovin <ilyayudovin123@gmail.com>
Date: Fri, 28 Aug 2020 19:41:42 +0300
Subject: fix eslint errors

---
 src/containers/Registration/Registration.tsx | 42 +++++++++++++++-------------
 1 file changed, 23 insertions(+), 19 deletions(-)

(limited to 'src/containers/Registration/Registration.tsx')

diff --git a/src/containers/Registration/Registration.tsx b/src/containers/Registration/Registration.tsx
index e250397..955d900 100644
--- a/src/containers/Registration/Registration.tsx
+++ b/src/containers/Registration/Registration.tsx
@@ -1,4 +1,9 @@
-import React, {useState, useRef, FormEvent, useMemo} from 'react';
+import React, {
+  useState,
+  useRef,
+  FormEvent,
+  useMemo
+} from 'react';
 import { useHistory } from 'react-router-dom';
 import { makeStyles } from '@material-ui/core/styles';
 import {
@@ -7,7 +12,7 @@ import {
   InputAdornment,
   IconButton
 } from '@material-ui/core';
-import { CheckCircle, Visibility, VisibilityOff } from '@material-ui/icons';
+import { Visibility, VisibilityOff } from '@material-ui/icons';
 import { post } from '../../requests';
 import { useAuth } from '../../hooks/useAuth';
 
@@ -46,9 +51,9 @@ interface ErrorStates {
 
 const Registration: React.FC = () => {
   const [values, setValues] = useState<ErrorStates>({
-    username: undefined,
-    email: undefined,
-    password: undefined,
+    username: false,
+    email: false,
+    password: false
   });
   const [showPassword, setShowPassword] = useState<boolean>(false);
 
@@ -60,16 +65,15 @@ const Registration: React.FC = () => {
   const history = useHistory();
 
   const isValid = useMemo(() => {
-    return values.username && values.email && values.password;
-  },[values]);
+    return !values.username && !values.email && !values.password;
+  }, [values]);
 
-  const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
+  const handleSubmit = (event:FormEvent<HTMLFormElement>) => {
     event.preventDefault();
     const username = usernameRef.current?.value?.toLowerCase();
     const password = passwordRef.current?.value;
     const email = emailRef.current?.value;
     if (username && password && isValid) {
-      console.log('yes');
       post('/users', { username, password, email })
         .then(() => login(username, password))
         .then(() => history.push(`/profile/${username}`));
@@ -88,19 +92,19 @@ const Registration: React.FC = () => {
   const handleUsernameChange = (e: React.FocusEvent<HTMLInputElement>) => {
     setValues({
       ...values,
-      username: e.currentTarget.value.length > 0
+      username: e.currentTarget.value.length === 0
     });
   };
   const handleEmailChange = (e: React.FocusEvent<HTMLInputElement>) => {
     setValues({
       ...values,
-      email: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(e.currentTarget.value)
+      email: !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(e.currentTarget.value)
     });
   };
   const handlePasswordChange = (e: React.FocusEvent<HTMLInputElement>) => {
     setValues({
       ...values,
-      password: e.currentTarget.value.length > 6
+      password: e.currentTarget.value.length < 6
     });
   };
 
@@ -111,24 +115,24 @@ const Registration: React.FC = () => {
         <TextField
           inputRef={usernameRef}
           label="Username"
-          error={!values.username}
-          helperText={!values.username && 'This field is required'}
+          error={values.username}
+          helperText={values.username && 'This field is required'}
           required
           onBlur={handleUsernameChange}
         />
         <TextField
           inputRef={emailRef}
           label="Email"
-          error={!values.email}
-          helperText={!values.email && 'Invalid email address'}
+          error={values.email}
+          helperText={values.email && 'Invalid email address'}
           onBlur={handleEmailChange}
         />
         <TextField
           inputRef={passwordRef}
           label="Password"
           required
-          error={!values.password}
-          helperText={!values.password && 'Should be at least 6 characters'}
+          error={values.password}
+          helperText={values.password && 'Should be at least 6 characters'}
           type={showPassword ? 'text' : 'password'}
           onBlur={handlePasswordChange}
           InputProps={{
@@ -146,7 +150,7 @@ const Registration: React.FC = () => {
             )
           }}
         />
-        <Button variant="contained" type="submit" >submit</Button>
+        <Button variant="contained" type="submit">submit</Button>
       </form>
       <div className={classes.formTransfer}>
         <div>Already have an account?</div>
-- 
cgit v1.2.3


From 421a1e8d73714dce004e7682dfa3c52ccdb0f71f Mon Sep 17 00:00:00 2001
From: ilyayudovin <ilyayudovin123@gmail.com>
Date: Fri, 28 Aug 2020 20:15:25 +0300
Subject: convert username input to lowercase

---
 src/containers/Registration/Registration.tsx | 55 +++++++++++++++-------------
 1 file changed, 30 insertions(+), 25 deletions(-)

(limited to 'src/containers/Registration/Registration.tsx')

diff --git a/src/containers/Registration/Registration.tsx b/src/containers/Registration/Registration.tsx
index 955d900..ff9af60 100644
--- a/src/containers/Registration/Registration.tsx
+++ b/src/containers/Registration/Registration.tsx
@@ -44,13 +44,13 @@ const useStyles = makeStyles(theme => ({
 }));
 
 interface ErrorStates {
-  username: boolean | undefined;
-  email: boolean | undefined;
-  password: boolean | undefined;
+  username: boolean;
+  email: boolean;
+  password: boolean;
 }
 
 const Registration: React.FC = () => {
-  const [values, setValues] = useState<ErrorStates>({
+  const [errors, setErrors] = useState<ErrorStates>({
     username: false,
     email: false,
     password: false
@@ -65,10 +65,10 @@ const Registration: React.FC = () => {
   const history = useHistory();
 
   const isValid = useMemo(() => {
-    return !values.username && !values.email && !values.password;
-  }, [values]);
+    return !errors.username && !errors.email && !errors.password;
+  }, [errors]);
 
-  const handleSubmit = (event:FormEvent<HTMLFormElement>) => {
+  const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
     event.preventDefault();
     const username = usernameRef.current?.value?.toLowerCase();
     const password = passwordRef.current?.value;
@@ -89,25 +89,29 @@ const Registration: React.FC = () => {
   const handleMouseDownPassword = (event: React.MouseEvent<HTMLButtonElement>) => {
     event.preventDefault();
   };
-  const handleUsernameChange = (e: React.FocusEvent<HTMLInputElement>) => {
-    setValues({
-      ...values,
-      username: e.currentTarget.value.length === 0
+  const handleUsernameChange = (event: React.FocusEvent<HTMLInputElement>) => {
+    setErrors({
+      ...errors,
+      username: event.currentTarget.value.length === 0
     });
   };
-  const handleEmailChange = (e: React.FocusEvent<HTMLInputElement>) => {
-    setValues({
-      ...values,
-      email: !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(e.currentTarget.value)
+  const handleEmailChange = (event: React.FocusEvent<HTMLInputElement>) => {
+    setErrors({
+      ...errors,
+      email: !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(event.currentTarget.value)
     });
   };
-  const handlePasswordChange = (e: React.FocusEvent<HTMLInputElement>) => {
-    setValues({
-      ...values,
-      password: e.currentTarget.value.length < 6
+  const handlePasswordChange = (event: React.FocusEvent<HTMLInputElement>) => {
+    setErrors({
+      ...errors,
+      password: event.currentTarget.value.length < 6
     });
   };
 
+  const handleToLowerCase = (e: React.ChangeEvent<HTMLInputElement>) => {
+    e.target.value = ("" + e.target.value).toLowerCase();
+  };
+
   return (
     <>
       <div className={classes.formHeader}>Sign Up</div>
@@ -115,24 +119,25 @@ const Registration: React.FC = () => {
         <TextField
           inputRef={usernameRef}
           label="Username"
-          error={values.username}
-          helperText={values.username && 'This field is required'}
+          error={errors.username}
+          helperText={errors.username && 'This field is required'}
           required
           onBlur={handleUsernameChange}
+          onInput={handleToLowerCase}
         />
         <TextField
           inputRef={emailRef}
           label="Email"
-          error={values.email}
-          helperText={values.email && 'Invalid email address'}
+          error={errors.email}
+          helperText={errors.email && 'Invalid email address'}
           onBlur={handleEmailChange}
         />
         <TextField
           inputRef={passwordRef}
           label="Password"
           required
-          error={values.password}
-          helperText={values.password && 'Should be at least 6 characters'}
+          error={errors.password}
+          helperText={errors.password && 'Should be at least 6 characters'}
           type={showPassword ? 'text' : 'password'}
           onBlur={handlePasswordChange}
           InputProps={{
-- 
cgit v1.2.3


From ceff44e622a07c5c17484e0222c78785fe12e6d2 Mon Sep 17 00:00:00 2001
From: ilyayudovin <ilyayudovin123@gmail.com>
Date: Fri, 28 Aug 2020 20:19:25 +0300
Subject: fix eslint errors

---
 src/containers/Registration/Registration.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src/containers/Registration/Registration.tsx')

diff --git a/src/containers/Registration/Registration.tsx b/src/containers/Registration/Registration.tsx
index ff9af60..709d04e 100644
--- a/src/containers/Registration/Registration.tsx
+++ b/src/containers/Registration/Registration.tsx
@@ -109,7 +109,7 @@ const Registration: React.FC = () => {
   };
 
   const handleToLowerCase = (e: React.ChangeEvent<HTMLInputElement>) => {
-    e.target.value = ("" + e.target.value).toLowerCase();
+    e.target.value = e.target.value.toString().toLowerCase();
   };
 
   return (
-- 
cgit v1.2.3


From ae005b8444aacc4071512f38031043156b6854c4 Mon Sep 17 00:00:00 2001
From: ilyayudovin <ilyayudovin123@gmail.com>
Date: Sat, 29 Aug 2020 00:22:27 +0300
Subject: hide error state onFocue input

---
 src/containers/Registration/Registration.tsx | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

(limited to 'src/containers/Registration/Registration.tsx')

diff --git a/src/containers/Registration/Registration.tsx b/src/containers/Registration/Registration.tsx
index 709d04e..e7c8874 100644
--- a/src/containers/Registration/Registration.tsx
+++ b/src/containers/Registration/Registration.tsx
@@ -44,16 +44,16 @@ const useStyles = makeStyles(theme => ({
 }));
 
 interface ErrorStates {
-  username: boolean;
-  email: boolean;
-  password: boolean;
+  username: boolean | undefined;
+  email: boolean | undefined;
+  password: boolean | undefined;
 }
 
 const Registration: React.FC = () => {
   const [errors, setErrors] = useState<ErrorStates>({
-    username: false,
-    email: false,
-    password: false
+    username: undefined,
+    email: undefined,
+    password: undefined
   });
   const [showPassword, setShowPassword] = useState<boolean>(false);
 
@@ -112,6 +112,13 @@ const Registration: React.FC = () => {
     e.target.value = e.target.value.toString().toLowerCase();
   };
 
+  const handleFocus = (value: string) => () => {
+    setErrors({
+      ...errors,
+      [value]: undefined
+    });
+  };
+
   return (
     <>
       <div className={classes.formHeader}>Sign Up</div>
@@ -124,6 +131,7 @@ const Registration: React.FC = () => {
           required
           onBlur={handleUsernameChange}
           onInput={handleToLowerCase}
+          onFocus={handleFocus('username')}
         />
         <TextField
           inputRef={emailRef}
@@ -131,6 +139,7 @@ const Registration: React.FC = () => {
           error={errors.email}
           helperText={errors.email && 'Invalid email address'}
           onBlur={handleEmailChange}
+          onFocus={handleFocus('email')}
         />
         <TextField
           inputRef={passwordRef}
@@ -140,6 +149,7 @@ const Registration: React.FC = () => {
           helperText={errors.password && 'Should be at least 6 characters'}
           type={showPassword ? 'text' : 'password'}
           onBlur={handlePasswordChange}
+          onFocus={handleFocus('password')}
           InputProps={{
             endAdornment: (
               <InputAdornment position="end">
-- 
cgit v1.2.3


From e3d230ffcc344b9027b19a136525f105149f0982 Mon Sep 17 00:00:00 2001
From: ilyayudovin <ilyayudovin123@gmail.com>
Date: Sat, 29 Aug 2020 02:20:22 +0300
Subject: add fixed height for inputs to avoid jumping errorText

---
 src/containers/Registration/Registration.tsx | 6 ++++++
 1 file changed, 6 insertions(+)

(limited to 'src/containers/Registration/Registration.tsx')

diff --git a/src/containers/Registration/Registration.tsx b/src/containers/Registration/Registration.tsx
index e7c8874..422cf92 100644
--- a/src/containers/Registration/Registration.tsx
+++ b/src/containers/Registration/Registration.tsx
@@ -40,6 +40,9 @@ const useStyles = makeStyles(theme => ({
     marginLeft: 10,
     color: 'green',
     cursor: 'pointer'
+  },
+  textField: {
+    height: 70
   }
 }));
 
@@ -132,6 +135,7 @@ const Registration: React.FC = () => {
           onBlur={handleUsernameChange}
           onInput={handleToLowerCase}
           onFocus={handleFocus('username')}
+          className={classes.textField}
         />
         <TextField
           inputRef={emailRef}
@@ -140,6 +144,7 @@ const Registration: React.FC = () => {
           helperText={errors.email && 'Invalid email address'}
           onBlur={handleEmailChange}
           onFocus={handleFocus('email')}
+          className={classes.textField}
         />
         <TextField
           inputRef={passwordRef}
@@ -164,6 +169,7 @@ const Registration: React.FC = () => {
               </InputAdornment>
             )
           }}
+          className={classes.textField}
         />
         <Button variant="contained" type="submit">submit</Button>
       </form>
-- 
cgit v1.2.3


From 868e380262dcef15d9645ceb912d18701ecb61fb Mon Sep 17 00:00:00 2001
From: eug-vs <eug-vs@keemail.me>
Date: Sat, 29 Aug 2020 14:29:28 +0300
Subject: feat: use yup and formik

---
 src/containers/Registration/Registration.tsx | 203 +++++++++++----------------
 1 file changed, 84 insertions(+), 119 deletions(-)

(limited to 'src/containers/Registration/Registration.tsx')

diff --git a/src/containers/Registration/Registration.tsx b/src/containers/Registration/Registration.tsx
index 422cf92..b5c56e6 100644
--- a/src/containers/Registration/Registration.tsx
+++ b/src/containers/Registration/Registration.tsx
@@ -1,10 +1,7 @@
-import React, {
-  useState,
-  useRef,
-  FormEvent,
-  useMemo
-} 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,
@@ -16,6 +13,22 @@ 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()
+    .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: {
@@ -42,137 +55,89 @@ const useStyles = makeStyles(theme => ({
     cursor: 'pointer'
   },
   textField: {
-    height: 70
+    height: theme.spacing(8)
   }
 }));
 
-interface ErrorStates {
-  username: boolean | undefined;
-  email: boolean | undefined;
-  password: boolean | undefined;
-}
-
 const Registration: React.FC = () => {
-  const [errors, setErrors] = useState<ErrorStates>({
-    username: undefined,
-    email: undefined,
-    password: undefined
-  });
-  const [showPassword, setShowPassword] = 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 isValid = useMemo(() => {
-    return !errors.username && !errors.email && !errors.password;
-  }, [errors]);
-
-  const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
-    event.preventDefault();
-    const username = usernameRef.current?.value?.toLowerCase();
-    const password = passwordRef.current?.value;
-    const email = emailRef.current?.value;
-    if (username && password && isValid) {
-      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 handleClickShowPassword = () => {
-    setShowPassword(prevState => !prevState);
-  };
-  const handleMouseDownPassword = (event: React.MouseEvent<HTMLButtonElement>) => {
-    event.preventDefault();
-  };
-  const handleUsernameChange = (event: React.FocusEvent<HTMLInputElement>) => {
-    setErrors({
-      ...errors,
-      username: event.currentTarget.value.length === 0
-    });
-  };
-  const handleEmailChange = (event: React.FocusEvent<HTMLInputElement>) => {
-    setErrors({
-      ...errors,
-      email: !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(event.currentTarget.value)
-    });
-  };
-  const handlePasswordChange = (event: React.FocusEvent<HTMLInputElement>) => {
-    setErrors({
-      ...errors,
-      password: event.currentTarget.value.length < 6
-    });
-  };
 
-  const handleToLowerCase = (e: React.ChangeEvent<HTMLInputElement>) => {
-    e.target.value = e.target.value.toString().toLowerCase();
-  };
+  const handleSubmit = ({ username, email, password }: Fields) => {
+    post('/users', { username, email, password })
+      .then(() => login(username, password))
+      .then(() => history.push(`/profile/${username}`));
+  }
 
-  const handleFocus = (value: string) => () => {
-    setErrors({
-      ...errors,
-      [value]: undefined
-    });
+  const handleClickShowPassword = () => {
+    setShowPassword(prevState => !prevState);
   };
 
   return (
     <>
       <div className={classes.formHeader}>Sign Up</div>
-      <form className={classes.root} noValidate autoComplete="off" onSubmit={handleSubmit}>
-        <TextField
-          inputRef={usernameRef}
-          label="Username"
-          error={errors.username}
-          helperText={errors.username && 'This field is required'}
-          required
-          onBlur={handleUsernameChange}
-          onInput={handleToLowerCase}
-          onFocus={handleFocus('username')}
-          className={classes.textField}
-        />
-        <TextField
-          inputRef={emailRef}
-          label="Email"
-          error={errors.email}
-          helperText={errors.email && 'Invalid email address'}
-          onBlur={handleEmailChange}
-          onFocus={handleFocus('email')}
-          className={classes.textField}
-        />
-        <TextField
-          inputRef={passwordRef}
-          label="Password"
-          required
-          error={errors.password}
-          helperText={errors.password && 'Should be at least 6 characters'}
-          type={showPassword ? 'text' : 'password'}
-          onBlur={handlePasswordChange}
-          onFocus={handleFocus('password')}
-          InputProps={{
-            endAdornment: (
-              <InputAdornment position="end">
-                <IconButton
-                  size="small"
-                  aria-label="toggle password visibility"
-                  onClick={handleClickShowPassword}
-                  onMouseDown={handleMouseDownPassword}
-                >
-                  {showPassword ? <Visibility /> : <VisibilityOff />}
-                </IconButton>
-              </InputAdornment>
-            )
-          }}
-          className={classes.textField}
-        />
-        <Button variant="contained" type="submit">submit</Button>
-      </form>
+      <Formik
+        initialValues={{ username: '', email: '', password: '' }}
+        validationSchema={validationSchema}
+        onSubmit={handleSubmit}
+      >
+        {({ values, errors, touched, isSubmitting }) => (
+          <Form className={classes.root}>
+            <Field
+              id="username"
+              name="username"
+              label="Username"
+              value={values.username.toLowerCase()}
+              error={touched.username && !!errors.username}
+              helperText={touched.username && errors.username}
+              required
+              className={classes.textField}
+              as={TextField}
+            />
+            <Field
+              name="email"
+              label="Email"
+              value={values.email}
+              error={touched.email && !!errors.email}
+              helperText={touched.email && errors.email}
+              required
+              className={classes.textField}
+              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"
+                      aria-label="toggle password visibility"
+                      onClick={handleClickShowPassword}
+                    >
+                      {showPassword ? <Visibility /> : <VisibilityOff />}
+                    </IconButton>
+                  </InputAdornment>
+                )
+              }}
+              className={classes.textField}
+            />
+            <Button variant="contained" type="submit" disabled={isSubmitting}>submit</Button>
+          </Form>
+        )}
+      </Formik>
       <div className={classes.formTransfer}>
         <div>Already have an account?</div>
         <span
-- 
cgit v1.2.3


From bf7c63cd53dde93bffe24eb1426b8bfc2037646b Mon Sep 17 00:00:00 2001
From: eug-vs <eug-vs@keemail.me>
Date: Sat, 29 Aug 2020 15:30:48 +0300
Subject: feat: use Formik in Login form

---
 src/containers/Registration/Registration.tsx | 17 ++++-------------
 1 file changed, 4 insertions(+), 13 deletions(-)

(limited to 'src/containers/Registration/Registration.tsx')

diff --git a/src/containers/Registration/Registration.tsx b/src/containers/Registration/Registration.tsx
index b5c56e6..fb2dc8c 100644
--- a/src/containers/Registration/Registration.tsx
+++ b/src/containers/Registration/Registration.tsx
@@ -21,6 +21,7 @@ interface Fields {
 
 const validationSchema = Yup.object({
   username: Yup.string()
+    .lowercase('Must be lowercase')
     .required('This field is required'),
   email: Yup.string()
     .email('Invalid email address')
@@ -54,9 +55,6 @@ const useStyles = makeStyles(theme => ({
     color: 'green',
     cursor: 'pointer'
   },
-  textField: {
-    height: theme.spacing(8)
-  }
 }));
 
 const Registration: React.FC = () => {
@@ -75,7 +73,7 @@ const Registration: React.FC = () => {
       .then(() => history.push(`/profile/${username}`));
   }
 
-  const handleClickShowPassword = () => {
+  const toggleShowPassword = () => {
     setShowPassword(prevState => !prevState);
   };
 
@@ -88,7 +86,7 @@ const Registration: React.FC = () => {
         onSubmit={handleSubmit}
       >
         {({ values, errors, touched, isSubmitting }) => (
-          <Form className={classes.root}>
+          <Form className={classes.root} autoComplete="off">
             <Field
               id="username"
               name="username"
@@ -97,7 +95,6 @@ const Registration: React.FC = () => {
               error={touched.username && !!errors.username}
               helperText={touched.username && errors.username}
               required
-              className={classes.textField}
               as={TextField}
             />
             <Field
@@ -107,7 +104,6 @@ const Registration: React.FC = () => {
               error={touched.email && !!errors.email}
               helperText={touched.email && errors.email}
               required
-              className={classes.textField}
               as={TextField}
             />
             <Field
@@ -122,17 +118,12 @@ const Registration: React.FC = () => {
               InputProps={{
                 endAdornment: (
                   <InputAdornment position="end">
-                    <IconButton
-                      size="small"
-                      aria-label="toggle password visibility"
-                      onClick={handleClickShowPassword}
-                    >
+                    <IconButton size="small" onClick={toggleShowPassword} >
                       {showPassword ? <Visibility /> : <VisibilityOff />}
                     </IconButton>
                   </InputAdornment>
                 )
               }}
-              className={classes.textField}
             />
             <Button variant="contained" type="submit" disabled={isSubmitting}>submit</Button>
           </Form>
-- 
cgit v1.2.3


From b7aed6ed7df2cea67924d34154671afb75edb7c2 Mon Sep 17 00:00:00 2001
From: eug-vs <eug-vs@keemail.me>
Date: Sat, 29 Aug 2020 15:34:17 +0300
Subject: fix: resovle eslint errors

---
 src/containers/Registration/Registration.tsx | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'src/containers/Registration/Registration.tsx')

diff --git a/src/containers/Registration/Registration.tsx b/src/containers/Registration/Registration.tsx
index fb2dc8c..a3aedb3 100644
--- a/src/containers/Registration/Registration.tsx
+++ b/src/containers/Registration/Registration.tsx
@@ -28,7 +28,7 @@ const validationSchema = Yup.object({
     .required('This field is required'),
   password: Yup.string()
     .min(6, 'Should be at least 6 characters')
-    .required('This field is required'),
+    .required('This field is required')
 });
 
 const useStyles = makeStyles(theme => ({
@@ -54,7 +54,7 @@ const useStyles = makeStyles(theme => ({
     marginLeft: 10,
     color: 'green',
     cursor: 'pointer'
-  },
+  }
 }));
 
 const Registration: React.FC = () => {
@@ -71,7 +71,7 @@ const Registration: React.FC = () => {
     post('/users', { username, email, password })
       .then(() => login(username, password))
       .then(() => history.push(`/profile/${username}`));
-  }
+  };
 
   const toggleShowPassword = () => {
     setShowPassword(prevState => !prevState);
@@ -118,7 +118,7 @@ const Registration: React.FC = () => {
               InputProps={{
                 endAdornment: (
                   <InputAdornment position="end">
-                    <IconButton size="small" onClick={toggleShowPassword} >
+                    <IconButton size="small" onClick={toggleShowPassword}>
                       {showPassword ? <Visibility /> : <VisibilityOff />}
                     </IconButton>
                   </InputAdornment>
-- 
cgit v1.2.3

