Skip to content

Commit

Permalink
Merge 3c217cc into 3f44ff4
Browse files Browse the repository at this point in the history
  • Loading branch information
Benkimeric committed May 31, 2019
2 parents 3f44ff4 + 3c217cc commit 9ac8e68
Show file tree
Hide file tree
Showing 16 changed files with 409 additions and 34 deletions.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,16 @@
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^0.18.0",
"coveralls": "^3.0.3",
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.13.2",
"express": "^4.17.1",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-redux": "^7.0.3",
"react-router-dom": "^5.0.0",
"react-toastify": "^5.1.1",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0",
"semantic-ui-react": "^0.87.1"
Expand Down
82 changes: 79 additions & 3 deletions src/assets/styles/login.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,80 @@
.login h2 {
color: blue;
font-size: 18px;
.sign-in-page {
h1 {
text-align: center;
margin-top: 2%;
}

.hidden {
display: none;
}

.show {
display: block;
}

.signin-form {
display: inline-block;
-moz-box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.5);
-webkit-box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.5);
box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.5);
padding: 70px 90px 90px 90px;
width: 40%;
height: 75%;
margin: auto;
display: flex;
justify-content: space-between;
flex-direction: column;
margin-top: 2%;
border-radius: 5px;
}

.separator {
display: flex;
align-items: center;
&-line {
height: 2px;
background: #cecece;
width: 48%;
}
&-text {
background: transparent;
border-radius: 50%;
margin: 0 5px 0 5px;
border: 2px solid #cecece;
padding: 1%;
}
margin-bottom: 4%;
margin-top: 4%;
}

.social {
display: flex;
justify-content: center;
&-facebook {
color: white;
background-color: #3b5998;
margin-right: 10%;
}
&-google {
color: white;
background-color: #db4437;
}
}

.submit-btn {
margin-bottom: 5%;
background: #3472d6;
color: white;
padding: 4%;
margin-top: 5%;
}

.login {
display: flex;
align-items: center;
margin-top: 10%;
&-text {
margin: -14px 5px 0 5px;
}
}
}
3 changes: 3 additions & 0 deletions src/components/App.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import React, { Component, Fragment } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { ToastContainer } from 'react-toastify';
import Header from './layout/Header';
import routes from '../routes';
import 'react-toastify/dist/ReactToastify.css';

class App extends Component {
render() {
return (
<div>
<ToastContainer />
<Router>
<Fragment>
<Header />
Expand Down
76 changes: 72 additions & 4 deletions src/components/auth/Login.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,82 @@
import React, { Component } from 'react';
import { Button, Form, Icon } from 'semantic-ui-react';
import '../../assets/styles/login.scss';
import { Link } from 'react-router-dom';

export class Login extends Component {
class LoginForm extends Component {
render() {
const {
onSubmit, onChange, email, password,
} = this.props;
return (
<div className="login">
<h2>Welcome back ! Login to Authors Haven</h2>
<div className="sign-in-page">
<h1>Authors Haven</h1>
<div className="signin-form">
<h1>Login</h1>
<Form onSubmit={onSubmit}>
<Form.Field>
<label id="test">Email</label>
<input
placeholder="email"
id="email"
type="email"
onChange={onChange}
required
/>
</Form.Field>
<Form.Field>
<label>Password</label>
<input
placeholder="password"
id="password"
onChange={onChange}
type="Password"
required
/>
</Form.Field>
<Button
fluid
className="submit-btn"
disabled={
!email.match(/^[a-zA-z0-9_.]+@[a-zA-z0-9-]+\.[a-z]+$/)
|| !password.match(/^[a-zA-Z0-9]{8,}$/)
}
type="submit"
>
Login
</Button>
</Form>
<div>
<div className="separator">
<div className="separator-line" />
<p className="separator-text">OR</p>
<div className="separator-line" />
</div>
<div className="social">
<Icon
name="facebook f"
size="large"
circular
className="social-facebook"
/>
<Icon
name="google"
size="large"
circular
className="social-google"
/>
</div>
<div className="login">
<p>No account?</p>
<Link className="login-text" to="/signup">
Signup here.
</Link>
</div>
</div>
</div>
</div>
);
}
}

export default Login;
export default LoginForm;
33 changes: 26 additions & 7 deletions src/components/layout/Header.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,40 @@
import React, { Component } from 'react';
import { Menu } from 'semantic-ui-react';
import { NavLink } from 'react-router-dom';
import { connect } from 'react-redux';
import LoggedInLinks from './LoggedInLinks';
import LoggedOutLinks from './LoggedOutLinks';
import { isLoggedIn } from '../../helpers';

export default class Header extends Component {
class Header extends Component {
render() {
const { login } = this.props;
const links = login.isAuthentincated ? (
<LoggedInLinks />
) : (
<LoggedOutLinks />
);
return (
<Menu>
<NavLink to="/">
<Menu.Item header>Authors Haven</Menu.Item>
</NavLink>
<NavLink to="/">
<Menu.Item name="Home" />
</NavLink>
<NavLink to="/login">
<Menu.Item name="login" />
</NavLink>
<Menu.Menu position="right">
<NavLink to="/">
<Menu.Item name="Home" />
</NavLink>
{links}
</Menu.Menu>
</Menu>
);
}
}

const mapStateToProps = state => ({
login: state.LoginReducer,
});

export default connect(
mapStateToProps,
null,
)(Header);
33 changes: 33 additions & 0 deletions src/components/layout/LoggedInLinks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react';
import { NavLink, withRouter } from 'react-router-dom';
import { Menu } from 'semantic-ui-react';
import { connect } from 'react-redux';
import { logoutUser } from '../../redux/actions/loginActions';


class LoggedInLinks extends React.Component {
handleLogout = () => {
localStorage.clear();
const { logoutUser } = this.props;
logoutUser();
this.props.history.push('/login');
};

render() {
return <Menu.Item onClick={this.handleLogout} name="Logout" />;
}
}

const mapStateToProps = state => ({
login: state.loginUser,
error: state.LoginReducer.error,
});

const mapDispatchToProps = () => ({
logoutUser,
});

export default connect(
mapStateToProps,
mapDispatchToProps(),
)(withRouter(LoggedInLinks));
11 changes: 11 additions & 0 deletions src/components/layout/LoggedOutLinks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import { NavLink } from 'react-router-dom';
import { Menu } from 'semantic-ui-react';

const LoggedOutLinks = () => (
<NavLink to="/login">
<Menu.Item name="login" />
</NavLink>
);

export default LoggedOutLinks;
26 changes: 26 additions & 0 deletions src/helpers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { toast } from 'react-toastify';

export const successToast = message => {
toast.success(message, {
position: toast.POSITION.TOP_CENTER,
autoClose: 3000,
hideProgressBar: true,
pauseOnHover: true,
});
};

export const errorToast = message => {
toast.error(message, {
position: toast.POSITION.TOP_CENTER,
autoClose: 3000,
hideProgressBar: true,
pauseOnHover: true,
});
};

export const isLoggedIn = () => {
if (localStorage.getItem('token')) {
return true;
}
return false;
};
42 changes: 42 additions & 0 deletions src/redux/actions/loginActions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import axios from 'axios';
import { toast } from 'react-toastify';
import { LOGIN_USER } from '../constants';
import { successToast, errorToast } from '../../helpers';

export const loginUser = (data, history) => (dispatch) => {
dispatch({ type: LOGIN_USER });
axios
.post(
'https://ah-the-jedi-backend-staging.herokuapp.com/api/users/login/',
data,
)
.then((response) => {
dispatch(loginSuccess(response.data));

successToast(`Welcome ${response.data.user.username}`);
history.push('/');
})
.catch((error) => {
console.log(error);
dispatch(loginFailure(error));
errorToast(error.response.data.errors.error[0]);
});
};

export const logoutUser = () => (dispatch) => {
dispatch(logout());
};

export const loginSuccess = response => ({
type: `${LOGIN_USER}_SUCCESS`,
response,
});

export const loginFailure = error => ({
type: `${LOGIN_USER}_FAILURE`,
error,
});

export const logout = () => ({
type: `${LOGIN_USER}_LOGOUT`,
});
1 change: 1 addition & 0 deletions src/redux/constants/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const LOGIN_USER = 'LOGIN_USER';
5 changes: 4 additions & 1 deletion src/redux/reducers/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { combineReducers } from 'redux';
import LoginReducer from './LoginReducer';

const rootReducer = combineReducers({});
const rootReducer = combineReducers({
LoginReducer,
});

export default rootReducer;
Loading

0 comments on commit 9ac8e68

Please sign in to comment.