102 lines
1.8 KiB
TypeScript
102 lines
1.8 KiB
TypeScript
'use client'
|
|
|
|
import {
|
|
Chart as ChartJS,
|
|
CategoryScale,
|
|
LinearScale,
|
|
RadialLinearScale,
|
|
BarElement,
|
|
PointElement,
|
|
LineElement,
|
|
ArcElement,
|
|
Tooltip,
|
|
Legend,
|
|
Title,
|
|
} from 'chart.js'
|
|
import { Line, Bar, Radar, Doughnut, PolarArea, Bubble, Pie, Scatter } from 'react-chartjs-2'
|
|
import { useMemo } from 'react'
|
|
|
|
ChartJS.register(
|
|
CategoryScale,
|
|
LinearScale,
|
|
RadialLinearScale,
|
|
BarElement,
|
|
PointElement,
|
|
LineElement,
|
|
ArcElement,
|
|
Tooltip,
|
|
Legend,
|
|
Title
|
|
)
|
|
|
|
type ChartType = 'bar' | 'line' | 'pie' | 'doughnut' | 'radar'
|
|
|
|
type ChartProps = {
|
|
type: ChartType
|
|
labels: string[]
|
|
datasets: {
|
|
label: string
|
|
data: number[]
|
|
backgroundColor?: string | string[]
|
|
borderColor?: string
|
|
borderWidth?: number
|
|
}[]
|
|
title?: string
|
|
height?: number
|
|
hideLabels?: boolean
|
|
}
|
|
|
|
export default function Chart({
|
|
type,
|
|
labels,
|
|
datasets,
|
|
title,
|
|
height = 300,
|
|
hideLabels
|
|
}: ChartProps) {
|
|
const data = useMemo(() => ({ labels, datasets }), [labels, datasets])
|
|
|
|
const options = useMemo(
|
|
() => ({
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
legend: {
|
|
display: !hideLabels,
|
|
position: 'top' as const,
|
|
},
|
|
title: {
|
|
display: !!title,
|
|
text: title,
|
|
},
|
|
},
|
|
scales: hideLabels
|
|
? {
|
|
x: { display: false },
|
|
y: { display: false },
|
|
}
|
|
: undefined,
|
|
}),
|
|
[title, hideLabels]
|
|
)
|
|
|
|
const chartMap = {
|
|
line: Line,
|
|
bar: Bar,
|
|
radar: Radar,
|
|
doughnut: Doughnut,
|
|
polararea: PolarArea,
|
|
bubble: Bubble,
|
|
pie: Pie,
|
|
scatter: Scatter,
|
|
}
|
|
|
|
const ChartComponent = chartMap[type]
|
|
|
|
return (
|
|
<div style={{ height }}>
|
|
<ChartComponent data={data} options={options} />
|
|
</div>
|
|
)
|
|
}
|