UNPKG

pagamio-frontend-commons-lib

Version:

Pagamio library for Frontend reusable components like the form engine and table container

122 lines (121 loc) 9.67 kB
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; import ReactECharts from 'echarts-for-react'; import { useCallback, useMemo, useState } from 'react'; import Card from '../components/CardWrapper'; import ChartDetailsModal from '../components/ChartDetailsModal'; import ChartWrapper from '../components/ChartWrapper'; import { useChartData } from '../hooks/useChartData'; import { DashboardPaths, createTooltipFormatter, formatDonutChartData, processTooltipFields } from '../utils'; import { getChartBarOptions, getLargeDatasetChartOptions } from '../utils/chartOptions'; // Add sortMetricData function const sortMetricData = (data, valueKey, sortOrder = 'desc') => { return [...data].sort((a, b) => { const aValue = Number(a[valueKey]) || 0; const bValue = Number(b[valueKey]) || 0; return sortOrder === 'asc' ? aValue - bValue : bValue - aValue; }); }; const constructMetricData = (baseData, queryConfig, isEmpty, loading, error, refreshFn) => ({ value: baseData?.[queryConfig.valueKey] ?? 0, previousValue: baseData?.[queryConfig.previousValueKey] ?? 0, change: baseData?.[queryConfig.changeKey] ?? 0, title: queryConfig.title, format: queryConfig.format, isEmpty, loading, error, refresh: () => { refreshFn().catch(() => { }); }, }); const HorizontalBarChart = ({ title, colorScheme = ['#60A5FA', '#93C5FD'], className = '', url = DashboardPaths.QUERY, tooltipValueFormat, query, sortOrder = 'desc', tooltipTitle = 'Value', tooltipUnit = '', tooltipAdditionalFields = [], metricDetailData, ...props }) => { const [isModalOpen, setIsModalOpen] = useState(false); const { data: metricData = [], error, isEmpty, loading, refresh } = useChartData(url, query); const statisticsUrl = metricDetailData?.statisticsUrl ?? DashboardPaths.METRICS; const { data: fullMetricData = [], error: fullDataError, isEmpty: isfullMetricDataEmpty, loading: isLoadingFullMetricData, refresh: refreshFullMetricData, } = useChartData(url, { ...query, limit: undefined, }); const useStatisticData = (queryProps) => { const { data, error, isEmpty, loading, refresh } = useChartData(statisticsUrl, { ...queryProps.query, }); return { data, error, isEmpty, loading, refresh }; }; const { data: itemStatData, error: itemStatDataError, isEmpty: isitemStatMetricDataEmpty, loading: isLoadingItemStatlMetricData, refresh: refreshItemStatMetricData, } = useStatisticData(metricDetailData.itemStatisticsQuery); const { data: valueStatData, error: valueStatDataError, isEmpty: isValueStatMetricDataEmpty, loading: isLoadingValueStatlMetricData, refresh: refreshValueStatMetricData, } = useStatisticData(metricDetailData.valueMetricsQuery); const { data: averageStatData, error: averageStatDataError, isEmpty: isAverageStatMetricDataEmpty, loading: isLoadingAverageStatlMetricData, refresh: refreshAverageStatMetricData, } = useStatisticData(metricDetailData.averageMetricsQuery); const { data: distributionStatData, error: distributionStatDataError, isEmpty: isDistributionStatMetricDataEmpty, loading: isLoadingDistributionStatlMetricData, refresh: refreshDistributionStatMetricData, } = useChartData(url, { ...metricDetailData.distributionMetricsQuery.query, }); const sortedMetricData = useMemo(() => sortMetricData(metricData, metricDetailData.valueKey, sortOrder), [metricData, metricDetailData.valueKey, sortOrder]); const sortedFullMetricData = useMemo(() => sortMetricData(fullMetricData, metricDetailData.valueKey, sortOrder), [fullMetricData, metricDetailData.valueKey, sortOrder]); const processedTooltipFields = useMemo(() => processTooltipFields(tooltipAdditionalFields), [tooltipAdditionalFields]); const tooltipFormatterFn = useMemo(() => createTooltipFormatter(tooltipValueFormat, tooltipTitle, tooltipUnit, processedTooltipFields, metricData), [tooltipTitle, tooltipUnit, processedTooltipFields, metricData]); const createChartOptions = useCallback((data, title, colorScheme, metricDetailData, tooltipConfig) => { const formatterFn = tooltipConfig ? createTooltipFormatter(tooltipValueFormat, tooltipConfig.tooltipTitle ?? tooltipTitle, tooltipConfig.tooltipUnit ?? tooltipUnit, tooltipConfig.tooltipFields ?? processedTooltipFields, tooltipConfig.data ?? data) : tooltipFormatterFn; return getChartBarOptions({ title, colorScheme, yAxisDataNameKey: metricDetailData.yAxisDataNameKey, xAxisNameKey: metricDetailData.xAxisNameKey, xAxisLabel: metricDetailData.xAxisLabel, yAxisLabel: metricDetailData.yAxisLabel, chartToolTip: { ...metricDetailData.chartToolTip, formatter: formatterFn, }, data, }); }, [tooltipFormatterFn, tooltipTitle, tooltipUnit, processedTooltipFields]); const createChartOptionsWithData = useCallback((data, tooltipConfig) => createChartOptions(data, title, colorScheme, metricDetailData, tooltipConfig), [title, colorScheme, metricDetailData, createChartOptions]); const chartBarOptions = useMemo(() => createChartOptionsWithData(sortedMetricData), [sortedMetricData, createChartOptionsWithData]); const fullChartOptions = useMemo(() => createChartOptionsWithData(sortedFullMetricData), [sortedFullMetricData, createChartOptionsWithData]); const { topFiveItems, bottomFiveItems } = useMemo(() => { if (!sortedFullMetricData.length) { return { topFiveItems: [], bottomFiveItems: [], }; } const topFiveMetric = sortedFullMetricData.slice(0, 5); const bottomFiveMetric = sortedFullMetricData.slice(-5).reverse(); return { topFiveItems: createChartOptionsWithData(topFiveMetric, { tooltipTitle: metricDetailData.topFiveChartTitle, tooltipUnit, tooltipFields: processedTooltipFields, data: topFiveMetric, }), bottomFiveItems: createChartOptionsWithData(bottomFiveMetric, { tooltipTitle: metricDetailData.bottomFiveChartTitle, tooltipUnit, tooltipFields: processedTooltipFields, data: bottomFiveMetric, }), }; }, [sortedFullMetricData, createChartOptionsWithData, tooltipUnit, processedTooltipFields]); const distributionMetricData = useMemo(() => { const formattedData = formatDonutChartData(distributionStatData ?? [], metricDetailData.distributionMetricsQuery.xAxisDataValueKey, metricDetailData.distributionMetricsQuery.seriesDataValueKey); const distributionMetricOptions = getLargeDatasetChartOptions({ data: formattedData }); return distributionMetricOptions; }, [ distributionStatData, metricDetailData.distributionMetricsQuery.seriesDataValueKey, metricDetailData.distributionMetricsQuery.xAxisDataValueKey, ]); return (_jsxs(_Fragment, { children: [_jsx(Card, { title: title, ...props, onOpenDetails: metricData ? () => setIsModalOpen(true) : undefined, children: _jsx(ChartWrapper, { loading: loading, error: error, isEmpty: isEmpty, onRetry: refresh, children: _jsx("div", { className: "mt-[19px]", children: _jsx(ReactECharts, { option: chartBarOptions, style: { height: '100%', minHeight: '300px' }, className: "h-[300px] md:h-[400px]", opts: { renderer: 'canvas' }, notMerge: true }) }) }) }), _jsx(ChartDetailsModal, { title: metricDetailData.title, isOpen: isModalOpen, onClose: () => setIsModalOpen(false), data: fullMetricData, columns: metricDetailData.dataGridColumns, error: fullDataError, isEmpty: isfullMetricDataEmpty, loading: isLoadingFullMetricData, detailsTableTitle: metricDetailData.detailsTableTitle, refresh: refreshFullMetricData, renderDetailsChart: fullMetricData.length <= 40, topFivePerformingChartTitle: metricDetailData.topFiveChartTitle, bottomFivePerformingChartTitle: metricDetailData.bottomFiveChartTitle, top5PerformingItems: topFiveItems, bottom5NonPerformingItems: bottomFiveItems, chartData: fullChartOptions, valueKey: metricDetailData.valueKey, dataGridQuery: query, searchKey: metricDetailData.dataGridSearchKey, searchInputPlaceHolder: metricDetailData.dataSearchInputPlaceHolder, itemMetricsData: constructMetricData(itemStatData, metricDetailData.itemStatisticsQuery, isitemStatMetricDataEmpty, isLoadingItemStatlMetricData, itemStatDataError, refreshItemStatMetricData), valueMetricsData: constructMetricData(valueStatData, metricDetailData.valueMetricsQuery, isValueStatMetricDataEmpty, isLoadingValueStatlMetricData, valueStatDataError, refreshValueStatMetricData), averageMetricsData: constructMetricData(averageStatData, metricDetailData.averageMetricsQuery, isAverageStatMetricDataEmpty, isLoadingAverageStatlMetricData, averageStatDataError, refreshAverageStatMetricData), distributionMetricsData: { data: distributionMetricData ?? [], title: metricDetailData.distributionMetricsQuery.title, isEmpty: isDistributionStatMetricDataEmpty, loading: isLoadingDistributionStatlMetricData, error: distributionStatDataError, refresh: () => { refreshDistributionStatMetricData().catch(() => { }); }, chartToolTip: metricDetailData.distributionMetricsQuery.chartToolTip, } })] })); }; export default HorizontalBarChart;