Admin platform audit: fix bugs, harden backend, add auto-refresh, clean dead code
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m23s

Phase 1 — Critical bugs:
- Fix deliberation participant selection (wire jury group query)
- Fix reports "By Round" tab (inline content instead of 404 route)
- Fix messages "Sent History" (add message.sent procedure, wire tab)
- Add missing fields to competition award form (criteriaText, maxRankedPicks)
- Wire LiveControlPanel buttons (cursor, voting, scores)
- Fix ResultLockControls empty snapshot (fetch actual data before lock)
- Fix SubmissionWindowManager losing fields on edit

Phase 2 — Backend fixes:
- Remove write-in-query from specialAward.get
- Fix award eligibility job overwriting manual shortlist overrides
- Fix filtering startJob deleting all prior results (defer cleanup to post-success)
- Tighten access control: protectedProcedure → adminProcedure on 8 procedures
- Add audit logging to deliberation mutations
- Add FINALIST/SEMIFINALIST delete guard on project.delete/bulkDelete

Phase 3 — Auto-refresh:
- Add refetchInterval to 15+ admin pages/components (10s–30s)
- Fix AI job polling: derive speed from job status for all viewers

Phase 4 — Dead code cleanup:
- Delete unused command-palette, pdf-report, admin-page-transition
- Remove dead subItems sidebar code, unused GripVertical import
- Replace redundant isGenerating state with mutation.isPending
- Add Role column to jury members table
- Remove misleading manual mentor assignment stub

Phase 5 — UX improvements:
- Fix rounds page single-competition assumption (add selector)
- Remove raw UUID fallback in deliberation config
- Fix programs page "Stage" → "Round" terminology

Phase 6 — Backend hardening:
- Complete logAudit calls (add prisma, ipAddress, userAgent)
- Batch analytics queries (fix N+1 in getCrossRoundComparison, getYearOverYear)
- Batch user.bulkCreate writes (assignments, jury memberships, intents)
- Remove any casts from deliberation service (typed PrismaClient + TransactionClient)
- Fix stale DeliberationStatus enum values blocking build

40 files changed, 1010 insertions(+), 612 deletions(-)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 08:20:13 +01:00
parent aa1bf564ee
commit 1308c3ba87
40 changed files with 1011 additions and 613 deletions

View File

@@ -122,18 +122,19 @@ export default function RoundsPage() {
const [competitionEdits, setCompetitionEdits] = useState<Record<string, unknown>>({})
const [editingCompId, setEditingCompId] = useState<string | null>(null)
const [filterType, setFilterType] = useState<string>('all')
const [selectedCompId, setSelectedCompId] = useState<string | null>(null)
const { data: competitions, isLoading } = trpc.competition.list.useQuery(
{ programId: programId! },
{ enabled: !!programId }
{ enabled: !!programId, refetchInterval: 30_000 }
)
// Use the first (and usually only) competition
const comp = competitions?.[0]
// Auto-select first competition, or use the user's selection
const comp = competitions?.find((c: any) => c.id === selectedCompId) ?? competitions?.[0]
const { data: compDetail, isLoading: isLoadingDetail } = trpc.competition.getById.useQuery(
{ id: comp?.id! },
{ enabled: !!comp?.id }
{ enabled: !!comp?.id, refetchInterval: 30_000 }
)
const { data: awards } = trpc.specialAward.list.useQuery(
@@ -289,6 +290,22 @@ export default function RoundsPage() {
return (
<TooltipProvider delayDuration={200}>
<div className="space-y-5">
{/* Competition selector (when multiple exist) */}
{competitions && competitions.length > 1 && (
<Select value={comp.id} onValueChange={setSelectedCompId}>
<SelectTrigger className="w-[280px] mb-4">
<SelectValue placeholder="Select competition" />
</SelectTrigger>
<SelectContent>
{competitions.map((c: any) => (
<SelectItem key={c.id} value={c.id}>
{c.name}
</SelectItem>
))}
</SelectContent>
</Select>
)}
{/* ── Header Bar ──────────────────────────────────────────────── */}
<div className="flex items-start justify-between gap-4">
<div className="min-w-0">