Skip to content

Commit bc4dcf3

Browse files
[#690] Create chart revenue to cost ratio
1 parent ef1e357 commit bc4dcf3

File tree

3 files changed

+120
-0
lines changed

3 files changed

+120
-0
lines changed

frontend/src/pages/cases/steps/UnderstandIncomeGap.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
ChartHouseholdIncomeComposition,
1212
ChartNeededIncomeLevel,
1313
ChartFarmEconomicEfficiency,
14+
ChartRevenueToCostRatio,
1415
} from "../visualizations";
1516
import { routePath } from "../../../components/route";
1617

@@ -116,6 +117,10 @@ const UnderstandIncomeGap = ({
116117
<Col span={24}>
117118
<ChartFarmEconomicEfficiency />
118119
</Col>
120+
121+
<Col span={24}>
122+
<ChartRevenueToCostRatio />
123+
</Col>
119124
</Row>
120125
);
121126
};
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import React, { useRef, useMemo, useState } from "react";
2+
import { Card, Row, Col, Space } from "antd";
3+
import { SegmentSelector, VisualCardWrapper } from "../components";
4+
import Chart from "../../../components/chart";
5+
import { CaseVisualState, CurrentCaseState } from "../store";
6+
7+
// What we are showing here:
8+
// The total income earned from the primary commodity divided by total cost of the primary commodity.
9+
10+
const colors = { current: "#1b726f", feasible: "#9cc2c1" };
11+
12+
const ChartRevenueToCostRatio = () => {
13+
const chartFarmEconomicEfficiencyRef = useRef(null);
14+
const currentCase = CurrentCaseState.useState((s) => s);
15+
const dashboardData = CaseVisualState.useState((s) => s.dashboardData);
16+
17+
const [selectedSegment, setSelectedSegment] = useState(null);
18+
19+
const chartData = useMemo(() => {
20+
const primaryCaseCommodityID = currentCase?.case_commodities?.find(
21+
(cc) => cc?.commodity_type === "focus"
22+
)?.id;
23+
24+
const currentDashboardData = dashboardData.find(
25+
(d) => d.id === selectedSegment
26+
);
27+
28+
const primaryAnswers = currentDashboardData?.answers?.filter(
29+
(a) => a.caseCommodityId === primaryCaseCommodityID
30+
);
31+
32+
const costAnswers = primaryAnswers?.filter((a) => a?.question?.id === 5);
33+
const landAnswers = primaryAnswers?.filter((a) => a?.question?.id === 2);
34+
const volumeAnswers = primaryAnswers?.filter((a) => a?.question?.id === 3);
35+
const priceAnswers = primaryAnswers?.filter((a) => a?.question?.id === 4);
36+
37+
// psudocode
38+
// for values in (current, feasible):
39+
// total_cost = primary-5 * primary-2
40+
// revenue = primary-2*primary-3*primary-4
41+
// revenue_to_cost_ration = revnue/total_cost
42+
43+
const data = ["current", "feasible"].map((it) => {
44+
const cost = costAnswers?.find((val) => val.name === it)?.value || 0;
45+
const land = landAnswers?.find((val) => val.name === it)?.value || 0;
46+
const volume = volumeAnswers?.find((val) => val.name === it)?.value || 0;
47+
const price = priceAnswers?.find((val) => val.name === it)?.value || 0;
48+
49+
const totalCost = cost * land;
50+
const revenue = land * price * volume;
51+
const revenueToCostRatio = revenue / totalCost;
52+
53+
return {
54+
name: it,
55+
value: revenueToCostRatio,
56+
currency: currentCase?.currency,
57+
color: colors[it],
58+
};
59+
});
60+
return data;
61+
}, [currentCase, dashboardData, selectedSegment]);
62+
63+
return (
64+
<Card className="card-visual-wrapper">
65+
<Row gutter={[20, 20]} align="middle">
66+
<Col span={10}>
67+
<Space direction="vertical">
68+
<div className="section-title">Revenue to cost ratio</div>
69+
<div className="section-description">
70+
This ratio shows how much revenue the crop generates for every
71+
unit of money spent producing it. It is calculated as crop revenue
72+
divided by production costs and reflects the farmer&apos;s return
73+
on investment after accounting for price levels, premiums and
74+
production practices. Higher values indicate profitable production
75+
and effective farm and post-harvest management, while lower values
76+
point to thin margins, unfavourable prices or overspending on
77+
inputs. Tracking this ratio over time helps assess financial
78+
resilience and how market conditions or agronomic changes
79+
influence household income.
80+
</div>
81+
</Space>
82+
</Col>
83+
<Col span={14}>
84+
<VisualCardWrapper
85+
title="Change Indicators"
86+
bordered
87+
exportElementRef={chartFarmEconomicEfficiencyRef}
88+
exportFilename="Farm Economic Efficiency"
89+
>
90+
<Row gutter={[20, 20]}>
91+
<Col span={24}>
92+
<SegmentSelector
93+
selectedSegment={selectedSegment}
94+
setSelectedSegment={setSelectedSegment}
95+
/>
96+
</Col>
97+
<Col span={24}>
98+
<Chart
99+
wrapper={false}
100+
type="BAR"
101+
loading={!chartData.length}
102+
data={chartData}
103+
extra={{ axisTitle: { y: `${currentCase?.currency}` } }}
104+
/>
105+
</Col>
106+
</Row>
107+
</VisualCardWrapper>
108+
</Col>
109+
</Row>
110+
</Card>
111+
);
112+
};
113+
114+
export default ChartRevenueToCostRatio;

frontend/src/pages/cases/visualizations/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ export { default as TableScenarioOutcomes } from "./TableScenarioOutcomes";
1414
export { default as ChartHouseholdIncomeComposition } from "./ChartHouseholdIncomeComposition";
1515
export { default as ChartNeededIncomeLevel } from "./ChartNeededIncomeLevel";
1616
export { default as ChartFarmEconomicEfficiency } from "./ChartFarmEconomicEfficiency";
17+
export { default as ChartRevenueToCostRatio } from "./ChartRevenueToCostRatio";

0 commit comments

Comments
 (0)