Skip to content

Commit a03ec39

Browse files
Merge pull request #4193 from OneCommunityGlobal/fix/bm-expenditure-charts
Mani shashank; fix/BM Dashboard Financials Tracking, Cost-prediction
2 parents e1eb951 + cd0c6b4 commit a03ec39

14 files changed

Lines changed: 1400 additions & 106 deletions

src/components/BMDashboard/CostPrediction/CostPredictionPage.jsx

Lines changed: 639 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
/* Cost Prediction Page Styles */
2+
.costPredictionPage {
3+
padding: 20px;
4+
background-color: var(--card-bg);
5+
min-height: 100vh;
6+
color: var(--text-color);
7+
}
8+
9+
/* Chart Title Container */
10+
.chartTitleContainer {
11+
display: flex;
12+
align-items: center;
13+
justify-content: center;
14+
margin-bottom: 15px;
15+
padding: 0 10px;
16+
position: relative;
17+
}
18+
19+
.costPredictionTitle {
20+
margin: 0;
21+
font-size: 18px;
22+
font-weight: 600;
23+
color: var(--text-color);
24+
text-align: center;
25+
}
26+
27+
.costPredictionInfoButton {
28+
background: none;
29+
border: none;
30+
cursor: pointer;
31+
padding: 4px;
32+
border-radius: 4px;
33+
color: var(--text-color);
34+
opacity: 0.7;
35+
transition: opacity 0.2s ease;
36+
position: absolute;
37+
right: 10px;
38+
}
39+
40+
.costPredictionInfoButton:hover {
41+
opacity: 1;
42+
}
43+
44+
.costPredictionTooltip {
45+
max-width: 300px;
46+
font-size: 12px;
47+
line-height: 1.4;
48+
z-index: 1000 !important;
49+
position: fixed !important;
50+
}
51+
52+
/* Dropdown Container */
53+
.dropdownContainer {
54+
display: flex;
55+
gap: 10px;
56+
margin-bottom: 15px;
57+
padding: 0 10px;
58+
flex-wrap: wrap;
59+
}
60+
61+
.dropdownItem {
62+
flex: 1;
63+
min-width: 120px;
64+
}
65+
66+
.multiSelect {
67+
min-width: 150px;
68+
}
69+
70+
/* Chart Wrapper - protects from external styles */
71+
.costPredictionWrapper {
72+
width: 100%;
73+
height: 100%;
74+
padding: 10px;
75+
box-sizing: border-box;
76+
position: relative;
77+
background-color: var(--card-bg);
78+
border-radius: 8px;
79+
box-shadow: 0 2px 4px rgb(0 0 0 / 10%);
80+
}
81+
82+
/* Chart Container */
83+
.costPredictionChartContainer {
84+
position: relative;
85+
height: 500px;
86+
width: 100%;
87+
padding: 0 10px;
88+
margin-bottom: 5px;
89+
background-color: transparent;
90+
}
91+
92+
/* Chart Legend */
93+
.chartLegend {
94+
width: 100%;
95+
text-align: center;
96+
font-size: 14px;
97+
margin-top: 2px;
98+
color: var(--text-color);
99+
display: flex;
100+
justify-content: center;
101+
gap: 6px;
102+
flex-wrap: wrap;
103+
align-items: center;
104+
}
105+
106+
.costChartLoading,
107+
.costChartError,
108+
.costChartEmpty {
109+
display: flex;
110+
align-items: center;
111+
justify-content: center;
112+
height: 100%;
113+
color: var(--text-color);
114+
font-size: 16px;
115+
}
116+
117+
.costChartError {
118+
color: #ff4d4f;
119+
}
120+
121+
/* Chart Tooltip Styling */
122+
.costPredictionChartContainer :global(.recharts-tooltip-wrapper) {
123+
z-index: 1000 !important;
124+
}
125+
126+
.costPredictionChartContainer :global(.recharts-default-tooltip) {
127+
background-color: var(--card-bg) !important;
128+
border: 1px solid var(--button-hover) !important;
129+
border-radius: 4px !important;
130+
box-shadow: 0 2px 8px rgb(0 0 0 / 15%) !important;
131+
padding: 8px !important;
132+
}
133+
134+
.costPredictionChartContainer :global(.recharts-tooltip-label) {
135+
color: var(--text-color) !important;
136+
font-weight: bold !important;
137+
margin-bottom: 4px !important;
138+
}
139+
140+
.costPredictionChartContainer :global(.recharts-tooltip-item) {
141+
color: var(--text-color) !important;
142+
padding: 2px 0 !important;
143+
}
144+
145+
.costPredictionChartContainer :global(.recharts-tooltip-item-name) {
146+
color: var(--text-color) !important;
147+
}
148+
149+
.costPredictionChartContainer :global(.recharts-tooltip-item-value) {
150+
color: var(--text-color) !important;
151+
font-weight: bold !important;
152+
}
153+
154+
/* Dark mode styles */
155+
:global(.dark-mode) .costPredictionPage {
156+
background-color: #1e2736;
157+
color: #e0e0e0;
158+
}
159+
160+
:global(.dark-mode) .costPredictionWrapper {
161+
background-color: #2c3344;
162+
}
163+
164+
:global(.dark-mode) .costPredictionChartContainer {
165+
background-color: #1e2736;
166+
color: #e0e0e0;
167+
}
168+
169+
:global(.dark-mode) .costPredictionChartContainer :global(.recharts-default-tooltip) {
170+
background-color: #2c3344 !important;
171+
border-color: #364156 !important;
172+
color: #e0e0e0 !important;
173+
}
174+
175+
:global(.dark-mode) .costPredictionTitle {
176+
color: #e0e0e0;
177+
}
178+
179+
:global(.dark-mode) .costPredictionInfoButton {
180+
color: #e0e0e0;
181+
}
182+
183+
:global(.dark-mode) .costPredictionInfoButton:hover {
184+
color: #fff;
185+
}
186+
187+
/* Dark-mode body overrides for Recharts (replaces injected <style>) */
188+
:global(.dark-mode-body) :global(.recharts-wrapper),
189+
:global(.dark-mode-body) :global(.recharts-surface) {
190+
background-color: #1e2736 !important;
191+
}
192+
193+
:global(.dark-mode-body) :global(.recharts-cartesian-grid-horizontal) line,
194+
:global(.dark-mode-body) :global(.recharts-cartesian-grid-vertical) line {
195+
stroke: #364156 !important;
196+
}
197+
198+
:global(.dark-mode-body) :global(.recharts-text) {
199+
fill: #e0e0e0 !important;
200+
}
201+
202+
:global(.dark-mode-body) :global(.recharts-default-legend) {
203+
background-color: #1e2736 !important;
204+
}
205+
206+
:global(.dark-mode-body) :global(.recharts-legend-item-text) {
207+
color: #e0e0e0 !important;
208+
}
209+
210+
:global(.dark-mode-body) :global(.recharts-tooltip-wrapper) {
211+
background-color: transparent !important;
212+
}
213+
214+
/* Responsive adjustments */
215+
@media (width <= 768px) {
216+
.dropdownContainer {
217+
flex-direction: column;
218+
}
219+
220+
.dropdownItem {
221+
min-width: 100%;
222+
}
223+
224+
.costPredictionTitle {
225+
font-size: 16px;
226+
}
227+
228+
.costPredictionChartContainer {
229+
height: 400px;
230+
}
231+
232+
.costPredictionPage {
233+
padding: 10px;
234+
}
235+
}
236+
237+
@media (width <= 480px) {
238+
.chartTitleContainer {
239+
flex-direction: column;
240+
align-items: flex-start;
241+
gap: 8px;
242+
}
243+
244+
.costPredictionChartContainer {
245+
height: 350px;
246+
}
247+
}

src/components/BMDashboard/WeeklyProjectSummary/CostPredictionChart.jsx

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useState, useEffect } from 'react';
2+
import PropTypes from 'prop-types';
23
import { useDispatch, useSelector } from 'react-redux';
34
import {
45
LineChart,
@@ -13,6 +14,7 @@ import {
1314
} from 'recharts';
1415
import styles from './CostPredictionChart.module.css';
1516
import projectCostService from '../../../services/projectCostService';
17+
import { getTooltipStyles } from '../../../utils/bmChartStyles';
1618

1719
// Custom dot renderer (unchanged)
1820
function renderDotTopOrBottom(lineKey, color) {
@@ -145,6 +147,7 @@ function CostPredictionChart({ projectId }) {
145147
y={y + 15} // push text down so it doesn’t overlap axis line
146148
textAnchor="middle"
147149
fill={darkMode ? '#e5e7eb' : '#9ca3af'}
150+
fontSize={12}
148151
>
149152
{payload.value}
150153
</text>
@@ -153,13 +156,22 @@ function CostPredictionChart({ projectId }) {
153156
/>
154157
<YAxis
155158
tick={({ x, y, payload }) => (
156-
<text x={x} y={y} textAnchor="end" fill={darkMode ? '#e5e7eb' : '#9ca3af'}>
159+
<text
160+
x={x}
161+
y={y}
162+
textAnchor="end"
163+
fill={darkMode ? '#e5e7eb' : '#9ca3af'}
164+
fontSize={12}
165+
>
157166
{payload.value}
158167
</text>
159168
)}
160169
/>
161170
{/* Tooltip & Legend */}
162-
<Tooltip />
171+
<Tooltip
172+
{...getTooltipStyles(darkMode)}
173+
cursor={{ stroke: darkMode ? '#e0e0e0' : '#999' }}
174+
/>
163175
<Legend
164176
verticalAlign="bottom"
165177
height={48}
@@ -170,7 +182,7 @@ function CostPredictionChart({ projectId }) {
170182
<li key={item.label} className={styles.legendListItem}>
171183
{/* icon */}
172184
{item.type === 'circle' ? (
173-
<span className={styles.legendItem} />
185+
<span className={styles.legendItem} style={{ backgroundColor: item.color }} />
174186
) : (
175187
<svg width="18" height="12">
176188
<line
@@ -185,7 +197,7 @@ function CostPredictionChart({ projectId }) {
185197
</svg>
186198
)}
187199
{/* label */}
188-
<span style={{ color: item.color }}>{item.label}</span>
200+
<span style={{ color: darkMode ? '#e5e7eb' : '#374151' }}>{item.label}</span>
189201
</li>
190202
))}
191203
</ul>
@@ -230,4 +242,8 @@ function CostPredictionChart({ projectId }) {
230242
);
231243
}
232244

245+
CostPredictionChart.propTypes = {
246+
projectId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
247+
};
248+
233249
export default CostPredictionChart;

src/components/BMDashboard/WeeklyProjectSummary/CostPredictionChart.module.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
.title {
2-
margin: 0 0 8px 0;
2+
margin: 0 0 8px;
33
text-align: center;
44
font-size: 24px;
55
font-weight: normal;
@@ -19,14 +19,14 @@
1919
list-style: none;
2020
margin: 0;
2121
padding: 0;
22+
font-size: 12px;
2223
}
2324

2425
.legendItem {
2526
display: inline-block;
2627
width: 12px;
2728
height: 12px;
2829
border-radius: 50%;
29-
background: var(--text-color);
3030
}
3131

3232
.legendListItem {

0 commit comments

Comments
 (0)