diff --git a/src/libs/LoginUtils.js b/src/libs/LoginUtils.js index 4c7e8a7d3d48..c4f160f8cf40 100644 --- a/src/libs/LoginUtils.js +++ b/src/libs/LoginUtils.js @@ -1,4 +1,13 @@ +import Str from 'expensify-common/lib/str'; +import Onyx from 'react-native-onyx'; import CONST from '../CONST'; +import ONYXKEYS from '../ONYXKEYS'; + +let countryCodeByIP; +Onyx.connect({ + key: ONYXKEYS.COUNTRY_CODE, + callback: val => countryCodeByIP = val || 1, +}); /** * Remove the special chars from the phone number @@ -20,7 +29,20 @@ function getPhoneNumberWithoutUSCountryCodeAndSpecialChars(phone) { return getPhoneNumberWithoutSpecialChars(phone.replace(/^\+1/, '')); } +/** + * Append user country code to the phone number + * + * @param {String} phone + * @return {String} + */ +function appendCountryCode(phone) { + return (Str.isValidPhone(phone) && !phone.includes('+')) + ? `+${countryCodeByIP}${phone}` + : phone; +} + export { getPhoneNumberWithoutSpecialChars, getPhoneNumberWithoutUSCountryCodeAndSpecialChars, + appendCountryCode, }; diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index bf88721ae0a0..2b91b20462a4 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -10,6 +10,7 @@ import * as Localize from './Localize'; import Permissions from './Permissions'; import * as CollectionUtils from './CollectionUtils'; import Navigation from './Navigation/Navigation'; +import * as LoginUtils from './LoginUtils'; /** * OptionsListUtils is used to build a list options passed to the OptionsList component. Several different UI views can @@ -580,9 +581,8 @@ function getOptions(reports, personalDetails, { // If the phone number doesn't have an international code then let's prefix it with the // current user's international code based on their IP address. - const login = (Str.isValidPhone(searchValue) && !searchValue.includes('+')) - ? `+${countryCodeByIP}${searchValue}` - : searchValue; + const login = LoginUtils.appendCountryCode(searchValue); + if (login && (noOptions || noOptionsMatchExactly) && !isCurrentUser({login}) && _.every(selectedOptions, option => option.login !== login) @@ -764,14 +764,16 @@ function getHeaderMessage(hasSelectableOptions, hasUserToInvite, searchValue, ma return Localize.translate(preferredLocale, 'common.maxParticipantsReached', {count: CONST.REPORT.MAXIMUM_PARTICIPANTS}); } - if (searchValue && CONST.REGEX.DIGITS_AND_PLUS.test(searchValue) && !Str.isValidPhone(searchValue)) { + const isValidPhone = Str.isValidPhone(LoginUtils.appendCountryCode(searchValue)); + + if (searchValue && CONST.REGEX.DIGITS_AND_PLUS.test(searchValue) && !isValidPhone) { return Localize.translate(preferredLocale, 'messages.errorMessageInvalidPhone'); } // Without a search value, it would be very confusing to see a search validation message. // Therefore, this skips the validation when there is no search value. if (searchValue && !hasSelectableOptions && !hasUserToInvite) { - if (/^\d+$/.test(searchValue) && !Str.isValidPhone(searchValue)) { + if (/^\d+$/.test(searchValue) && !isValidPhone) { return Localize.translate(preferredLocale, 'messages.errorMessageInvalidPhone'); }