Commit c748274f authored by Shiva Komirishetti's avatar Shiva Komirishetti

Activities api changes

parent f9ab470a
import React from "react";
function DashboardIcon() {
return (
<svg
className="size-4"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
<polyline points="9 22 9 12 15 12 15 22" />
</svg>
);
}
export default DashboardIcon;
import React from "react";
function ReportsIcon() {
return (
<svg
className="size-4"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z" />
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z" />
</svg>
);
}
export default ReportsIcon;
......@@ -29,12 +29,12 @@ function Accordion({ title, data ,handleAddActivity,open,handleAccordian}) {
// }
// },[userDetails,id])
useEffect(()=>{
if(reports?.length !==null){
dispatch(calculateDefaultScore(reports))
dispatch(calculateInitiativeScore(reports))
}
},[reports,id])
// useEffect(()=>{
// if(reports?.length !==null){
// dispatch(calculateDefaultScore(reports))
// dispatch(calculateInitiativeScore(reports))
// }
// },[reports,id])
function handleClick(){
handleAccordian(title)
......
import React from "react";
import { Link } from "react-router-dom";
import { Link, useParams } from "react-router-dom";
import SetWindowSize from '../../utils/SetWindowSize';
import DashboardIcon from '../../assets/icons/dashboardIcon';
import ReportsIcon from '../../assets/icons/reportsIcon';
const menus = [
{title: "Dashboard", path: '/dashboard', icon: <DashboardIcon/>},
{title: "Reports", path: '/reportees', icon: <ReportsIcon />}
]
function Sidebar() {
const url = window.location.href;
const [windowWidth, windowHeight] = SetWindowSize();
return (
......@@ -12,51 +20,20 @@ function Sidebar() {
data-hs-accordion-always-open
>
<ul className="space-y-1.5">
<li>
<Link
className={`flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-slate-700 rounded-lg hover:bg-gray-100 `}
to={`/dashboard`}
>
<svg
className="size-4"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
<polyline points="9 22 9 12 15 12 15 22" />
</svg>
Dashboard
</Link>
</li>
<li>
<Link
className={`flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-slate-700 rounded-lg hover:bg-gray-100 `} to={`/reportees`}
>
<svg
className="size-4"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
{
menus.map((menu) => (
<li>
<Link
className={`flex items-center${url.includes(menu.path) && 'bg-gray-500'} gap-x-3.5 py-2 px-2.5 text-sm text-slate-700 rounded-lg hover:bg-gray-100 `}
to={menu.path}
>
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z" />
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z" />
</svg>
Reports
</Link>
</li>
<span>{menu.icon}</span>
{menu.title}
</Link>
</li>
))
}
</ul>
</nav>
</div>
......
......@@ -101,7 +101,7 @@ function Exporttable() {
if (reportees?.length > 0) {
return (
<div>
<div className={` overflow-auto sm:rounded-lg p-4 bg-gray-100`}>
<div className={` overflow-auto sm:rounded-lg p-4 bg-[#E9EDEE]`}>
<div className="text-blue-800 py-3 pl-2 text-center">
{" "}
Genarate Report
......
......@@ -4,7 +4,7 @@ import { useParams, useNavigate } from "react-router";
import { base_url } from "../../utils/constants";
import axios from 'axios';
import { fetchReportees,setViewReportee } from "../../redux/reducers/reporteesSlice";
import {fetchReporteeActivities} from '../../redux/reducers/viewreporteeSlice'
import {fetchReporteeActivities, fetchActivitiesAvg} from '../../redux/reducers/viewreporteeSlice'
import Accordion from "../../components/accordion";
import {scoreColor} from '../../utils/commonFunctions';
......@@ -14,12 +14,10 @@ function Viewreportee() {
const navigate = useNavigate();
const {reportees, viewReportee } = useSelector((state) => state.reportees);
const user = useSelector((state) => state.userDetails.user)
const { reports, loading, error } = useSelector((state) => state.reports);
const { reports, loading, error, dutiesReports, initiativeReports } = useSelector((state) => state.reports);
const [open, setOpen] = useState({ "accordianOne": false, "accordianTwo": false });
/*Example post data
{
"empId":41689,
......@@ -27,20 +25,25 @@ function Viewreportee() {
"toDate":"2024-03-11"
}
*/
const activities = useMemo(() => {
if (reports) {
const filtered = Object.groupBy(reports, ({ type }) => type);
return filtered;
const fetchActivities = (type) => {
const data ={
empId:viewReportee?.empId,
types:[type],
page: 1,
perPage: 5
}
}, [reports, viewReportee]);
dispatch(fetchReporteeActivities(data))
}
const handleAccordian = (value) => {
switch (value) {
case "Duties":
setOpen({ ...open, "accordianOne": !open["accordianOne"], "accordianTwo": false });
fetchActivities('duties')
break;
case "Initiatives":
setOpen({ ...open, "accordianOne": false, "accordianTwo": !open["accordianTwo"] });
fetchActivities('initiative')
break;
default:
setOpen({ "accordianOne": false, "accordianTwo": false });
......@@ -51,7 +54,6 @@ function Viewreportee() {
if (user) {
const data = {
reportees: user.reportees,
sort: { type: "empId", order: 1 },
page: 1,
perPage: 10,
};
......@@ -68,7 +70,8 @@ function Viewreportee() {
}
await axios.post(`${base_url}/createActivity`, newData)
.then(async (result) => {
fetchLatestReporteesData()
fetchLatestReporteesData();
fetchActivities(activityData?.type)
})
} else {
alert("Please login")
......@@ -77,14 +80,14 @@ function Viewreportee() {
useEffect(()=>{
if(reportees.length>0 && viewReportee !== null)
dispatch(fetchReporteeActivities({empId:viewReportee?.empId}))
},[reportees,viewReportee])
dispatch(fetchActivitiesAvg({empId:viewReportee?.empId, types:["duties", "initiative"]}))
},[viewReportee])
// useEffect(()=>{
// if(reportees.length){
// dispatch(setViewReportee(viewReportee?.empId))
// }
// },[reportees])
useEffect(()=>{
if(reportees.length){
dispatch(setViewReportee(viewReportee?.empId))
}
},[reportees])
......@@ -142,10 +145,10 @@ function Viewreportee() {
</div>
<div className="">
<div className="">
<Accordion title="Duties" open={open.accordianOne} handleAccordian={handleAccordian} data={activities?.duties} handleAddActivity={handleAddActivity} />
<Accordion title="Duties" open={open.accordianOne} handleAccordian={handleAccordian} data={dutiesReports} handleAddActivity={handleAddActivity} />
</div>
<div className="">
<Accordion title="Initiatives" open={open.accordianTwo} handleAccordian={handleAccordian} data={activities?.initiative} handleAddActivity={handleAddActivity} />
<Accordion title="Initiatives" open={open.accordianTwo} handleAccordian={handleAccordian} data={initiativeReports} handleAddActivity={handleAddActivity} />
</div>
</div>
</div>
......
......@@ -4,6 +4,8 @@ import axios from "axios";
const initialState = {
reports: null,
dutiesReports: null,
initiativeReports: null,
defaultAvgScore:0,
initiativeAvgScore:0,
loading: false,
......@@ -13,6 +15,12 @@ const initialState = {
export const fetchReporteeActivities = createAsyncThunk("getReports", async (data) => {
return await axios
.post(`${base_url}/getActivities`, data)
.then((response) => response.data?.activities);
});
export const fetchActivitiesAvg = createAsyncThunk("getActivities-avg", async (data) => {
return await axios
.post(`${base_url}/getActivities-avg`, data)
.then((response) => response.data);
});
......@@ -23,39 +31,32 @@ const reportSlice = createSlice({
resetReports:() => {
return initialState
},
calculateDefaultScore:(state, action)=>{
if(action.payload===undefined){
return {...state,defaultAvgScore :0}
}else{
const dutiesItems = action.payload?.filter(item => item.type === "duties");
const totalDutiesScore =dutiesItems?.length? dutiesItems?.reduce((acc, curr) => acc+ Number(curr.score), 0):0;
const defaultAvgScore =totalDutiesScore===0?0: Number(totalDutiesScore) / Number(dutiesItems?.length);
return {...state,defaultAvgScore :Number(defaultAvgScore).toFixed(1)}
}
},
calculateInitiativeScore:(state,action)=>{
if(action.payload===undefined){
return {...state,initiativeAvgScore:0}
}
else{
const initiatiesItems = action.payload?.filter(item => item.type === "initiative");
const totalInitiateScore =initiatiesItems?.length? (initiatiesItems?.reduce((acc, curr) => acc+ Number(curr.score), 0)):0;
const initialAvgScore =totalInitiateScore===0?0: Number(totalInitiateScore) / Number(initiatiesItems?.length) ;
return {...state,initiativeAvgScore :Number(initialAvgScore).toFixed(1)}
}
},
},
extraReducers: (builder) => {
builder.addCase(fetchReporteeActivities.pending, (state) => {
return {...state,loading :true,error :"loading"}
});
builder.addCase(fetchReporteeActivities.fulfilled, (state, action) => {
return {...state,loading :false,error :"",reports:action.payload?.activities}
const {type} = action?.payload[0] ?? {}
return {...state,loading :false,error :"", [`${type}Reports`]: action.payload}
});
builder.addCase(fetchReporteeActivities.rejected, (state, action) => {
return {...state,loading :false,error :action.error || "Something went wrong!",reports:null}
});
// getActivities Api
builder.addCase(fetchActivitiesAvg.pending, (state) => {
return {...state,loading :true,error :"loading"}
});
builder.addCase(fetchActivitiesAvg.fulfilled, (state, action) => {
const avgScores = action.payload;
const dutiesAvg = avgScores.find(({type}) => type === "duties")
const initiatieAvg = avgScores.find(({type}) => type === "initiative")
return {...state,loading :false,error :"", defaultAvgScore: dutiesAvg?.avgScore.toFixed(1) || 0, initiativeAvgScore: initiatieAvg?.avgScore.toFixed(1) || 0}
});
builder.addCase(fetchActivitiesAvg.rejected, (state, action) => {
return {...state,loading :false,error :action.error || "Something went wrong!",reports:null}
});
},
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment