feat(final-docs): judge-doc curation — reviewVisibleRequirementIds filter, picker helper, admin procedures
- listFinalistDocumentsForReview filters prior-round files by the round's reviewVisibleRequirementIds (finale uploads always shown; null = show all) - listReviewVisibilityOptions: distinct prior-round slots + file counts for the picker - finalist.getReviewDocSettings / setReviewVisibleRequirements (adminProcedure, audited, preserves sibling configJson keys)
This commit is contained in:
@@ -19,7 +19,7 @@ import {
|
||||
resetOrCreatePendingConfirmation,
|
||||
confirmAttendanceInTx,
|
||||
} from '../services/finalist-enrollment'
|
||||
import { sendManualFinalDocReminders, listFinalistDocumentsForReview, userCanReviewFinals } from '../services/final-documents'
|
||||
import { sendManualFinalDocReminders, listFinalistDocumentsForReview, userCanReviewFinals, listReviewVisibilityOptions, reviewVisibleRequirementIds } from '../services/final-documents'
|
||||
|
||||
export const finalistRouter = router({
|
||||
/** List all per-category finalist slot quotas for a program. */
|
||||
@@ -1734,4 +1734,37 @@ export const finalistRouter = router({
|
||||
})
|
||||
return { ok: true, enabled: input.enabled }
|
||||
}),
|
||||
|
||||
/** Options + current selection for the "documents shown to judges" picker. */
|
||||
getReviewDocSettings: adminProcedure
|
||||
.input(z.object({ programId: z.string(), roundId: z.string() }))
|
||||
.query(async ({ ctx, input }) => {
|
||||
const round = await ctx.prisma.round.findUnique({ where: { id: input.roundId }, select: { configJson: true } })
|
||||
return {
|
||||
options: await listReviewVisibilityOptions(ctx.prisma, input.programId),
|
||||
selectedIds: reviewVisibleRequirementIds(round?.configJson ?? null),
|
||||
}
|
||||
}),
|
||||
|
||||
/** Set which prior-round documents finale judges see. null = show all (clears curation). */
|
||||
setReviewVisibleRequirements: adminProcedure
|
||||
.input(z.object({ roundId: z.string(), requirementIds: z.array(z.string()).nullable() }))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const round = await ctx.prisma.round.findUnique({ where: { id: input.roundId }, select: { configJson: true, roundType: true } })
|
||||
if (!round || round.roundType !== 'LIVE_FINAL') {
|
||||
throw new TRPCError({ code: 'BAD_REQUEST', message: 'Not a grand-final round' })
|
||||
}
|
||||
const { reviewVisibleRequirementIds: _omit, ...rest } = (round.configJson ?? {}) as Record<string, unknown>
|
||||
const next = input.requirementIds === null ? rest : { ...rest, reviewVisibleRequirementIds: input.requirementIds }
|
||||
await ctx.prisma.round.update({ where: { id: input.roundId }, data: { configJson: next as object } })
|
||||
await logAudit({
|
||||
prisma: ctx.prisma,
|
||||
userId: ctx.user.id,
|
||||
action: 'FINALIST_REVIEW_DOCS_CURATED',
|
||||
entityType: 'Round',
|
||||
entityId: input.roundId,
|
||||
detailsJson: { requirementIds: input.requirementIds },
|
||||
})
|
||||
return { ok: true }
|
||||
}),
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user