Fix observer reports: charts, filtering, project preview, dashboard stats
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m32s

- Rewrite diversity metrics: horizontal bar charts for ocean issues and
  geographic distribution (replaces unreadable vertical/donut charts)
- Rewrite juror score heatmap: expandable table with score distribution
- Rewrite juror consistency: horizontal bar visual with juror names
- Merge filtering tabs into single screening view with per-project
  AI reasoning and expandable rows
- Add project preview dialog for juror performance table
- Fix status breakdown for evaluation rounds (Fully/Partially/Not Reviewed)
- Show active round name instead of count on observer dashboard
- Move Global tab to last position, default to first round-specific tab
- Add 4-card stats layout for evaluation with reviews/project ratio
- Fix oceanIssue field (singular) and remove non-existent aiSummary

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-21 10:12:21 +01:00
parent 2e4b95f29c
commit 161cd1684a
12 changed files with 948 additions and 334 deletions

View File

@@ -129,7 +129,7 @@ function ReportsPageContent() {
const searchParams = useSearchParams()
const roundFromUrl = searchParams.get('round')
const [selectedValue, setSelectedValue] = useState<string | null>(roundFromUrl)
const [activeTab, setActiveTab] = useState('global')
const [activeTab, setActiveTab] = useState<string | null>(null)
const { data: programs, isLoading: stagesLoading } = trpc.program.list.useQuery({ includeStages: true })
@@ -150,9 +150,9 @@ function ReportsPageContent() {
}
}, [stages.length, selectedValue])
// Reset to global tab when round selection changes
// Reset to first round-specific tab when round selection changes
useEffect(() => {
setActiveTab('global')
setActiveTab(null)
}, [selectedValue])
const isAllRounds = selectedValue?.startsWith('all:')
@@ -167,8 +167,8 @@ function ReportsPageContent() {
: getRoundTabs(roundType)
const allTabs: TabDef[] = [
{ value: 'global', label: 'Global', icon: Globe },
...roundSpecificTabs,
{ value: 'global', label: 'Global', icon: Globe },
]
return (
@@ -206,7 +206,7 @@ function ReportsPageContent() {
</div>
{selectedValue && (
<Tabs value={activeTab} onValueChange={setActiveTab} className="space-y-6">
<Tabs value={activeTab ?? allTabs[0]?.value ?? 'global'} onValueChange={setActiveTab} className="space-y-6">
<TabsList>
{allTabs.map((tab) => (
<TabsTrigger key={tab.value} value={tab.value} className="gap-2">