Skip to content

Commit ecd7bc7

Browse files
Merge branch 'development' into aayush_event_details_popup_frontend
2 parents ac058a0 + 04e5398 commit ecd7bc7

61 files changed

Lines changed: 9055 additions & 5619 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.

package-lock.json

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

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
"html-to-pdfmake": "^2.0.6",
6565
"html2canvas": "^1.4.1",
6666
"jest": "^30.2.0",
67-
"joi": "^18.0.2",
67+
"joi": "^18.1.2",
6868
"joi-browser": "^13.4.0",
6969
"jquery": "^3.7.1",
7070
"jspdf": "^4.2.1",
@@ -127,6 +127,7 @@
127127
"tinymce": "^7.2.0",
128128
"util": "^0.12.5",
129129
"uuid": "^9.0.1",
130+
"validator": "^13.15.26",
130131
"webpack": "^5.104.1"
131132
},
132133
"resolutions": {

src/actions/bmdashboard/injuryActions.js

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import {
55
FETCH_INJURIES_FAILURE
66
} from './types';
77
import { ENDPOINTS } from '../../utils/URL';
8-
98
export const FETCH_BM_INJURY_DATA_REQUEST = 'FETCH_BM_INJURY_DATA_REQUEST';
109
export const FETCH_BM_INJURY_DATA_SUCCESS = 'FETCH_BM_INJURY_DATA_SUCCESS';
1110
export const FETCH_BM_INJURY_DATA_FAILURE = 'FETCH_BM_INJURY_DATA_FAILURE';
1211
export const RESET_BM_INJURY_DATA = 'RESET_BM_INJURY_DATA';
1312
export const FETCH_BM_INJURY_SEVERITIES = 'FETCH_BM_INJURY_SEVERITIES';
1413
export const FETCH_BM_INJURY_TYPES = 'FETCH_BM_INJURY_TYPES';
1514
export const FETCH_BM_INJURY_PROJECTS = 'FETCH_BM_INJURY_PROJECTS';
15+
export const FETCH_BM_INJURY_OVER_TIME = 'FETCH_BM_INJURY_OVER_TIME';
1616

1717
// Legacy constants for backward compatibility
1818
export const GET_INJURY_SEVERITY = 'GET_INJURY_SEVERITY';
@@ -47,6 +47,7 @@ const setInjuryDataError = payload => ({ type: FETCH_BM_INJURY_DATA_FAILURE, pay
4747
const setInjurySeverities = payload => ({ type: FETCH_BM_INJURY_SEVERITIES, payload });
4848
const setInjuryTypes = payload => ({ type: FETCH_BM_INJURY_TYPES, payload });
4949
const setInjuryProjects = payload => ({ type: FETCH_BM_INJURY_PROJECTS, payload });
50+
const setInjuryOverTime = payload => ({ type: FETCH_BM_INJURY_OVER_TIME, payload });
5051

5152
// Legacy action creators for backward compatibility
5253
export const setInjurySeverity = payload => ({
@@ -179,3 +180,33 @@ export const getInjuryData = async (projectId, startDate, endDate) => {
179180
// Return the data directly
180181
return response.data;
181182
};
183+
184+
export const fetchInjuriesOverTime = (filters = {}) => {
185+
return async dispatch => {
186+
try {
187+
const params = {};
188+
189+
if (filters.projectIds?.length) {
190+
params.projectIds = filters.projectIds.join(',');
191+
}
192+
if (filters.startDate && filters.endDate) {
193+
params.startDate = filters.startDate;
194+
params.endDate = filters.endDate;
195+
}
196+
if (filters.types?.length) {
197+
params.types = filters.types.join(',');
198+
}
199+
if (filters.departments?.length) {
200+
params.departments = filters.departments.join(',');
201+
}
202+
if (filters.severities?.length) {
203+
params.severities = filters.severities.join(',');
204+
}
205+
206+
const res = await axios.get(ENDPOINTS.BM_INJURY_OVER_TIME, { params });
207+
dispatch(setInjuryOverTime(res.data));
208+
} catch (err) {
209+
dispatch(setErrors(err.response?.data?.error || err.message));
210+
}
211+
};
212+
}

src/actions/eventActions.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ import { ENDPOINTS } from '~/utils/URL';
1313
*/
1414
export async function getEvents(params = {}) {
1515
try {
16-
const { type = '', location = '', page = 1, limit = 9, sortBy = 'date' } = params;
16+
const { type = '', location = '', page = 1, limit = 9, sortBy = 'date', userId = '' } = params;
1717
const queryParams = new URLSearchParams();
18+
if (userId) queryParams.append('userId', userId);
1819
if (type) queryParams.append('type', type);
1920
if (location) queryParams.append('location', location);
2021
queryParams.append('page', page);
@@ -68,3 +69,28 @@ export async function getEventLocations() {
6869
};
6970
}
7071
}
72+
73+
export async function joinWaitlist(eventId, userId, token) {
74+
const url = `${ENDPOINTS.EVENTS}/${eventId}/waitlist`;
75+
76+
return axios.post(
77+
url,
78+
{ userId },
79+
{
80+
headers: {
81+
Authorization: token,
82+
},
83+
}
84+
);
85+
}
86+
87+
export async function leaveWaitlist(eventId, userId, token) {
88+
const url = `${ENDPOINTS.EVENTS}/${eventId}/waitlist`;
89+
90+
return axios.delete(url, {
91+
data: { userId },
92+
headers: {
93+
Authorization: token,
94+
},
95+
});
96+
}

src/components/AttendanceSystem/AttendanceNoShowCharts.jsx

Lines changed: 26 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22

33
'use client';
44

5-
import { useState, useEffect } from 'react';
6-
import { useSelector } from 'react-redux';
7-
import axios from 'axios';
5+
import { useState, useMemo } from 'react';
86
import { PieChart, Pie, Cell, Tooltip, Legend, ResponsiveContainer } from 'recharts';
97
import { ENDPOINTS } from '~/utils/URL';
10-
import { events as mockEvents } from './mockData';
8+
import { events } from './mockData';
119
import styles from './AttendanceNoShowCharts.module.css';
10+
import { useSelector } from 'react-redux';
1211

13-
const attendanceColors = ['#0088FE', '#FF8042'];
12+
const attendanceColors = ['#0088FE', '#FF8042', '#FFBB28'];
1413
const noShowColors = ['#00C49F', '#FF0000'];
1514

1615
// Status color mapping
@@ -133,18 +132,21 @@ const renderCustomizedLabel = ({ cx, cy, midAngle, innerRadius, outerRadius, per
133132
<text
134133
x={x}
135134
y={y}
136-
fill="black"
137-
textAnchor={x > cx ? 'start' : 'end'}
135+
fill="white"
136+
textAnchor="middle"
138137
dominantBaseline="central"
139138
fontSize="12"
139+
fontWeight="bold"
140140
>
141-
{`${(percent * 100).toFixed(1)}%`}
141+
{percent > 0 ? `${(percent * 100).toFixed(0)}%` : ''}
142142
</text>
143143
);
144144
};
145145

146146
const CustomTooltip = ({ active, payload }) => {
147+
console.log(active, payload);
147148
if (active && payload && payload.length) {
149+
console.log('Tooltip payload:', payload);
148150
return (
149151
<div className={styles.chartTooltip}>
150152
<p className={styles.chartTooltipItem}>{`${payload[0].name} : ${payload[0].value}`}</p>
@@ -155,76 +157,14 @@ const CustomTooltip = ({ active, payload }) => {
155157
};
156158

157159
function AttendanceNoShowCharts() {
158-
const [events, setEvents] = useState(mockEvents);
159-
const [selectedEvent, setSelectedEvent] = useState(null);
160-
const [loading, setLoading] = useState(true);
160+
const [selectedId, setSelectedId] = useState(events[0].id);
161+
const [loading, setLoading] = useState(false);
161162
const [error, setError] = useState(null);
162163
const darkMode = useSelector(state => state.theme.darkMode);
163-
164-
// Fetch events data from backend
165-
useEffect(() => {
166-
const fetchEvents = async () => {
167-
setLoading(true);
168-
setError(null);
169-
try {
170-
const response = await axios.get(ENDPOINTS.EVENT_ATTENDANCE_STATS);
171-
172-
// Check if response has data in expected format
173-
if (response.data && Array.isArray(response.data)) {
174-
// Transform API data to match mock data format if needed
175-
const transformedEvents = response.data.map(transformEvent);
176-
177-
setEvents(transformedEvents);
178-
if (transformedEvents.length > 0) {
179-
setSelectedEvent(transformedEvents[0]);
180-
}
181-
} else if (response.data && response.data.events && Array.isArray(response.data.events)) {
182-
// Handle nested response structure
183-
const transformedEvents = response.data.events.map(transformEvent);
184-
185-
setEvents(transformedEvents);
186-
if (transformedEvents.length > 0) {
187-
setSelectedEvent(transformedEvents[0]);
188-
}
189-
} else {
190-
// If data format doesn't match, fall back to mock data
191-
throw new Error('Unexpected data format from API');
192-
}
193-
} catch (err) {
194-
// Fall back to mock data if API is unavailable or returns error
195-
// eslint-disable-next-line no-console
196-
console.warn('Failed to fetch events from API, using mock data:', err.message);
197-
// Calculate status for mock events
198-
const mockEventsWithStatus = mockEvents.map(event => ({
199-
...event,
200-
status: calculateEventStatus(event) || event.status,
201-
}));
202-
setEvents(mockEventsWithStatus);
203-
if (mockEventsWithStatus.length > 0) {
204-
setSelectedEvent(mockEventsWithStatus[0]);
205-
}
206-
setError('Using mock data - API endpoint not available');
207-
} finally {
208-
setLoading(false);
209-
}
210-
};
211-
212-
fetchEvents();
213-
}, []);
214-
215-
// Update selectedEvent when events change
216-
useEffect(() => {
217-
if (events.length > 0 && !selectedEvent) {
218-
setSelectedEvent(events[0]);
219-
}
220-
}, [events, selectedEvent]);
164+
const selectedEvent = useMemo(() => events.find(e => e.id === selectedId), [selectedId]);
221165

222166
const handleEventChange = e => {
223-
const selectedEventId = e.target.value;
224-
const newSelectedEvent = events.find(event => event.id === selectedEventId);
225-
if (newSelectedEvent) {
226-
setSelectedEvent(newSelectedEvent);
227-
}
167+
setSelectedId(e.target.value);
228168
};
229169

230170
const calculatePercentage = (value, total) => {
@@ -478,14 +418,19 @@ function AttendanceNoShowCharts() {
478418
)}
479419

480420
{/* No-Show Chart */}
481-
<div className={styles.chartWrapper}>
482-
<h3 className={styles.chartSectionTitle}>
483-
Registration vs Attendance
484-
{currentStatus === 'In Progress' && (
485-
<span className={styles.chartLiveBadge}>(Live)</span>
486-
)}
421+
<div style={{ width: '100%' }}>
422+
<h3
423+
style={{
424+
fontSize: '18px',
425+
fontWeight: '500',
426+
color: '#111827',
427+
marginBottom: '12px',
428+
textAlign: 'center',
429+
}}
430+
>
431+
No-Show Breakdown
487432
</h3>
488-
<div className={styles.chartContainer}>
433+
<div style={{ height: '300px', width: '100%' }}>
489434
<ResponsiveContainer width="100%" height="100%">
490435
<PieChart>
491436
<Pie

src/components/AttendanceSystem/AttendanceNoShowCharts.module.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,6 @@
166166
height: 12px;
167167
border-radius: 50%;
168168
}
169-
170169
.statusValue {
171170
font-size: 18px;
172171
font-weight: 600;

0 commit comments

Comments
 (0)