import React, { ReactNode } from 'react'; import { defineMessages, FormattedMessage as Message } from 'react-intl'; import { Helmet } from 'react-helmet-async'; import { SlideMotion } from 'app/components/ui/motion'; import { ScrollIntoView } from 'app/components/ui/scroll'; import { Input, Button, Form, FormModel, FormError } from 'app/components/ui/form'; import { BackButton } from 'app/components/profile/ProfileForm'; import styles from 'app/components/profile/profileForm.scss'; import helpLinks from 'app/components/auth/helpLinks.scss'; import Stepper from 'app/components/ui/stepper'; import changeEmail from './changeEmail.scss'; const STEPS_TOTAL = 3; export type ChangeEmailStep = 0 | 1 | 2; interface Props { onChangeStep: (step: ChangeEmailStep) => void; email: string; stepForms: Array; onSubmit: (step: ChangeEmailStep, form: FormModel) => Promise; step: ChangeEmailStep; code?: string; } interface State { newEmail: string | null; activeStep: ChangeEmailStep; code: string; } interface FormStepParams { form: FormModel; isActiveStep: boolean; isCodeSpecified: boolean; email: string; code?: string; } const labels = defineMessages({ changeEmailButton: 'Change E‑mail', sendEmailButton: 'Send E‑mail', codePlaceholder: 'Paste the code here', newEmailPlaceholder: 'Enter new E‑mail', }); export default class ChangeEmail extends React.Component { static get defaultProps(): Partial { return { stepForms: [new FormModel(), new FormModel(), new FormModel()], onChangeStep() {}, step: 0, }; } state: State = { newEmail: null, activeStep: this.props.step, code: this.props.code || '', }; static getDerivedStateFromProps(props: Props, state: State) { return { activeStep: typeof props.step === 'number' ? props.step : state.activeStep, code: props.code || state.code, }; } render() { const { activeStep } = this.state; const form = this.props.stepForms[activeStep]; return (
this.forceUpdate()}>
{(pageTitle) => (

{pageTitle}

)}

{activeStep > 0 ? : null} {this.renderStepForms()}
{this.isLastStep() ? null : ( )}
); } renderStepForms() { const { email } = this.props; const { activeStep, code } = this.state; const isCodeSpecified = !!this.props.code; return ( {new Array(STEPS_TOTAL).fill(0).map((_, step) => { const formParams: FormStepParams = { form: this.props.stepForms[step], isActiveStep: step === activeStep, isCodeSpecified, email, code, }; switch (step) { case 0: return this.renderStep0(formParams); case 1: return this.renderStep1(formParams); case 2: return this.renderStep2(formParams); } })} ); } renderStep0({ email, form }: FormStepParams): ReactNode { return (

{email}

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

{email}, }} />

); } renderStep2({ form, code, isCodeSpecified, isActiveStep }: FormStepParams): ReactNode { const { newEmail } = this.state; return (

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

); } nextStep() { const { activeStep } = this.state; const nextStep = activeStep + 1; let newEmail = null; if (activeStep === 1) { newEmail = this.props.stepForms[1].value('email'); } if (nextStep < STEPS_TOTAL) { this.setState({ activeStep: nextStep as ChangeEmailStep, newEmail, }); this.props.onChangeStep(nextStep as ChangeEmailStep); } } isLastStep() { return this.state.activeStep + 1 === STEPS_TOTAL; } onSwitchStep = (event: React.MouseEvent) => { event.preventDefault(); this.nextStep(); }; onCodeInput = (event: React.ChangeEvent) => { const { value } = event.target; if (this.props.code) { return; } this.setState({ code: value, }); }; onFormSubmit = () => { const { activeStep } = this.state; const form = this.props.stepForms[activeStep]; const promise = this.props.onSubmit(activeStep, form); if (!promise || !promise.then) { throw new Error('Expecting promise from onSubmit'); } promise.then( () => { this.nextStep(); this.setState({ code: '', }); }, (resp) => { if (resp.errors) { form.setErrors(resp.errors); this.forceUpdate(); } else { return Promise.reject(resp); } }, ); }; }