@@ -48,6 +48,7 @@ type LegendProps = {
|
||||
};
|
||||
|
||||
/** 차트 기본 스타일 */
|
||||
/*
|
||||
const customStyles = {
|
||||
legendContainer: {
|
||||
display: "flex",
|
||||
@@ -58,6 +59,23 @@ const customStyles = {
|
||||
marginTop: "10px",
|
||||
} as CSSProperties,
|
||||
};
|
||||
*/
|
||||
|
||||
/** 차트 기본 스타일 (라인차트와 동일하게) */
|
||||
const customStyles = {
|
||||
legendContainer: {
|
||||
display: "flex",
|
||||
flexWrap: "wrap", // 여러 줄로 자동 줄바꿈
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
gap: "12px", // 아이템 간 간격
|
||||
fontSize: "13px",
|
||||
fontWeight: "normal",
|
||||
marginTop: "16px",
|
||||
marginBottom: "8px",
|
||||
minHeight: "32px", // 범례 영역 높이 통일
|
||||
} as CSSProperties,
|
||||
};
|
||||
|
||||
// 커스텀 툴팁
|
||||
const CustomTooltip = ({ active, payload, label }: {
|
||||
@@ -82,6 +100,7 @@ const CustomTooltip = ({ active, payload, label }: {
|
||||
};
|
||||
|
||||
// 커스텀 범례
|
||||
/*
|
||||
const CustomLegend = (props: LegendProps) => {
|
||||
const { payload } = props;
|
||||
if (!payload) return null;
|
||||
@@ -97,12 +116,52 @@ const CustomLegend = (props: LegendProps) => {
|
||||
</div>
|
||||
);
|
||||
};
|
||||
*/
|
||||
|
||||
const CustomLegend = (props: LegendProps) => {
|
||||
const { payload } = props;
|
||||
if (!payload) return null;
|
||||
|
||||
return (
|
||||
<div style={customStyles.legendContainer}>
|
||||
{payload.map((entry: LegendEntry, index: number) => (
|
||||
<div
|
||||
key={`legend-${index}`}
|
||||
className="flex items-center"
|
||||
style={{
|
||||
minWidth: "90px",
|
||||
margin: "2px 0",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: "14px",
|
||||
height: "14px",
|
||||
backgroundColor: entry.fill,
|
||||
borderRadius: "3px",
|
||||
marginRight: "8px",
|
||||
minWidth: "14px",
|
||||
minHeight: "14px",
|
||||
}}
|
||||
></div>
|
||||
<span style={{ fontSize: "13px", whiteSpace: "nowrap" }}>
|
||||
{entry.payload?.label || entry.value}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default function DoughnutChart(props: {
|
||||
chartConfig: any;
|
||||
chartData: ChartDataItem[] | undefined;
|
||||
chartTitle: string
|
||||
}) {
|
||||
const legendData = props.chartData?.map(item => ({
|
||||
value: item.label,
|
||||
fill: props.chartConfig?.[item.label]?.fill || 'blue',
|
||||
})) ?? [];
|
||||
return (
|
||||
<Card className="flex flex-col">
|
||||
<CardContent className="flex-1 pb-0">
|
||||
@@ -130,9 +189,9 @@ export default function DoughnutChart(props: {
|
||||
nameKey="label"
|
||||
innerRadius={60}
|
||||
/>
|
||||
<CustomLegend />
|
||||
</PieChart>
|
||||
</ChartContainer>
|
||||
<CustomLegend payload={legendData} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
@@ -18,6 +18,7 @@ type LineChartProps = {
|
||||
}
|
||||
|
||||
/** 차트 기본 스타일 */
|
||||
/*
|
||||
const customStyles = {
|
||||
legendContainer: {
|
||||
display: "flex",
|
||||
@@ -28,6 +29,23 @@ const customStyles = {
|
||||
marginTop: "10px",
|
||||
} as CSSProperties,
|
||||
};
|
||||
*/
|
||||
|
||||
/** 차트 기본 스타일 */
|
||||
const customStyles = {
|
||||
legendContainer: {
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
gap: "12px",
|
||||
fontSize: "13px",
|
||||
fontWeight: "normal",
|
||||
marginTop: "16px",
|
||||
marginBottom: "8px",
|
||||
minHeight: "32px",
|
||||
} as CSSProperties,
|
||||
};
|
||||
|
||||
type LegendEntry = {
|
||||
value: string;
|
||||
@@ -60,7 +78,7 @@ const CustomTooltip = ({ active, payload, label }: { active?: boolean; payload?:
|
||||
};
|
||||
|
||||
// 커스텀 범례 (글씨 크기 키우기 + 스타일 추가)
|
||||
const CustomLegend = (props: LegendProps) => {
|
||||
/*const CustomLegend = (props: LegendProps) => {
|
||||
const { payload } = props;
|
||||
if (!payload) return null;
|
||||
|
||||
@@ -74,6 +92,40 @@ const CustomLegend = (props: LegendProps) => {
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};*/
|
||||
|
||||
// 커스텀 범례 (도넛차트와 동일하게)
|
||||
const CustomLegend = (props: LegendProps) => {
|
||||
const { payload } = props;
|
||||
if (!payload) return null;
|
||||
|
||||
return (
|
||||
<div style={customStyles.legendContainer}>
|
||||
{payload.map((entry: LegendEntry, index: number) => (
|
||||
<div
|
||||
key={`legend-${index}`}
|
||||
className="flex items-center"
|
||||
style={{
|
||||
minWidth: "90px",
|
||||
margin: "2px 0",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: "14px",
|
||||
height: "14px",
|
||||
backgroundColor: entry.color,
|
||||
borderRadius: "3px",
|
||||
marginRight: "8px",
|
||||
minWidth: "14px",
|
||||
minHeight: "14px",
|
||||
}}
|
||||
></div>
|
||||
<span style={{ fontSize: "13px", whiteSpace: "nowrap" }}>{entry.value}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
type DataType = {label: string; val: string};
|
||||
@@ -141,7 +193,7 @@ export default function Linechart({
|
||||
>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis dataKey="label" fontSize="8px" fontWeight="bold" />
|
||||
<YAxis yAxisId="left" className="text-[12px] font-bold" domain={[0, Math.ceil(lineMaxValue * 1.1)]} tickCount={6} orientation="left" label={{ value: yFieldText, className:"text-[12px] font-bold", angle: -90, position: 'insideLeft' }} />
|
||||
<YAxis yAxisId="left" className="text-[12px] font-bold" tickFormatter={(value) => value.toLocaleString()} tickCount={6} orientation="left" label={{ value: yFieldText, className:"text-[12px] font-bold", angle: -90, position: 'insideLeft' }} />
|
||||
<Tooltip content={<CustomTooltip />} />
|
||||
{showLegend && <Legend content={CustomLegend as ContentType}/>}
|
||||
{Object.keys(chartData).map((key) => {
|
||||
|
||||
Reference in New Issue
Block a user