pagamio-frontend-commons-lib
Version:
Pagamio library for Frontend reusable components like the form engine and table container
102 lines (101 loc) • 4.66 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import ReactECharts from 'echarts-for-react';
import { useMemo } from 'react';
import Card from '../components/CardWrapper';
import ChartWrapper from '../components/ChartWrapper';
import { useChartData } from '../hooks/useChartData';
import { DashboardPaths, createTooltipFormatter, processTooltipFields } from '../utils';
const BubbleChart = ({ title, xAxisLabel, yAxisLabel, colorPalette = ['#60A5FA', '#34D399', '#F87171', '#FBBF24', '#A78BFA'], className = '', query, url = DashboardPaths.QUERY, categoryDataKey, xAxisDataKey, yAxisDataKey, sizeDataKey, chartToolTip, tooltipValueFormat, tooltipTitle = 'Value', tooltipUnit = '', tooltipAdditionalFields = [], showDetailsModal = true, ...props }) => {
const { data: transformedData = [], error, isEmpty, loading, refresh, } = useChartData(url, query, (data) => {
return data.map((item) => ({
x: item[xAxisDataKey],
y: item[yAxisDataKey],
size: item[sizeDataKey],
category: item[categoryDataKey],
}));
});
// Get unique categories for legend
const categories = useMemo(() => Array.from(new Set(transformedData.map((item) => item.category))), [transformedData]);
const processedTooltipFields = useMemo(() => processTooltipFields(tooltipAdditionalFields), [tooltipAdditionalFields]);
const tooltipFormatterFn = useMemo(() => {
const currency = Array.isArray(transformedData) && transformedData.length > 0
? transformedData[0].currency
: undefined;
return createTooltipFormatter(tooltipValueFormat, tooltipTitle, tooltipUnit, processedTooltipFields, [], currency);
}, [tooltipValueFormat, tooltipTitle, tooltipUnit, processedTooltipFields, transformedData]);
const chartOptions = useMemo(() => {
if (!transformedData?.length)
return {};
// Calculate size scaling factor based on data
const maxSize = Math.max(...transformedData.map((item) => item.size));
const scaleFactor = 50 / maxSize; // Maximum bubble size of 50px
return {
tooltip: {
formatter: tooltipFormatterFn,
...chartToolTip,
},
legend: {
type: 'scroll',
orient: 'horizontal',
top: title ? '30' : '0',
data: categories,
},
grid: {
left: '5%',
right: '5%',
bottom: '10%',
top: title ? '80' : '60',
containLabel: true,
},
xAxis: {
type: 'value',
name: xAxisLabel,
nameLocation: 'middle',
nameGap: 30,
axisLabel: {
formatter: (value) => value.toLocaleString(),
},
},
yAxis: {
type: 'value',
name: yAxisLabel,
nameLocation: 'middle',
nameGap: 45,
axisLabel: {
formatter: (value) => value.toLocaleString(),
},
},
series: categories.map((category, index) => ({
name: category,
type: 'scatter',
data: transformedData
.filter((item) => item.category === category)
.map((item) => ({
value: [item.x, item.y, item.size],
itemStyle: {
color: colorPalette[index % colorPalette.length],
},
})),
symbolSize: (data) => {
return data[2] * scaleFactor;
},
emphasis: {
focus: 'series',
label: {
show: true,
formatter: (params) => params.data.value[2],
position: 'top',
},
},
})),
aria: {
enabled: true,
decal: {
show: false,
},
},
};
}, [transformedData, title, xAxisLabel, yAxisLabel, categories, colorPalette, tooltipFormatterFn]);
return (_jsx(Card, { title: title, ...props, children: _jsx(ChartWrapper, { loading: loading, error: error, isEmpty: isEmpty, onRetry: refresh, children: _jsx("div", { className: "mt-[19px]", children: _jsx(ReactECharts, { option: chartOptions, style: { height: '350px' }, notMerge: true }) }) }) }));
};
export default BubbleChart;