55 lines
1.8 KiB
TypeScript
55 lines
1.8 KiB
TypeScript
import { usePrisma } from "../../utils/prisma";
|
|
|
|
/** GET /api/admin/stats — Übersicht-Statistiken fürs Dashboard */
|
|
export default defineEventHandler(async (event) => {
|
|
const config = useRuntimeConfig();
|
|
const secret = getHeader(event, "x-admin-secret");
|
|
if (!config.adminSecret || secret !== config.adminSecret) {
|
|
throw createError({ statusCode: 401, message: "Unauthorized" });
|
|
}
|
|
|
|
const db = usePrisma();
|
|
const now = new Date();
|
|
const last7d = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
|
|
const last30d = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
|
|
|
|
const [
|
|
totalUsers,
|
|
newUsersWeek,
|
|
totalPosts,
|
|
newPostsWeek,
|
|
pendingDomains,
|
|
approvedDomains,
|
|
pendingFeedback,
|
|
totalFeedback,
|
|
lyraPosts,
|
|
] = await Promise.all([
|
|
db.profile.count(),
|
|
db.profile.count({ where: { createdAt: { gte: last7d } } }),
|
|
db.communityPost.count({ where: { isModerated: false } }),
|
|
db.communityPost.count({
|
|
where: { isModerated: false, createdAt: { gte: last7d } },
|
|
}),
|
|
db.domainSubmission.count({ where: { status: "pending" } }),
|
|
db.domainSubmission.count({ where: { status: "approved" } }),
|
|
db.feedbackItem.count({ where: { status: "PENDING" } }).catch(() => 0),
|
|
db.feedbackItem.count().catch(() => 0),
|
|
db.communityPost
|
|
.count({
|
|
where: {
|
|
userId: config.lyraBotUserId || undefined,
|
|
createdAt: { gte: last30d },
|
|
},
|
|
})
|
|
.catch(() => 0),
|
|
]);
|
|
|
|
return {
|
|
users: { total: totalUsers, newThisWeek: newUsersWeek },
|
|
posts: { total: totalPosts, newThisWeek: newPostsWeek },
|
|
domains: { pending: pendingDomains, approved: approvedDomains },
|
|
feedback: { pending: pendingFeedback, total: totalFeedback },
|
|
lyra: { postsLast30d: lyraPosts },
|
|
};
|
|
});
|