diff --git a/client/src/App.js b/client/src/App.js
index d69802b..78a86ab 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/Auth/Field.js b/client/src/components/Auth/Field.js
new file mode 100644
index 0000000..0eb21b6
--- /dev/null
+++ b/client/src/components/Auth/Field.js
@@ -0,0 +1,52 @@
+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";
+
+const Field = ({
+ name,
+ handleChange,
+ label,
+ half,
+ autoFocus,
+ type,
+ placeholder,
+}) => {
+ const [showPass, setShowPass] = useState(false);
+
+ const togglePasswordVisibility = () => {
+ setShowPass((show) => !show);
+ };
+
+ return (
+
+
+
+ {!showPass ? : }
+
+
+ ),
+ }
+ : null
+ }
+ />
+
+ );
+};
+
+export default Field;
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 0000000..09a203b
--- /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"}
+
+
+
+ );
+};
+
+export default AuthForm;
diff --git a/client/src/components/Auth/index.js b/client/src/components/Auth/index.js
new file mode 100644
index 0000000..881e741
--- /dev/null
+++ b/client/src/components/Auth/index.js
@@ -0,0 +1,33 @@
+import React from "react";
+import { Container } from "@material-ui/core";
+import { Switch, Route, useHistory } from "react-router-dom";
+import AuthForm from "./auth-form";
+import { useDispatch } from "react-redux";
+import { signin, signup } from "../../actions/auth";
+
+const Auth = () => {
+ const history = useHistory();
+ // eslint-disable-next-line
+ const user = JSON.parse(localStorage.getItem("profile"));
+
+ if (user) {
+ history.push("/dashboard");
+ }
+
+ const dispatch = useDispatch();
+
+ return (
+
+
+
+ dispatch(signin())} />
+
+
+ dispatch(signup())} />
+
+
+
+ );
+};
+
+export default Auth;
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 1248f48..53b2b12 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 (
-
-
-
-
-
-
-
+ );
+ return (
+
+
+
+
+
+ {user?.result?.name?.charAt(0)}
+
+
+
+ {({ TransitionProps, placement }) => (
+
+
+
+
+
+
+
+ )}
+
- )
-}
+
+
+ );
+};
-export default Header
+export default Header;
diff --git a/client/src/components/Login/Field.js b/client/src/components/Login/Field.js
deleted file mode 100644
index b12ee73..0000000
--- a/client/src/components/Login/Field.js
+++ /dev/null
@@ -1,55 +0,0 @@
-// 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';
-
-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}
- />
-
-);
-
-export default Field
diff --git a/client/src/components/Login/Login.js b/client/src/components/Login/Login.js
deleted file mode 100644
index 4b28821..0000000
--- 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' }
-
-
-
- )
-}
-
-export default Login
diff --git a/client/src/components/Password/Forgot.js b/client/src/components/Password/Forgot.js
index abce865..c8a27dc 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 8939be7..372f3b8 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';