diff --git a/src/libs/ValidationUtils.js b/src/libs/ValidationUtils.js
index a15fd74a8815..81b91e2101be 100644
--- a/src/libs/ValidationUtils.js
+++ b/src/libs/ValidationUtils.js
@@ -95,6 +95,24 @@ function isRequiredFulfilled(value) {
return Boolean(value);
}
+/**
+ * Used to add requiredField error to the fields passed.
+ *
+ * @param {Object} values
+ * @param {Array} requiredFields
+ * @returns {Object}
+ */
+function getFieldRequiredErrors(values, requiredFields) {
+ const errors = {};
+ _.each(requiredFields, (fieldKey) => {
+ if (isRequiredFulfilled(values[fieldKey])) {
+ return;
+ }
+ errors[fieldKey] = 'common.error.fieldRequired';
+ });
+ return errors;
+}
+
/**
* Validates that this is a valid expiration date. Supports the following formats:
* 1. MM/YY
@@ -451,6 +469,7 @@ export {
isValidIndustryCode,
isValidZipCode,
isRequiredFulfilled,
+ getFieldRequiredErrors,
isValidUSPhone,
isValidWebsite,
validateIdentity,
diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.js b/src/pages/EnablePayments/AdditionalDetailsStep.js
index cdf2ad16ac1b..9804edd63fcd 100644
--- a/src/pages/EnablePayments/AdditionalDetailsStep.js
+++ b/src/pages/EnablePayments/AdditionalDetailsStep.js
@@ -18,7 +18,6 @@ import TextLink from '../../components/TextLink';
import TextInput from '../../components/TextInput';
import * as Wallet from '../../libs/actions/Wallet';
import * as ValidationUtils from '../../libs/ValidationUtils';
-import * as ErrorUtils from '../../libs/ErrorUtils';
import AddressForm from '../ReimbursementAccount/AddressForm';
import DatePicker from '../../components/DatePicker';
import Form from '../../components/Form';
@@ -70,29 +69,6 @@ const defaultProps = {
...withCurrentUserPersonalDetailsDefaultProps,
};
-const INPUT_IDS = {
- LEGAL_FIRST_NAME: 'legalFirstName',
- LEGAL_LAST_NAME: 'legalLastName',
- PHONE_NUMBER: 'phoneNumber',
- DOB: 'dob',
- SSN: 'ssn',
- ADDRESS: {
- street: 'addressStreet',
- city: 'addressCity',
- state: 'addressState',
- zipCode: 'addressZip',
- },
-};
-const errorTranslationKeys = {
- legalFirstName: 'bankAccount.error.firstName',
- legalLastName: 'bankAccount.error.lastName',
- phoneNumber: 'bankAccount.error.phoneNumber',
- dob: 'bankAccount.error.dob',
- age: 'bankAccount.error.age',
- ssn: 'bankAccount.error.ssnLast4',
- ssnFull9: 'additionalDetailsStep.ssnFull9Error',
-};
-
const fieldNameTranslationKeys = {
legalFirstName: 'additionalDetailsStep.legalFirstNameLabel',
legalLastName: 'additionalDetailsStep.legalLastNameLabel',
@@ -113,50 +89,37 @@ function AdditionalDetailsStep({walletAdditionalDetails, translate, currentUserP
* @returns {Object}
*/
const validate = (values) => {
- const errors = {};
-
- if (_.isEmpty(values[INPUT_IDS.LEGAL_FIRST_NAME])) {
- errors[INPUT_IDS.LEGAL_FIRST_NAME] = errorTranslationKeys.legalFirstName;
- }
-
- if (_.isEmpty(values[INPUT_IDS.LEGAL_LAST_NAME])) {
- errors[INPUT_IDS.LEGAL_LAST_NAME] = errorTranslationKeys.legalLastName;
- }
-
- if (!ValidationUtils.isValidPastDate(values[INPUT_IDS.DOB]) || !ValidationUtils.meetsMaximumAgeRequirement(values[INPUT_IDS.DOB])) {
- ErrorUtils.addErrorMessage(errors, INPUT_IDS.DOB, errorTranslationKeys.dob);
- } else if (!ValidationUtils.meetsMinimumAgeRequirement(values[INPUT_IDS.DOB])) {
- ErrorUtils.addErrorMessage(errors, INPUT_IDS.DOB, errorTranslationKeys.age);
- }
+ const requiredFields = ['legalFirstName', 'legalLastName', 'addressStreet', 'addressCity', 'addressZipCode', 'phoneNumber', 'dob', 'ssn', 'addressState'];
+ const errors = ValidationUtils.getFieldRequiredErrors(values, requiredFields);
- if (!ValidationUtils.isValidAddress(values[INPUT_IDS.ADDRESS.street]) || _.isEmpty(values[INPUT_IDS.ADDRESS.street])) {
- errors[INPUT_IDS.ADDRESS.street] = 'bankAccount.error.addressStreet';
- }
-
- if (_.isEmpty(values[INPUT_IDS.ADDRESS.city])) {
- errors[INPUT_IDS.ADDRESS.city] = 'bankAccount.error.addressCity';
+ if (values.dob) {
+ if (!ValidationUtils.isValidPastDate(values.dob) || !ValidationUtils.meetsMaximumAgeRequirement(values.dob)) {
+ errors.dob = 'bankAccount.error.dob';
+ } else if (!ValidationUtils.meetsMinimumAgeRequirement(values.dob)) {
+ errors.dob = 'bankAccount.error.age';
+ }
}
- if (_.isEmpty(values[INPUT_IDS.ADDRESS.state])) {
- errors[INPUT_IDS.ADDRESS.state] = 'bankAccount.error.addressState';
+ if (values.addressStreet && !ValidationUtils.isValidAddress(values.addressStreet)) {
+ errors.addressStreet = 'bankAccount.error.addressStreet';
}
- if (!ValidationUtils.isValidZipCode(values[INPUT_IDS.ADDRESS.zipCode])) {
- errors[INPUT_IDS.ADDRESS.zipCode] = 'bankAccount.error.zipCode';
+ if (values.addressZipCode && !ValidationUtils.isValidZipCode(values.addressZipCode)) {
+ errors.addressZipCode = 'bankAccount.error.zipCode';
}
- if (!ValidationUtils.isValidUSPhone(values[INPUT_IDS.PHONE_NUMBER], true)) {
- errors[INPUT_IDS.PHONE_NUMBER] = errorTranslationKeys.phoneNumber;
+ if (values.phoneNumber && !ValidationUtils.isValidUSPhone(values.phoneNumber, true)) {
+ errors.phoneNumber = 'bankAccount.error.phoneNumber';
}
// walletAdditionalDetails stores errors returned by the server. If the server returns an SSN error
// then the user needs to provide the full 9 digit SSN.
if (walletAdditionalDetails.errorCode === CONST.WALLET.ERROR.SSN) {
- if (!ValidationUtils.isValidSSNFullNine(values[INPUT_IDS.SSN])) {
- errors[INPUT_IDS.SSN] = errorTranslationKeys.ssnFull9;
+ if (values.ssn && !ValidationUtils.isValidSSNFullNine(values.ssn)) {
+ errors.ssn = 'additionalDetailsStep.ssnFull9Error';
}
- } else if (!ValidationUtils.isValidSSNLastFour(values[INPUT_IDS.SSN])) {
- errors[INPUT_IDS.SSN] = errorTranslationKeys.ssn;
+ } else if (values.ssn && !ValidationUtils.isValidSSNLastFour(values.ssn)) {
+ errors.ssn = 'bankAccount.error.ssnLast4';
}
return errors;
@@ -167,17 +130,16 @@ function AdditionalDetailsStep({walletAdditionalDetails, translate, currentUserP
*/
const activateWallet = (values) => {
const personalDetails = {
- phoneNumber: parsePhoneNumber(values[INPUT_IDS.PHONE_NUMBER], {regionCode: CONST.COUNTRY.US}).number.significant,
- legalFirstName: values[INPUT_IDS.LEGAL_FIRST_NAME],
- legalLastName: values[INPUT_IDS.LEGAL_LAST_NAME],
- addressStreet: values[INPUT_IDS.ADDRESS.street],
- addressCity: values[INPUT_IDS.ADDRESS.city],
- addressState: values[INPUT_IDS.ADDRESS.state],
- addressZip: values[INPUT_IDS.ADDRESS.zipCode],
- dob: values[INPUT_IDS.DOB],
- ssn: values[INPUT_IDS.SSN],
+ phoneNumber: parsePhoneNumber(values.phoneNumber, {regionCode: CONST.COUNTRY.US}).number.significant,
+ legalFirstName: values.legalFirstName,
+ legalLastName: values.legalLastName,
+ addressStreet: values.addressStreet,
+ addressCity: values.addressCity,
+ addressState: values.addressState,
+ addressZip: values.addressZipCode,
+ dob: values.dob,
+ ssn: values.ssn,
};
-
// Attempt to set the personal details
Wallet.updatePersonalDetails(personalDetails);
};
@@ -222,7 +184,7 @@ function AdditionalDetailsStep({walletAdditionalDetails, translate, currentUserP
style={[styles.mh5, styles.flexGrow1]}
>
{
- const errorFields = {};
+ const requiredFields = ['routingNumber', 'accountNumber'];
+ const errors = ValidationUtils.getFieldRequiredErrors(values, requiredFields);
const routingNumber = values.routingNumber && values.routingNumber.trim();
if (
- !values.accountNumber ||
- (!CONST.BANK_ACCOUNT.REGEX.US_ACCOUNT_NUMBER.test(values.accountNumber.trim()) && !CONST.BANK_ACCOUNT.REGEX.MASKED_US_ACCOUNT_NUMBER.test(values.accountNumber.trim()))
+ values.accountNumber &&
+ !CONST.BANK_ACCOUNT.REGEX.US_ACCOUNT_NUMBER.test(values.accountNumber.trim()) &&
+ !CONST.BANK_ACCOUNT.REGEX.MASKED_US_ACCOUNT_NUMBER.test(values.accountNumber.trim())
) {
- errorFields.accountNumber = 'bankAccount.error.accountNumber';
- } else if (values.accountNumber === routingNumber) {
- errorFields.accountNumber = translate('bankAccount.error.routingAndAccountNumberCannotBeSame');
+ errors.accountNumber = 'bankAccount.error.accountNumber';
+ } else if (values.accountNumber && values.accountNumber === routingNumber) {
+ errors.accountNumber = translate('bankAccount.error.routingAndAccountNumberCannotBeSame');
}
- if (!routingNumber || !CONST.BANK_ACCOUNT.REGEX.SWIFT_BIC.test(routingNumber) || !ValidationUtils.isValidRoutingNumber(routingNumber)) {
- errorFields.routingNumber = 'bankAccount.error.routingNumber';
+ if (routingNumber && (!CONST.BANK_ACCOUNT.REGEX.SWIFT_BIC.test(routingNumber) || !ValidationUtils.isValidRoutingNumber(routingNumber))) {
+ errors.routingNumber = 'bankAccount.error.routingNumber';
}
if (!values.acceptTerms) {
- errorFields.acceptTerms = 'common.error.acceptTerms';
+ errors.acceptTerms = 'common.error.acceptTerms';
}
- return errorFields;
+ return errors;
},
[translate],
);
diff --git a/src/pages/ReimbursementAccount/CompanyStep.js b/src/pages/ReimbursementAccount/CompanyStep.js
index a57c80b0a7e2..3a963bc61295 100644
--- a/src/pages/ReimbursementAccount/CompanyStep.js
+++ b/src/pages/ReimbursementAccount/CompanyStep.js
@@ -80,54 +80,47 @@ class CompanyStep extends React.Component {
* @returns {Object} - Object containing the errors for each inputID, e.g. {inputID1: error1, inputID2: error2}
*/
validate(values) {
- const errors = {};
+ const requiredFields = [
+ 'companyName',
+ 'addressStreet',
+ 'addressZipCode',
+ 'addressCity',
+ 'addressState',
+ 'companyPhone',
+ 'website',
+ 'companyTaxID',
+ 'incorporationType',
+ 'incorporationDate',
+ 'incorporationState',
+ ];
+ const errors = ValidationUtils.getFieldRequiredErrors(values, requiredFields);
- if (!values.companyName) {
- errors.companyName = 'bankAccount.error.companyName';
- }
-
- if (!values.addressStreet || !ValidationUtils.isValidAddress(values.addressStreet)) {
+ if (values.addressStreet && !ValidationUtils.isValidAddress(values.addressStreet)) {
errors.addressStreet = 'bankAccount.error.addressStreet';
}
- if (!values.addressZipCode || !ValidationUtils.isValidZipCode(values.addressZipCode)) {
+ if (values.addressZipCode && !ValidationUtils.isValidZipCode(values.addressZipCode)) {
errors.addressZipCode = 'bankAccount.error.zipCode';
}
- if (!values.addressCity) {
- errors.addressCity = 'bankAccount.error.addressCity';
- }
-
- if (!values.addressState) {
- errors.addressState = 'bankAccount.error.addressState';
- }
-
- if (!values.companyPhone || !ValidationUtils.isValidUSPhone(values.companyPhone, true)) {
+ if (values.companyPhone && !ValidationUtils.isValidUSPhone(values.companyPhone, true)) {
errors.companyPhone = 'bankAccount.error.phoneNumber';
}
- if (!values.website || !ValidationUtils.isValidWebsite(values.website)) {
+ if (values.website && !ValidationUtils.isValidWebsite(values.website)) {
errors.website = 'bankAccount.error.website';
}
- if (!values.companyTaxID || !ValidationUtils.isValidTaxID(values.companyTaxID)) {
+ if (values.companyTaxID && !ValidationUtils.isValidTaxID(values.companyTaxID)) {
errors.companyTaxID = 'bankAccount.error.taxID';
}
- if (!values.incorporationType) {
- errors.incorporationType = 'bankAccount.error.companyType';
- }
-
- if (!values.incorporationDate || !ValidationUtils.isValidDate(values.incorporationDate)) {
+ if (values.incorporationDate && !ValidationUtils.isValidDate(values.incorporationDate)) {
errors.incorporationDate = 'common.error.dateInvalid';
- } else if (!values.incorporationDate || !ValidationUtils.isValidPastDate(values.incorporationDate)) {
+ } else if (values.incorporationDate && !ValidationUtils.isValidPastDate(values.incorporationDate)) {
errors.incorporationDate = 'bankAccount.error.incorporationDateFuture';
}
- if (!values.incorporationState) {
- errors.incorporationState = 'bankAccount.error.incorporationState';
- }
-
if (!values.hasNoConnectionToCannabis) {
errors.hasNoConnectionToCannabis = 'bankAccount.error.restrictedBusiness';
}
diff --git a/src/pages/ReimbursementAccount/RequestorStep.js b/src/pages/ReimbursementAccount/RequestorStep.js
index 0fa71833b34c..5fd962be3b0d 100644
--- a/src/pages/ReimbursementAccount/RequestorStep.js
+++ b/src/pages/ReimbursementAccount/RequestorStep.js
@@ -38,49 +38,26 @@ class RequestorStep extends React.Component {
* @returns {Object}
*/
validate(values) {
- const errors = {};
-
- if (!ValidationUtils.isRequiredFulfilled(values.firstName)) {
- errors.firstName = 'bankAccount.error.firstName';
- }
-
- if (!ValidationUtils.isRequiredFulfilled(values.lastName)) {
- errors.lastName = 'bankAccount.error.lastName';
- }
-
- if (!ValidationUtils.isRequiredFulfilled(values.dob)) {
- errors.dob = 'bankAccount.error.dob';
- }
+ const requiredFields = ['firstName', 'lastName', 'dob', 'ssnLast4', 'requestorAddressStreet', 'requestorAddressCity', 'requestorAddressState', 'requestorAddressZipCode'];
+ const errors = ValidationUtils.getFieldRequiredErrors(values, requiredFields);
if (values.dob) {
- if (!ValidationUtils.meetsMinimumAgeRequirement(values.dob)) {
- errors.dob = 'bankAccount.error.age';
- } else if (!ValidationUtils.meetsMaximumAgeRequirement(values.dob)) {
+ if (!ValidationUtils.isValidPastDate(values.dob) || !ValidationUtils.meetsMaximumAgeRequirement(values.dob)) {
errors.dob = 'bankAccount.error.dob';
+ } else if (!ValidationUtils.meetsMinimumAgeRequirement(values.dob)) {
+ errors.dob = 'bankAccount.error.age';
}
}
- if (!ValidationUtils.isRequiredFulfilled(values.ssnLast4) || !ValidationUtils.isValidSSNLastFour(values.ssnLast4)) {
+ if (values.ssnLast4 && !ValidationUtils.isValidSSNLastFour(values.ssnLast4)) {
errors.ssnLast4 = 'bankAccount.error.ssnLast4';
}
- if (!ValidationUtils.isRequiredFulfilled(values.requestorAddressStreet)) {
- errors.requestorAddressStreet = 'bankAccount.error.address';
- }
-
if (values.requestorAddressStreet && !ValidationUtils.isValidAddress(values.requestorAddressStreet)) {
errors.requestorAddressStreet = 'bankAccount.error.addressStreet';
}
- if (!ValidationUtils.isRequiredFulfilled(values.requestorAddressCity)) {
- errors.requestorAddressCity = 'bankAccount.error.addressCity';
- }
-
- if (!ValidationUtils.isRequiredFulfilled(values.requestorAddressState)) {
- errors.requestorAddressState = 'bankAccount.error.addressState';
- }
-
- if (!ValidationUtils.isRequiredFulfilled(values.requestorAddressZipCode) || !ValidationUtils.isValidZipCode(values.requestorAddressZipCode)) {
+ if (values.requestorAddressZipCode && !ValidationUtils.isValidZipCode(values.requestorAddressZipCode)) {
errors.requestorAddressZipCode = 'bankAccount.error.zipCode';
}
diff --git a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.js b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.js
index fa73d2b1a69a..90c469c4e25d 100644
--- a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.js
+++ b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.js
@@ -45,15 +45,14 @@ function DateOfBirthPage({translate, privatePersonalDetails}) {
* @returns {Object} - An object containing the errors for each inputID
*/
const validate = useCallback((values) => {
- const errors = {};
+ const requiredFields = ['dob'];
+ const errors = ValidationUtils.getFieldRequiredErrors(values, requiredFields);
+
const minimumAge = CONST.DATE_BIRTH.MIN_AGE;
const maximumAge = CONST.DATE_BIRTH.MAX_AGE;
-
- if (!values.dob || !ValidationUtils.isValidDate(values.dob)) {
- errors.dob = 'common.error.fieldRequired';
- }
const dateError = ValidationUtils.getAgeRequirementError(values.dob, minimumAge, maximumAge);
- if (dateError) {
+
+ if (values.dob && dateError) {
errors.dob = dateError;
}
diff --git a/src/pages/settings/Security/CloseAccountPage.js b/src/pages/settings/Security/CloseAccountPage.js
index 9ec5a52b8d3a..b2370156228a 100644
--- a/src/pages/settings/Security/CloseAccountPage.js
+++ b/src/pages/settings/Security/CloseAccountPage.js
@@ -2,7 +2,6 @@ import React, {useState, useEffect} from 'react';
import {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 HeaderWithBackButton from '../../../components/HeaderWithBackButton';
import Navigation from '../../../libs/Navigation/Navigation';
@@ -20,6 +19,7 @@ import ONYXKEYS from '../../../ONYXKEYS';
import Form from '../../../components/Form';
import CONST from '../../../CONST';
import ConfirmModal from '../../../components/ConfirmModal';
+import * as ValidationUtils from '../../../libs/ValidationUtils';
const propTypes = {
/** Session of currently logged in user */
@@ -63,10 +63,11 @@ function CloseAccountPage(props) {
};
const validate = (values) => {
+ const requiredFields = ['phoneOrEmail'];
const userEmailOrPhone = props.formatPhoneNumber(props.session.email);
- const errors = {};
+ const errors = ValidationUtils.getFieldRequiredErrors(values, requiredFields);
- if (_.isEmpty(values.phoneOrEmail) || userEmailOrPhone.toLowerCase() !== values.phoneOrEmail.toLowerCase()) {
+ if (values.phoneOrEmail && userEmailOrPhone.toLowerCase() !== values.phoneOrEmail.toLowerCase()) {
errors.phoneOrEmail = 'closeAccountPage.enterYourDefaultContactMethod';
}
return errors;
diff --git a/src/pages/settings/Wallet/AddDebitCardPage.js b/src/pages/settings/Wallet/AddDebitCardPage.js
index 7a04db30abed..ea0b4698a443 100644
--- a/src/pages/settings/Wallet/AddDebitCardPage.js
+++ b/src/pages/settings/Wallet/AddDebitCardPage.js
@@ -60,36 +60,33 @@ function DebitCardPage(props) {
* @returns {Boolean}
*/
const validate = (values) => {
- const errors = {};
+ const requiredFields = ['nameOnCard', 'cardNumber', 'expirationDate', 'securityCode', 'addressStreet', 'addressZipCode', 'addressState'];
+ const errors = ValidationUtils.getFieldRequiredErrors(values, requiredFields);
- if (!values.nameOnCard || !ValidationUtils.isValidLegalName(values.nameOnCard)) {
+ if (values.nameOnCard && !ValidationUtils.isValidLegalName(values.nameOnCard)) {
errors.nameOnCard = 'addDebitCardPage.error.invalidName';
}
- if (!values.cardNumber || !ValidationUtils.isValidDebitCard(values.cardNumber.replace(/ /g, ''))) {
+ if (values.cardNumber && !ValidationUtils.isValidDebitCard(values.cardNumber.replace(/ /g, ''))) {
errors.cardNumber = 'addDebitCardPage.error.debitCardNumber';
}
- if (!values.expirationDate || !ValidationUtils.isValidExpirationDate(values.expirationDate)) {
+ if (values.expirationDate && !ValidationUtils.isValidExpirationDate(values.expirationDate)) {
errors.expirationDate = 'addDebitCardPage.error.expirationDate';
}
- if (!values.securityCode || !ValidationUtils.isValidSecurityCode(values.securityCode)) {
+ if (values.securityCode && !ValidationUtils.isValidSecurityCode(values.securityCode)) {
errors.securityCode = 'addDebitCardPage.error.securityCode';
}
- if (!values.addressStreet || !ValidationUtils.isValidAddress(values.addressStreet)) {
+ if (values.addressStreet && !ValidationUtils.isValidAddress(values.addressStreet)) {
errors.addressStreet = 'addDebitCardPage.error.addressStreet';
}
- if (!values.addressZipCode || !ValidationUtils.isValidZipCode(values.addressZipCode)) {
+ if (values.addressZipCode && !ValidationUtils.isValidZipCode(values.addressZipCode)) {
errors.addressZipCode = 'addDebitCardPage.error.addressZipCode';
}
- if (!values.addressState || !values.addressState) {
- errors.addressState = 'addDebitCardPage.error.addressState';
- }
-
if (!values.acceptTerms) {
errors.acceptTerms = 'common.error.acceptTerms';
}
diff --git a/src/pages/settings/Wallet/AddPayPalMePage.js b/src/pages/settings/Wallet/AddPayPalMePage.js
index 042e0c8576e6..a95163bbae5c 100644
--- a/src/pages/settings/Wallet/AddPayPalMePage.js
+++ b/src/pages/settings/Wallet/AddPayPalMePage.js
@@ -38,8 +38,10 @@ const defaultProps = {
};
const validate = (values) => {
- const errors = {};
- if (!ValidationUtils.isValidPaypalUsername(values.payPalMeUsername)) {
+ const requiredFields = ['payPalMeUsername'];
+ const errors = ValidationUtils.getFieldRequiredErrors(values, requiredFields);
+
+ if (values.payPalMeUsername && !ValidationUtils.isValidPaypalUsername(values.payPalMeUsername)) {
errors.payPalMeUsername = 'addPayPalMePage.formatError';
}