Admin system overhaul: full round config UI, flattened navigation, juries, awards integration, evaluation rewrite
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m23s
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m23s
- Phase 1: 7 round config sub-components covering all ~65 Zod schema fields across INTAKE, FILTERING, EVALUATION, SUBMISSION, MENTORING, LIVE_FINAL, DELIBERATION - Phase 2: Replace Competitions nav with Rounds + add Juries; new /admin/rounds and /admin/rounds/[roundId] pages with tabbed detail (Config, Projects, Windows, Documents, Awards) - Phase 3: Top-level /admin/juries with list + detail pages (members table, settings panel, self-service review) - Phase 4: File requirements editor in round config; project detail per-requirement upload slots replacing generic drop zone - Phase 5: Awards edit page with source round dropdown, eligibility mode, auto-tag rules builder; round detail Awards tab; specialAward router enhanced with evaluationRoundId/eligibilityMode fields - Phase 6: Evaluation page rewrite supporting all 3 scoring modes (criteria/global/binary) with config-driven behavior; live voting UI polish - Phase 7: UI design polish across admin pages — consistent headers, cards, hover transitions, empty states, brand colors - Bulk upload page for admin project imports - File router enhanced with admin upload and submission window procedures Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -58,6 +58,15 @@ export const specialAwardRouter = router({
|
||||
program: {
|
||||
select: { id: true, name: true, year: true },
|
||||
},
|
||||
competition: {
|
||||
select: { id: true, name: true, rounds: { select: { id: true, name: true, roundType: true, sortOrder: true }, orderBy: { sortOrder: 'asc' } } },
|
||||
},
|
||||
evaluationRound: {
|
||||
select: { id: true, name: true, roundType: true },
|
||||
},
|
||||
awardJuryGroup: {
|
||||
select: { id: true, name: true },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -85,6 +94,10 @@ export const specialAwardRouter = router({
|
||||
scoringMode: z.enum(['PICK_WINNER', 'RANKED', 'SCORED']),
|
||||
maxRankedPicks: z.number().int().min(1).max(20).optional(),
|
||||
autoTagRulesJson: z.record(z.unknown()).optional(),
|
||||
competitionId: z.string().optional(),
|
||||
evaluationRoundId: z.string().optional(),
|
||||
juryGroupId: z.string().optional(),
|
||||
eligibilityMode: z.enum(['STAY_IN_MAIN', 'SEPARATE_POOL']).optional(),
|
||||
})
|
||||
)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
@@ -104,6 +117,10 @@ export const specialAwardRouter = router({
|
||||
scoringMode: input.scoringMode,
|
||||
maxRankedPicks: input.maxRankedPicks,
|
||||
autoTagRulesJson: input.autoTagRulesJson as Prisma.InputJsonValue ?? undefined,
|
||||
competitionId: input.competitionId,
|
||||
evaluationRoundId: input.evaluationRoundId,
|
||||
juryGroupId: input.juryGroupId,
|
||||
eligibilityMode: input.eligibilityMode,
|
||||
sortOrder: (maxOrder._max.sortOrder || 0) + 1,
|
||||
},
|
||||
})
|
||||
@@ -140,6 +157,10 @@ export const specialAwardRouter = router({
|
||||
autoTagRulesJson: z.record(z.unknown()).optional(),
|
||||
votingStartAt: z.date().optional(),
|
||||
votingEndAt: z.date().optional(),
|
||||
competitionId: z.string().nullable().optional(),
|
||||
evaluationRoundId: z.string().nullable().optional(),
|
||||
juryGroupId: z.string().nullable().optional(),
|
||||
eligibilityMode: z.enum(['STAY_IN_MAIN', 'SEPARATE_POOL']).optional(),
|
||||
})
|
||||
)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
|
||||
Reference in New Issue
Block a user