Jury management: create, delete, add/remove members from round detail page
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m0s

- Added Jury tab to round detail page with full jury management inline
- Create new jury groups (auto-assigns to current round)
- Delete jury groups with confirmation dialog
- Add/remove members with inline member list
- Assign/switch jury groups via dropdown selector
- Added delete endpoint to juryGroup router (unlinks rounds, deletes members)
- Removed CHAIR/OBSERVER role selectors from add-member dialog (all members)
- Removed role column from jury-members-table

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Matt
2026-02-16 12:46:01 +01:00
parent 86fa542371
commit 763b2ef0f5
4 changed files with 335 additions and 45 deletions

View File

@@ -249,6 +249,50 @@ export const juryGroupRouter = router({
return existing
}),
/**
* Delete a jury group entirely
*/
delete: adminProcedure
.input(z.object({ id: z.string() }))
.mutation(async ({ ctx, input }) => {
const group = await ctx.prisma.juryGroup.findUniqueOrThrow({
where: { id: input.id },
include: {
_count: { select: { assignments: true, rounds: true } },
},
})
// Unlink any rounds that reference this jury group
await ctx.prisma.round.updateMany({
where: { juryGroupId: input.id },
data: { juryGroupId: null },
})
// Delete all members first (cascade should handle this, but be explicit)
await ctx.prisma.juryGroupMember.deleteMany({
where: { juryGroupId: input.id },
})
await ctx.prisma.juryGroup.delete({ where: { id: input.id } })
await logAudit({
prisma: ctx.prisma,
userId: ctx.user.id,
action: 'DELETE',
entityType: 'JuryGroup',
entityId: input.id,
detailsJson: {
name: group.name,
competitionId: group.competitionId,
memberCount: group._count.assignments,
},
ipAddress: ctx.ip,
userAgent: ctx.userAgent,
})
return { success: true, name: group.name }
}),
/**
* Update a jury group member's role/overrides
*/