97 lines
2.5 KiB
TypeScript
97 lines
2.5 KiB
TypeScript
'use client';
|
|
|
|
import React from 'react';
|
|
import {
|
|
PieChart,
|
|
Pie,
|
|
Cell,
|
|
Tooltip,
|
|
Legend,
|
|
ResponsiveContainer
|
|
} from 'recharts';
|
|
import { ChartConfig } from '../types';
|
|
|
|
interface PieChartComponentProps {
|
|
data: any[];
|
|
config: ChartConfig;
|
|
width?: number;
|
|
height?: number;
|
|
}
|
|
|
|
/**
|
|
* 원형 차트 컴포넌트
|
|
* - Recharts PieChart 사용
|
|
* - 자동 색상 배치 및 레이블
|
|
*/
|
|
export function PieChartComponent({ data, config, width = 250, height = 200 }: PieChartComponentProps) {
|
|
const {
|
|
xAxis = 'x',
|
|
yAxis = 'y',
|
|
colors = ['#3B82F6', '#EF4444', '#10B981', '#F59E0B', '#8B5CF6', '#EC4899', '#06B6D4', '#84CC16'],
|
|
title,
|
|
showLegend = true
|
|
} = config;
|
|
|
|
// 파이 차트용 데이터 변환
|
|
const pieData = data.map((item, index) => ({
|
|
name: String(item[xAxis] || `항목 ${index + 1}`),
|
|
value: Number(item[yAxis]) || 0,
|
|
color: colors[index % colors.length]
|
|
})).filter(item => item.value > 0); // 0보다 큰 값만 표시
|
|
|
|
// 커스텀 레이블 함수
|
|
const renderLabel = (entry: any) => {
|
|
const percent = ((entry.value / pieData.reduce((sum, item) => sum + item.value, 0)) * 100).toFixed(1);
|
|
return `${percent}%`;
|
|
};
|
|
|
|
return (
|
|
<div className="w-full h-full p-2">
|
|
{title && (
|
|
<div className="text-center text-sm font-semibold text-gray-700 mb-2">
|
|
{title}
|
|
</div>
|
|
)}
|
|
|
|
<ResponsiveContainer width="100%" height="100%">
|
|
<PieChart>
|
|
<Pie
|
|
data={pieData}
|
|
cx="50%"
|
|
cy="50%"
|
|
labelLine={false}
|
|
label={renderLabel}
|
|
outerRadius={Math.min(width, height) * 0.3}
|
|
fill="#8884d8"
|
|
dataKey="value"
|
|
>
|
|
{pieData.map((entry, index) => (
|
|
<Cell key={`cell-${index}`} fill={entry.color} />
|
|
))}
|
|
</Pie>
|
|
|
|
<Tooltip
|
|
contentStyle={{
|
|
backgroundColor: 'white',
|
|
border: '1px solid #ccc',
|
|
borderRadius: '4px',
|
|
fontSize: '12px'
|
|
}}
|
|
formatter={(value: any, name: string) => [
|
|
typeof value === 'number' ? value.toLocaleString() : value,
|
|
name
|
|
]}
|
|
/>
|
|
|
|
{showLegend && (
|
|
<Legend
|
|
wrapperStyle={{ fontSize: '12px' }}
|
|
iconType="circle"
|
|
/>
|
|
)}
|
|
</PieChart>
|
|
</ResponsiveContainer>
|
|
</div>
|
|
);
|
|
}
|