UNPKG

@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
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;