From e70a644cf6ceeb58765491ecb96b346452beaead Mon Sep 17 00:00:00 2001 From: Tobi Oyeleye Date: Wed, 1 Dec 2021 14:15:49 +0100 Subject: [PATCH 1/2] fix signin & signup --- client/src/App.js | 4 +- .../src/components/{Login => Auth}/Field.js | 23 -- .../src/components/{Login => Auth}/Google.js | 0 client/src/components/{Login => Auth}/Icon.js | 0 .../{Login => Auth}/Login.module.css | 0 client/src/components/Auth/auth-form.js | 182 +++++++++++++++ client/src/components/Auth/index.js | 26 +++ client/src/components/Auth/login-form.js | 14 ++ client/src/components/Auth/signup-form.js | 13 ++ .../src/components/{Login => Auth}/styles.js | 0 client/src/components/Header/Header.js | 210 +++++++++--------- client/src/components/Login/Login.js | 126 ----------- client/src/components/Password/Forgot.js | 2 +- client/src/components/Password/Reset.js | 2 +- 14 files changed, 350 insertions(+), 252 deletions(-) rename client/src/components/{Login => Auth}/Field.js (65%) rename client/src/components/{Login => Auth}/Google.js (100%) rename client/src/components/{Login => Auth}/Icon.js (100%) rename client/src/components/{Login => Auth}/Login.module.css (100%) create mode 100644 client/src/components/Auth/auth-form.js create mode 100644 client/src/components/Auth/index.js create mode 100644 client/src/components/Auth/login-form.js create mode 100644 client/src/components/Auth/signup-form.js rename client/src/components/{Login => Auth}/styles.js (100%) delete mode 100644 client/src/components/Login/Login.js diff --git a/client/src/App.js b/client/src/App.js index d69802b4..78a86ab2 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -7,7 +7,7 @@ import Invoices from './components/Invoices/Invoices'; import InvoiceDetails from './components/InvoiceDetails/InvoiceDetails' import ClientList from './components/Clients/ClientList' import NavBar from './components/NavBar/NavBar'; -import Login from './components/Login/Login' +import Auth from './components/Auth' import Dashboard from './components/Dashboard/Dashboard'; import Footer from './components/Footer/Footer'; import Header from './components/Header/Header'; @@ -31,7 +31,7 @@ function App() { - + diff --git a/client/src/components/Login/Field.js b/client/src/components/Auth/Field.js similarity index 65% rename from client/src/components/Login/Field.js rename to client/src/components/Auth/Field.js index b12ee736..75438343 100644 --- a/client/src/components/Login/Field.js +++ b/client/src/components/Auth/Field.js @@ -1,26 +1,3 @@ -// import React from 'react' -// import styles from './Login.module.css' - -// const Field = ({ name, placeholder, type, handleChange }) => { - -// return ( -//
-// -//
-// ) -// } - -// export default Field - - - import React from 'react'; import { TextField, Grid, InputAdornment, IconButton } from '@material-ui/core'; diff --git a/client/src/components/Login/Google.js b/client/src/components/Auth/Google.js similarity index 100% rename from client/src/components/Login/Google.js rename to client/src/components/Auth/Google.js diff --git a/client/src/components/Login/Icon.js b/client/src/components/Auth/Icon.js similarity index 100% rename from client/src/components/Login/Icon.js rename to client/src/components/Auth/Icon.js diff --git a/client/src/components/Login/Login.module.css b/client/src/components/Auth/Login.module.css similarity index 100% rename from client/src/components/Login/Login.module.css rename to client/src/components/Auth/Login.module.css diff --git a/client/src/components/Auth/auth-form.js b/client/src/components/Auth/auth-form.js new file mode 100644 index 00000000..54697202 --- /dev/null +++ b/client/src/components/Auth/auth-form.js @@ -0,0 +1,182 @@ +import { Grid, Typography, Avatar, Paper, Button } from "@material-ui/core"; +import { useState } from "react"; +import Field from "./Field"; +import { GoogleLogin } from "react-google-login"; +// import ProgressButton from "react-progress-button"; +import LockOutlinedIcon from "@material-ui/icons/LockOutlined"; +import { Link } from "react-router-dom"; +import useStyles from "./styles"; +import styles from "./Login.module.css"; +import { createProfile } from "../../actions/profile"; +import { useDispatch } from "react-redux"; +import CircularProgress from "@material-ui/core/CircularProgress"; + +const initialState = { + firstName: "", + lastName: "", + email: "", + password: "", + confirmPassword: "", + profilePicture: "", + bio: "", +}; + +const AuthForm = ({ isSignup = false, onSubmit }) => { + const classes = useStyles(); + const [formData, setFormData] = useState(initialState); + + const handleChange = (e) => { + setFormData({ ...formData, [e.target.name]: e.target.value }); + }; + + const dispatch = useDispatch(); + const [isLoading, setIsLoading] = useState(false); + + const googleSuccess = async (res) => { + console.log(res); + const result = res?.profileObj; + const token = res?.tokenId; + dispatch( + createProfile({ + name: result?.name, + email: result?.email, + userId: result?.googleId, + phoneNumber: "", + businessName: "", + contactAddress: "", + logo: result?.imageUrl, + website: "", + }) + ); + + try { + dispatch({ type: "AUTH", data: { result, token } }); + + window.location.href = "/dashboard"; + } catch (error) { + console.log(error); + } + }; + + const googleError = (error) => { + console.log(error); + console.log("Google Sign In was unseccassful. Try again later"); + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + + if (typeof onSubmit === "function") { + try { + setIsLoading(true); + await Promise.resolve(onSubmit(formData)); + setIsLoading(false); + } catch (err) { + // handle error + setIsLoading(false); + } + } + }; + + return ( + + + + + + {isSignup ? "Sign up" : "Sign in"} + +
+ + {isSignup && ( + <> + + + + )} + + + {isSignup && ( + + )} + +
+
+ {isLoading ? ( + + ) : ( + + )} +
+
+ ( + + )} + onSuccess={googleSuccess} + onFailure={googleError} + cookiePolicy="single_host_origin" + /> +
+
+ + + {isSignup ? ( + Already have an account? Sign in + ) : ( + Don't have an account? Sign Up + )} + + + +

+ Forgotten Password? +

+ +
+
+ ); +}; + +export default AuthForm; diff --git a/client/src/components/Auth/index.js b/client/src/components/Auth/index.js new file mode 100644 index 00000000..224e0324 --- /dev/null +++ b/client/src/components/Auth/index.js @@ -0,0 +1,26 @@ +import React from "react"; +import { Container } from "@material-ui/core"; +import { Switch, Route, useHistory } from "react-router-dom"; +import SignupForm from "./signup-form"; +import LoginForm from "./login-form"; + +const Auth = () => { + const history = useHistory(); + // eslint-disable-next-line + const user = JSON.parse(localStorage.getItem("profile")); + + if (user) { + history.push("/dashboard"); + } + + return ( + + + + + + + ); +}; + +export default Auth; diff --git a/client/src/components/Auth/login-form.js b/client/src/components/Auth/login-form.js new file mode 100644 index 00000000..af45043b --- /dev/null +++ b/client/src/components/Auth/login-form.js @@ -0,0 +1,14 @@ +import AuthForm from "./auth-form"; +import { useDispatch } from "react-redux"; +import { signin } from "../../actions/auth"; + +const LoginForm = () => { + const dispatch = useDispatch(); + + const handleSubmit = (formData) => dispatch(signin(formData)); + + + return ; +}; + +export default LoginForm; diff --git a/client/src/components/Auth/signup-form.js b/client/src/components/Auth/signup-form.js new file mode 100644 index 00000000..17eed2d8 --- /dev/null +++ b/client/src/components/Auth/signup-form.js @@ -0,0 +1,13 @@ +import AuthForm from "./auth-form"; +import { signup } from "../../actions/auth"; +import { useDispatch } from "react-redux"; + +const SignupForm = () => { + const dispatch = useDispatch(); + + const handleSubmit = (formData) => dispatch(signup(formData)) + + return ; +}; + +export default SignupForm; diff --git a/client/src/components/Login/styles.js b/client/src/components/Auth/styles.js similarity index 100% rename from client/src/components/Login/styles.js rename to client/src/components/Auth/styles.js diff --git a/client/src/components/Header/Header.js b/client/src/components/Header/Header.js index 1248f480..53b2b128 100644 --- a/client/src/components/Header/Header.js +++ b/client/src/components/Header/Header.js @@ -1,64 +1,54 @@ -import React, { useState, useEffect } from 'react' -import { useHistory, useLocation } from 'react-router-dom' -import { useDispatch } from 'react-redux' -import decode from 'jwt-decode' -import styles from './Header.module.css' - -import Button from '@material-ui/core/Button'; -import ClickAwayListener from '@material-ui/core/ClickAwayListener'; -import Grow from '@material-ui/core/Grow'; -import Paper from '@material-ui/core/Paper'; -import Popper from '@material-ui/core/Popper'; -import MenuItem from '@material-ui/core/MenuItem'; -import MenuList from '@material-ui/core/MenuList'; -import { makeStyles } from '@material-ui/core/styles'; -import Avatar from '@material-ui/core/Avatar'; - +import React, { useState, useEffect } from "react"; +import { useHistory, useLocation } from "react-router-dom"; +import { useDispatch } from "react-redux"; +import decode from "jwt-decode"; +import styles from "./Header.module.css"; + +import Button from "@material-ui/core/Button"; +import ClickAwayListener from "@material-ui/core/ClickAwayListener"; +import Grow from "@material-ui/core/Grow"; +import Paper from "@material-ui/core/Paper"; +import Popper from "@material-ui/core/Popper"; +import MenuItem from "@material-ui/core/MenuItem"; +import MenuList from "@material-ui/core/MenuList"; +import { makeStyles } from "@material-ui/core/styles"; +import Avatar from "@material-ui/core/Avatar"; const useStyles = makeStyles((theme) => ({ root: { - display: 'flex', + display: "flex", }, paper: { marginRight: theme.spacing(2), }, })); - - const Header = () => { - const dispatch = useDispatch() - const [user, setUser] = useState(JSON.parse(localStorage.getItem('profile'))) - const history = useHistory() - const location = useLocation() - - - useEffect(() => { - setUser(JSON.parse(localStorage.getItem('profile'))) - },[location]) - - - const logout =() => { - dispatch({ type: 'LOGOUT' }) - history.push('/') - setUser(null) - } - - - useEffect(()=> { - const token = user?.token - // setUser(JSON.parse(localStorage.getItem('profile'))) - //If token expires, logout the user - if(token) { - const decodedToken = decode(token) - if(decodedToken.exp * 1000 < new Date().getTime()) logout() - } - // eslint-disable-next-line - }, [location, user]) //when location changes, set the user - - - + const dispatch = useDispatch(); + const [user, setUser] = useState(JSON.parse(localStorage.getItem("profile"))); + const history = useHistory(); + const location = useLocation(); + + useEffect(() => { + setUser(JSON.parse(localStorage.getItem("profile"))); + }, [location]); + + const logout = () => { + dispatch({ type: "LOGOUT" }); + history.push("/"); + setUser(null); + }; + useEffect(() => { + const token = user?.token; + // setUser(JSON.parse(localStorage.getItem('profile'))) + //If token expires, logout the user + if (token) { + const decodedToken = decode(token); + if (decodedToken.exp * 1000 < new Date().getTime()) logout(); + } + // eslint-disable-next-line + }, [location, user]); //when location changes, set the user const classes = useStyles(); const [open, setOpen] = React.useState(false); @@ -68,7 +58,7 @@ const Header = () => { setOpen((prevOpen) => !prevOpen); }; - const handleClose = (event ) => { + const handleClose = (event) => { if (anchorRef.current && anchorRef.current.contains(event.target)) { return; } @@ -76,14 +66,13 @@ const Header = () => { setOpen(false); }; - - const openLink =(link) => { - history.push(`/${link}`) - setOpen(false); - } + const openLink = (link) => { + history.push(`/${link}`); + setOpen(false); + }; function handleListKeyDown(event) { - if (event.key === 'Tab') { + if (event.key === "Tab") { event.preventDefault(); setOpen(false); } @@ -99,50 +88,73 @@ const Header = () => { prevOpen.current = open; }, [open]); - - - - if(!user) return ( -
- history.push('/')} src="https://i.postimg.cc/C5fxh51H/Arc-Invoice-Logo2.png" alt="arc-invoice" /> - -
- ) + if (!user) return ( -
-
-
- - - {({ TransitionProps, placement }) => ( - - - - - openLink('settings') }>{(user?.result?.name).split(" ")[0]} - logout()} >Logout - - - - - )} - + Get started +
-
- - + ); + return ( +
+
+
+ + + {({ TransitionProps, placement }) => ( + + + + + openLink("settings")}> + {(user?.result?.name).split(" ")[0]} + + logout()}>Logout + + + + + )} +
- ) -} +
+
+ ); +}; -export default Header +export default Header; diff --git a/client/src/components/Login/Login.js b/client/src/components/Login/Login.js deleted file mode 100644 index 4b28821c..00000000 --- a/client/src/components/Login/Login.js +++ /dev/null @@ -1,126 +0,0 @@ -import React, { useState } from 'react' -import Field from './Field' -import useStyles from './styles' -import styles from './Login.module.css' -import { GoogleLogin } from 'react-google-login' -import {useDispatch} from 'react-redux' -import { useHistory, Link } from 'react-router-dom' -import { signup, signin } from '../../actions/auth' -import { Avatar, Button, Paper, Grid, Typography, Container } from '@material-ui/core' -import LockOutlinedIcon from '@material-ui/icons/LockOutlined' -import { createProfile } from '../../actions/profile' -// import Google from './Google' -import { useSnackbar } from 'react-simple-snackbar' -import ProgressButton from 'react-progress-button' - - - -const initialState ={ firstName: '', lastName: '', email: '', password: '', confirmPassword: '', profilePicture: '', bio: ''} - -const Login = () => { - - const classes = useStyles(); - const [formData, setFormData] = useState(initialState) - const [isSignup, setIsSignup] = useState(false) - const dispatch = useDispatch() - const history = useHistory() - const [showPassword, setShowPassword] = useState(false); - // eslint-disable-next-line - const [openSnackbar, closeSnackbar] = useSnackbar() - const user = JSON.parse(localStorage.getItem('profile')) - - const handleShowPassword = () => setShowPassword(!showPassword); - const handleChange =(e)=> { - setFormData( {...formData, [e.target.name] : e.target.value} ) - } - - const handleSubmit =(e) => { - e.preventDefault() - if(isSignup) { - dispatch(signup(formData, openSnackbar)) - } else { - dispatch(signin(formData, openSnackbar)) - } - } - - - const switchMode =() => { - setIsSignup((prevState) => !prevState) - } - - const googleSuccess = async (res) => { - console.log(res) - const result = res?.profileObj - const token = res?.tokenId - dispatch(createProfile({name: result?.name, email: result?.email, userId: result?.googleId, phoneNumber: '', businessName: '', contactAddress: '', logo: result?.imageUrl, website: ''})) - - try { - dispatch({ type: "AUTH", data: {result, token}}) - - window.location.href='/dashboard' - - } catch (error) { - console.log(error) - } - } - const googleError =(error) => { - console.log(error) - console.log("Google Sign In was unseccassful. Try again later") - } - - - if(user) { - history.push('/dashboard') - } - - return ( - - - - - - { isSignup ? 'Sign up' : 'Sign in' } -
- - { isSignup && ( - <> - - - - )} - - - { isSignup && } - -
-
- {/* */} - { isSignup ? 'Sign Up' : 'Sign In' } -
-
- ( - - )} - onSuccess={googleSuccess} - onFailure={googleError} - cookiePolicy="single_host_origin" - /> -
-
- - - - - -

Forgotten Password?

-
-
-
- ) -} - -export default Login diff --git a/client/src/components/Password/Forgot.js b/client/src/components/Password/Forgot.js index abce865b..c8a27dcd 100644 --- a/client/src/components/Password/Forgot.js +++ b/client/src/components/Password/Forgot.js @@ -3,7 +3,7 @@ import { useDispatch } from 'react-redux'; import { useHistory } from 'react-router-dom' import { Button, Paper, Typography, Container, Grid } from '@material-ui/core'; import useStyles from './styles'; -import Field from '../Login/Field'; +import Field from '../Auth/Field'; import { forgot } from '../../actions/auth'; import styles from './Password.module.css' diff --git a/client/src/components/Password/Reset.js b/client/src/components/Password/Reset.js index 8939be7e..372f3b8a 100644 --- a/client/src/components/Password/Reset.js +++ b/client/src/components/Password/Reset.js @@ -2,7 +2,7 @@ import React, { useState } from 'react'; import { useDispatch } from 'react-redux'; import { Button, Paper, Typography, Container, Grid } from '@material-ui/core'; import useStyles from './styles'; -import Field from '../Login/Field'; +import Field from '../Auth/Field'; import { useParams, useHistory } from 'react-router-dom' import { reset } from '../../actions/auth'; From 445724980a694bab15f8bd26ac6a8b8ee9b6eb19 Mon Sep 17 00:00:00 2001 From: Tobi Oyeleye Date: Wed, 1 Dec 2021 16:00:57 +0100 Subject: [PATCH 2/2] clean up --- client/src/components/Auth/Field.js | 78 ++++++++++++++--------- client/src/components/Auth/auth-form.js | 2 +- client/src/components/Auth/index.js | 15 +++-- client/src/components/Auth/login-form.js | 14 ---- client/src/components/Auth/signup-form.js | 13 ---- 5 files changed, 61 insertions(+), 61 deletions(-) delete mode 100644 client/src/components/Auth/login-form.js delete mode 100644 client/src/components/Auth/signup-form.js diff --git a/client/src/components/Auth/Field.js b/client/src/components/Auth/Field.js index 75438343..0eb21b6f 100644 --- a/client/src/components/Auth/Field.js +++ b/client/src/components/Auth/Field.js @@ -1,32 +1,52 @@ -import React from 'react'; -import { TextField, Grid, InputAdornment, IconButton } from '@material-ui/core'; +import React, { useState } from "react"; +import { TextField, Grid, InputAdornment, IconButton } from "@material-ui/core"; -import Visibility from '@material-ui/icons/Visibility'; -import VisibilityOff from '@material-ui/icons/VisibilityOff'; +import Visibility from "@material-ui/icons/Visibility"; +import VisibilityOff from "@material-ui/icons/VisibilityOff"; -const Field = ({ name, handleChange, label, half, autoFocus, type, handleShowPassword, placeholder }) => ( - - - - {type === 'password' ? : } - - - ), - } : null} - /> - -); +const Field = ({ + name, + handleChange, + label, + half, + autoFocus, + type, + placeholder, +}) => { + const [showPass, setShowPass] = useState(false); -export default Field + const togglePasswordVisibility = () => { + setShowPass((show) => !show); + }; + + return ( + + + + {!showPass ? : } + + + ), + } + : null + } + /> + + ); +}; + +export default Field; diff --git a/client/src/components/Auth/auth-form.js b/client/src/components/Auth/auth-form.js index 54697202..09a203b8 100644 --- a/client/src/components/Auth/auth-form.js +++ b/client/src/components/Auth/auth-form.js @@ -136,7 +136,7 @@ const AuthForm = ({ isSignup = false, onSubmit }) => { type="submit" className={styles.submitBtn} > - {isSignup ? "Sign In" : "Sign Up"} + {isSignup ? "Sign Up" : "Sign In"} )}
diff --git a/client/src/components/Auth/index.js b/client/src/components/Auth/index.js index 224e0324..881e741b 100644 --- a/client/src/components/Auth/index.js +++ b/client/src/components/Auth/index.js @@ -1,8 +1,9 @@ import React from "react"; import { Container } from "@material-ui/core"; import { Switch, Route, useHistory } from "react-router-dom"; -import SignupForm from "./signup-form"; -import LoginForm from "./login-form"; +import AuthForm from "./auth-form"; +import { useDispatch } from "react-redux"; +import { signin, signup } from "../../actions/auth"; const Auth = () => { const history = useHistory(); @@ -13,11 +14,17 @@ const Auth = () => { history.push("/dashboard"); } + const dispatch = useDispatch(); + return ( - - + + dispatch(signin())} /> + + + dispatch(signup())} /> + ); diff --git a/client/src/components/Auth/login-form.js b/client/src/components/Auth/login-form.js deleted file mode 100644 index af45043b..00000000 --- a/client/src/components/Auth/login-form.js +++ /dev/null @@ -1,14 +0,0 @@ -import AuthForm from "./auth-form"; -import { useDispatch } from "react-redux"; -import { signin } from "../../actions/auth"; - -const LoginForm = () => { - const dispatch = useDispatch(); - - const handleSubmit = (formData) => dispatch(signin(formData)); - - - return ; -}; - -export default LoginForm; diff --git a/client/src/components/Auth/signup-form.js b/client/src/components/Auth/signup-form.js deleted file mode 100644 index 17eed2d8..00000000 --- a/client/src/components/Auth/signup-form.js +++ /dev/null @@ -1,13 +0,0 @@ -import AuthForm from "./auth-form"; -import { signup } from "../../actions/auth"; -import { useDispatch } from "react-redux"; - -const SignupForm = () => { - const dispatch = useDispatch(); - - const handleSubmit = (formData) => dispatch(signup(formData)) - - return ; -}; - -export default SignupForm;