import { and, count, desc, eq, gte, inArray, like } from "drizzle-orm"; import { AlertTriangle, Ban as BanIcon, Clock, Gavel, Radio, Shield, User as UserIcon, } from "lucide-react"; import { redirect } from "next/navigation"; import { StatsCard } from "@/components/admin/stats-card"; import Link from "@/components/link"; import { Badge } from "@/components/ui/badge"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { getMinStaffRank } from "@/lib/admin/min-staff-rank"; import { AdminAuditLog, Ban, db, SupportTickets, User } from "@/lib/db"; import { canAccess, getAdminContext, PERMS } from "@/lib/permissions"; const CFH_STATES: Record = { 0: { label: "Open", class: "bg-[var(--admin-error-subtle)] text-[var(--admin-error)]", }, 1: { label: "Picked", class: "bg-[var(--admin-warning-subtle)] text-[var(--admin-warning)]", }, 2: { label: "Closed", class: "bg-muted text-muted-foreground" }, }; export default async function ModerationDashboard() { const { session, permissions } = await getAdminContext(); if (!canAccess(permissions, PERMS.MODERATION_VIEW, session.user.rank)) redirect("/admin"); const now = Math.floor(Date.now() / 1000); const todayStart = now - (now % 86400); const minStaffRank = await getMinStaffRank(); const [ openCfhRows, pickedCfhRows, todayBansRows, modsOnlineRows, recentCfh, recentModActions, ] = await Promise.all([ db .select({ total: count() }) .from(SupportTickets) .where(eq(SupportTickets.state, 0)), db .select({ total: count() }) .from(SupportTickets) .where(eq(SupportTickets.state, 1)), db .select({ total: count() }) .from(Ban) .where(gte(Ban.timestamp, todayStart)), db .select({ total: count() }) .from(User) .where(and(eq(User.online, "1"), gte(User.rank, minStaffRank))), db.select().from(SupportTickets).orderBy(desc(SupportTickets.id)).limit(10), db .select({ id: AdminAuditLog.id, action: AdminAuditLog.action, details: AdminAuditLog.details, createdAt: AdminAuditLog.createdAt, userId: AdminAuditLog.userId, target: AdminAuditLog.target, targetId: AdminAuditLog.targetId, username: User.username, }) .from(AdminAuditLog) .leftJoin(User, eq(AdminAuditLog.userId, User.id)) .where(like(AdminAuditLog.action, "mod_%")) .orderBy(desc(AdminAuditLog.id)) .limit(10), ]); const openCfh = Number(openCfhRows[0]?.total ?? 0); const pickedCfh = Number(pickedCfhRows[0]?.total ?? 0); const todayBans = Number(todayBansRows[0]?.total ?? 0); const modsOnline = Number(modsOnlineRows[0]?.total ?? 0); // Fetch usernames for CFH tickets const userIds = [ ...new Set([ ...recentCfh.map((t) => t.senderId), ...recentCfh.map((t) => t.reportedId), ...recentCfh.map((t) => t.modId), ]), ].filter(Boolean) as number[]; const users = userIds.length > 0 ? await db .select({ id: User.id, username: User.username }) .from(User) .where(inArray(User.id, userIds)) : []; const userMap = new Map(users.map((u) => [u.id, u.username])); return (
{/* Stats */}
} href="/admin/moderation/cfh" /> } href="/admin/bans" /> } href="/admin/moderation/team" /> } href="/admin/moderation/actions" />
{/* Recent CFH */} Recent CFH Tickets View all {recentCfh.length === 0 ? (

No CFH tickets

) : (
{recentCfh.map((ticket) => { const state = CFH_STATES[ticket.state] ?? CFH_STATES[0]; return ( #{ticket.id}

{ticket.issue || "No description"}

{userMap.get(ticket.senderId) ?? "?"} →{" "} {userMap.get(ticket.reportedId) ?? "?"}

{state.label} ); })}
)}
{/* Recent Mod Actions */} Recent Mod Actions {recentModActions.length === 0 ? (

No recent actions

) : (
{recentModActions.map((log) => (

{log.action.replace("mod_", "").replace(/_/g, " ")}

by {log.username ?? "?"} · {log.target}{" "} {log.targetId ? `#${log.targetId}` : ""}

{log.createdAt}
))}
)}
); }