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