78 lines
2.1 KiB
TypeScript
78 lines
2.1 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
|
|
import { BookingStatus, CarbetStatus, UserRole } from "@/generated/prisma/enums";
|
|
import { prisma } from "@/lib/prisma";
|
|
|
|
export const runtime = "nodejs";
|
|
export const dynamic = "force-dynamic";
|
|
|
|
/**
|
|
* Metrics publiques, agrégées (jamais de PII).
|
|
* Format JSON simple — consommable par un script cron ou un dashboard léger.
|
|
*/
|
|
export async function GET() {
|
|
const now = new Date();
|
|
const last24h = new Date(now.getTime() - 86_400_000);
|
|
const last7d = new Date(now.getTime() - 7 * 86_400_000);
|
|
const last30d = new Date(now.getTime() - 30 * 86_400_000);
|
|
|
|
const [
|
|
carbetsPublished,
|
|
carbetsTotal,
|
|
bookings24h,
|
|
bookings7d,
|
|
bookings30d,
|
|
bookingsByStatus,
|
|
usersTotal,
|
|
usersByRole,
|
|
mediaTotal,
|
|
auditLast24h,
|
|
] = await Promise.all([
|
|
prisma.carbet.count({ where: { status: CarbetStatus.PUBLISHED } }),
|
|
prisma.carbet.count(),
|
|
prisma.booking.count({ where: { createdAt: { gte: last24h } } }),
|
|
prisma.booking.count({ where: { createdAt: { gte: last7d } } }),
|
|
prisma.booking.count({ where: { createdAt: { gte: last30d } } }),
|
|
prisma.booking.groupBy({
|
|
by: ["status"],
|
|
_count: { _all: true },
|
|
}),
|
|
prisma.user.count(),
|
|
prisma.user.groupBy({
|
|
by: ["role"],
|
|
_count: { _all: true },
|
|
}),
|
|
prisma.media.count(),
|
|
prisma.auditLog.count({ where: { createdAt: { gte: last24h } } }),
|
|
]);
|
|
|
|
return NextResponse.json({
|
|
generatedAt: now.toISOString(),
|
|
carbets: {
|
|
total: carbetsTotal,
|
|
published: carbetsPublished,
|
|
},
|
|
bookings: {
|
|
last24h: bookings24h,
|
|
last7d: bookings7d,
|
|
last30d: bookings30d,
|
|
byStatus: Object.fromEntries(
|
|
Object.values(BookingStatus).map((s) => [
|
|
s,
|
|
bookingsByStatus.find((b) => b.status === s)?._count._all ?? 0,
|
|
]),
|
|
),
|
|
},
|
|
users: {
|
|
total: usersTotal,
|
|
byRole: Object.fromEntries(
|
|
Object.values(UserRole).map((r) => [
|
|
r,
|
|
usersByRole.find((u) => u.role === r)?._count._all ?? 0,
|
|
]),
|
|
),
|
|
},
|
|
media: { total: mediaTotal },
|
|
audit: { last24h: auditLast24h },
|
|
});
|
|
}
|