parent
83ddd34c7c
commit
1bf1dad0b9
14 changed files with 342 additions and 54 deletions
@ -1,18 +1,33 @@ |
||||
import { |
||||
SEND_REGISTER_REQUEST, |
||||
SEND_EMAIL_VERIFICATION_REQUEST |
||||
SEND_EMAIL_VERIFICATION_REQUEST, |
||||
SEND_LOGIN_REQUEST, |
||||
SEND_LOGOUT_REQUEST |
||||
} from "../../constants/auth.constants"; |
||||
|
||||
export function sendRegisterRequest(postbody) { |
||||
export function sendRegisterRequest(postBody) { |
||||
return { |
||||
type: SEND_REGISTER_REQUEST, |
||||
data: postbody |
||||
data: postBody |
||||
}; |
||||
} |
||||
|
||||
export function sendEmailVerificationRequest(postbody) { |
||||
export function sendEmailVerificationRequest(postBody) { |
||||
return { |
||||
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 { 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); |
||||
|
@ -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); |
||||
|
@ -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 { SEND_REGISTER_REQUEST, SEND_EMAIL_VERIFICATION_REQUEST } from "../constants/auth.constants"; |
||||
import { registerUserFlow, verifyEmailFlow } from "./auth.sagas"; |
||||
import { |
||||
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() { |
||||
yield takeLatest(SEND_REGISTER_REQUEST, registerUserFlow); |
||||
yield takeLatest(SEND_EMAIL_VERIFICATION_REQUEST, verifyEmailFlow); |
||||
yield takeLatest(SEND_LOGIN_REQUEST, loginUserFlow); |
||||
yield takeLatest(SEND_LOGOUT_REQUEST, logoutUserFlow); |
||||
} |
||||
|
Loading…
Reference in new issue