import { z } from 'zod' import { TRPCError } from '@trpc/server' import { router, adminProcedure, protectedProcedure, juryProcedure } from '../trpc' import { previewRoundAssignment, executeRoundAssignment, getRoundCoverageReport, getUnassignedQueue, } from '../services/round-assignment' export const roundAssignmentRouter = router({ /** * Preview round assignments without committing */ preview: adminProcedure .input( z.object({ roundId: z.string(), honorIntents: z.boolean().default(true), requiredReviews: z.number().int().min(1).max(20).default(3), }) ) .query(async ({ ctx, input }) => { return previewRoundAssignment( input.roundId, { honorIntents: input.honorIntents, requiredReviews: input.requiredReviews, }, ctx.prisma, ) }), /** * Execute round assignments (create Assignment records) */ execute: adminProcedure .input( z.object({ roundId: z.string(), assignments: z.array( z.object({ userId: z.string(), projectId: z.string(), }) ).min(1), }) ) .mutation(async ({ ctx, input }) => { const result = await executeRoundAssignment( input.roundId, input.assignments, ctx.user.id, ctx.prisma, ) if (result.errors.length > 0 && result.created === 0) { throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: result.errors.join('; '), }) } return result }), /** * Get coverage report for a round */ coverageReport: protectedProcedure .input( z.object({ roundId: z.string(), requiredReviews: z.number().int().min(1).max(20).default(3), }) ) .query(async ({ ctx, input }) => { return getRoundCoverageReport(input.roundId, input.requiredReviews, ctx.prisma) }), /** * Get projects below required reviews threshold */ unassignedQueue: protectedProcedure .input( z.object({ roundId: z.string(), requiredReviews: z.number().int().min(1).max(20).default(3), }) ) .query(async ({ ctx, input }) => { return getUnassignedQueue(input.roundId, input.requiredReviews, ctx.prisma) }), /** * Get assignments for the current jury member in a specific round */ getMyAssignments: juryProcedure .input(z.object({ roundId: z.string() })) .query(async ({ ctx, input }) => { return ctx.prisma.assignment.findMany({ where: { roundId: input.roundId, userId: ctx.user.id, }, include: { project: { select: { id: true, title: true, competitionCategory: true }, }, evaluation: { select: { id: true, status: true, globalScore: true }, }, }, orderBy: { createdAt: 'asc' }, }) }), })