2022-01-05 11:34:43 +01:00
|
|
|
|
import React from 'react';
|
2021-02-16 13:54:16 +01:00
|
|
|
|
import { QueryClientProvider } from 'react-query';
|
2021-06-15 14:36:37 +02:00
|
|
|
|
import { matchSorter } from 'match-sorter';
|
2022-01-05 11:34:43 +01:00
|
|
|
|
import PropTypes from 'prop-types';
|
2020-10-07 17:42:41 +02:00
|
|
|
|
|
|
|
|
|
import ComboSearch from './ComboSearch';
|
2021-07-20 12:41:16 +02:00
|
|
|
|
import { queryClient } from './shared/queryClient';
|
2021-10-26 16:21:47 +02:00
|
|
|
|
import { ComboDepartementsSearch } from './ComboDepartementsSearch';
|
2022-01-05 11:34:43 +01:00
|
|
|
|
import { useHiddenField, groupId } from './shared/hooks';
|
2021-07-20 12:41:16 +02:00
|
|
|
|
|
|
|
|
|
// Avoid hiding similar matches for precise queries (like "Sainte Marie")
|
|
|
|
|
function searchResultsLimit(term) {
|
|
|
|
|
return term.length > 5 ? 10 : 5;
|
|
|
|
|
}
|
2020-10-07 17:42:41 +02:00
|
|
|
|
|
2021-06-15 14:36:37 +02:00
|
|
|
|
function expandResultsWithMultiplePostalCodes(term, results) {
|
2021-06-16 09:28:07 +02:00
|
|
|
|
// 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.
|
2021-06-15 14:36:37 +02:00
|
|
|
|
const expandedResults = results.flatMap((result) =>
|
|
|
|
|
result.codesPostaux.map((codePostal) => ({
|
|
|
|
|
...result,
|
|
|
|
|
codesPostaux: [codePostal]
|
|
|
|
|
}))
|
|
|
|
|
);
|
2021-06-16 09:28:07 +02:00
|
|
|
|
|
|
|
|
|
// 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);
|
2021-06-15 14:36:37 +02:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-26 16:21:47 +02:00
|
|
|
|
const placeholderDepartements = [
|
|
|
|
|
['63 – Puy-de-Dôme', 'Clermont-Ferrand'],
|
|
|
|
|
['77 – Seine-et-Marne', 'Melun'],
|
|
|
|
|
['22 – Côtes d’Armor', 'Saint-Brieuc'],
|
|
|
|
|
['47 – Lot-et-Garonne', 'Agen']
|
|
|
|
|
];
|
|
|
|
|
const [placeholderDepartement, placeholderCommune] =
|
|
|
|
|
placeholderDepartements[
|
|
|
|
|
Math.floor(Math.random() * (placeholderDepartements.length - 1))
|
|
|
|
|
];
|
|
|
|
|
|
2022-01-05 11:34:43 +01:00
|
|
|
|
function ComboCommunesSearch({ id, ...props }) {
|
|
|
|
|
const group = groupId(id);
|
|
|
|
|
const [departementValue, setDepartementValue] = useHiddenField(
|
|
|
|
|
group,
|
|
|
|
|
'departement'
|
2021-11-17 12:52:47 +01:00
|
|
|
|
);
|
2022-01-05 11:34:43 +01:00
|
|
|
|
const [codeDepartement, setCodeDepartement] = useHiddenField(
|
|
|
|
|
group,
|
|
|
|
|
'code_departement'
|
2021-11-17 12:52:47 +01:00
|
|
|
|
);
|
2022-01-05 11:34:43 +01:00
|
|
|
|
const departementDescribedBy = `${id}_departement_notice`;
|
|
|
|
|
const communeDescribedBy = `${id}_commune_notice`;
|
2021-10-26 16:21:47 +02:00
|
|
|
|
|
2020-10-07 17:42:41 +02:00
|
|
|
|
return (
|
2021-02-16 13:54:16 +01:00
|
|
|
|
<QueryClientProvider client={queryClient}>
|
2021-10-26 16:21:47 +02:00
|
|
|
|
<div>
|
|
|
|
|
<div className="notice" id={departementDescribedBy}>
|
|
|
|
|
<p>
|
|
|
|
|
Choisissez le département dans lequel se situe la commune. Vous
|
|
|
|
|
pouvez entrer le nom ou le code.
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
<ComboDepartementsSearch
|
2022-01-05 11:34:43 +01:00
|
|
|
|
{...props}
|
|
|
|
|
id={!codeDepartement ? id : null}
|
|
|
|
|
describedby={departementDescribedBy}
|
2021-10-26 16:21:47 +02:00
|
|
|
|
placeholder={placeholderDepartement}
|
2021-11-25 11:28:40 +01:00
|
|
|
|
addForeignDepartement={false}
|
2022-01-05 11:34:43 +01:00
|
|
|
|
value={departementValue}
|
2021-11-30 19:38:21 +01:00
|
|
|
|
onChange={(_, result) => {
|
2022-01-05 11:34:43 +01:00
|
|
|
|
setDepartementValue(result?.nom);
|
|
|
|
|
setCodeDepartement(result?.code);
|
2021-10-26 16:21:47 +02:00
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
2022-01-05 11:34:43 +01:00
|
|
|
|
{codeDepartement ? (
|
2021-10-26 16:21:47 +02:00
|
|
|
|
<div>
|
|
|
|
|
<div className="notice" id={communeDescribedBy}>
|
|
|
|
|
<p>
|
2021-11-25 11:11:03 +01:00
|
|
|
|
Choisissez la commune. Vous pouvez entrer le nom ou le code
|
|
|
|
|
postal.
|
2021-10-26 16:21:47 +02:00
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
<ComboSearch
|
2022-01-05 11:34:43 +01:00
|
|
|
|
{...props}
|
|
|
|
|
id={id}
|
|
|
|
|
describedby={communeDescribedBy}
|
2021-10-26 16:21:47 +02:00
|
|
|
|
placeholder={placeholderCommune}
|
|
|
|
|
scope="communes"
|
2022-01-05 11:34:43 +01:00
|
|
|
|
scopeExtra={codeDepartement}
|
2021-10-26 16:21:47 +02:00
|
|
|
|
minimumInputLength={2}
|
|
|
|
|
transformResult={({ code, nom, codesPostaux }) => [
|
|
|
|
|
code,
|
|
|
|
|
`${nom} (${codesPostaux[0]})`
|
|
|
|
|
]}
|
|
|
|
|
transformResults={expandResultsWithMultiplePostalCodes}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
) : null}
|
2021-02-16 13:54:16 +01:00
|
|
|
|
</QueryClientProvider>
|
2020-10-07 17:42:41 +02:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-05 11:34:43 +01:00
|
|
|
|
ComboCommunesSearch.propTypes = {
|
|
|
|
|
id: PropTypes.string
|
|
|
|
|
};
|
|
|
|
|
|
2020-10-07 17:42:41 +02:00
|
|
|
|
export default ComboCommunesSearch;
|