import React, { Component, PropTypes } from 'react'; import { FormattedMessage as Message } from 'react-intl'; import { Link } from 'react-router'; import classNames from 'classnames'; import Helmet from 'react-helmet'; import { Motion, spring } from 'react-motion'; import { Input, Button, Form, FormModel } from 'components/ui/form'; import styles from 'components/profile/profileForm.scss'; import helpLinks from 'components/auth/helpLinks.scss'; import MeasureHeight from 'components/MeasureHeight'; import changeEmail from './changeEmail.scss'; import messages from './ChangeEmail.intl.json'; const STEPS_TOTAL = 3; export default class ChangeEmail extends Component { static displayName = 'ChangeEmail'; static propTypes = { onChangeStep: PropTypes.func, email: PropTypes.string.isRequired, stepForms: PropTypes.arrayOf((propValue, key, componentName, location, propFullName) => { if (propValue.length !== 3) { return new Error(`\`${propFullName}\` must be an array of 3 FormModel instances. Validation failed.`); } if (!(propValue[key] instanceof FormModel)) { return new Error( `Invalid prop \`${propFullName}\` supplied to \ \`${componentName}\`. Validation failed.` ); } }), onSubmit: PropTypes.func.isRequired, step: PropTypes.oneOf([0, 1, 2]), code: PropTypes.string }; static get defaultProps() { return { stepForms: [ new FormModel(), new FormModel(), new FormModel() ], onChangeStep() {}, step: 0 }; } state = { activeStep: this.props.step, code: this.props.code || '' }; componentWillReceiveProps(nextProps) { this.setState({ activeStep: typeof nextProps.step === 'number' ? nextProps.step : this.state.activeStep, code: nextProps.code || '' }); } render() { const {activeStep} = this.state; const form = this.props.stepForms[activeStep]; return (
this.forceUpdate()} >
{(pageTitle) => (

{pageTitle}

)}

{(new Array(STEPS_TOTAL)).fill(0).map((_, step) => (
))}
{this.renderStepForms()}
{this.isLastStep() ? null : ( )}
); } renderStepForms() { const {email} = this.props; const {activeStep, code} = this.state; const isCodeSpecified = !!this.props.code; const activeStepHeight = this.state[`step${activeStep}Height`] || 0; // a hack to disable height animation on first render const isHeightMeasured = this.isHeightMeasured; this.isHeightMeasured = isHeightMeasured || activeStepHeight > 0; return ( {(interpolatingStyle) => (
{(new Array(STEPS_TOTAL)).fill(0).map((_, step) => { const form = this.props.stepForms[step]; return ( {this[`renderStep${step}`]({ email, code, form, isActiveStep: step === activeStep })} ); })}
)}
); } renderStep0({email}) { return (

{email}

); } renderStep1({email, form, code, isCodeSpecified, isActiveStep}) { return (

{email}) }} />

); } renderStep2({form, code, isCodeSpecified, isActiveStep}) { const newEmail = this.props.stepForms[1].value('email'); return (

{newEmail ? ( {newEmail}) }} /> {' '} ) : null}

); } onStepMeasure(step) { return (height) => this.setState({ [`step${step}Height`]: height }); } nextStep() { const {activeStep} = this.state; const nextStep = activeStep + 1; if (nextStep < STEPS_TOTAL) { this.setState({ activeStep: nextStep }); this.props.onChangeStep(nextStep); } } isLastStep() { return this.state.activeStep + 1 === STEPS_TOTAL; } onSwitchStep = (event) => { event.preventDefault(); this.nextStep(); }; onCodeInput = (event) => { const {value} = event.target; this.setState({ code: this.props.code || value }); }; onFormSubmit = () => { const {activeStep} = this.state; const promise = this.props.onSubmit(activeStep, this.props.stepForms[activeStep]); if (!promise || !promise.then) { throw new Error('Expecting promise from onSubmit'); } promise.then(() => this.nextStep(), () => this.forceUpdate()); }; }