Files
frontend/apps/sn/app/(with-base-layout)/ii/test/page_bar.tsx
T

143 lines
3.5 KiB
TypeScript

"use client";
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend,
type ChartOptions,
} from "chart.js";
import { Bar } from "react-chartjs-2";
import { Card, CardHeader, CardTitle, CardContent } from "@common/business_components/ui/chart/lib/card";
import { Button } from "@common/components";
// ChartJS 컴포넌트 등록
ChartJS.register(
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend
);
export default function TestPage() {
// 차트 데이터
const labels = ["한강", "낙동강", "영산강", "금강"];
const datasets = [
{
label: '20-25년',
data: [3859, 1066, 1929, 2828],
backgroundColor: '#3B82F6', // 파란색
borderRadius: 4,
},
{
label: '25년-30년',
data: [3153, 1420, 1204, 2877],
backgroundColor: '#EF4444', // 빨간색
borderRadius: 4,
},
{
label: '30년이상',
data: [9404, 1835, 1821, 8115],
backgroundColor: '#F87171', // 연한 빨간색/분홍색
borderRadius: 4,
},
];
// 각 지역별 총 길이 계산
const totalLengths = [44251, 33786, 11888, 14878];
// 차트 옵션 설정
const options: ChartOptions<"bar"> = {
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
grid: {
display: true,
},
},
y: {
beginAtZero: true,
min: 0,
max: 10000,
ticks: {
stepSize: 2000,
callback: function(value) {
return value + 'km';
}
},
grid: {
color: 'rgba(200, 200, 200, 0.3)',
}
}
},
plugins: {
legend: {
position: 'top',
align: 'start',
labels: {
boxWidth: 15,
padding: 15,
usePointStyle: false,
},
},
tooltip: {
callbacks: {
label: function(context) {
return `${context.dataset.label}: ${context.parsed.y}km`;
}
}
},
},
// 총 길이 데이터 표시를 위한 애니메이션 후 함수 설정
animation: {
onComplete: function(animation) {
const chart = animation.chart;
const ctx = chart.ctx;
// 각 데이터셋의 마지막 데이터셋의 인덱스
const lastDatasetIndex = datasets.length - 1;
// 텍스트 스타일 설정
ctx.font = '11px Arial';
ctx.fillStyle = '#333';
ctx.textAlign = 'center';
// 각 지역별로 총 길이 표시
labels.forEach((_, i) => {
const xPos = chart.scales.x ? chart.scales.x.getPixelForTick(i) : 0;
const yPos = chart.chartArea.top; // 차트 영역 최상단 위에 표시
// 막대 위에 총 길이 텍스트 표시
if (totalLengths[i]) ctx.fillText(`총 ${totalLengths[i].toLocaleString()}km`, xPos, yPos);
});
}
}
};
const data = {
labels,
datasets,
};
return (
<Card className="w-full">
<CardHeader className="flex flex-row items-center justify-between pb-2">
<CardTitle className="text-base">노후하수관로현황</CardTitle>
<Button size="sm">더보기</Button>
</CardHeader>
<CardContent className="pb-4">
{/* 너비 400px, 높이 150px로 조정 */}
<div className="w-[400px] h-[150px] mx-auto">
<Bar options={options} data={data} />
</div>
</CardContent>
</Card>
);
}