forked from Remchi/bookworm-react
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
283 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import React from "react"; | ||
import PropTypes from "prop-types"; | ||
import { Form, Button, Message } from "semantic-ui-react"; | ||
import isEmail from "validator/lib/isEmail"; | ||
import InlineError from "../messages/InlineError"; | ||
|
||
class ForgotPasswordForm extends React.Component { | ||
state = { | ||
data: { | ||
email: "" | ||
}, | ||
loading: false, | ||
errors: {} | ||
}; | ||
|
||
onChange = e => | ||
this.setState({ | ||
...this.state, | ||
data: { ...this.state.data, [e.target.name]: e.target.value } | ||
}); | ||
|
||
onSubmit = e => { | ||
e.preventDefault(); | ||
const errors = this.validate(this.state.data); | ||
this.setState({ errors }); | ||
if (Object.keys(errors).length === 0) { | ||
this.setState({ loading: true }); | ||
this.props | ||
.submit(this.state.data) | ||
.catch(err => | ||
this.setState({ errors: err.response.data.errors, loading: false }) | ||
); | ||
} | ||
}; | ||
|
||
validate = data => { | ||
const errors = {}; | ||
if (!isEmail(data.email)) errors.email = "Invalid email"; | ||
return errors; | ||
}; | ||
|
||
render() { | ||
const { errors, data, loading } = this.state; | ||
|
||
return ( | ||
<Form onSubmit={this.onSubmit} loading={loading}> | ||
{!!errors.global && <Message negative>{errors.global}</Message>} | ||
<Form.Field error={!!errors.email}> | ||
<label htmlFor="email">Email</label> | ||
<input | ||
type="email" | ||
id="email" | ||
name="email" | ||
placeholder="email" | ||
value={data.email} | ||
onChange={this.onChange} | ||
/> | ||
{errors.email && <InlineError text={errors.email} />} | ||
</Form.Field> | ||
<Button primary>ForgotPasswordForm</Button> | ||
</Form> | ||
); | ||
} | ||
} | ||
|
||
ForgotPasswordForm.propTypes = { | ||
submit: PropTypes.func.isRequired | ||
}; | ||
|
||
export default ForgotPasswordForm; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import React from "react"; | ||
import PropTypes from "prop-types"; | ||
import { Form, Button } from "semantic-ui-react"; | ||
import InlineError from "../messages/InlineError"; | ||
|
||
class ResetPasswordForm extends React.Component { | ||
state = { | ||
data: { | ||
token: this.props.token, | ||
password: "", | ||
passwordConfirmation: "" | ||
}, | ||
loading: false, | ||
errors: {} | ||
}; | ||
|
||
onChange = e => | ||
this.setState({ | ||
...this.state, | ||
data: { ...this.state.data, [e.target.name]: e.target.value } | ||
}); | ||
|
||
onSubmit = e => { | ||
e.preventDefault(); | ||
const errors = this.validate(this.state.data); | ||
this.setState({ errors }); | ||
if (Object.keys(errors).length === 0) { | ||
this.setState({ loading: true }); | ||
this.props | ||
.submit(this.state.data) | ||
.catch(err => | ||
this.setState({ errors: err.response.data.errors, loading: false }) | ||
); | ||
} | ||
}; | ||
|
||
validate = data => { | ||
const errors = {}; | ||
if (!data.password) errors.password = "Can't be blank"; | ||
if (data.password !== data.passwordConfirmation) | ||
errors.password = "Passwords must match"; | ||
return errors; | ||
}; | ||
|
||
render() { | ||
const { errors, data, loading } = this.state; | ||
|
||
return ( | ||
<Form onSubmit={this.onSubmit} loading={loading}> | ||
<Form.Field error={!!errors.password}> | ||
<label htmlFor="password">New Password</label> | ||
<input | ||
type="password" | ||
id="password" | ||
name="password" | ||
placeholder="your new password" | ||
value={data.password} | ||
onChange={this.onChange} | ||
/> | ||
{errors.password && <InlineError text={errors.password} />} | ||
</Form.Field> | ||
|
||
<Form.Field error={!!errors.passwordConfirmation}> | ||
<label htmlFor="passwordConfirmation"> | ||
Confirm your new password | ||
</label> | ||
<input | ||
type="password" | ||
id="passwordConfirmation" | ||
name="passwordConfirmation" | ||
placeholder="type it again, please" | ||
value={data.passwordConfirmation} | ||
onChange={this.onChange} | ||
/> | ||
{errors.passwordConfirmation && ( | ||
<InlineError text={errors.passwordConfirmation} /> | ||
)} | ||
</Form.Field> | ||
|
||
<Button primary>Reset</Button> | ||
</Form> | ||
); | ||
} | ||
} | ||
|
||
ResetPasswordForm.propTypes = { | ||
submit: PropTypes.func.isRequired, | ||
token: PropTypes.string.isRequired | ||
}; | ||
|
||
export default ResetPasswordForm; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import React from "react"; | ||
import PropTypes from "prop-types"; | ||
import { connect } from "react-redux"; | ||
import { Message } from "semantic-ui-react"; | ||
import ForgotPasswordForm from "../forms/ForgotPasswordForm"; | ||
import { resetPasswordRequest } from "../../actions/auth"; | ||
|
||
class ForgotPasswordPage extends React.Component { | ||
state = { | ||
success: false | ||
}; | ||
|
||
submit = data => | ||
this.props | ||
.resetPasswordRequest(data) | ||
.then(() => this.setState({ success: true })); | ||
|
||
render() { | ||
return ( | ||
<div> | ||
{this.state.success ? ( | ||
<Message>Email has been sent.</Message> | ||
) : ( | ||
<ForgotPasswordForm submit={this.submit} /> | ||
)} | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
ForgotPasswordPage.propTypes = { | ||
resetPasswordRequest: PropTypes.func.isRequired | ||
}; | ||
|
||
export default connect(null, { resetPasswordRequest })(ForgotPasswordPage); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import React from "react"; | ||
import PropTypes from "prop-types"; | ||
import { connect } from "react-redux"; | ||
import { Message } from "semantic-ui-react"; | ||
import ResetPasswordForm from "../forms/ResetPasswordForm"; | ||
import { validateToken, resetPassword } from "../../actions/auth"; | ||
|
||
class ResetPasswordPage extends React.Component { | ||
state = { | ||
loading: true, | ||
success: false | ||
}; | ||
|
||
componentDidMount() { | ||
this.props | ||
.validateToken(this.props.match.params.token) | ||
.then(() => this.setState({ loading: false, success: true })) | ||
.catch(() => this.setState({ loading: false, success: false })); | ||
} | ||
|
||
submit = data => | ||
this.props | ||
.resetPassword(data) | ||
.then(() => this.props.history.push("/login")); | ||
|
||
render() { | ||
const { loading, success } = this.state; | ||
const token = this.props.match.params.token; | ||
|
||
return ( | ||
<div> | ||
{loading && <Message>Loading</Message>} | ||
{!loading && | ||
success && <ResetPasswordForm submit={this.submit} token={token} />} | ||
{!loading && !success && <Message>Invalid Token</Message>} | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
ResetPasswordPage.propTypes = { | ||
validateToken: PropTypes.func.isRequired, | ||
resetPassword: PropTypes.func.isRequired, | ||
match: PropTypes.shape({ | ||
params: PropTypes.shape({ | ||
token: PropTypes.string.isRequired | ||
}).isRequired | ||
}).isRequired, | ||
history: PropTypes.shape({ | ||
push: PropTypes.func.isRequired | ||
}).isRequired | ||
}; | ||
|
||
export default connect(null, { validateToken, resetPassword })( | ||
ResetPasswordPage | ||
); |