forked from binary-com/deriv-app
-
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.
add Multisteps component, send email template & set up Deriv Password…
… form
- Loading branch information
Showing
17 changed files
with
441 additions
and
18 deletions.
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
48 changes: 48 additions & 0 deletions
48
packages/trader/src/App/Containers/AccountManagementModal/Components/multistep.jsx
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,48 @@ | ||
|
||
import React from 'react'; | ||
import { localize } from 'App/i18n'; | ||
import Icon from 'Assets/icon.jsx'; | ||
|
||
class MultiStep extends React.Component { | ||
state = { | ||
step : 0, | ||
component: this.props.steps[0].component, | ||
}; | ||
|
||
nextStep = () => { | ||
this.setState({ | ||
step: this.state.step + 1 | ||
}, () => this.setState({ | ||
component: this.props.steps[this.state.step].component | ||
})); | ||
} | ||
|
||
prevStep = () => { | ||
this.setState({ | ||
step: this.state.step - 1 | ||
}, () => this.setState({ | ||
component: this.props.steps[this.state.step].component | ||
})); | ||
} | ||
|
||
prevButton = () => ( | ||
this.state.step !== 0 && | ||
<a onClick={this.prevStep} className='multistep-btn'> | ||
<Icon icon='IconBack' className='multistep-btn__icon' /> | ||
{localize('Back')} | ||
</a> | ||
); | ||
|
||
render() { | ||
return ( | ||
<> | ||
{this.prevButton()} | ||
<div className='multistep-component'> | ||
{this.state.component} | ||
</div> | ||
</> | ||
); | ||
} | ||
}; | ||
|
||
export default MultiStep; |
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
106 changes: 106 additions & 0 deletions
106
...ontainers/AccountManagementModal/SecurityAndSafety/DerivPassword/change-password-form.jsx
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,106 @@ | ||
// import PropTypes from 'prop-types'; | ||
import React from 'react'; | ||
// import { WS } from 'Services'; | ||
import { localize } from 'App/i18n'; | ||
import { Formik } from 'formik'; | ||
import { | ||
Button, | ||
Input } from 'deriv-components'; | ||
import { | ||
FormBody, | ||
FormFooter } from '../../Components/layout-components.jsx'; | ||
import Loading from '../../../../../templates/app/components/loading.jsx'; | ||
|
||
const validateFields = values => { | ||
const errors = {}; | ||
const required_fields = ['old_password', 'new_password']; | ||
required_fields.forEach(required => { | ||
if (!values[required]) errors[required] = localize('This field is required'); | ||
}); | ||
if (values.old_password === values.new_password) { | ||
errors.new_password = localize('Current password and new password cannot be the same.'); | ||
} | ||
if (!/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]+/.test(values.new_password)) { | ||
errors.new_password = localize('Password should have lower and uppercase letters with numbers.'); | ||
} | ||
return errors; | ||
}; | ||
|
||
class ChangePasswordForm extends React.Component { | ||
state = { | ||
is_loading: false, | ||
} | ||
|
||
onSubmit = values => { | ||
console.log('on_submit: ', values); | ||
} | ||
|
||
render() { | ||
return ( | ||
<> | ||
<Formik | ||
initialValues={{ | ||
old_password: '', | ||
new_password: '', | ||
}} | ||
validate={validateFields} | ||
onSubmit={this.onSubmit} | ||
> | ||
{({ | ||
values, | ||
errors, | ||
touched, | ||
handleChange, | ||
handleBlur, | ||
handleSubmit, | ||
isSubmitting, | ||
validateField, | ||
}) => ( | ||
<form className='account-management-form' onSubmit={handleSubmit}> | ||
<div className='account-management-form-header'> | ||
<h1 className='account-management-form-header-text'> | ||
{localize('Change your Deriv password')} | ||
</h1> | ||
</div> | ||
{this.state.is_loading ? | ||
<FormBody> | ||
<Loading is_fullscreen={false} className='initial-loader--accounts-modal' /> | ||
</FormBody> | ||
: | ||
<FormBody scroll_offset='90px'> | ||
{/** TODO: replace with Input */} | ||
<label>Current password</label> | ||
<input type='password' name='old_password' value={values.old_password} onChange={handleChange} /> | ||
{errors.old_password || (touched.old_password && errors.old_password)} | ||
|
||
<label>New password</label> | ||
<input type='password' name='new_password' value={values.new_password} onChange={handleChange} /> | ||
{errors.new_password || (touched.new_password && errors.new_password)} | ||
</FormBody> | ||
} | ||
<FormFooter> | ||
<Button | ||
className='btn--secondary' | ||
type='button' | ||
onClick={this.props.onClickSendEmail} | ||
text={localize('Forgot your password?')} | ||
/> | ||
<Button | ||
className='btn--primary' | ||
type='submit' | ||
disabled={isSubmitting} | ||
has_effect | ||
text={localize('Submit')} | ||
/> | ||
</FormFooter> | ||
</form> | ||
)} | ||
</Formik> | ||
</> | ||
); | ||
} | ||
} | ||
|
||
// ChangePasswordForm.propTypes = {}; | ||
|
||
export default ChangePasswordForm; |
39 changes: 39 additions & 0 deletions
39
.../App/Containers/AccountManagementModal/SecurityAndSafety/DerivPassword/deriv-password.jsx
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,39 @@ | ||
// import PropTypes from 'prop-types'; | ||
import React from 'react'; | ||
import ChangePasswordForm from './change-password-form.jsx'; | ||
import ForgotYourPassword from './forgot-your-password.jsx'; | ||
import MultiStep from '../../Components/multistep.jsx'; | ||
|
||
class DerivPassword extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
this.steps = [ | ||
{ | ||
component: <ChangePasswordForm | ||
onClickSendEmail={() => { | ||
this.node.nextStep(); // go to the next step | ||
}} | ||
/>, | ||
}, | ||
{ | ||
component: <ForgotYourPassword | ||
onClickSendEmail={() => { | ||
}} | ||
/>, | ||
} | ||
]; | ||
} | ||
|
||
render() { | ||
return ( | ||
<MultiStep | ||
ref={node => this.node = node} | ||
steps={this.steps} | ||
/> | ||
); | ||
} | ||
} | ||
|
||
// DerivPassword.propTypes = {}; | ||
|
||
export default DerivPassword; |
34 changes: 34 additions & 0 deletions
34
...ontainers/AccountManagementModal/SecurityAndSafety/DerivPassword/forgot-your-password.jsx
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,34 @@ | ||
import React from 'react'; | ||
import { localize } from 'App/i18n'; | ||
import IconFirewall from 'Assets/AccountManagement/icon-firewall.svg'; | ||
import IconSpamEmail from 'Assets/AccountManagement/icon-spam-email.svg'; | ||
import IconTypo from 'Assets/AccountManagement/icon-typo.svg'; | ||
import IconWorkEmail from 'Assets/AccountManagement/icon-work-email.svg'; | ||
import SendEmailTemplate from '../../../Layout/send-email.jsx'; | ||
|
||
const ForgotYourPassword = ({ onClickSendEmail }) => ( | ||
<SendEmailTemplate | ||
className='forgot-password' | ||
subtitle={'Please click on the link in the email to reset your password.'} | ||
onClickSendEmail={onClickSendEmail} | ||
> | ||
<div className='forgot-password__content'> | ||
<IconSpamEmail /> | ||
<p>{localize('The email is in your spam folder (Sometimes things get lost there).')}</p> | ||
</div> | ||
<div className='forgot-password__content'> | ||
<IconTypo /> | ||
<p>{localize('The email address you entered had a mistake or typo (happens to the best of us).')}</p> | ||
</div> | ||
<div className='forgot-password__content'> | ||
<IconWorkEmail /> | ||
<p>{localize('You accidentally gave us another email address (Usually a work or a personal one instead of the one you meant).')}</p> | ||
</div> | ||
<div className='forgot-password__content'> | ||
<IconFirewall /> | ||
<p>{localize('We can’t deliver the email to this address (Usually because of firewalls or filtering).')}</p> | ||
</div> | ||
</SendEmailTemplate> | ||
); | ||
|
||
export default ForgotYourPassword; |
3 changes: 3 additions & 0 deletions
3
...trader/src/App/Containers/AccountManagementModal/SecurityAndSafety/DerivPassword/index.js
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,3 @@ | ||
import DerivPassword from './deriv-password.jsx'; | ||
|
||
export default DerivPassword; |
14 changes: 0 additions & 14 deletions
14
...ges/trader/src/App/Containers/AccountManagementModal/SecurityAndSafety/deriv-password.jsx
This file was deleted.
Oops, something went wrong.
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,93 @@ | ||
import PropTypes from 'prop-types'; | ||
import React from 'react'; | ||
import { Button } from 'deriv-components'; | ||
import { localize } from 'App/i18n'; | ||
import Icon from 'Assets/icon.jsx'; | ||
|
||
class SendEmailTemplate extends React.Component { | ||
resend_interval = null; | ||
|
||
state = { | ||
is_email_not_received_clicked: false, | ||
resend_timeout : this.props.resend_timeout || 60, | ||
} | ||
|
||
componentWillUnmount() { | ||
clearInterval(this.resend_interval); | ||
} | ||
|
||
onClickEmailNotReceived = () => { | ||
this.setState({ is_email_not_received_clicked: true }); | ||
} | ||
|
||
onClickResendEmail = () => { | ||
this.startCountdownTimer(); | ||
this.props.onClickSendEmail(); | ||
} | ||
|
||
startCountdownTimer = () => { | ||
this.setState(prevState => ({ | ||
resend_timeout: prevState.resend_timeout - 1 | ||
}), () => { | ||
this.resend_interval = setInterval(() => { | ||
if (this.state.resend_timeout === 1) { | ||
this.setState({ resend_timeout: 60 }); | ||
clearInterval(this.resend_interval); | ||
} else { | ||
this.setState(prevState => ( | ||
{ resend_timeout: prevState.resend_timeout - 1 } | ||
)); | ||
} | ||
}, 1000); | ||
}); | ||
} | ||
|
||
render() { | ||
const is_resend_btn_disabled = this.state.resend_timeout < 60; | ||
const resend_email_btn_text = (this.state.resend_timeout < 60 ? | ||
localize('Resend email in {{seconds}}s', { seconds: this.state.resend_timeout }) | ||
: | ||
localize('Resend email') | ||
); | ||
|
||
return ( | ||
<div className='send-email-template'> | ||
<div className='send-email-template__sent'> | ||
<Icon icon='IconEmailSent' className='send-email-template__icon'/> | ||
<h1 className='send-email-template__title'>{localize('We\'ve sent you an email')}</h1> | ||
<p className='send-email-template__subtitle'>{this.props.subtitle}</p> | ||
<Button | ||
className='btn--secondary send-email-template__btn' | ||
onClick={this.onClickEmailNotReceived} | ||
text={localize('Didn\'t receive the email?')} | ||
/> | ||
</div> | ||
{ | ||
this.state.is_email_not_received_clicked && | ||
<> | ||
<div className={`send-email-template__resend ${this.props.className}`}> | ||
{this.props.children} | ||
</div> | ||
<div className='send-email-template__cta'> | ||
<Button | ||
className='btn--primary send-email-template__cta-btn' | ||
is_disabled={is_resend_btn_disabled} | ||
has_effect | ||
text={resend_email_btn_text} | ||
onClick={this.onClickResendEmail} | ||
/> | ||
</div> | ||
</> | ||
} | ||
</div> | ||
) | ||
} | ||
} | ||
|
||
SendEmailTemplate.propTypes = { | ||
is_disabled : PropTypes.bool, | ||
onClickSendEmail: PropTypes.func, | ||
subtitle : PropTypes.string, | ||
}; | ||
|
||
export default SendEmailTemplate; |
8 changes: 8 additions & 0 deletions
8
packages/trader/src/Assets/AccountManagement/icon-firewall.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions
10
packages/trader/src/Assets/AccountManagement/icon-spam-email.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions
10
packages/trader/src/Assets/AccountManagement/icon-typo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.