57 lines
1.8 KiB
JavaScript
57 lines
1.8 KiB
JavaScript
import React from 'react';
|
|
import { QueryClientProvider } from 'react-query';
|
|
import { matchSorter } from 'match-sorter';
|
|
|
|
import ComboSearch from './ComboSearch';
|
|
import { queryClient } from './shared/queryClient';
|
|
|
|
// Avoid hiding similar matches for precise queries (like "Sainte Marie")
|
|
function searchResultsLimit(term) {
|
|
return term.length > 5 ? 10 : 5;
|
|
}
|
|
|
|
function expandResultsWithMultiplePostalCodes(term, results) {
|
|
// A single result may have several associated postal codes.
|
|
// To make the search results more precise, we want to generate
|
|
// an actual result for each postal code.
|
|
const expandedResults = results.flatMap((result) =>
|
|
result.codesPostaux.map((codePostal) => ({
|
|
...result,
|
|
codesPostaux: [codePostal]
|
|
}))
|
|
);
|
|
|
|
// Some very large cities (like Paris) have A LOT of associated postal codes.
|
|
// As we generated one result per postal code, we now have a lot of results
|
|
// for the same city. If the number of results is above the threshold, we use
|
|
// local search to narrow the results.
|
|
const limit = searchResultsLimit(term);
|
|
if (expandedResults.length > limit) {
|
|
return matchSorter(expandedResults, term, {
|
|
keys: [(item) => `${item.nom} (${item.codesPostaux[0]})`, 'code'],
|
|
sorter: (rankedItems) => rankedItems
|
|
}).slice(0, limit + 1);
|
|
}
|
|
|
|
return expandedResults;
|
|
}
|
|
|
|
function ComboCommunesSearch(params) {
|
|
return (
|
|
<QueryClientProvider client={queryClient}>
|
|
<ComboSearch
|
|
required={params.mandatory}
|
|
hiddenFieldId={params.hiddenFieldId}
|
|
scope="communes"
|
|
minimumInputLength={2}
|
|
transformResult={({ code, nom, codesPostaux }) => [
|
|
code,
|
|
`${nom} (${codesPostaux[0]})`
|
|
]}
|
|
transformResults={expandResultsWithMultiplePostalCodes}
|
|
/>
|
|
</QueryClientProvider>
|
|
);
|
|
}
|
|
|
|
export default ComboCommunesSearch;
|