date-picker-added

parent 10514b98
This diff is collapsed.
......@@ -15,10 +15,12 @@
"moment": "^2.30.1",
"mongodb": "^6.5.0",
"react": "^18.2.0",
"react-datepicker": "^6.3.0",
"react-dom": "^18.2.0",
"react-redux": "^9.1.0",
"react-router-dom": "^6.22.3",
"react-scripts": "5.0.1",
"react-tailwindcss-datepicker": "^1.6.6",
"redux-thunk": "^3.1.0",
"web-vitals": "^2.1.4"
},
......
......@@ -19,15 +19,15 @@ connectToDb((err) => {
});
//to get all the employees data
app.get("/employees", (req, res) => {
db.collection("employees")
.find()
.toArray()
.then((result) => {
res.send(result);
})
.catch((error) => res.status(401).send(error));
});
// app.get("/employees", (req, res) => {
// db.collection("employees")
// .find()
// .toArray()
// .then((result) => {
// res.send(result);
// })
// .catch((error) => res.status(401).send(error));
// });
//to get only individual employee data
app.get("/employee/:id", (req, res) => {
......@@ -116,7 +116,7 @@ app.post("/getreportees", (req, res) => {
"aId":"D001",
"type":"default",
"score":3,
"comments":"very good"
"comments":""
}
}
*/
......
import React, { useState } from "react";
import { useEffect } from "react";
const DateRangePicker = ({getReports}) => {
const [value, setValue] = useState({
startDate: "",
endDate: ""
});
const handleStartChange = (newValue) => {
setValue({...value,startDate: newValue});
}
const handleEndChange = (newValue) => {
setValue({...value,endDate: newValue});
}
useEffect(()=>{
console.log(value.startDate)
getReports({startDate:value.startDate?value.startDate:null,endDate:value.endDate?value.endDate:null} )
},[value])
return (
<div>
<label htmlFor="start" className="font-bold">From:</label>
<input type="date" id="start" name="start" onChange={(e)=>handleStartChange(e.target.value)} />
<label htmlFor="end" className="font-bold">To:</label>
<input type="date" id="end" name="end" onChange={(e)=>handleEndChange(e.target.value)}/>
</div>
)
};
export default DateRangePicker;
\ No newline at end of file
import React, { useState } from "react";
import AccordionTable from "./accordionTable";
import ModalButton from "../modal/modalButton";
import { useSelector ,useDispatch} from "react-redux";
import { useEffect } from "react";
import { calculateDefaultScore,calculateInitiativeScore } from "../../redux/reducers/reportSlice";
function Accordion({ title, data }) {
function Accordion({ title, data ,handleAddActivity}) {
const dispatch=useDispatch()
const [open, setOpen] = useState(false);
const { reports,defaultAvgScore,initiativeAvgScore } = useSelector((state) => state.reports);
useEffect(()=>{
dispatch(calculateDefaultScore(reports))
dispatch(calculateInitiativeScore(reports))
},[reports])
const headers = [
{ title: "Name", id: "aName", width: "30%" },
......@@ -13,15 +26,17 @@ function Accordion({ title, data }) {
];
return (
<div className="px-4">
<button
onClick={() => setOpen(!open)}
type="button"
className="flex items-center justify-between w-full py-2 px-5 mt-4 font-medium rtl:text-right bg-[#B7B7B7] 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"
className="flex items-center w-full py-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"
>
<span>{title}</span>
<div className="w-1/2 text-start">{title}</div>
<div className="w-1/2">Average Score :{title === "Default Activities:" ? defaultAvgScore : initiativeAvgScore}</div>
<svg
data-accordion-icon
className="w-3 h-3 rotate-180 shrink-0"
......@@ -44,8 +59,8 @@ function Accordion({ title, data }) {
aria-labelledby="accordion-collapse-heading-2"
>
<AccordionTable headers={headers} data={data} />
<div className="flex justify-end mr-4">
<ModalButton type={`${title === "Default Activities:" ? "default" : "initiative"}`}/>
<div className="justify-end mr-4 flex align-items-center justify-items-center">
<ModalButton type={`${title === "Default Activities:" ? "default" : "initiative"}`} handleAddActivity={handleAddActivity}/>
</div>
</div>
</div>
......
......@@ -3,11 +3,12 @@ import React, { useMemo, useEffect, useState, useCallback } from "react";
import { base_url } from "../../utils/constants";
export default function MyModal({ visible, onClose ,type}) {
export default function MyModal({ visible, onClose ,type,handleAddActivity}) {
const [activitiesList, setActivitiesList] = useState([])
const [enableSubmit,setEnableSubmit]=useState(false)
const [scoreType,setScoreType]=useState(1)
const [activityData,setActivityData]=useState({aName:"",aId:"",type:type,score:0,comments:""})
const [activityType,setActivtyType]=useState("")
const getActivitysList= async()=>{
const activities=await axios.get(`${base_url}/activities`)
......@@ -33,7 +34,7 @@ export default function MyModal({ visible, onClose ,type}) {
const handleSubmit=(e)=>{
onClose()
console.log(activityData)
handleAddActivity(activityData)
}
useEffect(()=>{handleScoreChange(activityData.score)},[scoreType])
......@@ -46,8 +47,12 @@ export default function MyModal({ visible, onClose ,type}) {
}
}, [activityData]);
const SentenceCase=(type)=>{
let str=type;
setActivtyType(str.charAt(0).toUpperCase() + str.slice(1).toLowerCase())
}
useEffect(()=>{
SentenceCase(type)
if (visible===false){
setActivityData({aName:"",aId:"",type:type,score:0,comments:""})
}else{
......@@ -61,7 +66,7 @@ export default function MyModal({ visible, onClose ,type}) {
return (
<div className="fixed inset-0 bg-black bg-opacity-25 backdrop-blur-sm flex items-center justify-center">
<div className="bg-white rounded lg:w-4/12 sm:w-100">
<div className=" text-white py-3 pl-2 bg-blue-500">Default Activity</div>
<div className=" text-white py-3 pl-2 bg-blue-500">{activityType} Activity</div>
<div>
<div>
<form className=" p-2 max-w-sm mx-auto">
......
import React, { useState } from "react";
import MyModal from "./index";
export default function ModalButton({type}) {
export default function ModalButton({type,handleAddActivity}) {
const [showMyModal, setShowMyModal] = useState(false);
const handleOnClose = () => setShowMyModal(false);
return (
<div className="bg-blue-400 bg-opacity-30">
{/* // <div className="max-w-3xl mx-auto">
// <div className="text-center py-3"> */}
<button
onClick={() => setShowMyModal(true)}
className="bg-red-400 text-white px-3 py-2 rounded hover:scale-95 transition text-xl">
Add Activity
</button>
{/* // </div>
// <p className="text-lg">
// </p>
// </div> */}
<MyModal onClose={handleOnClose} visible={showMyModal} type={type}/>
<MyModal onClose={handleOnClose} visible={showMyModal} handleAddActivity={handleAddActivity} type={type}/>
</div>
);
}
\ No newline at end of file
import React, { useState, useEffect, useMemo } from "react";
import { useSelector, useDispatch } from "react-redux";
import { useParams } from "react-router";
import { base_url } from "../../utils/constants";
import axios from 'axios';
import { fetchReports } from "../../redux/reducers/reportSlice";
import Accordion from "../../components/accordion";
import DateRangePicker from "../../components/DateRangePicker";
function Reports() {
const { id } = useParams();
const empId=Number(id)
const dispatch = useDispatch();
const reportees = useSelector((state) => state.reportees.reportees);
const [empDetails, setEmpDetails] = useState(null);
const { reports } = useSelector((state) => state.reports);
const { reports} = useSelector((state) => state.reports);
/*Example post data
{
......@@ -25,6 +29,28 @@ function Reports() {
}
}, [reports]);
const getReports=({startDate, endDate})=>{
const data={"empId":empId,"fromDate":startDate,"toDate":endDate}
dispatch(fetchReports(data))
}
const handleAddActivity=(activityData)=>{
if(id){
let newData={
"empId":empId,
"data":activityData
}
axios.post(`${base_url}/createActivity`,newData)
.then((result)=>{
getReports()
})
}else{
alert("Please login")
}
}
useEffect(() => {
if(id) {
const emp = reportees?.filter((item) => item.empId === Number(id));
......@@ -41,6 +67,8 @@ function Reports() {
})
},[id]);
useEffect(()=>{},[reports])
return (
<div className="p-4">
<div className="flex bg-white p-3">
......@@ -79,8 +107,11 @@ function Reports() {
</div>
</div>
<div className="max-h-[60vh] overflow-auto">
<Accordion title="Default Activities:" data={activities?.default} />
<Accordion title="Initiatives:" data={activities?.initiatives} />
<div className="container mx-auto mt-4 flex justify-end pe-4">
<DateRangePicker getReports={getReports}/>
</div>
<Accordion title="Default Activities:" data={activities?.default} handleAddActivity={handleAddActivity}/>
<Accordion title="Initiatives:" data={activities?.initiative} handleAddActivity={handleAddActivity}/>
</div>
</div>
);
......
......@@ -4,6 +4,8 @@ import axios from "axios";
const initialState = {
reports: [],
defaultAvgScore:0,
initiativeAvgScore:0,
loading: false,
error: null,
};
......@@ -20,26 +22,34 @@ const reportSlice = createSlice({
reducers: {
resetReports:() => {
return initialState
}
},
calculateDefaultScore:(state, action)=>{
const defaultItems = action.payload?.filter(item => item.type === "default");
const totalDefaultScore = defaultItems.reduce((acc, curr) => acc+ curr.score, 0);
const defaultAvgScore = totalDefaultScore > 0 ? totalDefaultScore / defaultItems.length : 0;
return {...state,defaultAvgScore :defaultAvgScore.toFixed(1)}
},
calculateInitiativeScore:(state,action)=>{
const defaultItems = action.payload?.filter(item => item.type === "initiative");
const totalDefaultScore = defaultItems.reduce((acc, curr) => acc+ curr.score, 0);
const defaultAvgScore = totalDefaultScore > 0 ? totalDefaultScore / defaultItems.length : 0;
return {...state,initiativeAvgScore :defaultAvgScore.toFixed(1)}
},
},
extraReducers: (builder) => {
builder.addCase(fetchReports.pending, (state) => {
state.loading = true;
state.error = "pending";
return {...state,loading :true,error :"pending"}
});
builder.addCase(fetchReports.fulfilled, (state, action) => {
state.loading = false;
state.reports = action.payload?.activities;
state.error = "";
return {...state,loading :false,error :"",reports:action.payload?.activities}
});
builder.addCase(fetchReports.rejected, (state, action) => {
state.loading = false;
state.reports = [];
state.error = action.error || "Something went wrong!";
return {...state,loading :false,error :action.error || "Something went wrong!",reports:[]}
});
},
});
export const {resetReports} = reportSlice.actions;
export const {resetReports,calculateDefaultScore,calculateInitiativeScore} = reportSlice.actions;
export default reportSlice.reducer;
......@@ -2,6 +2,7 @@ module.exports = {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
"./node_modules/react-tailwindcss-datepicker/dist/index.esm.js",
],
theme: {
fontSize: {
......
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