Completed Login/Logout/Protected Routes
This commit is contained in:
@@ -3,7 +3,9 @@ import { Route, Switch } from "react-router-dom";
|
||||
|
||||
import Login from "./Auth/Login";
|
||||
import Register from "./Auth/Register";
|
||||
import Settings from "./Auth/Settings";
|
||||
import VerifyEmail from "./Auth/VerifyEmail";
|
||||
import PrivateRoute from "./Shared/PrivateRoute";
|
||||
import About from "./Static/About";
|
||||
import Footer from "./Static/Footer";
|
||||
import Home from "./Static/Home";
|
||||
@@ -31,6 +33,7 @@ class App extends Component {
|
||||
path="/auth/verify-email/:emailKey"
|
||||
component={VerifyEmail}
|
||||
/>
|
||||
<PrivateRoute path="/auth/settings" component={Settings} />
|
||||
<Route component={NoMatch} />
|
||||
</Switch>
|
||||
</div>
|
||||
|
@@ -1,16 +1,111 @@
|
||||
import React, { Component } from "react";
|
||||
import { Container } from "semantic-ui-react";
|
||||
import { connect } from "react-redux";
|
||||
import { Redirect } from "react-router-dom";
|
||||
import { Container, Form, Header, Message } from "semantic-ui-react";
|
||||
|
||||
import {
|
||||
clearAuthRequestError,
|
||||
clearAuthRequestSuccess,
|
||||
setFormEmail,
|
||||
setFormPassword
|
||||
} from "../../actions/auth/reducer.actions";
|
||||
import { sendLoginRequest } from "../../actions/auth/saga.actions";
|
||||
import Error from "../Shared/Error";
|
||||
|
||||
class Login extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.props.dispatch(clearAuthRequestError());
|
||||
this.props.dispatch(clearAuthRequestSuccess());
|
||||
}
|
||||
|
||||
changeEmail = event => {
|
||||
this.props.dispatch(setFormEmail(event.target.value));
|
||||
};
|
||||
|
||||
changePassword = event => {
|
||||
this.props.dispatch(setFormPassword(event.target.value));
|
||||
};
|
||||
|
||||
onSubmitLogin = event => {
|
||||
event.preventDefault();
|
||||
const { dispatch, email, password } = this.props;
|
||||
dispatch(sendLoginRequest({ email, password }));
|
||||
};
|
||||
|
||||
render() {
|
||||
return <LoginView />;
|
||||
const {
|
||||
isSendingAuthRequest,
|
||||
authRequestError,
|
||||
authRequestSuccess,
|
||||
email,
|
||||
password,
|
||||
userToken
|
||||
} = this.props;
|
||||
if (userToken) return <Redirect to={"/"} />;
|
||||
return (
|
||||
<LoginView
|
||||
isSendingAuthRequest={isSendingAuthRequest}
|
||||
authRequestError={authRequestError}
|
||||
authRequestSuccess={authRequestSuccess}
|
||||
email={email}
|
||||
password={password}
|
||||
changeEmail={this.changeEmail}
|
||||
changePassword={this.changePassword}
|
||||
onSubmitLogin={this.onSubmitLogin}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const LoginView = () => (
|
||||
function mapStateToProps(state) {
|
||||
return { ...state.auth };
|
||||
}
|
||||
|
||||
const LoginView = ({
|
||||
isSendingAuthRequest,
|
||||
authRequestError,
|
||||
authRequestSuccess,
|
||||
email,
|
||||
password,
|
||||
changeEmail,
|
||||
changePassword,
|
||||
onSubmitLogin
|
||||
}) => (
|
||||
<Container>
|
||||
<p>Login</p>
|
||||
<Header>Login</Header>
|
||||
<Form
|
||||
loading={isSendingAuthRequest}
|
||||
onSubmit={onSubmitLogin}
|
||||
error={!!authRequestError}
|
||||
success={!!authRequestSuccess}
|
||||
>
|
||||
<Form.Field>
|
||||
<label>Email</label>
|
||||
<input
|
||||
placeholder="bob@gmail.com"
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={changeEmail}
|
||||
/>
|
||||
</Form.Field>
|
||||
<Form.Field>
|
||||
<label>Password</label>
|
||||
<input
|
||||
placeholder="••••••••"
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={changePassword}
|
||||
/>
|
||||
</Form.Field>
|
||||
<Error header="Login failed!" error={authRequestError} />
|
||||
<Message success>
|
||||
<Message.Header>Login successful!</Message.Header>
|
||||
<p>Redirecting you now...</p>
|
||||
</Message>
|
||||
<Form.Button>Login</Form.Button>
|
||||
</Form>
|
||||
</Container>
|
||||
);
|
||||
|
||||
export default Login;
|
||||
export default connect(mapStateToProps)(Login);
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Redirect } from "react-router-dom";
|
||||
import { Container, Form, Header, Message } from "semantic-ui-react";
|
||||
|
||||
import {
|
||||
@@ -50,8 +51,10 @@ class Register extends Component {
|
||||
authRequestSuccess,
|
||||
email,
|
||||
password,
|
||||
passwordConfirmation
|
||||
passwordConfirmation,
|
||||
userToken
|
||||
} = this.props;
|
||||
if (userToken) return <Redirect to={"/"} />;
|
||||
return (
|
||||
<RegisterView
|
||||
isSendingAuthRequest={isSendingAuthRequest}
|
||||
|
22
src/components/Auth/Settings.jsx
Normal file
22
src/components/Auth/Settings.jsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Container } from "semantic-ui-react";
|
||||
|
||||
class Settings extends Component {
|
||||
render() {
|
||||
return <SettingsView />;
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return { ...state.auth };
|
||||
}
|
||||
|
||||
const SettingsView = () => (
|
||||
<Container>
|
||||
<h1>Settings</h1>
|
||||
<p>todo, change password</p>
|
||||
</Container>
|
||||
);
|
||||
|
||||
export default connect(mapStateToProps)(Settings);
|
@@ -1,28 +1,61 @@
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Menu } from "semantic-ui-react";
|
||||
import { Dropdown, Menu } from "semantic-ui-react";
|
||||
|
||||
import { sendLogoutRequest } from "../actions/auth/saga.actions";
|
||||
|
||||
class Navbar extends Component {
|
||||
dispatchLogoutRequest = () => {
|
||||
this.props.dispatch(sendLogoutRequest());
|
||||
};
|
||||
|
||||
render() {
|
||||
const { userToken } = this.props;
|
||||
return (
|
||||
<Menu>
|
||||
<Menu.Item as={Link} to="/">
|
||||
Caremyway
|
||||
</Menu.Item>
|
||||
<Menu.Item as={Link} to="/about">
|
||||
About
|
||||
</Menu.Item>
|
||||
<Menu.Menu position="right">
|
||||
<Menu.Item as={Link} to="/auth/login">
|
||||
Login
|
||||
</Menu.Item>
|
||||
<Menu.Item as={Link} to="/auth/register">
|
||||
Register
|
||||
</Menu.Item>
|
||||
</Menu.Menu>
|
||||
</Menu>
|
||||
<NavbarView
|
||||
isAuthenticated={!!userToken}
|
||||
dispatchLogoutRequest={this.dispatchLogoutRequest}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Navbar;
|
||||
function mapStateToProps(state) {
|
||||
return { ...state.auth };
|
||||
}
|
||||
|
||||
const NavbarView = ({ isAuthenticated, dispatchLogoutRequest }) => (
|
||||
<Menu>
|
||||
<Menu.Item as={Link} to="/">
|
||||
Caremyway
|
||||
</Menu.Item>
|
||||
<Menu.Item as={Link} to="/about">
|
||||
About
|
||||
</Menu.Item>
|
||||
{!isAuthenticated &&
|
||||
<Menu.Menu position="right">
|
||||
<Menu.Item as={Link} to="/auth/login">
|
||||
Login
|
||||
</Menu.Item>
|
||||
<Menu.Item as={Link} to="/auth/register">
|
||||
Register
|
||||
</Menu.Item>
|
||||
</Menu.Menu>}
|
||||
{!!isAuthenticated &&
|
||||
<Menu.Menu position="right">
|
||||
<Dropdown item text="Account">
|
||||
<Dropdown.Menu>
|
||||
<Dropdown.Item as={Link} to="/auth/settings">
|
||||
Settings
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item onClick={dispatchLogoutRequest}>
|
||||
Logout
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
</Menu.Menu>}
|
||||
</Menu>
|
||||
);
|
||||
|
||||
export default connect(mapStateToProps)(Navbar);
|
||||
|
29
src/components/Shared/PrivateRoute.jsx
Normal file
29
src/components/Shared/PrivateRoute.jsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import PropTypes from "prop-types";
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Redirect, Route } from "react-router-dom";
|
||||
|
||||
const propTypes = {
|
||||
userToken: PropTypes.string,
|
||||
component: PropTypes.oneOfType([PropTypes.element, PropTypes.func]).isRequired
|
||||
};
|
||||
|
||||
const PrivateRoute = ({ userToken, component, ...rest }) => {
|
||||
return (
|
||||
<Route
|
||||
{...rest}
|
||||
render={props => {
|
||||
if (!!userToken) return React.createElement(component, props);
|
||||
return <Redirect to="/auth/login" />;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
PrivateRoute.propTypes = propTypes;
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
userToken: state.auth.userToken
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(PrivateRoute);
|
Reference in New Issue
Block a user