From ef1bf24388dc63ce44f6bfb21746ccc440051f38 Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 17 Feb 2026 12:33:20 +0100 Subject: [PATCH] Fix evaluation criteria, jury preferences, assignment config, and dashboard stats - Fix criteria not showing for jurors: fetch active form independently via getStageForm query instead of relying on existing evaluation record - Fix scoringMode default from 'global' to 'criteria' (matching schema) - Parse scale string format ("1-10") into minScore/maxScore for criteria display - Fix COI dialog dismissal: prevent outside click on evaluate page Dialog - Fix requiredReviews hardcoded to 3: read from round configJson in 4 locations - Add jury preferences banner for unconfirmed caps on jury dashboard - Add updateJuryPreferences tRPC procedure for self-service cap/ratio - Simplify onboarding: always show jury step, allow cap up to 50 - Add role/ratio/availability fields to jury member invite dialog - Simplify jury group settings (keep only defaultMaxAssignments) - Enforce deliberation showCollectiveRankings flag for non-admin users - Redesign dashboard stat cards: editorial data strip on mobile, clean grid layout on desktop (no more generic card pattern) Co-Authored-By: Claude Opus 4.6 --- .../[competitionId]/assignments/page.tsx | 16 +- .../(admin)/admin/juries/[groupId]/page.tsx | 113 ++----------- .../(admin)/admin/rounds/[roundId]/page.tsx | 73 +++++--- src/app/(auth)/onboarding/page.tsx | 96 +++++------ .../projects/[projectId]/evaluate/page.tsx | 46 +++-- src/app/(jury)/jury/page.tsx | 4 + .../assignment/assignment-preview-sheet.tsx | 4 +- .../admin/assignment/coverage-report.tsx | 7 +- .../admin/jury/add-member-dialog.tsx | 112 +++++++++++- .../dashboard/round-stats-evaluation.tsx | 153 +++++++---------- .../dashboard/round-stats-filtering.tsx | 160 ++++++++---------- .../dashboard/round-stats-generic.tsx | 154 +++++++---------- .../dashboard/round-stats-intake.tsx | 155 ++++++++--------- src/components/jury/preferences-banner.tsx | 144 ++++++++++++++++ src/server/routers/deliberation.ts | 34 +++- src/server/routers/user.ts | 78 +++++---- 16 files changed, 761 insertions(+), 588 deletions(-) create mode 100644 src/components/jury/preferences-banner.tsx diff --git a/src/app/(admin)/admin/competitions/[competitionId]/assignments/page.tsx b/src/app/(admin)/admin/competitions/[competitionId]/assignments/page.tsx index fc070c4..4991a1f 100644 --- a/src/app/(admin)/admin/competitions/[competitionId]/assignments/page.tsx +++ b/src/app/(admin)/admin/competitions/[competitionId]/assignments/page.tsx @@ -30,9 +30,16 @@ export default function AssignmentsDashboardPage() { id: competitionId, }) + const { data: selectedRound } = trpc.round.getById.useQuery( + { id: selectedRoundId }, + { enabled: !!selectedRoundId } + ) + + const requiredReviews = (selectedRound?.configJson as Record)?.requiredReviewsPerProject as number || 3 + const { data: unassignedQueue, isLoading: isLoadingQueue } = trpc.roundAssignment.unassignedQueue.useQuery( - { roundId: selectedRoundId, requiredReviews: 3 }, + { roundId: selectedRoundId, requiredReviews }, { enabled: !!selectedRoundId } ) @@ -111,7 +118,7 @@ export default function AssignmentsDashboardPage() { - + @@ -119,7 +126,7 @@ export default function AssignmentsDashboardPage() { Unassigned Projects - Projects with fewer than 3 assignments + Projects with fewer than {requiredReviews} assignments @@ -143,7 +150,7 @@ export default function AssignmentsDashboardPage() {

- {project.assignmentCount || 0} / 3 assignments + {project.assignmentCount || 0} / {requiredReviews} assignments
))} @@ -162,6 +169,7 @@ export default function AssignmentsDashboardPage() { roundId={selectedRoundId} open={previewSheetOpen} onOpenChange={setPreviewSheetOpen} + requiredReviews={requiredReviews} /> )} diff --git a/src/app/(admin)/admin/juries/[groupId]/page.tsx b/src/app/(admin)/admin/juries/[groupId]/page.tsx index c1ece75..54efaac 100644 --- a/src/app/(admin)/admin/juries/[groupId]/page.tsx +++ b/src/app/(admin)/admin/juries/[groupId]/page.tsx @@ -33,7 +33,6 @@ import { DialogTitle, } from '@/components/ui/dialog' import { Textarea } from '@/components/ui/textarea' -import { Switch } from '@/components/ui/switch' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { Table, @@ -523,11 +522,6 @@ function SettingsForm({ group, onSave, isPending }: SettingsFormProps) { name: group.name, description: group.description || '', defaultMaxAssignments: group.defaultMaxAssignments, - defaultCapMode: group.defaultCapMode, - softCapBuffer: group.softCapBuffer, - categoryQuotasEnabled: group.categoryQuotasEnabled, - allowJurorCapAdjustment: group.allowJurorCapAdjustment, - allowJurorRatioAdjustment: group.allowJurorRatioAdjustment, }) const handleSubmit = (e: React.FormEvent) => { @@ -562,99 +556,20 @@ function SettingsForm({ group, onSave, isPending }: SettingsFormProps) { /> -
-
- - - setFormData({ ...formData, defaultMaxAssignments: parseInt(e.target.value, 10) }) - } - /> -
- -
- - -
-
- - {formData.defaultCapMode === 'SOFT' && ( -
- - - setFormData({ ...formData, softCapBuffer: parseInt(e.target.value, 10) }) - } - /> -

- Number of assignments allowed above the cap when in soft mode -

-
- )} - -
-
-
- -

- Enable category-based assignment quotas -

-
- - setFormData({ ...formData, categoryQuotasEnabled: checked }) - } - /> -
- -
-
- -

- Allow jurors to set their own assignment cap during onboarding -

-
- - setFormData({ ...formData, allowJurorCapAdjustment: checked }) - } - /> -
- -
-
- -

- Allow jurors to set their own startup/concept ratio during onboarding -

-
- - setFormData({ ...formData, allowJurorRatioAdjustment: checked }) - } - /> -
+
+ + + setFormData({ ...formData, defaultMaxAssignments: parseInt(e.target.value, 10) || 15 }) + } + /> +

+ Suggested cap for new members. Per-member overrides and juror self-service preferences take priority. +

+ {autosaveStatus === 'saving' && ( + + + Saving... + + )} + {autosaveStatus === 'saved' && ( + + + Saved + + )} + {autosaveStatus === 'error' && ( + + + Save failed + )}
+
+ + +