parent
83ddd34c7c
commit
1bf1dad0b9
14 changed files with 342 additions and 54 deletions
@ -1,18 +1,33 @@ |
|||||||
import { |
import { |
||||||
SEND_REGISTER_REQUEST, |
SEND_REGISTER_REQUEST, |
||||||
SEND_EMAIL_VERIFICATION_REQUEST |
SEND_EMAIL_VERIFICATION_REQUEST, |
||||||
|
SEND_LOGIN_REQUEST, |
||||||
|
SEND_LOGOUT_REQUEST |
||||||
} from "../../constants/auth.constants"; |
} from "../../constants/auth.constants"; |
||||||
|
|
||||||
export function sendRegisterRequest(postbody) { |
export function sendRegisterRequest(postBody) { |
||||||
return { |
return { |
||||||
type: SEND_REGISTER_REQUEST, |
type: SEND_REGISTER_REQUEST, |
||||||
data: postbody |
data: postBody |
||||||
}; |
}; |
||||||
} |
} |
||||||
|
|
||||||
export function sendEmailVerificationRequest(postbody) { |
export function sendEmailVerificationRequest(postBody) { |
||||||
return { |
return { |
||||||
type: SEND_EMAIL_VERIFICATION_REQUEST, |
type: SEND_EMAIL_VERIFICATION_REQUEST, |
||||||
data: postbody |
data: postBody |
||||||
}; |
}; |
||||||
} |
} |
||||||
|
|
||||||
|
export function sendLoginRequest(postBody) { |
||||||
|
return { |
||||||
|
type: SEND_LOGIN_REQUEST, |
||||||
|
data: postBody |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
export function sendLogoutRequest() { |
||||||
|
return { |
||||||
|
type: SEND_LOGOUT_REQUEST |
||||||
|
} |
||||||
|
} |
||||||
|
@ -1,16 +1,111 @@ |
|||||||
import React, { Component } from "react"; |
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 { |
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() { |
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> |
<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> |
</Container> |
||||||
); |
); |
||||||
|
|
||||||
export default Login; |
export default connect(mapStateToProps)(Login); |
||||||
|
@ -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 React, { Component } from "react"; |
||||||
|
import { connect } from "react-redux"; |
||||||
import { Link } from "react-router-dom"; |
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 { |
class Navbar extends Component { |
||||||
|
dispatchLogoutRequest = () => { |
||||||
|
this.props.dispatch(sendLogoutRequest()); |
||||||
|
}; |
||||||
|
|
||||||
render() { |
render() { |
||||||
|
const { userToken } = this.props; |
||||||
return ( |
return ( |
||||||
<Menu> |
<NavbarView |
||||||
<Menu.Item as={Link} to="/"> |
isAuthenticated={!!userToken} |
||||||
Caremyway |
dispatchLogoutRequest={this.dispatchLogoutRequest} |
||||||
</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> |
|
||||||
); |
); |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
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); |
||||||
|
@ -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); |
@ -1,8 +1,20 @@ |
|||||||
import { takeLatest } from "redux-saga/effects"; |
import { takeLatest } from "redux-saga/effects"; |
||||||
import { SEND_REGISTER_REQUEST, SEND_EMAIL_VERIFICATION_REQUEST } from "../constants/auth.constants"; |
import { |
||||||
import { registerUserFlow, verifyEmailFlow } from "./auth.sagas"; |
SEND_REGISTER_REQUEST, |
||||||
|
SEND_EMAIL_VERIFICATION_REQUEST, |
||||||
|
SEND_LOGIN_REQUEST, |
||||||
|
SEND_LOGOUT_REQUEST |
||||||
|
} from "../constants/auth.constants"; |
||||||
|
import { |
||||||
|
registerUserFlow, |
||||||
|
verifyEmailFlow, |
||||||
|
loginUserFlow, |
||||||
|
logoutUserFlow |
||||||
|
} from "./auth.sagas"; |
||||||
|
|
||||||
export default function* rootSaga() { |
export default function* rootSaga() { |
||||||
yield takeLatest(SEND_REGISTER_REQUEST, registerUserFlow); |
yield takeLatest(SEND_REGISTER_REQUEST, registerUserFlow); |
||||||
yield takeLatest(SEND_EMAIL_VERIFICATION_REQUEST, verifyEmailFlow); |
yield takeLatest(SEND_EMAIL_VERIFICATION_REQUEST, verifyEmailFlow); |
||||||
|
yield takeLatest(SEND_LOGIN_REQUEST, loginUserFlow); |
||||||
|
yield takeLatest(SEND_LOGOUT_REQUEST, logoutUserFlow); |
||||||
} |
} |
||||||
|
Loading…
Reference in new issue