SPB Git forge

spb/lou-ka

Public

Lou·Ka — tous les logements à louer du Québec, un seul endroit.

232commits 1branches 0releases
172.9 MBsize
maindefault branch
2 days agolast push
HTML 98.9% Python 0.6%
2.5 KB · 74 lines tsx
Raw Blame History
1// -----------------------------------------------------------------------------2// Lou-Ka — Agrégateur de logements à louer (province de Québec)3// Auteur : Simon-Pierre Boucher — contact@spboucher.ai4// components/Pager.tsx : pagination éditoriale (12 annonces/page)5//   Précédent / numéros avec ellipses / Suivant + rappel « X–Y sur N ».6// -----------------------------------------------------------------------------7import { IcoChevronLeft, IcoChevronRight } from "./Icons";89/** 1 … 4 [5] 6 … 12 — fenêtre autour de la page courante, bornes toujours visibles */10function pageItems(page: number, pages: number): (number | "…")[] {11  if (pages <= 7) return Array.from({ length: pages }, (_, i) => i + 1);12  const win = new Set<number>([1, 2, page - 1, page, page + 1, pages - 1, pages]);13  const items: (number | "…")[] = [];14  let prev = 0;15  for (let n = 1; n <= pages; n++) {16    if (!win.has(n)) continue;17    if (prev && n - prev > 1) items.push("…");18    items.push(n);19    prev = n;20  }21  return items;22}2324export default function Pager({ page, pageSize, total, onPage }: {25  page: number;26  pageSize: number;27  total: number;28  onPage: (p: number) => void;29}) {30  const pages = Math.max(1, Math.ceil(total / pageSize));31  if (pages <= 1) return null;32  const from = (page - 1) * pageSize + 1;33  const to = Math.min(page * pageSize, total);34  return (35    <nav className="pager" aria-label="Pagination des résultats">36      <span className="pager-info">37        {from}–{to} <em>sur</em> {total.toLocaleString("fr-CA")}38      </span>39      <div className="pager-nav">40        <button41          className="pager-btn pager-arrow"42          disabled={page <= 1}43          onClick={() => onPage(page - 1)}44          aria-label="Page précédente"45        >46          <IcoChevronLeft size={14} />47        </button>48        {pageItems(page, pages).map((it, i) =>49          it === "…" ? (50            <span key={`e${i}`} className="pager-ellipsis" aria-hidden="true">…</span>51          ) : (52            <button53              key={it}54              className={`pager-btn ${it === page ? "on" : ""}`}55              aria-current={it === page ? "page" : undefined}56              onClick={() => it !== page && onPage(it)}57            >58              {it}59            </button>60          ),61        )}62        <button63          className="pager-btn pager-arrow"64          disabled={page >= pages}65          onClick={() => onPage(page + 1)}66          aria-label="Page suivante"67        >68          <IcoChevronRight size={14} />69        </button>70      </div>71    </nav>72  );73}74