Skip to content

Commit

Permalink
add Multisteps component, send email template & set up Deriv Password…
Browse files Browse the repository at this point in the history
… form
  • Loading branch information
klyanyi committed Sep 10, 2019
1 parent ce89ed9 commit 46fb07d
Show file tree
Hide file tree
Showing 17 changed files with 441 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const ProofOfIdentity = () => import('App/Containers/AccountManagementModal/Veri
const AccountLimits = () => import('App/Containers/AccountManagementModal/SecurityAndSafety/account-limits.jsx');
const ApiToken = () => import('App/Containers/AccountManagementModal/SecurityAndSafety/api-token.jsx');
const ConnectedApps = () => import('App/Containers/AccountManagementModal/SecurityAndSafety/connected-apps.jsx');
const DerivPassword = () => import('App/Containers/AccountManagementModal/SecurityAndSafety/deriv-password.jsx');
const DerivPassword = () => import('App/Containers/AccountManagementModal/SecurityAndSafety/DerivPassword');
const LoginHistory = () => import('App/Containers/AccountManagementModal/SecurityAndSafety/login-history.jsx');
const SelfExclusion = () => import('App/Containers/AccountManagementModal/SecurityAndSafety/self-exclusion.jsx');
const TwoFactorAuthentication = () => import('App/Containers/AccountManagementModal/SecurityAndSafety/two-factor-authentication.jsx');
Expand Down
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;
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class FinancialAssessment extends React.Component {
<i className='account-management-form-header-subheader'>
({localize('All fields are required')})
</i>
</h1>x
</h1>
</div>
{is_loading ?
<FormBody>
Expand Down
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;
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;
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;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import DerivPassword from './deriv-password.jsx';

export default DerivPassword;

This file was deleted.

93 changes: 93 additions & 0 deletions packages/trader/src/App/Containers/Layout/send-email.jsx
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;
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 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 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.
Loading

0 comments on commit 46fb07d

Please sign in to comment.