UNPKG

@pagamio/frontend-commons-lib

Version:

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

132 lines (131 loc) 8.81 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, processTooltipFields } from '../utils'; import { createDistributionMetricOptions, getGroupedChartOptions } from '../utils/chartOptions'; const useMetricData = (url, queryConfig) => { const { data, error, isEmpty, loading, refresh } = useChartData(url, { ...queryConfig.query, }); return { metricData: { value: data?.[queryConfig.valueKey] ?? 0, previousValue: queryConfig.previousValueKey ? (data?.[queryConfig.previousValueKey] ?? 0) : undefined, change: data?.[queryConfig.changeKey] ?? 0, title: queryConfig.title, format: queryConfig.format, isEmpty, loading, error, refresh: () => refresh().catch(() => { }), currency: data?.additionalData?.currency, }, data, error, isEmpty, loading, refresh, }; }; const GroupedBarChart = ({ title, className = '', url = DashboardPaths.QUERY, query, xAxisLabel, xAxisValueKey, leftYAxisValueKey, rightYAxisValueKey, tooltipValueFormat, chartToolTip, tooltipTitle = 'Value', tooltipUnit = '', tooltipAdditionalFields = [], yAxisLabelFormatter, metricDetailData, showDetailsModal = true, ...props }) => { const [isModalOpen, setIsModalOpen] = useState(false); const { data: metricData = [], error, isEmpty, loading, refresh } = useChartData(url, query); const statisticsUrl = metricDetailData?.statisticsUrl ?? DashboardPaths.METRICS; const processedTooltipFields = useMemo(() => processTooltipFields(tooltipAdditionalFields), [tooltipAdditionalFields]); const processedDistributionTooltipFields = useMemo(() => processTooltipFields(metricDetailData.distributionChartTooltip.tooltipAdditionalFields), [metricDetailData.distributionChartTooltip.tooltipAdditionalFields]); const tooltipFormatterFn = useMemo(() => createTooltipFormatter(tooltipValueFormat, tooltipTitle, tooltipUnit, processedTooltipFields, metricData, metricData[0]?.currency), [tooltipTitle, tooltipUnit, processedTooltipFields, metricData, tooltipValueFormat]); const createChartOptions = useCallback((data, title, metricDetailData, tooltipConfig) => { const tooltipFields = tooltipConfig?.tooltipFields ? processTooltipFields(tooltipConfig.tooltipFields) : processTooltipFields(processedTooltipFields); const formatterFn = tooltipConfig ? createTooltipFormatter(tooltipValueFormat, tooltipConfig.tooltipTitle ?? tooltipTitle, tooltipConfig.tooltipUnit ?? tooltipUnit, tooltipFields, tooltipConfig.data ?? data, tooltipConfig.data?.[0]?.currency ?? data[0]?.currency) : tooltipFormatterFn; return getGroupedChartOptions({ leftYAxisValueKey: leftYAxisValueKey, rightYAxisValueKey: rightYAxisValueKey, xAxisValueKey: xAxisValueKey, xAxisLabel: xAxisLabel, chartToolTip: { ...chartToolTip, formatter: formatterFn, }, data, yAxisLabelFormatter, }); }, [ tooltipFormatterFn, tooltipTitle, tooltipUnit, processedTooltipFields, chartToolTip, tooltipValueFormat, yAxisLabelFormatter, ]); const createChartOptionsWithData = useCallback((data, tooltipConfig) => createChartOptions(data, title, metricDetailData, tooltipConfig), [title, metricDetailData, createChartOptions]); const chartOptions = useMemo(() => createChartOptionsWithData(metricData), [metricData, createChartOptionsWithData]); const { metricData: itemMetricsData } = useMetricData(statisticsUrl, metricDetailData.itemStatisticsQuery); const { metricData: valueMetricsData } = useMetricData(statisticsUrl, metricDetailData.valueMetricsQuery); const { metricData: averageMetricsData } = useMetricData(statisticsUrl, metricDetailData.averageMetricsQuery); const { data: fullMetricData = [], error: fullDataError, isEmpty: isfullMetricDataEmpty, loading: isLoadingFullMetricData, refresh: refreshFullMetricData, } = useChartData(url, { ...query, limit: undefined, }); const fullChartOptions = useMemo(() => createChartOptionsWithData(fullMetricData), [fullMetricData, createChartOptionsWithData]); const { data: distributionStatData, error: distributionStatDataError, isEmpty: isDistributionStatMetricDataEmpty, loading: isLoadingDistributionStatlMetricData, refresh: refreshDistributionStatMetricData, } = useChartData(url, { ...metricDetailData.distributionMetricsQuery.query, }); const distributionMetricData = useMemo(() => { return createDistributionMetricOptions({ distributionChartTooltip: metricDetailData.distributionChartTooltip, distributionData: distributionStatData ?? [], processedTooltipFields: processedDistributionTooltipFields, xAxisDataValueKey: metricDetailData.distributionMetricsQuery.xAxisDataValueKey, seriesDataValueKey: metricDetailData.distributionMetricsQuery.seriesDataValueKey, }); }, [ distributionStatData, metricDetailData.distributionMetricsQuery.seriesDataValueKey, metricDetailData.distributionMetricsQuery.xAxisDataValueKey, metricDetailData.distributionChartTooltip, processedDistributionTooltipFields, ]); const { topFiveItems, bottomFiveItems } = useMemo(() => { if (!fullMetricData || fullMetricData.length === 0) { return { topFiveItems: [], bottomFiveItems: [], }; } const topFiveMetric = fullMetricData.slice(0, 5); const bottomFiveMetric = fullMetricData.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, }), }; }, [fullMetricData, createChartOptionsWithData, tooltipUnit, processedTooltipFields, metricDetailData]); 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: chartOptions, style: { height: '100%', minHeight: '340px' }, className: "h-[340px] md:h-[400px]", opts: { renderer: 'canvas' }, notMerge: true }) }) }) }), showDetailsModal && (_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, top5PerformingItems: topFiveItems, bottom5NonPerformingItems: bottomFiveItems, chartData: fullChartOptions, valueKey: metricDetailData.valueKey, dataGridQuery: query, searchKey: metricDetailData.dataGridSearchKey, searchInputPlaceHolder: metricDetailData.dataSearchInputPlaceHolder, itemMetricsData: itemMetricsData, valueMetricsData: valueMetricsData, averageMetricsData: averageMetricsData, distributionMetricsData: { data: distributionMetricData ?? [], title: metricDetailData.distributionMetricsQuery.title, isEmpty: isDistributionStatMetricDataEmpty, loading: isLoadingDistributionStatlMetricData, error: distributionStatDataError, refresh: () => refreshDistributionStatMetricData().catch(() => { }), chartToolTip: metricDetailData.distributionMetricsQuery.chartToolTip, } }))] })); }; export default GroupedBarChart;