Skip to content

Commit

Permalink
Merge pull request Expensify#49243 from Expensify/lucien/fix-duplicat…
Browse files Browse the repository at this point in the history
…e-savedSearches
  • Loading branch information
luacmartins committed Sep 18, 2024
2 parents 839fb44 + d823cca commit 448ca57
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 37 deletions.
88 changes: 51 additions & 37 deletions src/libs/SearchUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -529,53 +529,67 @@ function buildSearchQueryString(queryJSON?: SearchQueryJSON) {
* Given object with chosen search filters builds correct query string from them
*/
function buildQueryStringFromFilterValues(filterValues: Partial<SearchAdvancedFiltersForm>) {
const filtersString = Object.entries(filterValues).map(([filterKey, filterValue]) => {
if ((filterKey === FILTER_KEYS.MERCHANT || filterKey === FILTER_KEYS.DESCRIPTION || filterKey === FILTER_KEYS.REPORT_ID) && filterValue) {
const keyInCorrectForm = (Object.keys(CONST.SEARCH.SYNTAX_FILTER_KEYS) as FilterKeys[]).find((key) => CONST.SEARCH.SYNTAX_FILTER_KEYS[key] === filterKey);
if (keyInCorrectForm) {
return `${CONST.SEARCH.SYNTAX_FILTER_KEYS[keyInCorrectForm]}:${sanitizeString(filterValue as string)}`;
// We separate type and status filters from other filters to maintain hashes consistency for saved searches
const {type, status, ...otherFilters} = filterValues;
const filtersString: string[] = [];

if (type) {
const sanitizedType = sanitizeString(type);
filtersString.push(`${CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE}:${sanitizedType}`);
}

if (status) {
const sanitizedStatus = sanitizeString(status);
filtersString.push(`${CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS}:${sanitizedStatus}`);
}

const mappedFilters = Object.entries(otherFilters)
.map(([filterKey, filterValue]) => {
if ((filterKey === FILTER_KEYS.MERCHANT || filterKey === FILTER_KEYS.DESCRIPTION || filterKey === FILTER_KEYS.REPORT_ID) && filterValue) {
const keyInCorrectForm = (Object.keys(CONST.SEARCH.SYNTAX_FILTER_KEYS) as FilterKeys[]).find((key) => CONST.SEARCH.SYNTAX_FILTER_KEYS[key] === filterKey);
if (keyInCorrectForm) {
return `${CONST.SEARCH.SYNTAX_FILTER_KEYS[keyInCorrectForm]}:${sanitizeString(filterValue as string)}`;
}
}
}
if (filterKey === FILTER_KEYS.KEYWORD && filterValue) {
const value = (filterValue as string).split(' ').map(sanitizeString).join(' ');
return `${value}`;
}
if (filterKey === FILTER_KEYS.TYPE && filterValue) {
return `${CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE}:${sanitizeString(filterValue as string)}`;
}
if (filterKey === FILTER_KEYS.STATUS && filterValue) {
return `${CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS}:${sanitizeString(filterValue as string)}`;
}
if (
(filterKey === FILTER_KEYS.CATEGORY ||
filterKey === FILTER_KEYS.CARD_ID ||
filterKey === FILTER_KEYS.TAX_RATE ||
filterKey === FILTER_KEYS.EXPENSE_TYPE ||
filterKey === FILTER_KEYS.TAG ||
filterKey === FILTER_KEYS.CURRENCY ||
filterKey === FILTER_KEYS.FROM ||
filterKey === FILTER_KEYS.TO ||
filterKey === FILTER_KEYS.IN) &&
Array.isArray(filterValue) &&
filterValue.length > 0
) {
const filterValueArray = [...new Set<string>(filterValues[filterKey] ?? [])];
const keyInCorrectForm = (Object.keys(CONST.SEARCH.SYNTAX_FILTER_KEYS) as FilterKeys[]).find((key) => CONST.SEARCH.SYNTAX_FILTER_KEYS[key] === filterKey);
if (keyInCorrectForm) {
return `${CONST.SEARCH.SYNTAX_FILTER_KEYS[keyInCorrectForm]}:${filterValueArray.map(sanitizeString).join(',')}`;

if (filterKey === FILTER_KEYS.KEYWORD && filterValue) {
const value = (filterValue as string).split(' ').map(sanitizeString).join(' ');
return `${value}`;
}
}

return undefined;
});
if (
(filterKey === FILTER_KEYS.CATEGORY ||
filterKey === FILTER_KEYS.CARD_ID ||
filterKey === FILTER_KEYS.TAX_RATE ||
filterKey === FILTER_KEYS.EXPENSE_TYPE ||
filterKey === FILTER_KEYS.TAG ||
filterKey === FILTER_KEYS.CURRENCY ||
filterKey === FILTER_KEYS.FROM ||
filterKey === FILTER_KEYS.TO ||
filterKey === FILTER_KEYS.IN) &&
Array.isArray(filterValue) &&
filterValue.length > 0
) {
const filterValueArray = [...new Set<string>(filterValue)];
const keyInCorrectForm = (Object.keys(CONST.SEARCH.SYNTAX_FILTER_KEYS) as FilterKeys[]).find((key) => CONST.SEARCH.SYNTAX_FILTER_KEYS[key] === filterKey);
if (keyInCorrectForm) {
return `${CONST.SEARCH.SYNTAX_FILTER_KEYS[keyInCorrectForm]}:${filterValueArray.map(sanitizeString).join(',')}`;
}
}

return undefined;
})
.filter((filter): filter is string => !!filter);

filtersString.push(...mappedFilters);

const dateFilter = buildDateFilterQuery(filterValues);
filtersString.push(dateFilter);

const amountFilter = buildAmountFilterQuery(filterValues);
filtersString.push(amountFilter);

return filtersString.filter(Boolean).join(' ');
return filtersString.join(' ').trim();
}

/**
Expand Down
8 changes: 8 additions & 0 deletions src/pages/Search/AdvancedSearchFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ function AdvancedSearchFilters() {
const {singleExecution} = useSingleExecution();
const waitForNavigate = useWaitForNavigation();
const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT);
const [savedSearches] = useOnyx(ONYXKEYS.SAVED_SEARCHES);
const [searchAdvancedFilters = {} as SearchAdvancedFiltersForm] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM);
const [cardList = {}] = useOnyx(ONYXKEYS.CARD_LIST);
const taxRates = getAllTaxRates();
Expand All @@ -242,6 +243,13 @@ function AdvancedSearchFilters() {
};

const onSaveSearch = () => {
const savedSearchKeys = Object.keys(savedSearches ?? {});
if (savedSearches && savedSearchKeys.includes(String(queryJSON.hash))) {
// If the search is already saved, return early to prevent unnecessary API calls
Navigation.dismissModal();
return;
}

SearchActions.saveSearch({
queryJSON,
});
Expand Down

0 comments on commit 448ca57

Please sign in to comment.