date-picker-added

parent 10514b98
......@@ -20,10 +20,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"
},
......@@ -2390,6 +2392,54 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@floating-ui/core": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz",
"integrity": "sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==",
"dependencies": {
"@floating-ui/utils": "^0.2.1"
}
},
"node_modules/@floating-ui/dom": {
"version": "1.6.3",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz",
"integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==",
"dependencies": {
"@floating-ui/core": "^1.0.0",
"@floating-ui/utils": "^0.2.0"
}
},
"node_modules/@floating-ui/react": {
"version": "0.26.9",
"resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.9.tgz",
"integrity": "sha512-p86wynZJVEkEq2BBjY/8p2g3biQ6TlgT4o/3KgFKyTWoJLU1GZ8wpctwRqtkEl2tseYA+kw7dBAIDFcednfI5w==",
"dependencies": {
"@floating-ui/react-dom": "^2.0.8",
"@floating-ui/utils": "^0.2.1",
"tabbable": "^6.0.1"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/@floating-ui/react-dom": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.8.tgz",
"integrity": "sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==",
"dependencies": {
"@floating-ui/dom": "^1.6.1"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/@floating-ui/utils": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz",
"integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q=="
},
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.14",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
......@@ -3767,6 +3817,104 @@
"tailwindcss": "^1.5.0"
}
},
"node_modules/@testing-library/dom": {
"version": "9.3.4",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.4.tgz",
"integrity": "sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.10.4",
"@babel/runtime": "^7.12.5",
"@types/aria-query": "^5.0.1",
"aria-query": "5.1.3",
"chalk": "^4.1.0",
"dom-accessibility-api": "^0.5.9",
"lz-string": "^1.5.0",
"pretty-format": "^27.0.2"
},
"engines": {
"node": ">=14"
}
},
"node_modules/@testing-library/dom/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"peer": true,
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/@testing-library/dom/node_modules/aria-query": {
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz",
"integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==",
"peer": true,
"dependencies": {
"deep-equal": "^2.0.5"
}
},
"node_modules/@testing-library/dom/node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"peer": true,
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/@testing-library/dom/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"peer": true,
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/@testing-library/dom/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"peer": true
},
"node_modules/@testing-library/dom/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"peer": true,
"engines": {
"node": ">=8"
}
},
"node_modules/@testing-library/dom/node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"peer": true,
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@testing-library/jest-dom": {
"version": "5.17.0",
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz",
......@@ -6215,6 +6363,11 @@
"resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz",
"integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ=="
},
"node_modules/classnames": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
"integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="
},
"node_modules/clean-css": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz",
......@@ -6939,6 +7092,21 @@
"node": ">=10"
}
},
"node_modules/date-fns": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.5.0.tgz",
"integrity": "sha512-a+DwyXn7NOfdJireCzAA0B9p7jIXEu/Q9JKCyMYvH6+0vPUNbQceA0neXrdfJ/xzl3mhOh5vibQQ3936Tssm6A==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/kossnocorp"
}
},
"node_modules/dayjs": {
"version": "1.11.10",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz",
"integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==",
"peer": true
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
......@@ -15106,6 +15274,22 @@
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
},
"node_modules/react-datepicker": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-6.3.0.tgz",
"integrity": "sha512-1kDbFRDxfV7IMO/m6DgCHk+mzSbFMtJC1YTwp34rcBEMd6lVTROH7IUcCgl08rwTnjqV0iG3IzGlspB8wgjaBA==",
"dependencies": {
"@floating-ui/react": "^0.26.2",
"classnames": "^2.2.6",
"date-fns": "^3.3.1",
"prop-types": "^15.7.2",
"react-onclickoutside": "^6.13.0"
},
"peerDependencies": {
"react": "^16.9.0 || ^17 || ^18",
"react-dom": "^16.9.0 || ^17 || ^18"
}
},
"node_modules/react-dev-utils": {
"version": "12.0.1",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz",
......@@ -15245,6 +15429,19 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
},
"node_modules/react-onclickoutside": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.0.tgz",
"integrity": "sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A==",
"funding": {
"type": "individual",
"url": "https://github.com/Pomax/react-onclickoutside/blob/master/FUNDING.md"
},
"peerDependencies": {
"react": "^15.5.x || ^16.x || ^17.x || ^18.x",
"react-dom": "^15.5.x || ^16.x || ^17.x || ^18.x"
}
},
"node_modules/react-redux": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.0.tgz",
......@@ -15381,6 +15578,15 @@
}
}
},
"node_modules/react-tailwindcss-datepicker": {
"version": "1.6.6",
"resolved": "https://registry.npmjs.org/react-tailwindcss-datepicker/-/react-tailwindcss-datepicker-1.6.6.tgz",
"integrity": "sha512-kHSUonRO86PoYQQWPqpaSw2JeEn9OafdLsLBG85zO5Sfs23Ku8Ixt/YO+Is3TCBcFeOKnZgzhGLmP3NAXVlFkA==",
"peerDependencies": {
"dayjs": "^1.11.6",
"react": "^17.0.2 || ^18.2.0"
}
},
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
......@@ -16951,6 +17157,11 @@
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="
},
"node_modules/tabbable": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
"integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="
},
"node_modules/tailwindcss": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz",
......@@ -17407,6 +17618,19 @@
"is-typedarray": "^1.0.0"
}
},
"node_modules/typescript": {
"version": "4.9.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=4.2.0"
}
},
"node_modules/unbox-primitive": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
......
......@@ -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