[WEB-4877] fix: webapp crash because of bar chart (#7763)

* 🔧 fix: dynamic bar color handling and refactored color retrieval logic.

* ♻️  refactor: updated any to Record in getBarColor
This commit is contained in:
Jayash Tripathy
2025-09-10 17:44:52 +05:30
committed by GitHub
parent ac835bf287
commit 0f7bfdde91

View File

@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
"use client";
import React, { useMemo, useState } from "react";
import React, { useCallback, useMemo, useState } from "react";
import {
BarChart as CoreBarChart,
Bar,
@@ -21,6 +21,8 @@ import { CustomXAxisTick, CustomYAxisTick } from "../components/tick";
import { CustomTooltip } from "../components/tooltip";
import { barShapeVariants } from "./bar";
const DEFAULT_BAR_FILL_COLOR = "#000000";
export const BarChart = React.memo(<K extends string, T extends string>(props: TBarChartProps<K, T>) => {
const {
data,
@@ -44,21 +46,55 @@ export const BarChart = React.memo(<K extends string, T extends string>(props: T
const [activeLegend, setActiveLegend] = useState<string | null>(null);
// derived values
const { stackKeys, stackLabels, stackDotColors } = useMemo(() => {
const { stackKeys, stackLabels } = useMemo(() => {
const keys: string[] = [];
const labels: Record<string, string> = {};
const colors: Record<string, string> = {};
for (const bar of bars) {
keys.push(bar.key);
labels[bar.key] = bar.label;
// For tooltip, we need a string color. If fill is a function, use a default color
colors[bar.key] = typeof bar.fill === "function" ? bar.fill({}) : bar.fill;
}
return { stackKeys: keys, stackLabels: labels, stackDotColors: colors };
return { stackKeys: keys, stackLabels: labels };
}, [bars]);
// get bar color dynamically based on payload
const getBarColor = useCallback(
(payload: Record<string, string>[], barKey: string) => {
const bar = bars.find((b) => b.key === barKey);
if (!bar) return DEFAULT_BAR_FILL_COLOR;
if (typeof bar.fill === "function") {
const payloadItem = payload?.find((item) => item.dataKey === barKey);
if (payloadItem?.payload) {
try {
return bar.fill(payloadItem.payload);
} catch (error) {
console.error(error);
return DEFAULT_BAR_FILL_COLOR;
}
} else {
return DEFAULT_BAR_FILL_COLOR; // fallback color when no payload data
}
} else {
return bar.fill;
}
},
[bars]
);
// get all bar colors
const getAllBarColors = useCallback(
(payload: any[]) => {
const colors: Record<string, string> = {};
for (const bar of bars) {
colors[bar.key] = getBarColor(payload, bar.key);
}
return colors;
},
[bars, getBarColor]
);
const renderBars = useMemo(
() =>
bars.map((bar) => (
@@ -66,7 +102,6 @@ export const BarChart = React.memo(<K extends string, T extends string>(props: T
key={bar.key}
dataKey={bar.key}
stackId={bar.stackId}
fill={typeof bar.fill === "function" ? bar.fill({}) : bar.fill}
opacity={!!activeLegend && activeLegend !== bar.key ? 0.1 : 1}
shape={(shapeProps: any) => {
const shapeVariant = barShapeVariants[bar.shapeVariant ?? "bar"];
@@ -158,7 +193,7 @@ export const BarChart = React.memo(<K extends string, T extends string>(props: T
activeKey={activeBar}
itemKeys={stackKeys}
itemLabels={stackLabels}
itemDotColors={stackDotColors}
itemDotColors={getAllBarColors(payload || [])}
/>
);
}}