demarches-normaliennes/app/javascript/components/shared/queryClient.js

73 lines
2.1 KiB
JavaScript
Raw Normal View History

2021-02-16 13:54:16 +01:00
import { QueryClient } from 'react-query';
2020-10-07 17:41:20 +02:00
import { isNumeric } from '@utils';
2021-02-16 13:17:36 +01:00
import { matchSorter } from 'match-sorter';
2020-10-07 17:41:20 +02:00
2021-01-14 17:30:55 +01:00
const { api_geo_url, api_adresse_url, api_education_url } =
gon.autocomplete || {};
2020-10-07 17:41:20 +02:00
2021-02-16 13:54:16 +01:00
export const queryClient = new QueryClient({
defaultOptions: {
2020-10-07 17:41:20 +02:00
queries: {
queryFn: defaultQueryFn
}
}
});
// Avoid hiding similar matches for precise queries (like "Sainte Marie")
export function searchResultsLimit(term) {
return term.length > 5 ? 10 : 5;
}
2020-10-07 17:41:20 +02:00
function buildURL(scope, term) {
term = encodeURIComponent(term.replace(/\(|\)/g, ''));
2020-10-07 17:41:20 +02:00
if (scope === 'adresse') {
return `${api_adresse_url}/search?q=${term}&limit=5`;
2021-01-14 17:30:55 +01:00
} else if (scope === 'annuaire-education') {
return `${api_education_url}/search?dataset=fr-en-annuaire-education&q=${term}&rows=5`;
2021-04-20 12:55:07 +02:00
} else if (scope === 'communes') {
if (isNumeric(term)) {
return `${api_geo_url}/communes?codePostal=${term}&limit=5`;
}
const limit = searchResultsLimit(term);
2021-04-20 12:55:07 +02:00
return `${api_geo_url}/communes?nom=${term}&boost=population&limit=${limit}`;
2020-10-07 17:41:20 +02:00
} else if (isNumeric(term)) {
const code = term.padStart(2, '0');
return `${api_geo_url}/${scope}?code=${code}&limit=5`;
}
return `${api_geo_url}/${scope}?nom=${term}&limit=5`;
}
function buildOptions() {
if (window.AbortController) {
const controller = new AbortController();
const signal = controller.signal;
return [{ signal }, controller];
}
return [{}, null];
}
2021-02-16 13:54:16 +01:00
async function defaultQueryFn({ queryKey: [scope, term] }) {
2020-11-25 15:17:59 +01:00
if (scope == 'pays') {
2020-11-30 10:53:55 +01:00
return matchSorter(await getPays(), term, { keys: ['nom'] });
2020-11-25 15:17:59 +01:00
}
2020-10-07 17:41:20 +02:00
const url = buildURL(scope, term);
const [options, controller] = buildOptions();
const promise = fetch(url, options).then((response) => {
if (response.ok) {
return response.json();
}
throw new Error(`Error fetching from "${scope}" API`);
});
2020-10-07 17:41:20 +02:00
promise.cancel = () => controller && controller.abort();
return promise;
}
2020-11-30 10:53:55 +01:00
let paysCache;
async function getPays() {
if (!paysCache) {
paysCache = await fetch('/pays.json').then((response) => response.json());
}
return paysCache;
}