66 lines
1.7 KiB
TypeScript
66 lines
1.7 KiB
TypeScript
'use client'
|
|
|
|
import { BarChart } from '@tremor/react'
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
|
|
|
interface ProjectRankingData {
|
|
id: string
|
|
title: string
|
|
teamName: string | null
|
|
status: string
|
|
averageScore: number | null
|
|
evaluationCount: number
|
|
}
|
|
|
|
interface ProjectRankingsProps {
|
|
data: ProjectRankingData[]
|
|
limit?: number
|
|
}
|
|
|
|
export function ProjectRankingsChart({
|
|
data,
|
|
limit = 20,
|
|
}: ProjectRankingsProps) {
|
|
const scoredData = (data ?? []).filter(
|
|
(d): d is ProjectRankingData & { averageScore: number } =>
|
|
d.averageScore !== null,
|
|
)
|
|
|
|
if (!scoredData.length) return null
|
|
|
|
const displayData = scoredData.slice(0, limit)
|
|
|
|
const chartData = displayData.map((d) => ({
|
|
project:
|
|
d.title.length > 30 ? d.title.substring(0, 30) + '...' : d.title,
|
|
Score: parseFloat(d.averageScore.toFixed(2)),
|
|
}))
|
|
|
|
return (
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center justify-between">
|
|
<span>Project Rankings</span>
|
|
<span className="text-sm font-normal text-muted-foreground">
|
|
Top {displayData.length} of {scoredData.length} scored projects
|
|
</span>
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<BarChart
|
|
data={chartData}
|
|
index="project"
|
|
categories={['Score']}
|
|
colors={['blue']}
|
|
layout="horizontal"
|
|
yAxisWidth={200}
|
|
maxValue={10}
|
|
showLegend={false}
|
|
className={`h-[${Math.max(400, displayData.length * 30)}px]`}
|
|
style={{ height: `${Math.max(400, displayData.length * 30)}px` }}
|
|
/>
|
|
</CardContent>
|
|
</Card>
|
|
)
|
|
}
|