diff --git a/src/libs/ErrorUtils.js b/src/libs/ErrorUtils.js index 115468ff1ea6..bcc6c59cae2b 100644 --- a/src/libs/ErrorUtils.js +++ b/src/libs/ErrorUtils.js @@ -1,3 +1,4 @@ +import _ from 'underscore'; import CONST from '../CONST'; /** @@ -35,7 +36,23 @@ function getAuthenticateErrorMessage(response) { } } +/** + * @param {Object} onyxData + * @param {Object} onyxData.errors + * @returns {String} + */ +function getLatestErrorMessage(onyxData) { + return _.chain(onyxData.errors || []) + .keys() + .sortBy() + .reverse() + .map(key => onyxData.errors[key]) + .first() + .value(); +} + export { // eslint-disable-next-line import/prefer-default-export getAuthenticateErrorMessage, + getLatestErrorMessage, }; diff --git a/src/libs/actions/Session/index.js b/src/libs/actions/Session/index.js index 23373dcf93fb..e739ea26f1bd 100644 --- a/src/libs/actions/Session/index.js +++ b/src/libs/actions/Session/index.js @@ -90,11 +90,29 @@ function signOutAndRedirectToSignIn() { * @param {String} [login] */ function resendValidationLink(login = credentials.login) { - Onyx.merge(ONYXKEYS.ACCOUNT, {isLoading: true}); - DeprecatedAPI.ResendValidateCode({email: login}) - .finally(() => { - Onyx.merge(ONYXKEYS.ACCOUNT, {isLoading: false}); - }); + const optimisticData = [{ + onyxMethod: CONST.ONYX.METHOD.MERGE, + key: ONYXKEYS.ACCOUNT, + value: {isLoading: true}, + }]; + const successData = [{ + onyxMethod: CONST.ONYX.METHOD.MERGE, + key: ONYXKEYS.ACCOUNT, + value: { + isLoading: false, + message: Localize.translateLocal('resendValidationForm.linkHasBeenResent'), + }, + }]; + const failureData = [{ + onyxMethod: CONST.ONYX.METHOD.MERGE, + key: ONYXKEYS.ACCOUNT, + value: { + isLoading: false, + message: '', + }, + }]; + + API.write('RequestAccountValidationLink', {email: login}, {optimisticData, successData, failureData}); } /** diff --git a/src/pages/signin/LoginForm.js b/src/pages/signin/LoginForm.js index f80488fb3f4a..2490103b97e3 100755 --- a/src/pages/signin/LoginForm.js +++ b/src/pages/signin/LoginForm.js @@ -21,6 +21,7 @@ import FormAlertWithSubmitButton from '../../components/FormAlertWithSubmitButto import OfflineIndicator from '../../components/OfflineIndicator'; import {withNetwork} from '../../components/OnyxProvider'; import networkPropTypes from '../../components/networkPropTypes'; +import * as ErrorUtils from '../../libs/ErrorUtils'; const propTypes = { /** Should we dismiss the keyboard when transitioning away from the page? */ @@ -151,13 +152,7 @@ class LoginForm extends React.Component { render() { const formErrorTranslated = this.state.formError && this.props.translate(this.state.formError); - const error = formErrorTranslated || _.chain(this.props.account.errors || []) - .keys() - .sortBy() - .reverse() - .map(key => this.props.account.errors[key]) - .first() - .value(); + const error = formErrorTranslated || ErrorUtils.getLatestErrorMessage(this.props.account); return ( <> diff --git a/src/pages/signin/ResendValidationForm.js b/src/pages/signin/ResendValidationForm.js index e643e94eed73..0d1eb7069926 100755 --- a/src/pages/signin/ResendValidationForm.js +++ b/src/pages/signin/ResendValidationForm.js @@ -2,7 +2,6 @@ import React from 'react'; import {TouchableOpacity, View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import PropTypes from 'prop-types'; -import _ from 'underscore'; import Str from 'expensify-common/lib/str'; import styles from '../../styles/styles'; import Button from '../../components/Button'; @@ -17,6 +16,11 @@ import * as ReportUtils from '../../libs/ReportUtils'; import OfflineIndicator from '../../components/OfflineIndicator'; import networkPropTypes from '../../components/networkPropTypes'; import {withNetwork} from '../../components/OnyxProvider'; +import * as ErrorUtils from '../../libs/ErrorUtils'; +import Icon from '../../components/Icon'; +import * as Expensicons from '../../components/Icon/Expensicons'; +import colors from '../../styles/colors'; +import variables from '../../styles/variables'; const propTypes = { /* Onyx Props */ @@ -47,16 +51,6 @@ const defaultProps = { }; class ResendValidationForm extends React.Component { - constructor(props) { - super(props); - - this.validateAndSubmitForm = this.validateAndSubmitForm.bind(this); - - this.state = { - formSuccess: '', - }; - } - componentWillUnmount() { if (!this.successMessageTimer) { return; @@ -65,29 +59,12 @@ class ResendValidationForm extends React.Component { clearTimeout(this.successMessageTimer); } - /** - * Check that all the form fields are valid, then trigger the submit callback - */ - validateAndSubmitForm() { - this.setState({ - formSuccess: this.props.translate('resendValidationForm.linkHasBeenResent'), - }); - - if (!this.props.account.validated) { - Session.resendValidationLink(); - } else { - Session.resetPassword(); - } - - this.successMessageTimer = setTimeout(() => { - this.setState({formSuccess: ''}); - }, 5000); - } - render() { const isSMSLogin = Str.isSMSLogin(this.props.credentials.login); const login = isSMSLogin ? this.props.toLocalPhone(Str.removeSMSDomain(this.props.credentials.login)) : this.props.credentials.login; const loginType = (isSMSLogin ? this.props.translate('common.phone') : this.props.translate('common.email')).toLowerCase(); + const error = ErrorUtils.getLatestErrorMessage(this.props.account); + const successMessage = this.props.account.message; return ( <> @@ -107,10 +84,25 @@ class ResendValidationForm extends React.Component { {this.props.translate('resendValidationForm.weSentYouMagicSignInLink', {login, loginType})} - {!_.isEmpty(this.state.formSuccess) && ( - - {this.state.formSuccess} - + {successMessage && ( + + + + + + {successMessage} + + + )} + {!successMessage && error && ( + + + + + + {error} + + )} redirectToSignIn()}> @@ -123,7 +115,7 @@ class ResendValidationForm extends React.Component { success text={this.props.translate('resendValidationForm.resendLink')} isLoading={this.props.account.loading} - onPress={this.validateAndSubmitForm} + onPress={() => (this.props.account.validated ? Session.resetPassword() : Session.resendValidationLink())} isDisabled={this.props.network.isOffline} />