2026-01-30 13:41:32 +01:00
|
|
|
'use client'
|
|
|
|
|
|
Observer platform overhaul: Nivo charts, round-type stats, UX improvements
Phase 1: Fix 6 backend data bugs in analytics.ts (roundName filtering,
unscored projects, criteria scores, activeRoundCount scoping, email
privacy leaks in juror consistency + workload)
Phase 2-3: Migrate all 9 chart components from Recharts to Nivo
(@nivo/bar, @nivo/line, @nivo/pie, @nivo/scatterplot) with shared brand
theme, scoreGradient colors, and STATUS_COLORS map. Fixes scatter plot
outlier coloring and pie chart label visibility bugs.
Phase 4: Add round-type-aware stats (getRoundTypeStats backend +
RoundTypeStatsCards component) showing appropriate metrics per round
type (intake/filtering/evaluation/submission/mentoring/live/deliberation).
Phase 5: UX improvements — Stage→Round terminology, clickable dashboard
round links, URL-based round selection (?round=), round type indicators
in selectors, accessible Toggle-based cross-round comparison, sortable
project table columns (title/score/evaluations), brand score colors on
dashboard bar chart with aria labels.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 21:44:38 +01:00
|
|
|
import { ResponsiveBar } from '@nivo/bar'
|
2026-01-30 13:41:32 +01:00
|
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
Observer platform overhaul: Nivo charts, round-type stats, UX improvements
Phase 1: Fix 6 backend data bugs in analytics.ts (roundName filtering,
unscored projects, criteria scores, activeRoundCount scoping, email
privacy leaks in juror consistency + workload)
Phase 2-3: Migrate all 9 chart components from Recharts to Nivo
(@nivo/bar, @nivo/line, @nivo/pie, @nivo/scatterplot) with shared brand
theme, scoreGradient colors, and STATUS_COLORS map. Fixes scatter plot
outlier coloring and pie chart label visibility bugs.
Phase 4: Add round-type-aware stats (getRoundTypeStats backend +
RoundTypeStatsCards component) showing appropriate metrics per round
type (intake/filtering/evaluation/submission/mentoring/live/deliberation).
Phase 5: UX improvements — Stage→Round terminology, clickable dashboard
round links, URL-based round selection (?round=), round type indicators
in selectors, accessible Toggle-based cross-round comparison, sortable
project table columns (title/score/evaluations), brand score colors on
dashboard bar chart with aria labels.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 21:44:38 +01:00
|
|
|
import { nivoTheme, scoreGradient } from './chart-theme'
|
2026-01-30 13:41:32 +01:00
|
|
|
|
|
|
|
|
interface ScoreDistributionProps {
|
|
|
|
|
data: { score: number; count: number }[]
|
|
|
|
|
averageScore: number
|
|
|
|
|
totalScores: number
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function ScoreDistributionChart({
|
|
|
|
|
data,
|
|
|
|
|
averageScore,
|
|
|
|
|
totalScores,
|
|
|
|
|
}: ScoreDistributionProps) {
|
Observer platform overhaul: Nivo charts, round-type stats, UX improvements
Phase 1: Fix 6 backend data bugs in analytics.ts (roundName filtering,
unscored projects, criteria scores, activeRoundCount scoping, email
privacy leaks in juror consistency + workload)
Phase 2-3: Migrate all 9 chart components from Recharts to Nivo
(@nivo/bar, @nivo/line, @nivo/pie, @nivo/scatterplot) with shared brand
theme, scoreGradient colors, and STATUS_COLORS map. Fixes scatter plot
outlier coloring and pie chart label visibility bugs.
Phase 4: Add round-type-aware stats (getRoundTypeStats backend +
RoundTypeStatsCards component) showing appropriate metrics per round
type (intake/filtering/evaluation/submission/mentoring/live/deliberation).
Phase 5: UX improvements — Stage→Round terminology, clickable dashboard
round links, URL-based round selection (?round=), round type indicators
in selectors, accessible Toggle-based cross-round comparison, sortable
project table columns (title/score/evaluations), brand score colors on
dashboard bar chart with aria labels.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 21:44:38 +01:00
|
|
|
const chartData = data.map((d) => ({
|
|
|
|
|
score: String(d.score),
|
|
|
|
|
count: d.count,
|
|
|
|
|
}))
|
|
|
|
|
|
2026-01-30 13:41:32 +01:00
|
|
|
return (
|
|
|
|
|
<Card>
|
|
|
|
|
<CardHeader>
|
|
|
|
|
<CardTitle className="flex items-center justify-between">
|
|
|
|
|
<span>Score Distribution</span>
|
|
|
|
|
<span className="text-sm font-normal text-muted-foreground">
|
|
|
|
|
Avg: {averageScore.toFixed(2)} ({totalScores} scores)
|
|
|
|
|
</span>
|
|
|
|
|
</CardTitle>
|
|
|
|
|
</CardHeader>
|
|
|
|
|
<CardContent>
|
Observer platform overhaul: Nivo charts, round-type stats, UX improvements
Phase 1: Fix 6 backend data bugs in analytics.ts (roundName filtering,
unscored projects, criteria scores, activeRoundCount scoping, email
privacy leaks in juror consistency + workload)
Phase 2-3: Migrate all 9 chart components from Recharts to Nivo
(@nivo/bar, @nivo/line, @nivo/pie, @nivo/scatterplot) with shared brand
theme, scoreGradient colors, and STATUS_COLORS map. Fixes scatter plot
outlier coloring and pie chart label visibility bugs.
Phase 4: Add round-type-aware stats (getRoundTypeStats backend +
RoundTypeStatsCards component) showing appropriate metrics per round
type (intake/filtering/evaluation/submission/mentoring/live/deliberation).
Phase 5: UX improvements — Stage→Round terminology, clickable dashboard
round links, URL-based round selection (?round=), round type indicators
in selectors, accessible Toggle-based cross-round comparison, sortable
project table columns (title/score/evaluations), brand score colors on
dashboard bar chart with aria labels.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 21:44:38 +01:00
|
|
|
<div style={{ height: '300px' }}>
|
|
|
|
|
<ResponsiveBar
|
|
|
|
|
data={chartData}
|
|
|
|
|
keys={['count']}
|
|
|
|
|
indexBy="score"
|
|
|
|
|
theme={nivoTheme}
|
|
|
|
|
colors={(bar) => scoreGradient(Number(bar.indexValue))}
|
|
|
|
|
borderRadius={4}
|
|
|
|
|
enableLabel={true}
|
|
|
|
|
labelSkipHeight={12}
|
|
|
|
|
labelTextColor="#ffffff"
|
|
|
|
|
axisBottom={{
|
|
|
|
|
legend: 'Score',
|
|
|
|
|
legendPosition: 'middle',
|
|
|
|
|
legendOffset: 36,
|
|
|
|
|
}}
|
|
|
|
|
axisLeft={{
|
|
|
|
|
legend: 'Count',
|
|
|
|
|
legendPosition: 'middle',
|
|
|
|
|
legendOffset: -40,
|
|
|
|
|
}}
|
|
|
|
|
margin={{ top: 20, right: 20, bottom: 50, left: 50 }}
|
|
|
|
|
padding={0.2}
|
|
|
|
|
animate={true}
|
|
|
|
|
/>
|
2026-01-30 13:41:32 +01:00
|
|
|
</div>
|
|
|
|
|
</CardContent>
|
|
|
|
|
</Card>
|
|
|
|
|
)
|
|
|
|
|
}
|