Files
MOPC-Portal/src/components/charts/status-breakdown.tsx

78 lines
2.2 KiB
TypeScript
Raw Normal View History

'use client'
import { ResponsivePie } from '@nivo/pie'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { nivoTheme, getStatusColor, formatStatus } from './chart-theme'
interface StatusDataPoint {
status: string
count: number
}
interface StatusBreakdownProps {
data: StatusDataPoint[]
}
export function StatusBreakdownChart({ data }: StatusBreakdownProps) {
const total = data.reduce((sum, item) => sum + item.count, 0)
const pieData = data.map((d) => ({
id: d.status,
label: formatStatus(d.status),
value: d.count,
color: getStatusColor(d.status),
}))
return (
<Card>
<CardHeader>
<CardTitle className="flex items-center justify-between">
<span>Project Status Distribution</span>
<span className="text-sm font-normal text-muted-foreground">
{total} projects
</span>
</CardTitle>
</CardHeader>
<CardContent>
<div style={{ height: '300px' }}>
<ResponsivePie
data={pieData}
theme={nivoTheme}
colors={{ datum: 'data.color' }}
innerRadius={0.5}
padAngle={0.7}
cornerRadius={3}
activeOuterRadiusOffset={8}
margin={{ top: 40, right: 80, bottom: 80, left: 80 }}
enableArcLinkLabels={true}
arcLinkLabelsSkipAngle={10}
arcLinkLabelsTextColor="#374151"
arcLinkLabelsThickness={2}
arcLinkLabelsColor={{ from: 'color' }}
enableArcLabels={true}
arcLabelsSkipAngle={10}
arcLabelsTextColor={{ from: 'color', modifiers: [['darker', 2]] }}
legends={[
{
anchor: 'bottom',
direction: 'row',
justify: false,
translateX: 0,
translateY: 56,
itemsSpacing: 0,
itemWidth: 100,
itemHeight: 18,
itemTextColor: '#374151',
itemDirection: 'left-to-right',
itemOpacity: 1,
symbolSize: 12,
symbolShape: 'circle',
},
]}
/>
</div>
</CardContent>
</Card>
)
}