import Link from "next/link"; import { redirect } from "next/navigation"; import { desc, eq } from "drizzle-orm"; import { auth } from "@/auth"; import { db } from "@/db"; import { activityLog, members, membershipRequests, promotions } from "@/db/schema"; import { isStaff } from "@/lib/rbac"; export const dynamic = "force-dynamic"; function StatCard({ label, value, hint, valueColor = "#13324F", hintColor = "#9a8d72", }: { label: string; value: number | string; hint: string; valueColor?: string; hintColor?: string; }) { return (
{label}
{value}
{hint}
); } export default async function DashboardPage() { const session = await auth(); if (!isStaff(session?.user.role)) { redirect("/backend/espace"); } const [activeMembers, livePromos, pendingPromos, requests, activity] = await Promise.all([ db.select({ id: members.id }).from(members).where(eq(members.status, "active")), db.select({ id: promotions.id }).from(promotions).where(eq(promotions.status, "live")), db.select({ id: promotions.id }).from(promotions).where(eq(promotions.status, "pending")), db.select({ id: membershipRequests.id }).from(membershipRequests).where(eq(membershipRequests.status, "new")), db.select().from(activityLog).orderBy(desc(activityLog.createdAt)).limit(6), ]); const pendingCount = pendingPromos.length; function timeAgo(date: Date) { const diff = Date.now() - new Date(date).getTime(); const h = Math.floor(diff / 3_600_000); if (h < 1) return "à l'instant"; if (h < 24) return `il y a ${h} h`; const d = Math.floor(h / 24); return d === 1 ? "hier" : `il y a ${d} j`; } return (

Activité récente

{activity.length === 0 && (
Aucune activité récente.
)} {activity.map((a) => (
{timeAgo(a.createdAt)}
))}

Promotions à modérer

{pendingCount} en attente de validation.

Ouvrir la modération Espace adhérent
); }