67 lines
1.8 KiB
TypeScript
67 lines
1.8 KiB
TypeScript
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<string> };
|
|
|
|
export const keyValuePairsToQueryString = (
|
|
keyValuePairs: Array<KeyValuePair>
|
|
) =>
|
|
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,
|
|
};
|
|
};
|