mirror of
https://github.com/R0m1k3/PleinR.git
synced 2026-10-20 05:38:05 +02:00
Liste des adhérents actifs avec recherche (nom/métier), filtre par commune, filtres catégories (chips + compteurs), tri (A–Z / avec promotions), état vide et CTA d'adhésion — fidèle à la maquette. Chaque carte ouvre la fiche adhérent (/adherents/[id]). La recherche de l'accueil et la nav pointent vers /annuaire (la barre de recherche pré-remplit via ?q=). Nouvelles requêtes annuaire. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XwfhYHzC9hQWPDnQ2p53GL
167 lines
6.6 KiB
TypeScript
167 lines
6.6 KiB
TypeScript
import Link from "next/link";
|
|
import type { Metadata } from "next";
|
|
import { Sparkle } from "@/components/Sparkle";
|
|
import {
|
|
getActiveMembersWithCategory,
|
|
getAllCategories,
|
|
getLiveBadgesByMember,
|
|
} from "@/lib/queries";
|
|
import { AnnuaireClient, type DirectoryMember } from "./AnnuaireClient";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
export const metadata: Metadata = {
|
|
title: "Annuaire — Plein R",
|
|
description:
|
|
"L'annuaire des commerçants et entreprises du Bassin de Pompey. Trouvez un professionnel et ses bons plans.",
|
|
};
|
|
|
|
export default async function AnnuairePage({
|
|
searchParams,
|
|
}: {
|
|
searchParams: Promise<{ q?: string }>;
|
|
}) {
|
|
const { q } = await searchParams;
|
|
const [rawMembers, categories, badges] = await Promise.all([
|
|
getActiveMembersWithCategory(),
|
|
getAllCategories(),
|
|
getLiveBadgesByMember(),
|
|
]);
|
|
|
|
const badgeByMember = new Map<number, string | null>();
|
|
for (const b of badges) {
|
|
if (b.memberId != null && !badgeByMember.has(b.memberId)) {
|
|
badgeByMember.set(b.memberId, b.badge);
|
|
}
|
|
}
|
|
|
|
const members: DirectoryMember[] = rawMembers.map((m) => ({
|
|
...m,
|
|
hasPromo: badgeByMember.has(m.id),
|
|
promoBadge: badgeByMember.get(m.id) ?? null,
|
|
}));
|
|
|
|
return (
|
|
<div style={{ background: "#F6F2E8", minHeight: "100vh", fontFamily: "'Public Sans',sans-serif", color: "#33291D" }}>
|
|
{/* header */}
|
|
<header
|
|
className="container"
|
|
style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "18px 56px", gap: 20 }}
|
|
>
|
|
<Link href="/" style={{ display: "flex", alignItems: "center", gap: 10, textDecoration: "none" }}>
|
|
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
<img src="/assets/logo.png" alt="Plein R" style={{ height: 44, width: "auto" }} />
|
|
<span className="font-display" style={{ fontWeight: 800, fontSize: 20, color: "#13324F" }}>
|
|
Plein R
|
|
</span>
|
|
</Link>
|
|
<nav style={{ display: "flex", alignItems: "center", gap: 30, flexWrap: "wrap" }}>
|
|
<Link href="/" style={{ textDecoration: "none", color: "#6f6450", fontWeight: 500, fontSize: 15 }}>
|
|
Accueil
|
|
</Link>
|
|
<Link href="/annuaire" style={{ textDecoration: "none", color: "#3c3322", fontWeight: 600, fontSize: 15 }}>
|
|
Annuaire
|
|
</Link>
|
|
<Link href="/#promotions" style={{ textDecoration: "none", color: "#6f6450", fontWeight: 500, fontSize: 15 }}>
|
|
Promotions
|
|
</Link>
|
|
<Link
|
|
href="/backend"
|
|
style={{ textDecoration: "none", color: "#fff", background: "#9a6638", fontWeight: 600, fontSize: 14.5, padding: "10px 18px", borderRadius: 999 }}
|
|
>
|
|
Espace adhérent
|
|
</Link>
|
|
</nav>
|
|
</header>
|
|
|
|
<div className="container" style={{ paddingBottom: 56 }}>
|
|
{/* title block */}
|
|
<section style={{ position: "relative", padding: "14px 0 22px", overflow: "hidden" }}>
|
|
<Sparkle color="#E0A63C" size={18} style={{ top: 22, right: 30 }} duration={3.2} />
|
|
<Sparkle color="#6FB0C6" size={12} style={{ top: 60, right: 90 }} duration={2.7} delay={0.5} />
|
|
<div
|
|
style={{
|
|
display: "inline-flex",
|
|
alignItems: "center",
|
|
gap: 9,
|
|
background: "#fff",
|
|
border: "1px solid #e6dcc6",
|
|
color: "#9a6638",
|
|
fontSize: 12,
|
|
letterSpacing: "0.12em",
|
|
textTransform: "uppercase",
|
|
fontWeight: 800,
|
|
padding: "6px 13px",
|
|
borderRadius: 999,
|
|
marginBottom: 14,
|
|
}}
|
|
>
|
|
<span style={{ width: 7, height: 7, borderRadius: "50%", background: "#E0A63C" }} />
|
|
{members.length} adhérents
|
|
</div>
|
|
<h1 className="font-display" style={{ fontWeight: 800, fontSize: 40, letterSpacing: "-0.02em", margin: "0 0 8px", color: "#26201a" }}>
|
|
L'annuaire des commerçants & entreprises
|
|
</h1>
|
|
<p style={{ margin: 0, fontSize: 16.5, color: "#6c6150", maxWidth: 560 }}>
|
|
Trouvez un professionnel du Bassin de Pompey, découvrez sa fiche et ses bons plans.
|
|
</p>
|
|
</section>
|
|
|
|
<AnnuaireClient members={members} categories={categories} initialQuery={q ?? ""} />
|
|
|
|
{/* join CTA */}
|
|
<section
|
|
style={{
|
|
marginTop: 34,
|
|
position: "relative",
|
|
background: "linear-gradient(120deg,#13324F,#1d4a72)",
|
|
borderRadius: 20,
|
|
padding: "34px 40px",
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "space-between",
|
|
gap: 28,
|
|
overflow: "hidden",
|
|
flexWrap: "wrap",
|
|
}}
|
|
>
|
|
<Sparkle color="#E0A63C" size={18} style={{ top: 20, right: 40 }} duration={3.2} />
|
|
<div>
|
|
<div style={{ fontSize: 12.5, letterSpacing: "0.12em", textTransform: "uppercase", color: "#9fc6e6", fontWeight: 700, marginBottom: 8 }}>
|
|
Vous n'êtes pas encore référencé ?
|
|
</div>
|
|
<h2 className="font-display" style={{ fontWeight: 800, fontSize: 26, margin: 0, color: "#fff" }}>
|
|
Rejoignez l'annuaire Plein R
|
|
</h2>
|
|
</div>
|
|
<Link
|
|
href="/backend"
|
|
className="font-display"
|
|
style={{ textDecoration: "none", background: "#E0A63C", color: "#33291D", fontWeight: 700, fontSize: 15.5, padding: "14px 26px", borderRadius: 12, whiteSpace: "nowrap" }}
|
|
>
|
|
Adhérer à l'association
|
|
</Link>
|
|
</section>
|
|
</div>
|
|
|
|
{/* footer */}
|
|
<footer style={{ background: "#EFE9DA", borderTop: "1px solid #e2d6bd", padding: "28px 56px" }}>
|
|
<div className="container" style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 16, flexWrap: "wrap" }}>
|
|
<div style={{ display: "flex", alignItems: "center", gap: 10 }}>
|
|
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
<img src="/assets/logo.png" alt="Plein R" style={{ height: 36, width: "auto" }} />
|
|
<span className="font-display" style={{ fontWeight: 800, fontSize: 16, color: "#13324F" }}>
|
|
Plein R
|
|
</span>
|
|
</div>
|
|
<div style={{ fontSize: 13, color: "#8c8068", textAlign: "right", lineHeight: 1.7 }}>
|
|
contact@plein-r.fr · Bassin de Pompey
|
|
<br />
|
|
Réseau · Rencontre · Réussite
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
</div>
|
|
);
|
|
}
|