Files
MOPC-Portal/src/components/charts/cross-round-comparison.tsx

170 lines
5.3 KiB
TypeScript
Raw Normal View History

'use client'
import { ResponsiveBar } from '@nivo/bar'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { nivoTheme, BRAND_COLORS } from './chart-theme'
interface StageComparison {
roundId: string
roundName: string
projectCount: number
evaluationCount: number
completionRate: number
averageScore: number | null
scoreDistribution: { score: number; count: number }[]
}
interface CrossStageComparisonProps {
data: StageComparison[]
}
export function CrossStageComparisonChart({
data,
}: CrossStageComparisonProps) {
const baseData = data.map((round) => ({
name:
round.roundName.length > 20
? round.roundName.slice(0, 20) + '...'
: round.roundName,
projects: round.projectCount,
evaluations: round.evaluationCount,
completionRate: round.completionRate,
avgScore: round.averageScore
? parseFloat(round.averageScore.toFixed(2))
: 0,
}))
const sharedMargin = { top: 10, right: 10, bottom: 40, left: 40 }
return (
<Card>
<CardHeader>
<CardTitle>Round Metrics Comparison</CardTitle>
</CardHeader>
<CardContent>
<div className="grid grid-cols-2 gap-4">
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium">Projects</CardTitle>
</CardHeader>
<CardContent className="pt-0">
<div style={{ height: '200px' }}>
<ResponsiveBar
data={baseData}
keys={['projects']}
indexBy="name"
theme={nivoTheme}
colors={[BRAND_COLORS[0]]}
borderRadius={4}
enableLabel={true}
labelSkipHeight={12}
labelTextColor="#ffffff"
margin={sharedMargin}
padding={0.3}
axisBottom={{
tickRotation: -25,
}}
animate={true}
/>
</div>
</CardContent>
</Card>
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium">
Evaluations
</CardTitle>
</CardHeader>
<CardContent className="pt-0">
<div style={{ height: '200px' }}>
<ResponsiveBar
data={baseData}
keys={['evaluations']}
indexBy="name"
theme={nivoTheme}
colors={[BRAND_COLORS[2]]}
borderRadius={4}
enableLabel={true}
labelSkipHeight={12}
labelTextColor="#ffffff"
margin={sharedMargin}
padding={0.3}
axisBottom={{
tickRotation: -25,
}}
animate={true}
/>
</div>
</CardContent>
</Card>
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium">
Completion Rate
</CardTitle>
</CardHeader>
<CardContent className="pt-0">
<div style={{ height: '200px' }}>
<ResponsiveBar
data={baseData}
keys={['completionRate']}
indexBy="name"
theme={nivoTheme}
colors={[BRAND_COLORS[1]]}
valueScale={{ type: 'linear', max: 100 }}
borderRadius={4}
enableLabel={true}
labelSkipHeight={12}
labelTextColor="#ffffff"
valueFormat={(v) => `${v}%`}
margin={sharedMargin}
padding={0.3}
axisBottom={{
tickRotation: -25,
}}
axisLeft={{
format: (v) => `${v}%`,
}}
animate={true}
/>
</div>
</CardContent>
</Card>
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium">
Average Score
</CardTitle>
</CardHeader>
<CardContent className="pt-0">
<div style={{ height: '200px' }}>
<ResponsiveBar
data={baseData}
keys={['avgScore']}
indexBy="name"
theme={nivoTheme}
colors={[BRAND_COLORS[0]]}
valueScale={{ type: 'linear', max: 10 }}
borderRadius={4}
enableLabel={true}
labelSkipHeight={12}
labelTextColor="#ffffff"
margin={sharedMargin}
padding={0.3}
axisBottom={{
tickRotation: -25,
}}
animate={true}
/>
</div>
</CardContent>
</Card>
</div>
</CardContent>
</Card>
)
}