import Link from "next/link"; import { sql, eq } from "drizzle-orm"; import { db } from "@/db/client"; import { listings, reports, users, emailDeliveries, auditEvents } from "@/db/schema"; import { Stat } from "@/components/ui"; import { fmtInt } from "@/lib/format"; import { meta } from "@/lib/db"; export const dynamic = "force-dynamic"; export default async function AdminHome() { const d = db(); const [[l], [r], [u], [m], [a]] = await Promise.all([ d.select({ pending: sql`sum(case when status='PENDING_REVIEW' then 1 else 0 end)::int`, published: sql`sum(case when status='PUBLISHED' then 1 else 0 end)::int`, total: sql`count(*)::int` }).from(listings), d.select({ open: sql`count(*)::int` }).from(reports).where(eq(reports.status, "OPEN")), d.select({ n: sql`count(*)::int`, d7: sql`sum(case when created_at > now() - interval '7 days' then 1 else 0 end)::int` }).from(users), d.select({ n: sql`count(*)::int`, failed: sql`sum(case when status='FAILED' then 1 else 0 end)::int`, mocked: sql`sum(case when status='MOCKED' then 1 else 0 end)::int` }).from(emailDeliveries).where(sql`created_at > now() - interval '7 days'`), d.select({ n: sql`count(*)::int` }).from(auditEvents).where(sql`created_at > now() - interval '24 hours'`), ]); return (

Tableau de bord

Sources et synchronisation

Base canonique construite le {meta("built_at") ?? "—"} · {fmtInt(Number(meta("listings_sale")))} à vendre · {fmtInt(Number(meta("listings_rent")))} à louer · {fmtInt(Number(meta("properties")))} propriétés · {fmtInt(Number(meta("valuations")))} valuations. Journal : data/sync.log sur le nœud.

{!process.env.RESEND_API_KEY &&

RESEND_API_KEY absente : les courriels sont simulés (data/outbox/mails.jsonl). Configurer une clé et vérifier le domaine d'envoi avant l'ouverture publique des comptes.

}
); }