diff --git a/src/components/LBDashboard/BarGraphs/CompareGraphs.jsx b/src/components/LBDashboard/BarGraphs/CompareGraphs.jsx index 3c8453582f..cd6ef111d7 100644 --- a/src/components/LBDashboard/BarGraphs/CompareGraphs.jsx +++ b/src/components/LBDashboard/BarGraphs/CompareGraphs.jsx @@ -94,6 +94,126 @@ const getVerticalAxes = (nameKey, tickColor, xLabel, yDomain, yTicks, valueForma ), }); +const getChartAxes = ({ + isHorizontal, + tickColor, + valueFormatter, + nameKey, + xLabel, + yLabel, + ...props +}) => + isHorizontal + ? getHorizontalAxes({ + xDomain: props.xDomain, + xTicks: props.xTicks, + valueFormatter, + tickColor, + xLabel, + nameKey, + yCategoryWidth: props.yCategoryWidth, + yTickFormatter: props.yTickFormatter, + showYAxisTitle: props.showYAxisTitle, + yLabel, + }) + : getVerticalAxes( + nameKey, + tickColor, + xLabel, + props.yDomain, + props.yTicks, + valueFormatter, + yLabel, + ); + +const GraphHeader = ({ title, metricLabel, showMetricPill, headerChips, darkMode }) => ( +
+ {title} + {showMetricPill && ( + + {metricLabel} + + )} + +
+ {headerChips.map((chip, index) => ( +
+
+ {chip.label} +
+
+ {String(chip.value).toUpperCase()} +
+
+ ))} +
+
+); + +const NoDataMessage = ({ height, darkMode }) => ( +
+ No data available +
+); + +const CompareChart = ({ + data, + height, + isHorizontal, + margins, + gridColor, + axes, + valueKey, + barColor, + barSize, + valueFormatter, + tooltipLabel, + metricLabel, + title, + darkMode, +}) => ( + + + + {axes.xAxis} + {axes.yAxis} + + [valueFormatter(value), tooltipLabel || metricLabel || title]} + labelFormatter={label => `${label}`} + contentStyle={{ + background: darkMode ? '#1c2541' : '#fff', + border: `1px solid ${darkMode ? '#3a506b' : '#ccc'}`, + color: darkMode ? '#e1e1e1' : '#333', + }} + itemStyle={{ color: darkMode ? '#e1e1e1' : '#333' }} + labelStyle={{ color: darkMode ? '#e1e1e1' : '#333', fontWeight: 600 }} + /> + + + + + + +); + export function CompareBarGraph({ title, metricLabel, @@ -106,7 +226,7 @@ export function CompareBarGraph({ xLabel, yLabel, barColor = '#3b82f6', - valueFormatter = v => v, + valueFormatter = value => value, headerChips = [], xDomain, yDomain, @@ -116,7 +236,6 @@ export function CompareBarGraph({ height = 420, yCategoryWidth = 70, margins = { top: 16, right: 20, bottom: 46, left: 0 }, - maxBars, showYAxisTitle = true, yTickFormatter, darkMode = false, @@ -125,6 +244,22 @@ export function CompareBarGraph({ const tickColor = darkMode ? '#e1e1e1' : '#444'; const gridColor = darkMode ? '#3a506b' : '#e0e0e0'; + const axes = getChartAxes({ + isHorizontal, + tickColor, + valueFormatter, + nameKey, + xLabel, + yLabel, + xDomain, + yDomain, + xTicks, + yTicks, + yCategoryWidth, + yTickFormatter, + showYAxisTitle, + }); + return ( - {/* Title row + chips */} -
- {title} - {showMetricPill && ( - - {metricLabel} - - )} - - {/* chips on the right */} -
- {headerChips.map((c, i) => ( -
-
- {c.label} -
-
- {String(c.value).toUpperCase()} -
-
- ))} -
-
+ - {/* chart */} -
- - + {data?.length ? ( + - - {isHorizontal - ? (() => { - const axes = getHorizontalAxes({ - xDomain, - xTicks, - valueFormatter, - tickColor, - xLabel, - nameKey, - yCategoryWidth, - yTickFormatter, - showYAxisTitle, - yLabel, - }); - return ( - <> - {axes.xAxis} - {axes.yAxis} - - ); - })() - : (() => { - const axes = getVerticalAxes( - nameKey, - tickColor, - xLabel, - yDomain, - yTicks, - valueFormatter, - yLabel, - ); - return ( - <> - {axes.xAxis} - {axes.yAxis} - - ); - })()} - - [valueFormatter(v), tooltipLabel || metricLabel || title]} - labelFormatter={lbl => `${lbl}`} - contentStyle={{ - background: darkMode ? '#1c2541' : '#fff', - border: `1px solid ${darkMode ? '#3a506b' : '#ccc'}`, - color: darkMode ? '#e1e1e1' : '#333', - }} - itemStyle={{ color: darkMode ? '#e1e1e1' : '#333' }} - labelStyle={{ color: darkMode ? '#e1e1e1' : '#333', fontWeight: 600 }} - /> - - - - - + height={height} + isHorizontal={isHorizontal} + margins={margins} + gridColor={gridColor} + axes={axes} + valueKey={valueKey} + barColor={barColor} + barSize={barSize} + valueFormatter={valueFormatter} + tooltipLabel={tooltipLabel} + metricLabel={metricLabel} + title={title} + darkMode={darkMode} + /> + ) : ( + + )}
); } +GraphHeader.propTypes = { + title: PropTypes.string.isRequired, + metricLabel: PropTypes.string, + showMetricPill: PropTypes.bool.isRequired, + headerChips: PropTypes.arrayOf( + PropTypes.shape({ + label: PropTypes.string.isRequired, + value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + }), + ).isRequired, + darkMode: PropTypes.bool.isRequired, +}; + +NoDataMessage.propTypes = { + height: PropTypes.number.isRequired, + darkMode: PropTypes.bool.isRequired, +}; + +CompareChart.propTypes = { + data: PropTypes.arrayOf(PropTypes.object).isRequired, + height: PropTypes.number.isRequired, + isHorizontal: PropTypes.bool.isRequired, + margins: PropTypes.shape({ + top: PropTypes.number, + right: PropTypes.number, + bottom: PropTypes.number, + left: PropTypes.number, + }).isRequired, + gridColor: PropTypes.string.isRequired, + axes: PropTypes.shape({ + xAxis: PropTypes.node.isRequired, + yAxis: PropTypes.node.isRequired, + }).isRequired, + valueKey: PropTypes.string.isRequired, + barColor: PropTypes.string.isRequired, + barSize: PropTypes.number, + valueFormatter: PropTypes.func.isRequired, + tooltipLabel: PropTypes.string, + metricLabel: PropTypes.string, + title: PropTypes.string.isRequired, + darkMode: PropTypes.bool.isRequired, +}; + CompareBarGraph.propTypes = { title: PropTypes.string.isRequired, metricLabel: PropTypes.string, @@ -272,7 +378,6 @@ CompareBarGraph.propTypes = { bottom: PropTypes.number, left: PropTypes.number, }), - maxBars: PropTypes.number, showYAxisTitle: PropTypes.bool, yTickFormatter: PropTypes.func, darkMode: PropTypes.bool, diff --git a/src/components/LBDashboard/LBDashboard.jsx b/src/components/LBDashboard/LBDashboard.jsx index 4c1b5c8f85..7d30af966a 100644 --- a/src/components/LBDashboard/LBDashboard.jsx +++ b/src/components/LBDashboard/LBDashboard.jsx @@ -603,8 +603,8 @@ export function LBDashboard() { {compareType === 'villages' && ( - - + + - + {loadingVillages && (
Loading villages… @@ -636,10 +636,10 @@ export function LBDashboard() { showYAxisTitle={true} yTickFormatter={stripVillageWord} yCategoryWidth={120} - margins={{ top: 60, right: 110, bottom: 50, left: 20 }} + margins={{ top: 40, right: 40, bottom: 50, left: 40 }} barSize={24} maxBars={6} - height={480} + height={420} valueFormatter={valueFormatter} darkMode={darkMode} headerChips={[