'use client' import { ResponsiveBar } from '@nivo/bar' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { nivoTheme, scoreGradient } from './chart-theme' interface ProjectRankingData { id: string title: string teamName: string | null status: string averageScore: number | null evaluationCount: number } interface ProjectRankingsProps { data: ProjectRankingData[] limit?: number } type RankingBarDatum = { project: string score: number fullTitle: string teamName: string evaluationCount: number } export function ProjectRankingsChart({ data, limit = 20, }: ProjectRankingsProps) { const scoredData = data.filter( (d): d is ProjectRankingData & { averageScore: number } => d.averageScore !== null, ) const averageScore = scoredData.length > 0 ? scoredData.reduce((sum, d) => sum + d.averageScore, 0) / scoredData.length : 0 const displayData = scoredData.slice(0, limit) const chartData: RankingBarDatum[] = displayData.map((d) => ({ project: d.title.length > 30 ? d.title.substring(0, 30) + '...' : d.title, score: d.averageScore, fullTitle: d.title, teamName: d.teamName ?? '', evaluationCount: d.evaluationCount, })) return ( Project Rankings Top {displayData.length} of {scoredData.length} scored projects
scoreGradient(bar.data.score as number)} valueScale={{ type: 'linear', max: 10 }} borderRadius={4} enableLabel={true} label={(d) => { const v = d.value return v != null ? Number(v).toFixed(1) : '' }} labelSkipWidth={30} labelTextColor="#ffffff" margin={{ top: 10, right: 30, bottom: 30, left: 200 }} padding={0.2} markers={[ { axis: 'x', value: averageScore, lineStyle: { stroke: '#6b7280', strokeWidth: 2, strokeDasharray: '6 4', }, legend: `Avg: ${averageScore.toFixed(1)}`, legendPosition: 'top', textStyle: { fill: '#6b7280', fontSize: 11, }, }, ]} tooltip={({ data: rowData }) => (
{rowData.fullTitle} {rowData.teamName && ( <>
{rowData.teamName} )}
Score: {Number(rowData.score).toFixed(2)}
Evaluations: {rowData.evaluationCount}
)} animate={true} />
) }