Skip to content

Commit

Permalink
Merge pull request #24140 from huzaifa-99/23727-country-suggestion-fix
Browse files Browse the repository at this point in the history
Updated country and state searches to fix extra spaces + support searching with/without non alphabet chars in country name
  • Loading branch information
marcaaron authored Aug 7, 2023
2 parents 9811ed5 + 09f3579 commit 0dcb699
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 24 deletions.
1 change: 1 addition & 0 deletions src/CONST.js
Original file line number Diff line number Diff line change
Expand Up @@ -1166,6 +1166,7 @@ const CONST = {
SPECIAL_CHARS_WITHOUT_NEWLINE: /((?!\n)[()-\s\t])/g,
DIGITS_AND_PLUS: /^\+?[0-9]*$/,
ALPHABETIC_AND_LATIN_CHARS: /^[a-zA-ZÀ-ÿ ]*$/,
NON_ALPHABETIC_AND_NON_LATIN_CHARS: /[^a-zA-ZÀ-ÿ]/g,
POSITIVE_INTEGER: /^\d+$/,
PO_BOX: /\b[P|p]?(OST|ost)?\.?\s*[O|o|0]?(ffice|FFICE)?\.?\s*[B|b][O|o|0]?[X|x]?\.?\s+[#]?(\d+)\b/,
ANY_VALUE: /^.+$/,
Expand Down
17 changes: 5 additions & 12 deletions src/components/CountryPicker/CountrySelectorModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import useLocalize from '../../hooks/useLocalize';
import HeaderWithBackButton from '../HeaderWithBackButton';
import SelectionListRadio from '../SelectionListRadio';
import Modal from '../Modal';
import searchCountryOptions from '../../libs/searchCountryOptions';

const propTypes = {
/** Whether the modal is visible */
Expand Down Expand Up @@ -33,15 +34,6 @@ const defaultProps = {
onCountrySelected: () => {},
};

function filterOptions(searchValue, data) {
const trimmedSearchValue = searchValue.trim();
if (trimmedSearchValue.length === 0) {
return [];
}

return _.filter(data, (country) => country.text.toLowerCase().includes(searchValue.toLowerCase()));
}

function CountrySelectorModal({currentCountry, isVisible, onClose, onCountrySelected, setSearchValue, searchValue}) {
const {translate} = useLocalize();

Expand All @@ -52,12 +44,13 @@ function CountrySelectorModal({currentCountry, isVisible, onClose, onCountrySele
keyForList: countryISO,
text: countryName,
isSelected: currentCountry === countryISO,
searchValue: `${countryISO}${countryName}`.toLowerCase().replaceAll(CONST.REGEX.NON_ALPHABETIC_AND_NON_LATIN_CHARS, ''),
})),
[translate, currentCountry],
);

const filteredData = filterOptions(searchValue, countries);
const headerMessage = searchValue.trim() && !filteredData.length ? translate('common.noResultsFound') : '';
const searchResults = searchCountryOptions(searchValue, countries);
const headerMessage = searchValue.trim() && !searchResults.length ? translate('common.noResultsFound') : '';

return (
<Modal
Expand All @@ -77,7 +70,7 @@ function CountrySelectorModal({currentCountry, isVisible, onClose, onCountrySele
textInputLabel={translate('common.country')}
textInputPlaceholder={translate('countrySelectorModal.placeholderText')}
textInputValue={searchValue}
sections={[{data: filteredData, indexOffset: 0}]}
sections={[{data: searchResults, indexOffset: 0}]}
onSelectRow={onCountrySelected}
onChangeText={setSearchValue}
shouldFocusOnSelectRow
Expand Down
17 changes: 5 additions & 12 deletions src/components/StatePicker/StateSelectorModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Modal from '../Modal';
import HeaderWithBackButton from '../HeaderWithBackButton';
import SelectionListRadio from '../SelectionListRadio';
import useLocalize from '../../hooks/useLocalize';
import searchCountryOptions from '../../libs/searchCountryOptions';

const propTypes = {
/** Whether the modal is visible */
Expand Down Expand Up @@ -37,15 +38,6 @@ const defaultProps = {
label: undefined,
};

function filterOptions(searchValue, data) {
const trimmedSearchValue = searchValue.trim();
if (trimmedSearchValue.length === 0) {
return [];
}

return _.filter(data, (country) => country.text.toLowerCase().includes(searchValue.toLowerCase()));
}

function StateSelectorModal({currentState, isVisible, onClose, onStateSelected, searchValue, setSearchValue, label}) {
const {translate} = useLocalize();

Expand All @@ -56,12 +48,13 @@ function StateSelectorModal({currentState, isVisible, onClose, onStateSelected,
keyForList: state.stateISO,
text: state.stateName,
isSelected: currentState === state.stateISO,
searchValue: `${state.stateISO}${state.stateName}`.toLowerCase().replaceAll(CONST.REGEX.NON_ALPHABETIC_AND_NON_LATIN_CHARS, ''),
})),
[translate, currentState],
);

const filteredData = filterOptions(searchValue, countryStates);
const headerMessage = searchValue.trim() && !filteredData.length ? translate('common.noResultsFound') : '';
const searchResults = searchCountryOptions(searchValue, countryStates);
const headerMessage = searchValue.trim() && !searchResults.length ? translate('common.noResultsFound') : '';

return (
<Modal
Expand All @@ -82,7 +75,7 @@ function StateSelectorModal({currentState, isVisible, onClose, onStateSelected,
textInputLabel={label || translate('common.state')}
textInputPlaceholder={translate('stateSelectorModal.placeholderText')}
textInputValue={searchValue}
sections={[{data: filteredData, indexOffset: 0}]}
sections={[{data: searchResults, indexOffset: 0}]}
onSelectRow={onStateSelected}
onChangeText={setSearchValue}
shouldFocusOnSelectRow
Expand Down
22 changes: 22 additions & 0 deletions src/libs/searchCountryOptions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import _ from 'underscore';
import CONST from '../CONST';

/**
* Searches the countries/states data and returns sorted results based on the search query
* @param {String} searchValue
* @param {Object[]} countriesData - An array of country data objects
* @returns {Object[]} An array of countries/states sorted based on the search query
*/
function searchCountryOptions(searchValue, countriesData) {
const trimmedSearchValue = searchValue.toLowerCase().replaceAll(CONST.REGEX.NON_ALPHABETIC_AND_NON_LATIN_CHARS, '');
if (trimmedSearchValue.length === 0) {
return [];
}

const filteredData = _.filter(countriesData, (country) => country.searchValue.includes(trimmedSearchValue));

// sort by country code
return _.sortBy(filteredData, (country) => (country.value.toLowerCase() === trimmedSearchValue ? -1 : 1));
}

export default searchCountryOptions;

0 comments on commit 0dcb699

Please sign in to comment.