import { z } from 'zod' import { router, adminProcedure } from '../trpc' export const dashboardRouter = router({ /** * Get all dashboard stats in a single query batch. * Replaces the 16 parallel Prisma queries that were previously * run during SSR, which blocked the event loop and caused 503s. */ getStats: adminProcedure .input(z.object({ editionId: z.string() })) .query(async ({ ctx, input }) => { const { editionId } = input const edition = await ctx.prisma.program.findUnique({ where: { id: editionId }, select: { name: true, year: true }, }) if (!edition) return null const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) const [ activeRoundCount, totalRoundCount, projectCount, newProjectsThisWeek, totalJurors, activeJurors, evaluationStats, totalAssignments, recentRounds, latestProjects, categoryBreakdown, oceanIssueBreakdown, recentActivity, pendingCOIs, draftRounds, unassignedProjects, ] = await Promise.all([ ctx.prisma.round.count({ where: { programId: editionId, status: 'ACTIVE' }, }), ctx.prisma.round.count({ where: { programId: editionId }, }), ctx.prisma.project.count({ where: { programId: editionId }, }), ctx.prisma.project.count({ where: { programId: editionId, createdAt: { gte: sevenDaysAgo }, }, }), ctx.prisma.user.count({ where: { role: 'JURY_MEMBER', status: { in: ['ACTIVE', 'INVITED', 'NONE'] }, assignments: { some: { round: { programId: editionId } } }, }, }), ctx.prisma.user.count({ where: { role: 'JURY_MEMBER', status: 'ACTIVE', assignments: { some: { round: { programId: editionId } } }, }, }), ctx.prisma.evaluation.groupBy({ by: ['status'], where: { assignment: { round: { programId: editionId } } }, _count: true, }), ctx.prisma.assignment.count({ where: { round: { programId: editionId } }, }), ctx.prisma.round.findMany({ where: { programId: editionId }, orderBy: { createdAt: 'desc' }, take: 5, select: { id: true, name: true, status: true, votingStartAt: true, votingEndAt: true, submissionEndDate: true, _count: { select: { projects: true, assignments: true, }, }, assignments: { select: { evaluation: { select: { status: true } }, }, }, }, }), ctx.prisma.project.findMany({ where: { programId: editionId }, orderBy: { createdAt: 'desc' }, take: 8, select: { id: true, title: true, teamName: true, country: true, competitionCategory: true, oceanIssue: true, logoKey: true, createdAt: true, submittedAt: true, status: true, round: { select: { name: true } }, }, }), ctx.prisma.project.groupBy({ by: ['competitionCategory'], where: { programId: editionId }, _count: true, }), ctx.prisma.project.groupBy({ by: ['oceanIssue'], where: { programId: editionId }, _count: true, }), ctx.prisma.auditLog.findMany({ where: { timestamp: { gte: sevenDaysAgo }, }, orderBy: { timestamp: 'desc' }, take: 8, select: { id: true, action: true, entityType: true, timestamp: true, user: { select: { name: true } }, }, }), ctx.prisma.conflictOfInterest.count({ where: { hasConflict: true, reviewedAt: null, assignment: { round: { programId: editionId } }, }, }), ctx.prisma.round.count({ where: { programId: editionId, status: 'DRAFT' }, }), ctx.prisma.project.count({ where: { programId: editionId, round: { status: 'ACTIVE' }, assignments: { none: {} }, }, }), ]) return { edition, activeRoundCount, totalRoundCount, projectCount, newProjectsThisWeek, totalJurors, activeJurors, evaluationStats, totalAssignments, recentRounds, latestProjects, categoryBreakdown, oceanIssueBreakdown, recentActivity, pendingCOIs, draftRounds, unassignedProjects, } }), })