loading added

parent e89390d0
......@@ -19,8 +19,8 @@ connectToDb((err) => {
});
//to get all the employees data
app.get("/employees", (req, res) => {
db.collection("employees")
app.get("/employees", async(req, res) => {
await db.collection("employees")
.find()
.toArray()
.then((result) => {
......@@ -30,9 +30,9 @@ app.get("/employees", (req, res) => {
});
//to get only individual employee data
app.get("/employee/:id", (req, res) => {
app.get("/employee/:id", async(req, res) => {
let Id = parseInt(req.params.id);
db.collection("employees")
await db.collection("employees")
.findOne({ empId: Id }, { projection: { _id: false } })
.then((result) => {
if (!result)
......@@ -44,8 +44,6 @@ app.get("/employee/:id", (req, res) => {
});
//login Check
//require empId
//example {empId:41689}
app.post('/login', async (req, res) => {
const { empId } = req.body;
try {
......@@ -66,8 +64,8 @@ app.post('/login', async (req, res) => {
//to get activities to display
app.get("/activities", (req, res) => {
db.collection("activities_master")
app.get("/activities", async(req, res) => {
await db.collection("activities_master")
.find()
.toArray()
.then((result) => {
......@@ -84,7 +82,7 @@ Example of post Data
,"page":1,"perPage":10,
"searchText":"eng"
}*/
app.post("/getreportees", (req, res) => {
app.post("/getreportees",async (req, res) => {
let reporteesArray = req.body.reportees || [];
let sortBy = req.body.sort ? req.body.sort.type || "_id" : "_id";
let sortByOrder = req.body.sort ? parseInt(req.body.sort.order) || 1 : 1;
......@@ -115,7 +113,7 @@ app.post("/getreportees", (req, res) => {
};
aggre.push({ $facet: facet });
aggre.push({ $unwind: { path: "$totalCount" } });
db.collection("employees")
await db.collection("employees")
.aggregate(aggre)
.toArray()
.then((result) => {
......@@ -132,7 +130,7 @@ app.post("/getreportees", (req, res) => {
//Example of post Data
/*
{
"empId":41689,
"empId":10000,
"data":{
"aName":"Approval of timesheet",
"aId":"D001",
......@@ -142,135 +140,72 @@ app.post("/getreportees", (req, res) => {
}
}
*/
// app.post('/createActivity',async (req, res) => {
// const empId = req.body.empId;
// if (!empId) {
// res.status(401).json({ "message": "Employee id is missing" });
// return
// } else {
// let { data } = req.body;
// //data validation
// if (!_.get(data, "aName", "") || !_.get(data, "aId", "") || !_.get(data, "type", "") || !_.get(data, "score", "")) {
// res.status(401).json({ "error": "Invalid Activity data" });
// return;
// }
// if (data.score === (0 || -0) || data.score > 5 || data.score < -5) {
// res.status(401).json({ "message": "Score Should be between 1 to 5 or -1 to -5 only" });
// return
// }
// if(data["comments"]===undefined){
// res.status(401).json({ "message": "need comments field" });
// return
// }
// data = { ...data, "recorded_date": new Date() };
// data = Object.assign(data, { "_id": new ObjectId() })
// let query = { empId: empId };
// await db.collection('performance_master').findOne(query).then(async(result) => {
// if (result) {
// await db.collection('performance_master').updateOne(query, { $push: { "activities": data } })
// .then(async (updateRes) => {
// await calculateAverage(query);
// res.status(201).json({ "reuslt": updateRes });
// })
// .catch((error) => {
// res.json({ "error": error });
// });
// } else {
// let insertData = { empId: empId, activities: [] };
// insertData.activities.push(data);
// await db.collection('performance_master').insertOne(insertData).then(async (result) => {
// await calculateAverage(query);
// res.status(201).json({ "result": result });
// }).catch((error) => {
// res.json({ "message": error })
// })
// }
// }).catch((error) => {
// console.log(error)
// res.send(query)
// })
// }
// })
app.post('/createActivity', async (req, res) => {
app.post('/createActivity',async (req, res) => {
const empId = req.body.empId;
if (!empId) {
res.status(401).json({ "message": "Employee id is missing" });
return;
return
} else {
let { data } = req.body;
// Data validation
if (
data === undefined ||
typeof data.aName !== 'string' || data.aName.trim() === '' ||
typeof data.aId !== 'string' || data.aId.trim() === '' ||
typeof data.type !== 'string' || data.type.trim() === '' ||
typeof data.score !== 'number'
) {
//data validation
if (!_.get(data, "aName", "") || !_.get(data, "aId", "") || !_.get(data, "type", "") || !_.get(data, "score", "")) {
res.status(401).json({ "error": "Invalid Activity data" });
return;
}
if (data.score === 0 || data.score === -0 || data.score > 5 || data.score < -5) {
res.status(401).json({ "message": "Score should be between 1 to 5 or -1 to -5 only" });
return;
if (data.score === (0 || -0) || data.score > 5 || data.score < -5) {
res.status(401).json({ "message": "Score Should be between 1 to 5 or -1 to -5 only" });
return
}
if (data.comments === undefined) {
res.status(401).json({ "message": "Need comments field" });
return;
if(data["comments"]===undefined){
res.status(401).json({ "message": "need comments field" });
return
}
data = { ...data, "recorded_date": new Date() };
data = Object.assign(data, { "_id": new ObjectId() });
data = Object.assign(data, { "_id": new ObjectId() })
let query = { empId: empId };
await db.collection('performance_master').findOne(query).then(async (result) => {
await db.collection('performance_master').findOne(query).then(async(result) => {
if (result) {
await db.collection('performance_master').updateOne(query, { $push: { "activities": data } })
await db.collection('performance_master').updateOne(query, { $push: { "activities": data } })
.then(async (updateRes) => {
await calculateAverage(result); // Pass result instead of query
res.status(201).json({ "result": updateRes });
await calculateAverage(query);
res.status(201).json({ "reuslt": updateRes });
})
.catch((error) => {
res.json({ "error": error });
});
} else {
let insertData = { empId: empId, activities: [] };
insertData.activities.push(data);
await db.collection('performance_master').insertOne(insertData).then(async (result) => {
await calculateAverage(result); // Pass result instead of query
await db.collection('performance_master').insertOne(insertData).then(async (result) => {
await calculateAverage(query);
res.status(201).json({ "result": result });
}).catch((error) => {
res.json({ "message": error });
});
res.json({ "message": error })
})
}
}).catch((error) => {
console.log(error);
res.send(error);
});
}
});
console.log(error)
res.send(query)
})
}
})
//calculating average score and updating into employees data
const calculateAverage = (query) => {
return new Promise((res, rej) => {
db.collection("performance_master")
const calculateAverage = async(query) => {
return await new Promise(async(res, rej) => {
await db.collection("performance_master")
.findOne(query)
.then((result) => {
.then(async(result) => {
let activitiesList = result.activities;
let activitiesLength = activitiesList.length;
let score = activitiesList.reduce((acc, curr) => { return acc + curr.score }, 0);
......@@ -283,7 +218,7 @@ const calculateAverage = (query) => {
averageScore = averageScore.toFixed(1);
}
db.collection("employees")
await db.collection("employees")
.updateOne(query, { $set: { score: Number(averageScore) } })
.then((result) => {
res(result);
......@@ -304,7 +239,7 @@ const calculateAverage = (query) => {
"toDate":"2024-03-14"
}
*/
app.post("/getActivities", (req, res) => {
app.post("/getActivities", async(req, res) => {
let { empId, fromDate, toDate, today } = req.body;
if (!empId || typeof empId == "string") {
res.status(401).json({ message: "Employee id is missing / EmpId should be string only" });
......@@ -330,7 +265,7 @@ app.post("/getActivities", (req, res) => {
$lte: moment().toDate(),
};
}
db.collection("performance_master")
await db.collection("performance_master")
.findOne(query)
.then((results) => {
res.status(201).json(results);
......@@ -339,4 +274,4 @@ app.post("/getActivities", (req, res) => {
res.status(401).json({ message: "Error fetching data" }, error);
});
}
});
});
\ No newline at end of file
......@@ -7,27 +7,30 @@ import { useEffect } from "react";
import {useParams} from 'react-router'
import { fetchReportees } from "../../redux/reducers/reporteesSlice";
import { calculateDefaultScore,calculateInitiativeScore } from "../../redux/reducers/reportSlice";
import Loading from "../loading Component/Loading";
function Accordion({ title, data ,handleAddActivity,open,handleAccordian}) {
const dispatch=useDispatch()
const {id}=useParams()
const { reports,defaultAvgScore,initiativeAvgScore } = useSelector((state) => state.reports);
const { reports,defaultAvgScore,initiativeAvgScore ,loading} = useSelector((state) => state.reports);
const userDetails = useSelector((state) => state.userDetails);
useEffect(()=>{
const data = {
reportees: userDetails.user.reportees,
sort: { type: "empId", order: 1 },
page: 1,
perPage: 10,
}
dispatch(fetchReportees(data))
if(userDetails.user!==null){
const data = {
reportees: userDetails.user.reportees,
sort: { type: "empId", order: 1 },
page: 1,
perPage: 10,
}
dispatch(fetchReportees(data))
}
},[userDetails,id])
useEffect(()=>{
if(reports !=[]){
if(reports !==null){
dispatch(calculateDefaultScore(reports))
dispatch(calculateInitiativeScore(reports))
}
......@@ -42,36 +45,41 @@ function Accordion({ title, data ,handleAddActivity,open,handleAccordian}) {
{ title: "Score", id: "score", width: "10%", render: (value) => <div className="w-[35px] bg-blue-200 rounded-md text-center p-[4px]">{value}</div> },
{ title: "Comments", id: "comments", width: "40%" },
];
return (
<div className="px-4">
<button
onClick={handleClick}
type="button"
className="flex items-center rounded-lg w-full py-2 px-2 mt-4 font-medium rtl:text-right bg-white text-gray-500 border border-[#B7B7B7] focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-800 dark:border-gray-700 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 gap-3" data-accordion-target="#accordion-collapse-body-2" aria-expanded="false" aria-controls="accordion-collapse-body-2" >
<div className="w-1/2 text-start ms-2">{title}</div>
<div className="w-1/2 flex justify-between">
Average Score :{title === "Default" ? defaultAvgScore : initiativeAvgScore}
<ModalButton type={`${title === "Default" ? "default" : "initiative"}`} handleAddActivity={handleAddActivity}/>
if(loading && title =="Default")return <Loading/>
if(!loading){
return (
<div className="px-4">
<button
onClick={handleClick}
type="button"
className="flex items-center rounded-lg w-full py-2 px-2 mt-4 font-medium rtl:text-right bg-white text-gray-500 border border-[#B7B7B7] focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-800 dark:border-gray-700 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 gap-3" data-accordion-target="#accordion-collapse-body-2" aria-expanded="false" aria-controls="accordion-collapse-body-2" >
<div className="w-1/2 text-start ms-2">{title}</div>
<div className="w-1/2 flex justify-between">
Average Score :{title === "Default" ? defaultAvgScore : initiativeAvgScore}
<ModalButton type={`${title === "Default" ? "default" : "initiative"}`} handleAddActivity={handleAddActivity}/>
</div>
<svg data-accordion-icon className="w-3 h-3 rotate-180 shrink-0" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
<path
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M9 5 5 1 1 5"
/>
</svg>
</button>
<div
className={`${!open && "hidden"} mt-2`}
aria-labelledby="accordion-collapse-heading-2"
>
<Table headers={headers} loading={loading} data={data} maxHeight={10}/>
</div>
<svg data-accordion-icon className="w-3 h-3 rotate-180 shrink-0" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
<path
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M9 5 5 1 1 5"
/>
</svg>
</button>
<div
className={`${!open && "hidden"} mt-2`}
aria-labelledby="accordion-collapse-heading-2"
>
<Table headers={headers} data={data} maxHeight={10}/>
</div>
</div>
);
);
}
}
export default Accordion;
......@@ -6,7 +6,6 @@ const DateRangePicker = ({getReports}) => {
const [value, setValue] = useState({
startDate: "",
endDate: ""
});
const handleStartChange = (newValue) => {
......@@ -17,7 +16,9 @@ const DateRangePicker = ({getReports}) => {
}
useEffect(()=>{
if(value.startDate!=="" & value.endDate!==""){
getReports(value.startDate?value.startDate:null,value.endDate?value.endDate:null )
}
},[value])
return (
......
......@@ -2,20 +2,21 @@ import React,{useEffect,useState} from "react";
import { Link } from "react-router-dom";
import { useSelector } from "react-redux";
import { useParams } from "react-router-dom";
import Loading from "../loading Component/Loading";
function LeftSidebar() {
const reportees = useSelector((state) => state.reportees.reportees);
const {reportees,loading} = useSelector((state) => state.reportees);
const {id} = useParams()
// const [refresh,setRefresh]=useState(false)
// useEffect(()=>{ setRefresh(!refresh)},[reportees])
return (
<div className="mt-2 w-[30%] flex flex-col px-[5px]">
<p className="text-xl text-blue-400 font-semibold pl-4 mt-3">
My Reportees
</p>
<div className="p-2 bg-[#E9EDEE] mt-4 max-h-[80vh] overflow-auto">
{
(loading)? <Loading/>:
<div className="p-2 bg-[#E9EDEE] mt-4 max-h-[80vh] overflow-auto">
{reportees?.map(({ empName, score, empId }) => (
<Link
to={`/viewreportee/${empId}`}
......@@ -32,6 +33,8 @@ function LeftSidebar() {
</Link>
))}
</div>
}
</div>
);
}
......
import React, { memo } from 'react';
import Loader1 from './Loade1.gif'
import Spin from './Spin1.png'
const Loading = memo(() => {
return (
<div className='w-100'>
<p className='text-blue-500 flex justify-center items-center h-full mt-28'>
<img src={Spin} alt="Loading" width={100} height={100} />
{/* loading */}
</p>
</div>
);
});
export default Loading;
\ No newline at end of file
import React from "react";
import Loading from "../loading Component/Loading";
function Table({headers, data, maxHeight}) {
function Table({headers, data,loading, maxHeight}) {
if(loading) return <Loading/>
return (
<div className={` overflow-x-auto sm:rounded-lg p-4 max-h-[${maxHeight}vh]`}>
<table className="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400 bg-transparent justify-center border-separate border-spacing-y-2">
......
import React, { useEffect } from "react";
import React, { useEffect, useState } from "react";
import { Link ,useNavigate} from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import { fetchReportees } from "../../redux/reducers/reporteesSlice";
......@@ -7,9 +7,10 @@ import Table from '../../components/table';
function Dashboard() {
const dispatch = useDispatch();
const navigate=useNavigate();
const reportees = useSelector((state) => state.reportees.reportees);
const {reportees,loading} = useSelector((state) => state.reportees);
const userDetails = useSelector((state) => state.userDetails);
const reporteIds = userDetails.user.reportees || [];
const [reporteIds,setReporteIds] =useState([]);
// userDetails.user.reportees || [];
useEffect(() => {
if (reporteIds.length > 0) {
......@@ -24,7 +25,8 @@ function Dashboard() {
}, [reporteIds]);
useEffect(() => {
if(userDetails.user !== null){
if(userDetails.user){
setReporteIds(userDetails.user.reportees)
navigate("/dashboard")
}else{
navigate("/")
......@@ -63,7 +65,7 @@ function Dashboard() {
return (
<div>
<Table headers={headers} data={reportees} maxHeight={88}/>
<Table headers={headers} data={reportees} loading={loading} maxHeight={88}/>
</div>
)
}
......
......@@ -15,7 +15,7 @@ function Reports() {
const reportees = useSelector((state) => state.reportees.reportees);
const user=useSelector((state)=>state.userDetails.user)
const [empDetails, setEmpDetails] = useState(null);
const { reports } = useSelector((state) => state.reports);
const { reports ,loading,error} = useSelector((state) => state.reports);
const [open, setOpen] = useState({"accordianOne":true,"accordianTwo":false});
......@@ -28,7 +28,7 @@ function Reports() {
}
*/
const activities = useMemo(() => {
if (reports !== undefined) {
if (reports) {
const filtered = Object.groupBy(reports, ({ type }) => type);
return filtered;
}
......@@ -96,9 +96,6 @@ function Reports() {
})
}, [id,reportees]);
return (
<div className="p-4" >
<div className=" bg-white p-3">
......@@ -142,6 +139,7 @@ function Reports() {
</div>
</div>
);
// }
}
......
......@@ -3,7 +3,7 @@ import { base_url } from "../../utils/constants";
import axios from "axios";
const initialState = {
reports: [],
reports: null,
defaultAvgScore:0,
initiativeAvgScore:0,
loading: false,
......@@ -39,13 +39,13 @@ const reportSlice = createSlice({
},
extraReducers: (builder) => {
builder.addCase(fetchReports.pending, (state) => {
return {...state,loading :true,error :"pending"}
return {...state,loading :true,error :"loading"}
});
builder.addCase(fetchReports.fulfilled, (state, action) => {
return {...state,loading :false,error :"",reports:action.payload?.activities}
});
builder.addCase(fetchReports.rejected, (state, action) => {
return {...state,loading :false,error :action.error || "Something went wrong!",reports:[]}
return {...state,loading :false,error :action.error || "Something went wrong!",reports:null}
});
},
});
......
import {resetUser} from '../redux/reducers/userSlice';
import {resetReportees} from '../redux/reducers/reporteesSlice';
import { resetReports } from '../redux/reducers/reportSlice';
const clearStore = (dispatch) => {
dispatch(resetUser());
dispatch(resetReportees());
dispatch(resetReports())
};
export default clearStore;
\ No newline at end of file
// export const base_url = 'http://localhost:4000'
export const base_url = 'https://nisumscorecardserverdev.netlify.app/.netlify/functions/api'
\ No newline at end of file
export const base_url = 'https://nisumscorecardserverdev.netlify.app/.netlify/functions/api'
// export const base_url = 'https://nisumscorecardservertesting.netlify.app/.netlify/functions/api'
\ No newline at end of file
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