--- import BaseLayout from "../layouts/BaseLayout.astro"; import { getSets } from "../lib/tcgdex-cache"; import { isLoggedIn } from "../lib/auth"; const { pb } = Astro.locals; if (!isLoggedIn(Astro.locals)) { return Astro.redirect("/login"); } const search = Astro.url.searchParams.get("search") ?? ""; const serie = Astro.url.searchParams.get("serie") ?? ""; const set = Astro.url.searchParams.get("set") ?? ""; const sort = Astro.url.searchParams.get("sort") ?? ""; const hasFilter = !!(serie || set); interface CardSummary { id: string; name: string; localId?: string; image?: string; setId: string; serieId: string; serieName: string; set: { name: string }; } let cards: CardSummary[] = []; let serieFacets: { id: string; name: string; count: number }[] = []; let setFacets: { id: string; name: string; count: number }[] = []; if (search.length >= 3) { try { const params = new URLSearchParams(); params.set("name", `like:${search}*`); if (sort === "name-asc" || sort === "name-desc") { params.set("sort:field", "name"); params.set("sort:order", sort === "name-asc" ? "asc" : "desc"); } // The list endpoint returns summaries (id, name, localId, image) only, // so serie/set filters are derived from the results themselves: a // card's set id is the part of its id before the last "-" and the // cached set metadata maps each set to its serie. Filtering is // applied locally so the facet pills always reflect the full results. const [res, allSets] = await Promise.all([ fetch(`https://api.tcgdex.net/v2/fr/cards?${params}`), getSets(), ]); if (res.ok) { const summaries: { id: string }[] = await res.json(); const setById = new Map(allSets.map((s) => [s.id, s])); const enriched: CardSummary[] = summaries.map((card) => { const setId = card.id.replace(/-[^-]+$/, ""); const meta = setById.get(setId); return { ...card, setId, serieId: meta?.serie?.id ?? "", serieName: meta?.serie?.name ?? "", set: { name: meta?.name ?? setId }, }; }); const countBy = ( key: "serieId" | "setId", ): { id: string; name: string; count: number }[] => { const counts = new Map< string, { name: string; count: number } >(); for (const c of enriched) { const id = c[key]; if (!id) continue; const name = key === "serieId" ? c.serieName : c.set.name; const entry = counts.get(id) ?? { name, count: 0 }; entry.count++; counts.set(id, entry); } return [...counts.entries()] .map(([id, v]) => ({ id, ...v })) .sort((a, b) => b.count - a.count); }; serieFacets = countBy("serieId"); setFacets = countBy("setId"); cards = enriched.filter( (c) => (!serie || c.serieId === serie) && (!set || c.setId === set), ); } } catch { // Keep empty results on network failure } } // A search can span dozens of sets — keep the pill row to the most common ones const MAX_SET_PILLS = 12; const visibleSetFacets = setFacets.slice(0, MAX_SET_PILLS); ---
{search && ( )}
{serieFacets.length > 0 && ( <>
Série {serieFacets.map((f) => ( ))}
Set {visibleSetFacets.map((f) => ( ))}
{(hasFilter || sort) && ( ✕ Réinitialiser )}
)}
{ search.length > 0 && search.length < 3 ? (

Recherche trop courte

Entrez au moins 3 caractères pour lancer la recherche.

) : search.length >= 3 && cards.length === 0 ? (

Aucun résultat

Aucune carte trouvée pour "{search}"{hasFilter && " avec ces filtres"}. Essayez d'autres critères.

) : cards.length > 0 ? ( <>

{cards.length} carte{cards.length > 1 ? "s" : ""} trouvée{cards.length > 1 ? "s" : ""}

{cards.map((card) => ( {card.name}

{card.name}

{card.id}
))}
) : (

Rechercher une carte

Recherchez une carte par nom, puis filtrez les résultats par série et par set.

) }