From c46311ebb21ea8aee6f91ffdaaa99da8fcce7fb2 Mon Sep 17 00:00:00 2001 From: Jasper Huang Date: Thu, 5 Aug 2021 12:01:53 -0700 Subject: [PATCH 01/15] Add errorOutline style to TextInput --- src/components/TextInputWithLabel.js | 7 ++++++- src/styles/styles.js | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/components/TextInputWithLabel.js b/src/components/TextInputWithLabel.js index 63cdd87dbb89..6e9abe401177 100644 --- a/src/components/TextInputWithLabel.js +++ b/src/components/TextInputWithLabel.js @@ -54,7 +54,12 @@ const TextInputWithLabel = props => ( )} diff --git a/src/styles/styles.js b/src/styles/styles.js index b1ade504e459..53ce3d4a1cf7 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -511,6 +511,10 @@ const styles = { noOutline: addOutlineWidth({}, 0), + errorOutline: { + borderColor: colors.red, + }, + formLabel: { fontFamily: fontFamily.GTA_BOLD, fontWeight: fontWeightBold, From 18dcbeb81195e2271276b236c3090663bbe2a169 Mon Sep 17 00:00:00 2001 From: Jasper Huang Date: Thu, 5 Aug 2021 12:02:52 -0700 Subject: [PATCH 02/15] Keep track of bank Account errors in Onyx --- src/libs/actions/BankAccounts.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index 23ea4e36a16a..7bc3a3e769b6 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -563,6 +563,10 @@ function validateBankAccount(bankAccountID, validateCode) { }); } +function showBankAccountError(error) { + Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {error}).then(() => Growl.error(error)); +} + /** * Create or update the bank account in db with the updated data. * @@ -725,12 +729,12 @@ function setupWithdrawalAccount(data) { goToWithdrawalAccountSetupStep(nextStep, achData); if (error) { - Growl.error(error, 5000); + showBankAccountError(error); } }); } -function hideExistingOwnersError() { +function hideBankAccountErrors() { Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {error: '', existingOwnersList: ''}); } @@ -746,5 +750,6 @@ export { goToWithdrawalAccountSetupStep, setupWithdrawalAccount, validateBankAccount, - hideExistingOwnersError, + hideBankAccountErrors, + showBankAccountError, }; From ed5af851ff6556154625487b5af430933b97972d Mon Sep 17 00:00:00 2001 From: Jasper Huang Date: Thu, 5 Aug 2021 12:03:24 -0700 Subject: [PATCH 03/15] Update BankAccountStep --- src/pages/ReimbursementAccount/BankAccountStep.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/pages/ReimbursementAccount/BankAccountStep.js b/src/pages/ReimbursementAccount/BankAccountStep.js index b38563acdef0..637a5410a222 100644 --- a/src/pages/ReimbursementAccount/BankAccountStep.js +++ b/src/pages/ReimbursementAccount/BankAccountStep.js @@ -23,7 +23,7 @@ import exampleCheckImage from '../../../assets/images/example-check-image.png'; import Text from '../../components/Text'; import { goToWithdrawalAccountSetupStep, - hideExistingOwnersError, + hideBankAccountErrors, setupWithdrawalAccount, } from '../../libs/actions/BankAccounts'; import ConfirmModal from '../../components/ConfirmModal'; @@ -211,8 +211,16 @@ class BankAccountStep extends React.Component { placeholder={this.props.translate('bankAccount.routingNumber')} keyboardType="number-pad" value={this.state.routingNumber} - onChangeText={routingNumber => this.setState({routingNumber})} + onChangeText={(routingNumber) => { + if (this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.routingNumber')) { + hideBankAccountErrors(); + } + this.setState({routingNumber}); + }} disabled={shouldDisableInputs} + errorText={this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.routingNumber') + ? this.props.reimbursementAccount.error + : ''} /> From 59ac4c4be96355eeef41c6ef87598a095a93530f Mon Sep 17 00:00:00 2001 From: Jasper Huang Date: Thu, 5 Aug 2021 12:03:38 -0700 Subject: [PATCH 04/15] Update CompanyStep error handling --- src/pages/ReimbursementAccount/CompanyStep.js | 94 +++++++++++++++---- 1 file changed, 77 insertions(+), 17 deletions(-) diff --git a/src/pages/ReimbursementAccount/CompanyStep.js b/src/pages/ReimbursementAccount/CompanyStep.js index c0fc39effba9..b791a8281cdc 100644 --- a/src/pages/ReimbursementAccount/CompanyStep.js +++ b/src/pages/ReimbursementAccount/CompanyStep.js @@ -6,7 +6,11 @@ import Str from 'expensify-common/lib/str'; import moment from 'moment'; import HeaderWithCloseButton from '../../components/HeaderWithCloseButton'; import CONST from '../../CONST'; -import {goToWithdrawalAccountSetupStep, setupWithdrawalAccount} from '../../libs/actions/BankAccounts'; +import { + goToWithdrawalAccountSetupStep, hideBankAccountErrors, + setupWithdrawalAccount, + showBankAccountError, +} from '../../libs/actions/BankAccounts'; import Navigation from '../../libs/Navigation/Navigation'; import Text from '../../components/Text'; import TextInputWithLabel from '../../components/TextInputWithLabel'; @@ -66,47 +70,47 @@ class CompanyStep extends React.Component { */ validate() { if (!this.state.password.trim()) { - Growl.error(this.props.translate('common.passwordCannotBeBlank')); + showBankAccountError(this.props.translate('common.passwordCannotBeBlank')); return false; } if (!isValidAddress(this.state.addressStreet)) { - Growl.error(this.props.translate('bankAccount.error.addressStreet')); + showBankAccountError(this.props.translate('bankAccount.error.addressStreet')); return false; } if (this.state.addressState === '') { - Growl.error(this.props.translate('bankAccount.error.addressState')); + showBankAccountError(this.props.translate('bankAccount.error.addressState')); return false; } if (!isValidZipCode(this.state.addressZipCode)) { - Growl.error(this.props.translate('bankAccount.error.zipCode')); + showBankAccountError(this.props.translate('bankAccount.error.zipCode')); return false; } if (!Str.isValidURL(this.state.website)) { - Growl.error(this.props.translate('bankAccount.error.website')); + showBankAccountError(this.props.translate('bankAccount.error.website')); return false; } if (!/[0-9]{9}/.test(this.state.companyTaxID)) { - Growl.error(this.props.translate('bankAccount.error.taxID')); + showBankAccountError(this.props.translate('bankAccount.error.taxID')); return false; } if (!isValidDate(this.state.incorporationDate)) { - Growl.error(this.props.translate('bankAccount.error.incorporationDate')); + showBankAccountError(this.props.translate('bankAccount.error.incorporationDate')); return false; } if (!isValidIndustryCode(this.state.industryCode)) { - Growl.error(this.props.translate('bankAccount.error.industryCode')); + showBankAccountError(this.props.translate('bankAccount.error.industryCode')); return false; } if (!this.state.hasNoConnectionToCannabis) { - Growl.error(this.props.translate('bankAccount.error.restrictedBusiness')); + showBankAccountError(this.props.translate('bankAccount.error.restrictedBusiness')); return false; } @@ -150,8 +154,16 @@ class CompanyStep extends React.Component { this.setState({addressStreet})} + onChangeText={(addressStreet) => { + if (this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.addressStreet')) { + hideBankAccountErrors(); + } + this.setState({addressStreet}); + }} value={this.state.addressStreet} + errorText={this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.addressStreet') + ? this.props.translate('bankAccount.error.addressStreet') + : ''} /> @@ -172,8 +184,16 @@ class CompanyStep extends React.Component { this.setState({addressZipCode})} + onChangeText={(addressZipCode) => { + if (this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.zipCode')) { + hideBankAccountErrors(); + } + this.setState({addressZipCode}); + }} value={this.state.addressZipCode} + errorText={this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.zipCode') + ? this.props.translate('bankAccount.error.zipCode') + : ''} /> this.setState({website})} + onChangeText={(website) => { + if (this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.website')) { + hideBankAccountErrors(); + } + this.setState({website}); + }} value={this.state.website} + errorText={this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.website') + ? this.props.translate('bankAccount.error.website') + : ''} /> this.setState({companyTaxID})} + onChangeText={(companyTaxID) => { + if (this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.taxID')) { + hideBankAccountErrors(); + } + this.setState({companyTaxID}); + }} value={this.state.companyTaxID} disabled={shouldDisableCompanyTaxID} + errorText={this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.taxID') + ? this.props.translate('bankAccount.error.taxID') + : ''} /> {this.props.translate('companyStep.companyType')} @@ -211,9 +247,17 @@ class CompanyStep extends React.Component { {/* TODO: Replace with date picker */} this.setState({incorporationDate})} + onChangeText={(incorporationDate) => { + if (this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.incorporationDate')) { + hideBankAccountErrors(); + } + this.setState({incorporationDate}); + }} value={this.state.incorporationDate} placeholder={this.props.translate('companyStep.incorporationDatePlaceholder')} + errorText={this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.incorporationDate') + ? this.props.translate('bankAccount.error.incorporationDate') + : ''} /> @@ -230,8 +274,16 @@ class CompanyStep extends React.Component { helpLinkText={this.props.translate('common.whatThis')} helpLinkURL="https://www.naics.com/search/" containerStyles={[styles.mt4]} - onChangeText={industryCode => this.setState({industryCode})} + onChangeText={(industryCode) => { + if (this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.industryCode')) { + hideBankAccountErrors(); + } + this.setState({industryCode}); + }} value={this.state.industryCode} + errorText={this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.industryCode') + ? this.props.translate('bankAccount.error.industryCode') + : ''} /> this.setState({password})} + onChangeText={(password) => { + if (this.props.reimbursementAccount.error === this.props.translate('common.passwordCannotBeBlank')) { + hideBankAccountErrors(); + } + this.setState({password}); + }} value={this.state.password} onSubmitEditing={this.submit} + errorText={this.props.reimbursementAccount.error === this.props.translate('common.passwordCannotBeBlank') + ? this.props.translate('common.passwordCannotBeBlank') + : ''} /> Date: Thu, 5 Aug 2021 12:03:52 -0700 Subject: [PATCH 05/15] Update IdentityForm to handle DOB errors --- src/pages/ReimbursementAccount/IdentityForm.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/pages/ReimbursementAccount/IdentityForm.js b/src/pages/ReimbursementAccount/IdentityForm.js index 3122d5e6532b..5efdd346631f 100644 --- a/src/pages/ReimbursementAccount/IdentityForm.js +++ b/src/pages/ReimbursementAccount/IdentityForm.js @@ -41,6 +41,9 @@ const propTypes = { ssnLast4: PropTypes.string, }), + /** Any errors that the API can throw from invalid form data */ + error: PropTypes.string, + ...withLocalizePropTypes, }; @@ -56,10 +59,11 @@ const defaultProps = { dob: '', ssnLast4: '', }, + error: '', }; const IdentityForm = ({ - translate, values, onFieldChange, style, + translate, values, onFieldChange, style, error, }) => { const { firstName, lastName, street, city, state, zipCode, dob, ssnLast4, @@ -88,6 +92,7 @@ const IdentityForm = ({ placeholder={translate('common.dateFormat')} value={dob} onChangeText={val => onFieldChange('dob', val)} + errorText={error} /> Date: Thu, 5 Aug 2021 12:08:32 -0700 Subject: [PATCH 06/15] Update propTypes --- .../BeneficialOwnersStep.js | 28 ++++++++++++-- src/pages/ReimbursementAccount/CompanyStep.js | 27 ++++++++++++-- .../ReimbursementAccount/RequestorStep.js | 37 +++++++++++++++++-- 3 files changed, 81 insertions(+), 11 deletions(-) diff --git a/src/pages/ReimbursementAccount/BeneficialOwnersStep.js b/src/pages/ReimbursementAccount/BeneficialOwnersStep.js index 8562fbef130a..fec43d64b986 100644 --- a/src/pages/ReimbursementAccount/BeneficialOwnersStep.js +++ b/src/pages/ReimbursementAccount/BeneficialOwnersStep.js @@ -2,6 +2,7 @@ import _ from 'underscore'; import React from 'react'; import PropTypes from 'prop-types'; import {ScrollView, View} from 'react-native'; +import {withOnyx} from 'react-native-onyx'; import Text from '../../components/Text'; import HeaderWithCloseButton from '../../components/HeaderWithCloseButton'; import styles from '../../styles/styles'; @@ -11,17 +12,29 @@ import Button from '../../components/Button'; import IdentityForm from './IdentityForm'; import FixedFooter from '../../components/FixedFooter'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; -import {goToWithdrawalAccountSetupStep, setupWithdrawalAccount} from '../../libs/actions/BankAccounts'; +import { + goToWithdrawalAccountSetupStep, + hideBankAccountErrors, + setupWithdrawalAccount, +} from '../../libs/actions/BankAccounts'; import Navigation from '../../libs/Navigation/Navigation'; import CONST from '../../CONST'; import {isValidIdentity} from '../../libs/ValidationUtils'; import Growl from '../../libs/Growl'; +import ONYXKEYS from '../../ONYXKEYS'; +import compose from '../../libs/compose'; const propTypes = { /** Name of the company */ companyName: PropTypes.string.isRequired, ...withLocalizePropTypes, + + /** Bank account currently in setup */ + reimbursementAccount: PropTypes.shape({ + /** Error set when handling the API response */ + error: PropTypes.string, + }).isRequired, }; class BeneficialOwnersStep extends React.Component { @@ -160,6 +173,9 @@ class BeneficialOwnersStep extends React.Component { onFieldChange={(fieldName, value) => this.setState((prevState) => { const beneficialOwners = [...prevState.beneficialOwners]; beneficialOwners[index][fieldName] = value; + if (fieldName === 'dob' && this.props.reimbursementAccount.error) { + hideBankAccountErrors(); + } return {beneficialOwners}; })} values={{ @@ -230,5 +246,11 @@ class BeneficialOwnersStep extends React.Component { } BeneficialOwnersStep.propTypes = propTypes; - -export default withLocalize(BeneficialOwnersStep); +export default compose( + withLocalize, + withOnyx({ + reimbursementAccount: { + key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, + }, + }), +)(BeneficialOwnersStep); diff --git a/src/pages/ReimbursementAccount/CompanyStep.js b/src/pages/ReimbursementAccount/CompanyStep.js index b791a8281cdc..eeb07d2a36a8 100644 --- a/src/pages/ReimbursementAccount/CompanyStep.js +++ b/src/pages/ReimbursementAccount/CompanyStep.js @@ -4,6 +4,8 @@ import React from 'react'; import {View, ScrollView} from 'react-native'; import Str from 'expensify-common/lib/str'; import moment from 'moment'; +import PropTypes from 'prop-types'; +import {withOnyx} from 'react-native-onyx'; import HeaderWithCloseButton from '../../components/HeaderWithCloseButton'; import CONST from '../../CONST'; import { @@ -22,10 +24,21 @@ import TextLink from '../../components/TextLink'; import Picker from '../../components/Picker'; import StatePicker from '../../components/StatePicker'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; -import Growl from '../../libs/Growl'; import { isValidAddress, isValidDate, isValidIndustryCode, isValidZipCode, } from '../../libs/ValidationUtils'; +import compose from '../../libs/compose'; +import ONYXKEYS from '../../ONYXKEYS'; + +const propTypes = { + /** Bank account currently in setup */ + reimbursementAccount: PropTypes.shape({ + /** Error set when handling the API response */ + error: PropTypes.string, + }).isRequired, + + ...withLocalizePropTypes, +}; class CompanyStep extends React.Component { constructor(props) { @@ -337,6 +350,12 @@ class CompanyStep extends React.Component { } } -CompanyStep.propTypes = withLocalizePropTypes; - -export default withLocalize(CompanyStep); +CompanyStep.propTypes = propTypes; +export default compose( + withLocalize, + withOnyx({ + reimbursementAccount: { + key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, + }, + }), +)(CompanyStep); diff --git a/src/pages/ReimbursementAccount/RequestorStep.js b/src/pages/ReimbursementAccount/RequestorStep.js index 2287724daa9b..9dc5a22337cf 100644 --- a/src/pages/ReimbursementAccount/RequestorStep.js +++ b/src/pages/ReimbursementAccount/RequestorStep.js @@ -1,6 +1,8 @@ import React from 'react'; import lodashGet from 'lodash/get'; import {View, ScrollView} from 'react-native'; +import PropTypes from 'prop-types'; +import {withOnyx} from 'react-native-onyx'; import styles from '../../styles/styles'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; import HeaderWithCloseButton from '../../components/HeaderWithCloseButton'; @@ -9,13 +11,29 @@ import TextLink from '../../components/TextLink'; import Navigation from '../../libs/Navigation/Navigation'; import CheckboxWithLabel from '../../components/CheckboxWithLabel'; import Text from '../../components/Text'; -import {goToWithdrawalAccountSetupStep, setupWithdrawalAccount} from '../../libs/actions/BankAccounts'; +import { + goToWithdrawalAccountSetupStep, + hideBankAccountErrors, + setupWithdrawalAccount, +} from '../../libs/actions/BankAccounts'; import Button from '../../components/Button'; import FixedFooter from '../../components/FixedFooter'; import IdentityForm from './IdentityForm'; import {isValidIdentity} from '../../libs/ValidationUtils'; import Growl from '../../libs/Growl'; import Onfido from '../../components/Onfido'; +import compose from '../../libs/compose'; +import ONYXKEYS from '../../ONYXKEYS'; + +const propTypes = { + /** Bank account currently in setup */ + reimbursementAccount: PropTypes.shape({ + /** Error set when handling the API response */ + error: PropTypes.string, + }).isRequired, + + ...withLocalizePropTypes, +}; class RequestorStep extends React.Component { constructor(props) { @@ -46,6 +64,11 @@ class RequestorStep extends React.Component { zipCode: 'requestorAddressZipCode', }; const fieldName = lodashGet(renamedFields, field, field); + + if (field === 'dob' && this.props.reimbursementAccount.error) { + hideBankAccountErrors(); + } + this.setState({[fieldName]: value}); } @@ -189,7 +212,13 @@ class RequestorStep extends React.Component { } } -RequestorStep.propTypes = withLocalizePropTypes; +RequestorStep.propTypes = propTypes; RequestorStep.displayName = 'RequestorStep'; - -export default withLocalize(RequestorStep); +export default compose( + withLocalize, + withOnyx({ + reimbursementAccount: { + key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, + }, + }), +)(RequestorStep); From 9bf41ec01b706cb78d2bf2d5e97f582c112cfc9c Mon Sep 17 00:00:00 2001 From: Jasper Huang Date: Thu, 5 Aug 2021 16:41:57 -0700 Subject: [PATCH 07/15] use variable for error --- .../ReimbursementAccount/BankAccountStep.js | 10 +++---- src/pages/ReimbursementAccount/CompanyStep.js | 29 ++++++++++--------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/pages/ReimbursementAccount/BankAccountStep.js b/src/pages/ReimbursementAccount/BankAccountStep.js index 637a5410a222..5c0ef8ebbbf1 100644 --- a/src/pages/ReimbursementAccount/BankAccountStep.js +++ b/src/pages/ReimbursementAccount/BankAccountStep.js @@ -130,8 +130,8 @@ class BankAccountStep extends React.Component { const isFromPlaid = this.props.achData.setupType === CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID; const shouldDisableInputs = Boolean(this.props.achData.bankAccountID) || isFromPlaid; const existingOwners = this.props.reimbursementAccount.existingOwners; - const isExistingOwnersErrorVisible = Boolean(this.props.reimbursementAccount.error - && existingOwners); + const error = this.props.reimbursementAccount.error; + const isExistingOwnersErrorVisible = Boolean(error && existingOwners); return ( { - if (this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.routingNumber')) { + if (error === this.props.translate('bankAccount.error.routingNumber')) { hideBankAccountErrors(); } this.setState({routingNumber}); }} disabled={shouldDisableInputs} - errorText={this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.routingNumber') - ? this.props.reimbursementAccount.error - : ''} + errorText={error === this.props.translate('bankAccount.error.routingNumber') ? error : ''} /> acc || !this.state[curr].trim(), false); + const error = this.props.reimbursementAccount.error; return ( <> { - if (this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.addressStreet')) { + if (error === this.props.translate('bankAccount.error.addressStreet')) { hideBankAccountErrors(); } this.setState({addressStreet}); }} value={this.state.addressStreet} - errorText={this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.addressStreet') + errorText={error === this.props.translate('bankAccount.error.addressStreet') ? this.props.translate('bankAccount.error.addressStreet') : ''} /> @@ -198,13 +199,13 @@ class CompanyStep extends React.Component { label={this.props.translate('common.zip')} containerStyles={[styles.mt4]} onChangeText={(addressZipCode) => { - if (this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.zipCode')) { + if (error === this.props.translate('bankAccount.error.zipCode')) { hideBankAccountErrors(); } this.setState({addressZipCode}); }} value={this.state.addressZipCode} - errorText={this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.zipCode') + errorText={error === this.props.translate('bankAccount.error.zipCode') ? this.props.translate('bankAccount.error.zipCode') : ''} /> @@ -220,13 +221,13 @@ class CompanyStep extends React.Component { label={this.props.translate('companyStep.companyWebsite')} containerStyles={[styles.mt4]} onChangeText={(website) => { - if (this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.website')) { + if (error === this.props.translate('bankAccount.error.website')) { hideBankAccountErrors(); } this.setState({website}); }} value={this.state.website} - errorText={this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.website') + errorText={error === this.props.translate('bankAccount.error.website') ? this.props.translate('bankAccount.error.website') : ''} /> @@ -235,14 +236,14 @@ class CompanyStep extends React.Component { containerStyles={[styles.mt4]} keyboardType={CONST.KEYBOARD_TYPE.PHONE_PAD} onChangeText={(companyTaxID) => { - if (this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.taxID')) { + if (error === this.props.translate('bankAccount.error.taxID')) { hideBankAccountErrors(); } this.setState({companyTaxID}); }} value={this.state.companyTaxID} disabled={shouldDisableCompanyTaxID} - errorText={this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.taxID') + errorText={error === this.props.translate('bankAccount.error.taxID') ? this.props.translate('bankAccount.error.taxID') : ''} /> @@ -261,14 +262,14 @@ class CompanyStep extends React.Component { { - if (this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.incorporationDate')) { + if (error === this.props.translate('bankAccount.error.incorporationDate')) { hideBankAccountErrors(); } this.setState({incorporationDate}); }} value={this.state.incorporationDate} placeholder={this.props.translate('companyStep.incorporationDatePlaceholder')} - errorText={this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.incorporationDate') + errorText={error === this.props.translate('bankAccount.error.incorporationDate') ? this.props.translate('bankAccount.error.incorporationDate') : ''} /> @@ -288,13 +289,13 @@ class CompanyStep extends React.Component { helpLinkURL="https://www.naics.com/search/" containerStyles={[styles.mt4]} onChangeText={(industryCode) => { - if (this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.industryCode')) { + if (error === this.props.translate('bankAccount.error.industryCode')) { hideBankAccountErrors(); } this.setState({industryCode}); }} value={this.state.industryCode} - errorText={this.props.reimbursementAccount.error === this.props.translate('bankAccount.error.industryCode') + errorText={error === this.props.translate('bankAccount.error.industryCode') ? this.props.translate('bankAccount.error.industryCode') : ''} /> @@ -305,14 +306,14 @@ class CompanyStep extends React.Component { autoCompleteType="password" textContentType="password" onChangeText={(password) => { - if (this.props.reimbursementAccount.error === this.props.translate('common.passwordCannotBeBlank')) { + if (error === this.props.translate('common.passwordCannotBeBlank')) { hideBankAccountErrors(); } this.setState({password}); }} value={this.state.password} onSubmitEditing={this.submit} - errorText={this.props.reimbursementAccount.error === this.props.translate('common.passwordCannotBeBlank') + errorText={error === this.props.translate('common.passwordCannotBeBlank') ? this.props.translate('common.passwordCannotBeBlank') : ''} /> From 39aa09d8adca5eb76702c660cf0c6bdb6bc13d72 Mon Sep 17 00:00:00 2001 From: Jasper Huang Date: Thu, 5 Aug 2021 16:51:29 -0700 Subject: [PATCH 08/15] style --- src/pages/ReimbursementAccount/BankAccountStep.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/ReimbursementAccount/BankAccountStep.js b/src/pages/ReimbursementAccount/BankAccountStep.js index 5c0ef8ebbbf1..9cbce7a6c3f4 100644 --- a/src/pages/ReimbursementAccount/BankAccountStep.js +++ b/src/pages/ReimbursementAccount/BankAccountStep.js @@ -218,7 +218,8 @@ class BankAccountStep extends React.Component { this.setState({routingNumber}); }} disabled={shouldDisableInputs} - errorText={error === this.props.translate('bankAccount.error.routingNumber') ? error : ''} + errorText={error === this.props.translate('bankAccount.error.routingNumber') + ? error : ''} /> Date: Thu, 5 Aug 2021 16:58:06 -0700 Subject: [PATCH 09/15] Rename functikon --- src/libs/actions/BankAccounts.js | 6 +++--- src/pages/ReimbursementAccount/CompanyStep.js | 20 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index 7bc3a3e769b6..5af1cfa68377 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -563,7 +563,7 @@ function validateBankAccount(bankAccountID, validateCode) { }); } -function showBankAccountError(error) { +function showBankAccountFormValidationError(error) { Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {error}).then(() => Growl.error(error)); } @@ -729,7 +729,7 @@ function setupWithdrawalAccount(data) { goToWithdrawalAccountSetupStep(nextStep, achData); if (error) { - showBankAccountError(error); + showBankAccountFormValidationError(error); } }); } @@ -751,5 +751,5 @@ export { setupWithdrawalAccount, validateBankAccount, hideBankAccountErrors, - showBankAccountError, + showBankAccountFormValidationError, }; diff --git a/src/pages/ReimbursementAccount/CompanyStep.js b/src/pages/ReimbursementAccount/CompanyStep.js index 50421f648b69..e172832078f1 100644 --- a/src/pages/ReimbursementAccount/CompanyStep.js +++ b/src/pages/ReimbursementAccount/CompanyStep.js @@ -11,7 +11,7 @@ import CONST from '../../CONST'; import { goToWithdrawalAccountSetupStep, hideBankAccountErrors, setupWithdrawalAccount, - showBankAccountError, + showBankAccountFormValidationError, } from '../../libs/actions/BankAccounts'; import Navigation from '../../libs/Navigation/Navigation'; import Text from '../../components/Text'; @@ -83,47 +83,47 @@ class CompanyStep extends React.Component { */ validate() { if (!this.state.password.trim()) { - showBankAccountError(this.props.translate('common.passwordCannotBeBlank')); + showBankAccountFormValidationError(this.props.translate('common.passwordCannotBeBlank')); return false; } if (!isValidAddress(this.state.addressStreet)) { - showBankAccountError(this.props.translate('bankAccount.error.addressStreet')); + showBankAccountFormValidationError(this.props.translate('bankAccount.error.addressStreet')); return false; } if (this.state.addressState === '') { - showBankAccountError(this.props.translate('bankAccount.error.addressState')); + showBankAccountFormValidationError(this.props.translate('bankAccount.error.addressState')); return false; } if (!isValidZipCode(this.state.addressZipCode)) { - showBankAccountError(this.props.translate('bankAccount.error.zipCode')); + showBankAccountFormValidationError(this.props.translate('bankAccount.error.zipCode')); return false; } if (!Str.isValidURL(this.state.website)) { - showBankAccountError(this.props.translate('bankAccount.error.website')); + showBankAccountFormValidationError(this.props.translate('bankAccount.error.website')); return false; } if (!/[0-9]{9}/.test(this.state.companyTaxID)) { - showBankAccountError(this.props.translate('bankAccount.error.taxID')); + showBankAccountFormValidationError(this.props.translate('bankAccount.error.taxID')); return false; } if (!isValidDate(this.state.incorporationDate)) { - showBankAccountError(this.props.translate('bankAccount.error.incorporationDate')); + showBankAccountFormValidationError(this.props.translate('bankAccount.error.incorporationDate')); return false; } if (!isValidIndustryCode(this.state.industryCode)) { - showBankAccountError(this.props.translate('bankAccount.error.industryCode')); + showBankAccountFormValidationError(this.props.translate('bankAccount.error.industryCode')); return false; } if (!this.state.hasNoConnectionToCannabis) { - showBankAccountError(this.props.translate('bankAccount.error.restrictedBusiness')); + showBankAccountFormValidationError(this.props.translate('bankAccount.error.restrictedBusiness')); return false; } From 5d9ceafe70d5d5cbf4ec42193b1ff5c379c5f1cb Mon Sep 17 00:00:00 2001 From: Jasper Huang Date: Thu, 5 Aug 2021 16:59:13 -0700 Subject: [PATCH 10/15] update comment --- src/pages/ReimbursementAccount/IdentityForm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/ReimbursementAccount/IdentityForm.js b/src/pages/ReimbursementAccount/IdentityForm.js index 5efdd346631f..59902be1a9de 100644 --- a/src/pages/ReimbursementAccount/IdentityForm.js +++ b/src/pages/ReimbursementAccount/IdentityForm.js @@ -41,7 +41,7 @@ const propTypes = { ssnLast4: PropTypes.string, }), - /** Any errors that the API can throw from invalid form data */ + /** Any errors that can arise from form validation */ error: PropTypes.string, ...withLocalizePropTypes, From d37f9d41aed9f57138ec157f692a8ee3bb11952e Mon Sep 17 00:00:00 2001 From: Jasper Huang Date: Mon, 9 Aug 2021 06:47:57 -1000 Subject: [PATCH 11/15] Add red field outlines for the inputs in the IdentityForm --- src/libs/ValidationUtils.js | 11 ++++--- .../ReimbursementAccount/IdentityForm.js | 33 ++++++++++++++++--- .../ReimbursementAccount/RequestorStep.js | 5 --- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/libs/ValidationUtils.js b/src/libs/ValidationUtils.js index 28b3075e45ab..7694952a34bb 100644 --- a/src/libs/ValidationUtils.js +++ b/src/libs/ValidationUtils.js @@ -2,6 +2,7 @@ import moment from 'moment'; import CONST from '../CONST'; import Growl from './Growl'; import {translateLocal} from './translate'; +import {showBankAccountFormValidationError} from './actions/BankAccounts'; /** * Validating that this is a valid address (PO boxes are not allowed) @@ -74,27 +75,27 @@ function isValidSSNLastFour(ssnLast4) { */ function isValidIdentity(identity) { if (!isValidAddress(identity.street)) { - Growl.error(translateLocal('bankAccount.error.address')); + showBankAccountFormValidationError(translateLocal('bankAccount.error.address')); return false; } if (identity.state === '') { - Growl.error(translateLocal('bankAccount.error.addressState')); + showBankAccountFormValidationError(translateLocal('bankAccount.error.addressState')); return false; } if (!isValidZipCode(identity.zipCode)) { - Growl.error(translateLocal('bankAccount.error.zipCode')); + showBankAccountFormValidationError(translateLocal('bankAccount.error.zipCode')); return false; } if (!isValidDate(identity.dob)) { - Growl.error(translateLocal('bankAccount.error.dob')); + showBankAccountFormValidationError(translateLocal('bankAccount.error.dob')); return false; } if (!isValidSSNLastFour(identity.ssnLast4)) { - Growl.error(translateLocal('bankAccount.error.ssnLast4')); + showBankAccountFormValidationError(translateLocal('bankAccount.error.ssnLast4')); return false; } diff --git a/src/pages/ReimbursementAccount/IdentityForm.js b/src/pages/ReimbursementAccount/IdentityForm.js index 59902be1a9de..c36c96b9c578 100644 --- a/src/pages/ReimbursementAccount/IdentityForm.js +++ b/src/pages/ReimbursementAccount/IdentityForm.js @@ -6,6 +6,8 @@ import StatePicker from '../../components/StatePicker'; import TextInputWithLabel from '../../components/TextInputWithLabel'; import styles from '../../styles/styles'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; +import {translateLocal} from '../../libs/translate'; +import {hideBankAccountErrors} from '../../libs/actions/BankAccounts'; const propTypes = { /** Style for wrapping View */ @@ -91,20 +93,37 @@ const IdentityForm = ({ containerStyles={[styles.mt4]} placeholder={translate('common.dateFormat')} value={dob} - onChangeText={val => onFieldChange('dob', val)} + onChangeText={(val) => { + if (error === translateLocal('bankAccount.error.dob')) { + hideBankAccountErrors(); + } + onFieldChange('dob', val); + }} errorText={error} /> onFieldChange('ssnLast4', val)} + onChangeText={(val) => { + if (error === translateLocal('bankAccount.error.ssnLast4')) { + hideBankAccountErrors(); + } + onFieldChange('ssnLast4', val); + }} + errorText={error} /> onFieldChange('street', val)} + onChangeText={(val) => { + if (error === translateLocal('bankAccount.error.address')) { + hideBankAccountErrors(); + } + onFieldChange('street', val); + }} + errorText={error} /> @@ -126,7 +145,13 @@ const IdentityForm = ({ label={translate('common.zip')} containerStyles={[styles.mt4]} value={zipCode} - onChangeText={val => onFieldChange('zipCode', val)} + onChangeText={(val) => { + if (error === translateLocal('bankAccount.error.zipCode')) { + hideBankAccountErrors(); + } + onFieldChange('zipCode', val); + }} + errorText={error} /> ); diff --git a/src/pages/ReimbursementAccount/RequestorStep.js b/src/pages/ReimbursementAccount/RequestorStep.js index 9dc5a22337cf..56ef5d56d28a 100644 --- a/src/pages/ReimbursementAccount/RequestorStep.js +++ b/src/pages/ReimbursementAccount/RequestorStep.js @@ -64,11 +64,6 @@ class RequestorStep extends React.Component { zipCode: 'requestorAddressZipCode', }; const fieldName = lodashGet(renamedFields, field, field); - - if (field === 'dob' && this.props.reimbursementAccount.error) { - hideBankAccountErrors(); - } - this.setState({[fieldName]: value}); } From 29c11944b1d5a35ea6d2bb35fbf98a9ee5cabf24 Mon Sep 17 00:00:00 2001 From: Jasper Huang Date: Mon, 9 Aug 2021 06:51:49 -1000 Subject: [PATCH 12/15] Remove unused imports --- src/libs/ValidationUtils.js | 1 - src/pages/ReimbursementAccount/RequestorStep.js | 1 - 2 files changed, 2 deletions(-) diff --git a/src/libs/ValidationUtils.js b/src/libs/ValidationUtils.js index 7694952a34bb..8c6522a040c2 100644 --- a/src/libs/ValidationUtils.js +++ b/src/libs/ValidationUtils.js @@ -1,6 +1,5 @@ import moment from 'moment'; import CONST from '../CONST'; -import Growl from './Growl'; import {translateLocal} from './translate'; import {showBankAccountFormValidationError} from './actions/BankAccounts'; diff --git a/src/pages/ReimbursementAccount/RequestorStep.js b/src/pages/ReimbursementAccount/RequestorStep.js index 56ef5d56d28a..7ad9cd796235 100644 --- a/src/pages/ReimbursementAccount/RequestorStep.js +++ b/src/pages/ReimbursementAccount/RequestorStep.js @@ -13,7 +13,6 @@ import CheckboxWithLabel from '../../components/CheckboxWithLabel'; import Text from '../../components/Text'; import { goToWithdrawalAccountSetupStep, - hideBankAccountErrors, setupWithdrawalAccount, } from '../../libs/actions/BankAccounts'; import Button from '../../components/Button'; From 46cc705c846478a2a0f85a05951e2efaba7812d3 Mon Sep 17 00:00:00 2001 From: Jasper Huang Date: Mon, 9 Aug 2021 07:15:36 -1000 Subject: [PATCH 13/15] Fix form validation --- src/pages/ReimbursementAccount/BeneficialOwnersStep.js | 4 +--- src/pages/ReimbursementAccount/IdentityForm.js | 9 +++++---- src/pages/ReimbursementAccount/RequestorStep.js | 1 + 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/pages/ReimbursementAccount/BeneficialOwnersStep.js b/src/pages/ReimbursementAccount/BeneficialOwnersStep.js index fec43d64b986..8a92ed2eb0cf 100644 --- a/src/pages/ReimbursementAccount/BeneficialOwnersStep.js +++ b/src/pages/ReimbursementAccount/BeneficialOwnersStep.js @@ -173,9 +173,6 @@ class BeneficialOwnersStep extends React.Component { onFieldChange={(fieldName, value) => this.setState((prevState) => { const beneficialOwners = [...prevState.beneficialOwners]; beneficialOwners[index][fieldName] = value; - if (fieldName === 'dob' && this.props.reimbursementAccount.error) { - hideBankAccountErrors(); - } return {beneficialOwners}; })} values={{ @@ -188,6 +185,7 @@ class BeneficialOwnersStep extends React.Component { dob: owner.dob || '', ssnLast4: owner.ssnLast4 || '', }} + error={this.props.reimbursementAccount.error} /> {this.state.beneficialOwners.length > 1 && ( this.removeBeneficialOwner(owner)}> diff --git a/src/pages/ReimbursementAccount/IdentityForm.js b/src/pages/ReimbursementAccount/IdentityForm.js index c36c96b9c578..0ce065559b28 100644 --- a/src/pages/ReimbursementAccount/IdentityForm.js +++ b/src/pages/ReimbursementAccount/IdentityForm.js @@ -70,6 +70,7 @@ const IdentityForm = ({ const { firstName, lastName, street, city, state, zipCode, dob, ssnLast4, } = values; + console.log(">>>>", error); return ( @@ -99,7 +100,7 @@ const IdentityForm = ({ } onFieldChange('dob', val); }} - errorText={error} + errorText={error === translateLocal('bankAccount.error.dob') ? error : ''} /> @@ -151,7 +152,7 @@ const IdentityForm = ({ } onFieldChange('zipCode', val); }} - errorText={error} + errorText={error === translateLocal('bankAccount.error.zipCode') ? error : ''} /> ); diff --git a/src/pages/ReimbursementAccount/RequestorStep.js b/src/pages/ReimbursementAccount/RequestorStep.js index 7ad9cd796235..122b5825acbf 100644 --- a/src/pages/ReimbursementAccount/RequestorStep.js +++ b/src/pages/ReimbursementAccount/RequestorStep.js @@ -133,6 +133,7 @@ class RequestorStep extends React.Component { dob: this.state.dob, ssnLast4: this.state.ssnLast4, }} + error={this.props.reimbursementAccount.error} /> Date: Mon, 9 Aug 2021 07:18:23 -1000 Subject: [PATCH 14/15] Remove unused imports --- src/pages/ReimbursementAccount/BeneficialOwnersStep.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/ReimbursementAccount/BeneficialOwnersStep.js b/src/pages/ReimbursementAccount/BeneficialOwnersStep.js index 8a92ed2eb0cf..e86f22f44bf4 100644 --- a/src/pages/ReimbursementAccount/BeneficialOwnersStep.js +++ b/src/pages/ReimbursementAccount/BeneficialOwnersStep.js @@ -14,7 +14,6 @@ import FixedFooter from '../../components/FixedFooter'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; import { goToWithdrawalAccountSetupStep, - hideBankAccountErrors, setupWithdrawalAccount, } from '../../libs/actions/BankAccounts'; import Navigation from '../../libs/Navigation/Navigation'; From 79856ee586ba629b3dc212fa99c8b81ba7cde330 Mon Sep 17 00:00:00 2001 From: Jasper Huang Date: Mon, 9 Aug 2021 07:21:52 -1000 Subject: [PATCH 15/15] remove debug --- src/pages/ReimbursementAccount/IdentityForm.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/ReimbursementAccount/IdentityForm.js b/src/pages/ReimbursementAccount/IdentityForm.js index 0ce065559b28..cb60f03b8c28 100644 --- a/src/pages/ReimbursementAccount/IdentityForm.js +++ b/src/pages/ReimbursementAccount/IdentityForm.js @@ -70,7 +70,6 @@ const IdentityForm = ({ const { firstName, lastName, street, city, state, zipCode, dob, ssnLast4, } = values; - console.log(">>>>", error); return (