Skip to content

Commit 9d4e3a3

Browse files
Merge pull request #5298 from OneCommunityGlobal/Neeraj_Fix_Demand_Across_Villages_Graph
Neeraj Fix Demand Across Villages Graph Rendering Issue
2 parents 504885d + d5d524c commit 9d4e3a3

2 files changed

Lines changed: 212 additions & 107 deletions

File tree

src/components/LBDashboard/BarGraphs/CompareGraphs.jsx

Lines changed: 207 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,126 @@ const getVerticalAxes = (nameKey, tickColor, xLabel, yDomain, yTicks, valueForma
9494
),
9595
});
9696

97+
const getChartAxes = ({
98+
isHorizontal,
99+
tickColor,
100+
valueFormatter,
101+
nameKey,
102+
xLabel,
103+
yLabel,
104+
...props
105+
}) =>
106+
isHorizontal
107+
? getHorizontalAxes({
108+
xDomain: props.xDomain,
109+
xTicks: props.xTicks,
110+
valueFormatter,
111+
tickColor,
112+
xLabel,
113+
nameKey,
114+
yCategoryWidth: props.yCategoryWidth,
115+
yTickFormatter: props.yTickFormatter,
116+
showYAxisTitle: props.showYAxisTitle,
117+
yLabel,
118+
})
119+
: getVerticalAxes(
120+
nameKey,
121+
tickColor,
122+
xLabel,
123+
props.yDomain,
124+
props.yTicks,
125+
valueFormatter,
126+
yLabel,
127+
);
128+
129+
const GraphHeader = ({ title, metricLabel, showMetricPill, headerChips, darkMode }) => (
130+
<div
131+
className={styles.graphTitle}
132+
style={{ display: 'flex', alignItems: 'center', color: darkMode ? '#e1e1e1' : undefined }}
133+
>
134+
<span style={{ flex: 1 }}>{title}</span>
135+
{showMetricPill && (
136+
<span className={styles.metricPill} style={{ marginRight: 12 }}>
137+
{metricLabel}
138+
</span>
139+
)}
140+
141+
<div style={{ display: 'flex', gap: 16 }}>
142+
{headerChips.map((chip, index) => (
143+
<div key={`${chip.label}-${chip.value}`} style={{ textAlign: 'center', lineHeight: 1.1 }}>
144+
<div style={{ fontSize: 12, fontWeight: 600, color: darkMode ? '#e1e1e1' : undefined }}>
145+
{chip.label}
146+
</div>
147+
<div style={{ fontSize: 11, color: darkMode ? '#a0b0c8' : '#777', letterSpacing: 0.2 }}>
148+
{String(chip.value).toUpperCase()}
149+
</div>
150+
</div>
151+
))}
152+
</div>
153+
</div>
154+
);
155+
156+
const NoDataMessage = ({ height, darkMode }) => (
157+
<div
158+
style={{
159+
height,
160+
display: 'flex',
161+
alignItems: 'center',
162+
justifyContent: 'center',
163+
color: darkMode ? '#e1e1e1' : '#666',
164+
}}
165+
>
166+
No data available
167+
</div>
168+
);
169+
170+
const CompareChart = ({
171+
data,
172+
height,
173+
isHorizontal,
174+
margins,
175+
gridColor,
176+
axes,
177+
valueKey,
178+
barColor,
179+
barSize,
180+
valueFormatter,
181+
tooltipLabel,
182+
metricLabel,
183+
title,
184+
darkMode,
185+
}) => (
186+
<ResponsiveContainer width="100%" height={height}>
187+
<BarChart data={data} layout={isHorizontal ? 'vertical' : 'horizontal'} margin={margins}>
188+
<CartesianGrid strokeDasharray="3 3" stroke={gridColor} />
189+
{axes.xAxis}
190+
{axes.yAxis}
191+
192+
<Tooltip
193+
formatter={value => [valueFormatter(value), tooltipLabel || metricLabel || title]}
194+
labelFormatter={label => `${label}`}
195+
contentStyle={{
196+
background: darkMode ? '#1c2541' : '#fff',
197+
border: `1px solid ${darkMode ? '#3a506b' : '#ccc'}`,
198+
color: darkMode ? '#e1e1e1' : '#333',
199+
}}
200+
itemStyle={{ color: darkMode ? '#e1e1e1' : '#333' }}
201+
labelStyle={{ color: darkMode ? '#e1e1e1' : '#333', fontWeight: 600 }}
202+
/>
203+
204+
<Bar dataKey={valueKey} radius={[4, 4, 4, 4]} fill={barColor} barSize={barSize}>
205+
<LabelList
206+
dataKey={valueKey}
207+
position={isHorizontal ? 'right' : 'top'}
208+
formatter={valueFormatter}
209+
style={{ fontSize: 15, fontWeight: 600 }}
210+
offset={8}
211+
/>
212+
</Bar>
213+
</BarChart>
214+
</ResponsiveContainer>
215+
);
216+
97217
export function CompareBarGraph({
98218
title,
99219
metricLabel,
@@ -106,7 +226,7 @@ export function CompareBarGraph({
106226
xLabel,
107227
yLabel,
108228
barColor = '#3b82f6',
109-
valueFormatter = v => v,
229+
valueFormatter = value => value,
110230
headerChips = [],
111231
xDomain,
112232
yDomain,
@@ -116,7 +236,6 @@ export function CompareBarGraph({
116236
height = 420,
117237
yCategoryWidth = 70,
118238
margins = { top: 16, right: 20, bottom: 46, left: 0 },
119-
maxBars,
120239
showYAxisTitle = true,
121240
yTickFormatter,
122241
darkMode = false,
@@ -125,6 +244,22 @@ export function CompareBarGraph({
125244
const tickColor = darkMode ? '#e1e1e1' : '#444';
126245
const gridColor = darkMode ? '#3a506b' : '#e0e0e0';
127246

247+
const axes = getChartAxes({
248+
isHorizontal,
249+
tickColor,
250+
valueFormatter,
251+
nameKey,
252+
xLabel,
253+
yLabel,
254+
xDomain,
255+
yDomain,
256+
xTicks,
257+
yTicks,
258+
yCategoryWidth,
259+
yTickFormatter,
260+
showYAxisTitle,
261+
});
262+
128263
return (
129264
<Card
130265
className={`${styles.graphCard} ${darkMode ? styles.darkCard : ''}`}
@@ -133,113 +268,84 @@ export function CompareBarGraph({
133268
}
134269
>
135270
<CardBody className={`${styles.graphCardBody} ${darkMode ? styles.darkCardBody : ''}`}>
136-
{/* Title row + chips */}
137-
<div
138-
className={styles.graphTitle}
139-
style={{ display: 'flex', alignItems: 'center', color: darkMode ? '#e1e1e1' : undefined }}
140-
>
141-
<span style={{ flex: 1 }}>{title}</span>
142-
{showMetricPill && (
143-
<span className={styles.metricPill} style={{ marginRight: 12 }}>
144-
{metricLabel}
145-
</span>
146-
)}
147-
148-
{/* chips on the right */}
149-
<div style={{ display: 'flex', gap: 16 }}>
150-
{headerChips.map((c, i) => (
151-
<div key={i} style={{ textAlign: 'center', lineHeight: 1.1 }}>
152-
<div
153-
style={{ fontSize: 12, fontWeight: 600, color: darkMode ? '#e1e1e1' : undefined }}
154-
>
155-
{c.label}
156-
</div>
157-
<div
158-
style={{ fontSize: 11, color: darkMode ? '#a0b0c8' : '#777', letterSpacing: 0.2 }}
159-
>
160-
{String(c.value).toUpperCase()}
161-
</div>
162-
</div>
163-
))}
164-
</div>
165-
</div>
271+
<GraphHeader
272+
title={title}
273+
metricLabel={metricLabel}
274+
showMetricPill={showMetricPill}
275+
headerChips={headerChips}
276+
darkMode={darkMode}
277+
/>
166278

167-
{/* chart */}
168-
<div className={styles.graphCanvas}>
169-
<ResponsiveContainer width="100%" height={height}>
170-
<BarChart
279+
<div className={styles.graphCanvas} style={{ width: '100%', minHeight: `${height}px` }}>
280+
{data?.length ? (
281+
<CompareChart
171282
data={data}
172-
layout={isHorizontal ? 'vertical' : 'horizontal'}
173-
margin={margins}
174-
>
175-
<CartesianGrid strokeDasharray="3 3" stroke={gridColor} />
176-
{isHorizontal
177-
? (() => {
178-
const axes = getHorizontalAxes({
179-
xDomain,
180-
xTicks,
181-
valueFormatter,
182-
tickColor,
183-
xLabel,
184-
nameKey,
185-
yCategoryWidth,
186-
yTickFormatter,
187-
showYAxisTitle,
188-
yLabel,
189-
});
190-
return (
191-
<>
192-
{axes.xAxis}
193-
{axes.yAxis}
194-
</>
195-
);
196-
})()
197-
: (() => {
198-
const axes = getVerticalAxes(
199-
nameKey,
200-
tickColor,
201-
xLabel,
202-
yDomain,
203-
yTicks,
204-
valueFormatter,
205-
yLabel,
206-
);
207-
return (
208-
<>
209-
{axes.xAxis}
210-
{axes.yAxis}
211-
</>
212-
);
213-
})()}
214-
215-
<Tooltip
216-
formatter={v => [valueFormatter(v), tooltipLabel || metricLabel || title]}
217-
labelFormatter={lbl => `${lbl}`}
218-
contentStyle={{
219-
background: darkMode ? '#1c2541' : '#fff',
220-
border: `1px solid ${darkMode ? '#3a506b' : '#ccc'}`,
221-
color: darkMode ? '#e1e1e1' : '#333',
222-
}}
223-
itemStyle={{ color: darkMode ? '#e1e1e1' : '#333' }}
224-
labelStyle={{ color: darkMode ? '#e1e1e1' : '#333', fontWeight: 600 }}
225-
/>
226-
<Bar dataKey={valueKey} radius={[4, 4, 4, 4]} fill={barColor} barSize={barSize}>
227-
<LabelList
228-
dataKey={valueKey}
229-
position={isHorizontal ? 'right' : 'top'}
230-
formatter={valueFormatter}
231-
style={{ fontSize: 15, fontWeight: 600 }}
232-
offset={8}
233-
/>
234-
</Bar>
235-
</BarChart>
236-
</ResponsiveContainer>
283+
height={height}
284+
isHorizontal={isHorizontal}
285+
margins={margins}
286+
gridColor={gridColor}
287+
axes={axes}
288+
valueKey={valueKey}
289+
barColor={barColor}
290+
barSize={barSize}
291+
valueFormatter={valueFormatter}
292+
tooltipLabel={tooltipLabel}
293+
metricLabel={metricLabel}
294+
title={title}
295+
darkMode={darkMode}
296+
/>
297+
) : (
298+
<NoDataMessage height={height} darkMode={darkMode} />
299+
)}
237300
</div>
238301
</CardBody>
239302
</Card>
240303
);
241304
}
242305

306+
GraphHeader.propTypes = {
307+
title: PropTypes.string.isRequired,
308+
metricLabel: PropTypes.string,
309+
showMetricPill: PropTypes.bool.isRequired,
310+
headerChips: PropTypes.arrayOf(
311+
PropTypes.shape({
312+
label: PropTypes.string.isRequired,
313+
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
314+
}),
315+
).isRequired,
316+
darkMode: PropTypes.bool.isRequired,
317+
};
318+
319+
NoDataMessage.propTypes = {
320+
height: PropTypes.number.isRequired,
321+
darkMode: PropTypes.bool.isRequired,
322+
};
323+
324+
CompareChart.propTypes = {
325+
data: PropTypes.arrayOf(PropTypes.object).isRequired,
326+
height: PropTypes.number.isRequired,
327+
isHorizontal: PropTypes.bool.isRequired,
328+
margins: PropTypes.shape({
329+
top: PropTypes.number,
330+
right: PropTypes.number,
331+
bottom: PropTypes.number,
332+
left: PropTypes.number,
333+
}).isRequired,
334+
gridColor: PropTypes.string.isRequired,
335+
axes: PropTypes.shape({
336+
xAxis: PropTypes.node.isRequired,
337+
yAxis: PropTypes.node.isRequired,
338+
}).isRequired,
339+
valueKey: PropTypes.string.isRequired,
340+
barColor: PropTypes.string.isRequired,
341+
barSize: PropTypes.number,
342+
valueFormatter: PropTypes.func.isRequired,
343+
tooltipLabel: PropTypes.string,
344+
metricLabel: PropTypes.string,
345+
title: PropTypes.string.isRequired,
346+
darkMode: PropTypes.bool.isRequired,
347+
};
348+
243349
CompareBarGraph.propTypes = {
244350
title: PropTypes.string.isRequired,
245351
metricLabel: PropTypes.string,
@@ -272,7 +378,6 @@ CompareBarGraph.propTypes = {
272378
bottom: PropTypes.number,
273379
left: PropTypes.number,
274380
}),
275-
maxBars: PropTypes.number,
276381
showYAxisTitle: PropTypes.bool,
277382
yTickFormatter: PropTypes.func,
278383
darkMode: PropTypes.bool,

src/components/LBDashboard/LBDashboard.jsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -603,8 +603,8 @@ export function LBDashboard() {
603603

604604
{compareType === 'villages' && (
605605
<AnalysisSection title="By Village" darkMode={darkMode}>
606-
<Row xs="1" md="3" className="g-3">
607-
<Col>
606+
<Row xs="1" lg="3" className="g-3">
607+
<Col lg="4" md="12">
608608
<DemandOverTime
609609
compareType="villages"
610610
metric={mappedMetric}
@@ -614,7 +614,7 @@ export function LBDashboard() {
614614
/>
615615
</Col>
616616

617-
<Col>
617+
<Col lg="4" md="12">
618618
{loadingVillages && (
619619
<div className={getClassNames('', styles.darkText, darkMode)}>
620620
Loading villages…
@@ -636,10 +636,10 @@ export function LBDashboard() {
636636
showYAxisTitle={true}
637637
yTickFormatter={stripVillageWord}
638638
yCategoryWidth={120}
639-
margins={{ top: 60, right: 110, bottom: 50, left: 20 }}
639+
margins={{ top: 40, right: 40, bottom: 50, left: 40 }}
640640
barSize={24}
641641
maxBars={6}
642-
height={480}
642+
height={420}
643643
valueFormatter={valueFormatter}
644644
darkMode={darkMode}
645645
headerChips={[

0 commit comments

Comments
 (0)