Skip to content

Commit 23c4978

Browse files
Merge pull request #4000 from OneCommunityGlobal/development
Frontend Release to Main [4.42]
2 parents b9aaa6e + a715a63 commit 23c4978

80 files changed

Lines changed: 17615 additions & 2632 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

dummy.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// trigger reopen

eslint.config.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ module.exports = [
3333
'src/components/Reports/PeopleReport/components/PeopleTasksPieChart.test.jsx',
3434
// Ignore entire component folders
3535
'src/components/Badge/**',
36-
'src/components/Projects/**',
3736
'src/components/SummaryManagement/**',
3837
'src/components/TeamMemberTasks/**',
3938
'src/components/Teams/TeamMembersPopup.jsx',

package-lock.json

Lines changed: 14869 additions & 375 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@
7474
"rc-slider": "^11.1.8",
7575
"react": "^18.3.1",
7676
"react-autosuggest": "^10.1.0",
77-
"react-beautiful-dnd": "^13.1.1",
7877
"react-bootstrap": "^1.0.1",
7978
"react-chartjs-2": "^5.3.0",
8079
"react-circular-progressbar": "^2.1.0",
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import axios from 'axios';
2+
import { ENDPOINTS } from '../../utils/URL';
3+
import {toast} from 'react-toastify';
4+
import { ADD_EVENT_FEEDBACK } from "../../constants/communityPortal/eventFeedbackConstant";
5+
6+
export const addEventFeedback = (eventFeedback) => {
7+
return async dispatch => {
8+
try {
9+
const res = await axios
10+
.post(ENDPOINTS.CP_ADD_EVENT_FEEDBACK, eventFeedback);
11+
if (res.status === 201)
12+
toast.success('Event Feedback submitted successfully!');
13+
dispatch ({
14+
type:ADD_EVENT_FEEDBACK,
15+
payload:eventFeedback
16+
});
17+
}
18+
catch(error) {
19+
if (error.response.status === 500)
20+
toast.error('Error submitting Event Feedback. Please try again.');
21+
else if (error.response.status === 404 ||error.response.status === 403 || error.response.status === 400)
22+
toast.error('Permission or Validation Error. Please check your input or access rights');
23+
else {
24+
toast.error('Error submitting Event Feedback. Please try again.');
25+
}
26+
};
27+
28+
}
29+
30+
}

src/components/Auth/PermissionWatcher.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { getUserProfile } from '../../actions/userProfile';
99

1010
function PermissionWatcher() {
1111
const dispatch = useDispatch();
12-
const { isAuthenticated, forceLogoutAt } = useSelector(state => state.auth);
12+
const { isAuthenticated, forceLogoutAt } = useSelector(state => state.auth || {});
1313
const userProfile = useSelector(state => state.userProfile);
1414
const isAcknowledged = userProfile?.permissions?.isAcknowledged !== false;
1515
const [isAckLoading, setIsAckLoading] = useState(false);

src/components/BMDashboard/LessonsLearnt/LessonsLearntChart.jsx

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ function ChartTitle({ title }) {
5353
return <h2 className={styles.chartTitle}>{title}</h2>;
5454
}
5555

56-
export default function LessonsLearntChart() {
56+
const LessonsLearntChart = () => {
5757
const [selectedProjects, setSelectedProjects] = useState([]);
5858
const [startDate, setStartDate] = useState(null);
5959
const [endDate, setEndDate] = useState(null);
@@ -116,19 +116,34 @@ export default function LessonsLearntChart() {
116116
</div>
117117

118118
<div className={styles.chartWrapper}>
119-
{isLoading ? <p>Loading...</p> : <Bar data={chartData} options={chartOptions} />}
120-
<div className={styles.percentageLabels}>
121-
{lessonsData.map((d, idx) => (
122-
<span
123-
key={idx}
124-
className={styles.percentageLabel}
125-
style={{ left: `${(idx + 0.5) * (100 / lessonsData.length)}%` }}
126-
>
127-
{d.percentage}%
128-
</span>
129-
))}
130-
</div>
119+
{isLoading ? (
120+
<p>Loading...</p>
121+
) : lessonsData.length === 0 ? (
122+
<p>No lessons data available for the selected criteria</p>
123+
) : (
124+
<>
125+
<Bar data={chartData} options={chartOptions} />
126+
<div className={styles.percentageLabels}>
127+
{lessonsData.map((d, idx) => (
128+
<span
129+
key={idx}
130+
className={styles.percentageLabel}
131+
style={{
132+
left:
133+
lessonsData.length > 0
134+
? `${(idx + 0.5) * (100 / lessonsData.length)}%`
135+
: '0%',
136+
}}
137+
>
138+
{d.percentage}%
139+
</span>
140+
))}
141+
</div>
142+
</>
143+
)}
131144
</div>
132145
</div>
133146
);
134-
}
147+
};
148+
149+
export default LessonsLearntChart;

src/components/BMDashboard/UtilizationChart/UtilizationChart.jsx

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,17 @@ function UtilizationChart() {
2020

2121
const fetchChartData = async () => {
2222
try {
23-
const response = await axios.get(
24-
`${process.env.REACT_APP_APIENDPOINT}/tools/utilization`,
25-
{
26-
params: {
27-
startDate,
28-
endDate,
29-
tool: toolFilter,
30-
project: projectFilter,
31-
},
32-
headers: {
33-
Authorization: localStorage.getItem('token'),
34-
},
35-
}
36-
);
23+
const response = await axios.get(`${process.env.REACT_APP_APIENDPOINT}/tools/utilization`, {
24+
params: {
25+
startDate,
26+
endDate,
27+
tool: toolFilter,
28+
project: projectFilter,
29+
},
30+
headers: {
31+
Authorization: localStorage.getItem('token'),
32+
},
33+
});
3734
setToolsData(response.data);
3835
} catch (err) {
3936
setError('Failed to load utilization data.');
@@ -143,10 +140,7 @@ function UtilizationChart() {
143140
className={styles.datepickerWrapper}
144141
/>
145142

146-
<button
147-
onClick={handleApplyClick}
148-
className={styles.button}
149-
>
143+
<button onClick={handleApplyClick} className={styles.button}>
150144
Apply
151145
</button>
152146
</div>
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { useEffect, useState } from 'react';
2+
import { PieChart, Pie, Cell, Tooltip, Legend } from 'recharts';
3+
import axios from 'axios';
4+
import styles from './ExpenditureChart.module.css';
5+
6+
const COLORS = ['#6777EF', '#A0CD61', '#F5CD4B'];
7+
const CATEGORIES = ['Labor', 'Equipment', 'Materials'];
8+
9+
function normalizeData(data) {
10+
return CATEGORIES.map(cat => {
11+
const found = data.find(d => d.category === cat);
12+
return found || { category: cat, amount: 0 };
13+
});
14+
}
15+
16+
const renderCustomLabel = ({ cx, cy, midAngle, outerRadius, percent, name }) => {
17+
const RADIAN = Math.PI / 180;
18+
const radius = outerRadius * 0.6;
19+
const x = cx + radius * Math.cos(-midAngle * RADIAN);
20+
const y = cy + radius * Math.sin(-midAngle * RADIAN);
21+
22+
return (
23+
<text
24+
x={x}
25+
y={y}
26+
fill="white"
27+
textAnchor="middle"
28+
dominantBaseline="central"
29+
fontSize={10}
30+
fontWeight="600"
31+
>
32+
{`${name}: ${(percent * 100).toFixed(1)}%`}
33+
</text>
34+
);
35+
};
36+
37+
function ExpenditureChart({ projectId }) {
38+
const [actual, setActual] = useState([]);
39+
const [planned, setPlanned] = useState([]);
40+
const [loading, setLoading] = useState(true);
41+
const [error, setError] = useState(null);
42+
43+
useEffect(() => {
44+
const fetchData = async () => {
45+
if (!projectId) return;
46+
setLoading(true);
47+
setError(null);
48+
try {
49+
const res = await axios.get(
50+
`${process.env.REACT_APP_APIENDPOINT}/bm/expenditure/${projectId}/pie`,
51+
);
52+
setActual(res.data.actual);
53+
setPlanned(res.data.planned);
54+
} catch (err) {
55+
setError('Failed to load expenditure data');
56+
} finally {
57+
setLoading(false);
58+
}
59+
};
60+
fetchData();
61+
}, [projectId]);
62+
63+
const renderChart = (data, title) => (
64+
<div className={styles.expenditure - chart - card}>
65+
<h4 className={styles.expenditure - chart - title}>{title}</h4>
66+
<PieChart width={280} height={280}>
67+
<Pie
68+
data={data}
69+
dataKey="amount"
70+
nameKey="category"
71+
cx="50%"
72+
cy="50%"
73+
outerRadius={120}
74+
label={renderCustomLabel}
75+
labelLine={false}
76+
stroke="none"
77+
>
78+
{data.map((entry, index) => (
79+
<Cell key={entry.category || index} fill={COLORS[index % COLORS.length]} />
80+
))}
81+
</Pie>
82+
<Tooltip />
83+
<Legend layout="horizontal" verticalAlign="bottom" align="center" height={20} />
84+
</PieChart>
85+
</div>
86+
);
87+
88+
if (loading)
89+
return <div className={styles.expenditure - chart - loading}>Loading expenditure data...</div>;
90+
if (error) return <div className={styles.expenditure - chart - error}>{error}</div>;
91+
92+
return (
93+
<div className={styles.expenditure - chart - wrapper}>
94+
{renderChart(normalizeData(actual), 'Actual Expenditure')}
95+
{renderChart(normalizeData(planned), 'Planned Expenditure')}
96+
</div>
97+
);
98+
}
99+
100+
export default ExpenditureChart;
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
.expenditure-chart-wrapper {
2+
display: flex;
3+
justify-content: center;
4+
flex-wrap: wrap;
5+
gap: 16px;
6+
width: 100%;
7+
padding: 0;
8+
margin: 0;
9+
}
10+
11+
.expenditure-chart-card {
12+
flex: 1 1 220px;
13+
max-width: 260px;
14+
padding: 12px 10px;
15+
min-height: 300px;
16+
background: var(--card-bg);
17+
box-shadow: 0 2px 4px var(--card-shadow);
18+
border-radius: 8px;
19+
display: flex;
20+
flex-direction: column;
21+
align-items: center;
22+
justify-content: flex-start;
23+
}
24+
25+
.expenditure-chart-title {
26+
font-size: 1.1rem;
27+
font-weight: bold;
28+
text-align: center;
29+
margin-bottom: 6px;
30+
}
31+
32+
.recharts-legend-wrapper {
33+
margin-top: -10px !important;
34+
}
35+
36+
.recharts-legend-item-text {
37+
font-size: 12px !important;
38+
white-space: nowrap;
39+
}
40+
41+
.recharts-pie-label-text {
42+
font-size: 10px !important;
43+
font-weight: 600;
44+
fill: white;
45+
text-anchor: middle;
46+
alignment-baseline: central;
47+
white-space: nowrap;
48+
}
49+
50+
.dark-mode .expenditure-chart-card {
51+
background: var(--card-bg);
52+
box-shadow: 0 2px 5px rgba(255, 255, 255, 0.08);
53+
}
54+
55+
.dark-mode .expenditure-chart-title {
56+
color: var(--text-color);
57+
}
58+
59+
.dark-mode .recharts-default-tooltip {
60+
background-color: #333 !important;
61+
color: #fff !important;
62+
border: 1px solid #555 !important;
63+
}

0 commit comments

Comments
 (0)