import Link from "next/link"; import { redirect } from "next/navigation"; import { asc, eq, ilike } from "drizzle-orm"; import { getSession } from "@/lib/session"; import { db } from "@/db"; import { categories, members, users } from "@/db/schema"; import { can } from "@/lib/rbac"; import { AddMemberPanel } from "./AddMemberPanel"; import { BackfillAccountsForm } from "./BackfillAccountsForm"; export const dynamic = "force-dynamic"; function initialsOf(name: string) { return name.split(/\s+/).map((w) => w[0]).join("").slice(0, 2).toUpperCase(); } export default async function AdherentsPage({ searchParams, }: { searchParams: Promise<{ q?: string }>; }) { const session = await getSession(); if (!can(session?.user.role, "manageMembers")) { redirect("/backend"); } const { q } = await searchParams; const search = (q ?? "").trim(); const cats = await db .select({ id: categories.id, label: categories.label }) .from(categories) .orderBy(asc(categories.sort)); const rows = await db .select({ id: members.id, name: members.name, email: members.email, city: members.city, status: members.status, categoryLabel: categories.label, }) .from(members) .leftJoin(categories, eq(members.categoryId, categories.id)) .where(search ? ilike(members.name, `%${search}%`) : undefined) .orderBy(asc(members.name)); // Adhérents sans compte de connexion (créés avant l'arrivée des comptes). const accountRows = await db .select({ email: users.email, memberId: users.memberId }) .from(users); const linkedMemberIds = new Set(accountRows.map((u) => u.memberId).filter((x): x is number => x != null)); const takenEmails = new Set(accountRows.map((u) => u.email.toLowerCase())); const allForCount = await db.select({ id: members.id, email: members.email }).from(members); const missingAccounts = allForCount.filter((m) => { if (linkedMemberIds.has(m.id)) return false; const e = (m.email ?? "").trim().toLowerCase(); return !!e && !takenEmails.has(e); }).length; return (
{missingAccounts > 0 && }
Adhérent
Catégorie
Commune
Statut
Action
{rows.length === 0 && (
Aucun adhérent trouvé.
)} {rows.map((m) => { const active = m.status === "active"; return (
{initialsOf(m.name)}
{m.name}
{m.email}
{m.categoryLabel ?? "—"}
{m.city ?? "—"}
{active ? "Actif" : "En attente"}
Modifier
); })}
); }