import { SortByPropMap, getSearchableTerms, } from "~/state/selectors/characterUtils"; import { SortOrderEnum } from "~/types"; import { logListingSearchChanged } from "./analytics"; import { byProp } from "./sortUtils"; type KeyValuePair = { key: string; value: string | Array }; export const keyValuePairsToQueryString = ( keyValuePairs: Array ) => keyValuePairs .map(({ key, value }) => Array.isArray(value) ? value.map((v) => `${key}=${v}`).join("&") : `${key}=${value}` ) .join("&"); export const queryListToMap = (queries) => { return queries.reduce((queryMap, { key, value }) => { queryMap[key] = value; return queryMap; }, {}); }; export const matchesSearchTerm = (lowerSearch: string) => (searchableTerm: string) => searchableTerm.toLowerCase().includes(lowerSearch); export const applyQueriesClientSide = (queryMap) => (json: any) => { let data = json.data || []; const { search, sortBy, sortOrder = SortOrderEnum.Ascending } = queryMap; if (search) { const matchesSearch = matchesSearchTerm(search.toLowerCase()); data = data.filter((character) => getSearchableTerms(character).some(matchesSearch) ); // Logging this here will duplicate the log if a search term is used and then the sort is changed. // If this was logged in MyCharactersListing.handleSearchChanged, then it wouldn't have the context of all data and would miss matches in some scenarios. // This function is debounced to prevent spamming the logs as the user types. logListingSearchChanged(data, matchesSearch); } const sortByPropSelector = SortByPropMap[sortBy]; if (sortByPropSelector) { data = data.sort(byProp(sortByPropSelector)); if (sortOrder === SortOrderEnum.Descending) { data.reverse(); } } return { ...json, data, }; };