Skip to content

Commit

Permalink
Merge pull request #15976 from bernhardoj/fix/15547
Browse files Browse the repository at this point in the history
fix inconsistent phone number validation
  • Loading branch information
deetergp authored Mar 16, 2023
2 parents c40148b + cffd938 commit 0efe6ac
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 5 deletions.
22 changes: 22 additions & 0 deletions src/libs/LoginUtils.js
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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,
};
12 changes: 7 additions & 5 deletions src/libs/OptionsListUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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');
}

Expand Down

0 comments on commit 0efe6ac

Please sign in to comment.