Refactor requests, refactor users, add home dashboard

This commit is contained in:
2026-01-02 00:02:24 +01:00
parent 36fb2358dd
commit 4b308a5c21
20 changed files with 761 additions and 319 deletions

View File

@ -0,0 +1,123 @@
"use server";
import { prisma } from "@/lib/prisma";
type CountRow<K extends string> = {
[P in K]: string;
} & { _count: { _all: number } };
function toCountMapSafe(rows: any[], key: string) {
const out: Record<string, number> = {};
for (const r of rows) out[String(r[key])] = Number(r?._count?._all ?? 0);
return out;
}
export async function getAdminDashboard() {
const now = new Date();
const days = (n: number) => new Date(now.getTime() - n * 24 * 60 * 60 * 1000);
const [
artworkTotal,
artworkPublished,
artworkNeedsWork,
artworkNsfw,
artworkHeader,
colorStatusRows,
recentArtworks,
commissionTotal,
commissionStatusRows,
commissionNew7d,
commissionNew30d,
recentRequests,
userTotal,
userUnverified,
userBanned,
] = await Promise.all([
prisma.artwork.count(),
prisma.artwork.count({ where: { published: true } }),
prisma.artwork.count({ where: { needsWork: true } }),
prisma.artwork.count({ where: { nsfw: true } }),
prisma.artwork.count({ where: { setAsHeader: true } }),
prisma.artwork.groupBy({
by: ["colorStatus"],
_count: { _all: true },
}),
prisma.artwork.findMany({
orderBy: { createdAt: "desc" },
take: 10,
select: {
id: true,
name: true,
slug: true,
createdAt: true,
published: true,
needsWork: true,
colorStatus: true,
},
}),
prisma.commissionRequest.count(),
prisma.commissionRequest.groupBy({
by: ["status"],
_count: { _all: true },
}),
prisma.commissionRequest.count({ where: { createdAt: { gte: days(7) } } }),
prisma.commissionRequest.count({ where: { createdAt: { gte: days(30) } } }),
prisma.commissionRequest.findMany({
orderBy: { createdAt: "desc" },
take: 10,
select: {
id: true,
createdAt: true,
status: true,
customerName: true,
customerEmail: true,
},
}),
prisma.user.count(),
prisma.user.count({ where: { emailVerified: false } }),
prisma.user.count({ where: { banned: true } }),
]);
const colorStatus = toCountMapSafe(colorStatusRows, "colorStatus");
const commissionStatus = toCountMapSafe(commissionStatusRows, "status");
return {
artworks: {
total: artworkTotal,
published: artworkPublished,
unpublished: artworkTotal - artworkPublished,
needsWork: artworkNeedsWork,
nsfw: artworkNsfw,
header: artworkHeader,
colorStatus: {
PENDING: colorStatus.PENDING ?? 0,
PROCESSING: colorStatus.PROCESSING ?? 0,
READY: colorStatus.READY ?? 0,
FAILED: colorStatus.FAILED ?? 0,
},
recent: recentArtworks,
},
commissions: {
total: commissionTotal,
status: {
NEW: commissionStatus.NEW ?? 0,
REVIEWING: commissionStatus.REVIEWING ?? 0,
ACCEPTED: commissionStatus.ACCEPTED ?? 0,
REJECTED: commissionStatus.REJECTED ?? 0,
SPAM: commissionStatus.SPAM ?? 0,
},
new7d: commissionNew7d,
new30d: commissionNew30d,
recent: recentRequests,
},
users: {
total: userTotal,
unverified: userUnverified,
banned: userBanned,
},
};
}