import { redirect } from "next/navigation"; import type { CSSProperties } from "react"; import { and, desc, eq } from "drizzle-orm"; import { auth } from "@/auth"; import { db } from "@/db"; import { meetingRegistrations, meetings } from "@/db/schema"; import { can } from "@/lib/rbac"; import { confirmMeetingRegistration, deleteMeetingRegistration, updateMeetingRegistration, } from "../actions"; export const dynamic = "force-dynamic"; function formatDate(date: Date) { return new Intl.DateTimeFormat("fr-FR", { day: "numeric", month: "short", year: "numeric", hour: "2-digit", minute: "2-digit" }).format(date); } export default async function InscriptionsPage({ searchParams }: { searchParams: Promise<{ meeting?: string }> }) { const session = await auth(); if (!can(session?.user.role, "manageMeetings")) redirect("/backend"); const { meeting: meetingParam } = await searchParams; const selectedMeetingId = Number(meetingParam) || null; const [meetingRows, registrationRows] = await Promise.all([ db.select({ id: meetings.id, title: meetings.title, startsAt: meetings.startsAt }).from(meetings).orderBy(desc(meetings.startsAt)), db .select({ id: meetingRegistrations.id, meetingId: meetingRegistrations.meetingId, meetingTitle: meetings.title, meetingStartsAt: meetings.startsAt, attendeeName: meetingRegistrations.attendeeName, attendeeCompany: meetingRegistrations.attendeeCompany, attendeeEmail: meetingRegistrations.attendeeEmail, attendeePhone: meetingRegistrations.attendeePhone, status: meetingRegistrations.status, imageConsent: meetingRegistrations.imageConsent, createdAt: meetingRegistrations.createdAt, }) .from(meetingRegistrations) .innerJoin(meetings, eq(meetings.id, meetingRegistrations.meetingId)) .where(selectedMeetingId ? and(eq(meetingRegistrations.meetingId, selectedMeetingId)) : undefined) .orderBy(desc(meetings.startsAt), desc(meetingRegistrations.createdAt)), ]); return (
Participants
{registrationRows.length} inscription{registrationRows.length > 1 ? "s" : ""} affichée{registrationRows.length > 1 ? "s" : ""}
{registrationRows.map((registration) => (
{registration.attendeeName}
{registration.meetingTitle} · {formatDate(registration.meetingStartsAt)}
{registration.status === "confirmed" ? "Confirmée" : "En attente"} {registration.imageConsent ? "Image autorisée" : "Image refusée"}
{registration.status !== "confirmed" && (
)}
))} {registrationRows.length === 0 &&
Aucune inscription pour cette sélection.
}
); } const sectionLabel: CSSProperties = { fontSize: 12.5, letterSpacing: "0.08em", textTransform: "uppercase", color: "#9a8d72", fontWeight: 800 }; const cardStyle: CSSProperties = { background: "#fff", border: "1px solid #e6dcc6", borderRadius: 8, padding: 20 }; const badgeBase: CSSProperties = { display: "inline-block", borderRadius: 999, padding: "5px 10px", fontSize: 11.5, fontWeight: 800 }; const confirmedBadge: CSSProperties = { ...badgeBase, background: "#e6f4ec", color: "#1f8a5b" }; const pendingBadge: CSSProperties = { ...badgeBase, background: "#fbeede", color: "#9a6638" }; const consentBadge: CSSProperties = { ...badgeBase, background: "#eaf0f6", color: "#2C6FB3" }; const refusalBadge: CSSProperties = { ...badgeBase, background: "#fbe9e6", color: "#d8472b" }; const primaryButton: CSSProperties = { border: "none", background: "#13324F", color: "#fff", borderRadius: 8, padding: "11px 16px", fontWeight: 800, cursor: "pointer" }; const secondaryButton: CSSProperties = { border: "1px solid #d8cdb4", background: "#fff", color: "#6f6450", borderRadius: 8, padding: "11px 16px", fontWeight: 800, cursor: "pointer" }; const confirmButton: CSSProperties = { border: "none", background: "#1f8a5b", color: "#fff", borderRadius: 8, padding: "9px 14px", fontWeight: 800, cursor: "pointer" }; const dangerButton: CSSProperties = { border: "1px solid #e0c3bb", background: "#fff", color: "#d8472b", borderRadius: 8, padding: "8px 13px", fontWeight: 800, cursor: "pointer" }; const emptyStyle: CSSProperties = { background: "#fff", border: "1px solid #e6dcc6", borderRadius: 8, padding: 28, color: "#8c8068", textAlign: "center" };