update frontend
This commit is contained in:
parent
5bffb63028
commit
1565d1c72d
|
|
@ -0,0 +1,105 @@
|
||||||
|
/**
|
||||||
|
* recoSearch.js
|
||||||
|
*
|
||||||
|
* BUT: Optionnel.
|
||||||
|
* - Si tu veux que le frontend fasse une "suggestion/recherche" via Rico,
|
||||||
|
* FAIS-LE via le core-api (BFF), pas direct vers Rico.
|
||||||
|
*
|
||||||
|
* IMPORTANT:
|
||||||
|
* - Si tu n'importes pas ce fichier, rien ne change dans ton UI.
|
||||||
|
* - Ton search bar actuelle filtre déjà localement (0 call réseau).
|
||||||
|
*/
|
||||||
|
|
||||||
|
const DEFAULT_PATHS = [
|
||||||
|
"/api/reco/search",
|
||||||
|
"/api/reco/suggest",
|
||||||
|
"/api/search",
|
||||||
|
"/api/recommendations/search",
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalise un item venant du core-api.
|
||||||
|
* On reste permissif: Rico / core-api peut renvoyer plusieurs shapes.
|
||||||
|
*/
|
||||||
|
function normalizeOne(r) {
|
||||||
|
if (!r || typeof r !== "object") return null;
|
||||||
|
|
||||||
|
const title =
|
||||||
|
(r.title ?? r.name ?? r.label ?? r.display_name ?? r.disp ?? r.text ?? "")
|
||||||
|
.toString()
|
||||||
|
.trim();
|
||||||
|
|
||||||
|
// coords possibles
|
||||||
|
const lat = typeof r.lat === "number" ? r.lat : (typeof r.latitude === "number" ? r.latitude : null);
|
||||||
|
const lon = typeof r.lon === "number" ? r.lon : (typeof r.lng === "number" ? r.lng : null);
|
||||||
|
|
||||||
|
const coords =
|
||||||
|
Array.isArray(r.coords) && r.coords.length === 2
|
||||||
|
? r.coords
|
||||||
|
: (lat != null && lon != null ? [lon, lat] : null);
|
||||||
|
|
||||||
|
const type = (r.type ?? r.kind ?? r.entity ?? "").toString().toLowerCase().trim();
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: (r.id ?? r._id ?? r.key ?? title).toString(),
|
||||||
|
type: type || (coords ? "place" : "item"),
|
||||||
|
title,
|
||||||
|
subtitle: (r.subtitle ?? r.sub ?? r.extra ?? r.category ?? "").toString(),
|
||||||
|
coords,
|
||||||
|
raw: r,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tente une recherche sur une liste de paths (au cas où le endpoint exact diffère).
|
||||||
|
* Retourne [] sur 404/erreur.
|
||||||
|
*/
|
||||||
|
async function tryFetchAnyPath(q, { signal } = {}) {
|
||||||
|
const query = (q || "").toString().trim();
|
||||||
|
if (!query) return [];
|
||||||
|
|
||||||
|
// Permet override runtime si tu veux:
|
||||||
|
// window.__SW_RECO_SEARCH_PATH = "/api/reco/search"
|
||||||
|
const override =
|
||||||
|
typeof window !== "undefined" && window.__SW_RECO_SEARCH_PATH
|
||||||
|
? String(window.__SW_RECO_SEARCH_PATH)
|
||||||
|
: "";
|
||||||
|
|
||||||
|
const paths = override ? [override, ...DEFAULT_PATHS] : DEFAULT_PATHS;
|
||||||
|
|
||||||
|
for (const p of paths) {
|
||||||
|
try {
|
||||||
|
const url = `${p}?q=${encodeURIComponent(query)}`;
|
||||||
|
const res = await fetch(url, { credentials: "include", signal });
|
||||||
|
|
||||||
|
if (res.status === 404) continue;
|
||||||
|
if (!res.ok) return []; // évite spam erreurs
|
||||||
|
const data = await res.json().catch(() => null);
|
||||||
|
|
||||||
|
const arr = Array.isArray(data)
|
||||||
|
? data
|
||||||
|
: Array.isArray(data?.items)
|
||||||
|
? data.items
|
||||||
|
: Array.isArray(data?.results)
|
||||||
|
? data.results
|
||||||
|
: [];
|
||||||
|
|
||||||
|
return arr.map(normalizeOne).filter(Boolean);
|
||||||
|
} catch (e) {
|
||||||
|
// Abort => stop net
|
||||||
|
if (e && (e.name === "AbortError" || e.code === 20)) return [];
|
||||||
|
// autres erreurs => on teste prochain path
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* recoSearch(query): renvoie une liste normalisée.
|
||||||
|
* - "safe" : retourne [] si rien marche.
|
||||||
|
*/
|
||||||
|
export async function recoSearch(query, opts = {}) {
|
||||||
|
return tryFetchAnyPath(query, opts);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue