From 96bd716c81d19ad352b9a3573f81eed67d26bb39 Mon Sep 17 00:00:00 2001 From: harshavarma29 Date: Mon, 3 Nov 2025 21:00:57 -0600 Subject: [PATCH 1/2] Created chart for job roles hit and applications, added all the relevant files --- .../JobsHitsApplicationsActions.js | 26 + .../JobsHitsApplicationsChart.jsx | 229 + .../JobsHitsApplicationsChart.module.css | 167 + .../JobsApplicationsHitsConstants.js | 3 + src/reducers/index.js | 2 + .../JobsHitsApplicationsReducer.js | 36 + src/routes.jsx | 7 + src/utils/URL.js | 1 + yarn.lock | 18188 ++++++++-------- 9 files changed, 9565 insertions(+), 9094 deletions(-) create mode 100644 src/actions/jobAnalytics/JobsHitsApplicationsActions.js create mode 100644 src/components/JobAnalytics/JobsHitsApplicationsChart/JobsHitsApplicationsChart.jsx create mode 100644 src/components/JobAnalytics/JobsHitsApplicationsChart/JobsHitsApplicationsChart.module.css create mode 100644 src/constants/jobAnalytics/JobsApplicationsHitsConstants.js create mode 100644 src/reducers/jobAnalytics/JobsHitsApplicationsReducer.js diff --git a/src/actions/jobAnalytics/JobsHitsApplicationsActions.js b/src/actions/jobAnalytics/JobsHitsApplicationsActions.js new file mode 100644 index 0000000000..908a1121ba --- /dev/null +++ b/src/actions/jobAnalytics/JobsHitsApplicationsActions.js @@ -0,0 +1,26 @@ +import { JOBS_APPS_HITS_REQUEST, JOBS_APPS_HITS_REQUEST_SUCCESS, JOBS_APPS_HITS_REQUEST_FAILURE } from '../../constants/jobAnalytics/JobsApplicationsHitsConstants'; +import { ENDPOINTS } from '../../utils/URL'; + +export const fetchJobsHitsApplications = (queryParams, token) => async (dispatch) => { + dispatch({ type: JOBS_APPS_HITS_REQUEST }); + + try { + const response = await fetch(`${ENDPOINTS.JOB_HITS_AND_APPLICATIONS}?${queryParams}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Authorization': token + } + }); + + const data = await response.json(); + + if(!response.ok) { + throw new Error(data.error || 'Failed to fetch data'); + } + + dispatch({ type: JOBS_APPS_HITS_REQUEST_SUCCESS, payload: data }); + } catch (error) { + dispatch({ type: JOBS_APPS_HITS_REQUEST_FAILURE, payload: error.message }); + } +} diff --git a/src/components/JobAnalytics/JobsHitsApplicationsChart/JobsHitsApplicationsChart.jsx b/src/components/JobAnalytics/JobsHitsApplicationsChart/JobsHitsApplicationsChart.jsx new file mode 100644 index 0000000000..23e0eda7d8 --- /dev/null +++ b/src/components/JobAnalytics/JobsHitsApplicationsChart/JobsHitsApplicationsChart.jsx @@ -0,0 +1,229 @@ +import { Fragment, useEffect, useState } from 'react'; +import { fetchJobsHitsApplications } from '../../../actions/jobAnalytics/JobsHitsApplicationsActions'; +import { useDispatch, useSelector } from 'react-redux'; +import { BarChart, XAxis, YAxis, Tooltip, Legend, Bar, ResponsiveContainer, Brush } from 'recharts'; +import styles from './JobsHitsApplicationsChart.module.css'; +import Select from 'react-select'; +import DatePicker from 'react-datepicker'; + +export const JobsHitsApplicationsChart = () => { + const [startDate, setStartDate] = useState(null); + const [endDate, setEndDate] = useState(null); + const [selectedRoles, setSelectedRoles] = useState([]); + const [roleOptions, setRoleOptions] = useState([]); + const [roleAssigned, setRoleAssigned] = useState(false); + + const { loading, data, error } = useSelector(state => state.jobsHitsApplications); + const darkMode = useSelector(state => state.theme.darkMode); + const dispatch = useDispatch(); + const token = localStorage.getItem('token'); + + useEffect(() => { + const queryParams = new URLSearchParams(); + if (startDate) queryParams.append('startDate', startDate.toISOString()); + if (endDate) queryParams.append('endDate', endDate.toISOString()); + if (selectedRoles.length > 0) { + const roles = selectedRoles.map(role => role.value).join(','); + queryParams.append('roles', roles); + } + dispatch(fetchJobsHitsApplications(queryParams.toString(), token)); + }, [startDate, endDate, selectedRoles, dispatch, token]); + + useEffect(() => { + if (data && data.length > 0 && !roleAssigned) { + setRoleOptions( + data.map(item => { + return { + value: item.role, + label: item.role, + }; + }, setRoleAssigned(true)), + ); + } + }, [loading, error, data]); + + const CustomYAxisNames = ({ x, y, payload }) => { + const text = payload.value; + const truncated = text.split(' ').slice(0, 2); + + return ( + + {truncated.map((line, index) => ( + + {text} + {line} + + ))} + + ); + }; + + const handleStartDateChange = date => { + if (endDate && date > endDate) { + setEndDate(date); + } + setStartDate(date); + }; + + const handleEndDateChange = date => { + if (startDate && date < startDate) { + setStartDate(date); + } + setEndDate(date); + }; + + const handleResetDates = () => { + setStartDate(null); + setEndDate(null); + }; + + return ( + +
+

Role-wise Hits and Applications

+
+
+
+ {startDate || endDate ? ( + + ) : ( + + )} +
+
+ + +
+
+ + +
+
+ +
+
+ +