Files
archicratie-edition/src/pages/recherche/index.astro
Archicratia 64e56e8abc
All checks were successful
SMOKE / smoke (push) Successful in 6s
CI / build-and-anchors (push) Successful in 44s
CI / build-and-anchors (pull_request) Successful in 36s
feat(ui): harmoniser navigation pages d’entrée et recherche
2026-04-25 01:31:14 +02:00

162 lines
4.8 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
import SiteLayout from "../../layouts/SiteLayout.astro";
---
<SiteLayout title="Recherche">
<section class="search-page" aria-labelledby="search-title">
<header class="landing-hero search-hero">
<p class="landing-kicker">Exploration transversale</p>
<h1 id="search-title">Recherche</h1>
<p class="landing-lead">
Rechercher un terme, une notion ou un passage dans les textes de lédition web.
</p>
</header>
<section class="landing-section search-panel" aria-label="Formulaire de recherche">
<div class="search-controls">
<label class="search-field search-field--main">
<span>Terme</span>
<input id="q" type="search" autocomplete="off" placeholder="Ex. archicratie, régulation, inertie…" />
</label>
<label class="search-field">
<span>Édition</span>
<select id="edition">
<option value="">Toutes</option>
<option value="archicrat-ia">Essai-thèse</option>
<option value="cas-ia">Cas IA</option>
<option value="glossaire">Glossaire</option>
<option value="commencer">Commencer</option>
</select>
</label>
<label class="search-field">
<span>Niveau</span>
<select id="level">
<option value="">Tous</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
</label>
</div>
<p id="status" class="search-status" aria-live="polite"></p>
<ol id="results" class="search-results"></ol>
</section>
</section>
<script is:inline>
(() => {
const q = document.getElementById("q");
const ed = document.getElementById("edition");
const lv = document.getElementById("level");
const status = document.getElementById("status");
const results = document.getElementById("results");
let pfPromise = null;
async function getPagefind() {
if (pfPromise) return pfPromise;
pfPromise = (async () => {
try {
const pagefind = await import("/pagefind/pagefind.js");
await pagefind.init?.();
return pagefind;
} catch (e) {
console.error("[Recherche] Pagefind init failed:", e);
return null;
}
})();
return pfPromise;
}
function currentFilters() {
const filters = {};
if (ed.value) filters.edition = ed.value;
if (lv.value) filters.level = lv.value;
return Object.keys(filters).length ? filters : null;
}
function setStatus(msg) {
status.textContent = msg;
}
function clearResults() {
results.innerHTML = "";
}
async function runSearch() {
const term = q.value.trim();
if (!term) {
setStatus("Tape un terme pour lancer une recherche.");
clearResults();
return;
}
const pagefind = await getPagefind();
if (!pagefind) {
setStatus("Index de recherche indisponible. Lance `npm run build` puis `npm run preview`.");
clearResults();
return;
}
const opts = {};
const filters = currentFilters();
if (filters) opts.filters = filters;
setStatus("Recherche en cours…");
const search = await pagefind.debouncedSearch(term, opts, 250);
if (search === null) return;
const items = await Promise.all(search.results.slice(0, 24).map((r) => r.data()));
clearResults();
if (!items.length) {
setStatus("Aucun résultat pour cette recherche.");
return;
}
setStatus(`${items.length} résultat(s) affiché(s) sur ${search.results.length}.`);
for (const item of items) {
const li = document.createElement("li");
li.className = "search-result";
const a = document.createElement("a");
a.className = "search-result__title";
a.href = item.url;
a.textContent = item.meta?.title || item.url;
const meta = document.createElement("div");
meta.className = "search-result__meta";
const edition = item.meta?.edition ? `édition : ${item.meta.edition}` : "";
const level = item.meta?.level ? `niveau : ${item.meta.level}` : "";
const version = item.meta?.version ? `v${item.meta.version}` : "";
meta.textContent = [edition, level, version].filter(Boolean).join(" · ");
const excerpt = document.createElement("div");
excerpt.className = "search-result__excerpt";
excerpt.innerHTML = item.excerpt || "";
li.appendChild(a);
if (meta.textContent) li.appendChild(meta);
li.appendChild(excerpt);
results.appendChild(li);
}
}
q.addEventListener("focus", () => { getPagefind(); });
q.addEventListener("input", runSearch);
ed.addEventListener("change", runSearch);
lv.addEventListener("change", runSearch);
setStatus("Tape un terme pour lancer une recherche.");
})();
</script>
</SiteLayout>