Commit 859b581b authored by Shiva Komirishetti's avatar Shiva Komirishetti

layout changes and redux persist changes

parent eee13f7c
......@@ -26,6 +26,7 @@
"react-router-dom": "^6.22.3",
"react-scripts": "5.0.1",
"react-tailwindcss-datepicker": "^1.6.6",
"redux-persist": "^6.0.0",
"redux-thunk": "^3.1.0",
"web-vitals": "^2.1.4"
},
......@@ -15647,6 +15648,14 @@
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w=="
},
"node_modules/redux-persist": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/redux-persist/-/redux-persist-6.0.0.tgz",
"integrity": "sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==",
"peerDependencies": {
"redux": ">4.0.0"
}
},
"node_modules/redux-thunk": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
......
......@@ -4,7 +4,6 @@
"private": true,
"dependencies": {
"@reduxjs/toolkit": "^2.2.1",
"@tailwindcss/ui": "^0.7.2",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
......@@ -20,7 +19,7 @@
"react-redux": "^9.1.0",
"react-router-dom": "^6.22.3",
"react-scripts": "5.0.1",
"react-tailwindcss-datepicker": "^1.6.6",
"redux-persist": "^6.0.0",
"redux-thunk": "^3.1.0",
"web-vitals": "^2.1.4"
},
......
......@@ -17,8 +17,7 @@ const DateRangePicker = ({getReports}) => {
}
useEffect(()=>{
console.log(value.startDate)
getReports({startDate:value.startDate?value.startDate:null,endDate:value.endDate?value.endDate:null} )
getReports(value.startDate?value.startDate:null,value.endDate?value.endDate:null )
},[value])
return (
......
import React, { useState } from "react";
import AccordionTable from "./accordionTable";
import Table from "../table";
import moment from "moment";
import ModalButton from "../modal/modalButton";
import { useSelector ,useDispatch} from "react-redux";
import { useEffect } from "react";
......@@ -20,8 +21,8 @@ function Accordion({ title, data ,handleAddActivity}) {
const headers = [
{ title: "Name", id: "aName", width: "30%" },
{ title: "Date", id: "recorded_date", width: "20%" },
{ title: "Score", id: "score", width: "10%" },
{ title: "Date", id: "recorded_date", width: "20%", render: (value) => moment(value).format('DD-MM-YYYY') },
{ 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 (
......@@ -58,7 +59,7 @@ function Accordion({ title, data ,handleAddActivity}) {
className={`${!open && "hidden"} mt-2`}
aria-labelledby="accordion-collapse-heading-2"
>
<AccordionTable headers={headers} data={data} />
<Table headers={headers} data={data} maxHeight={30}/>
<div className="justify-end mr-4 flex align-items-center justify-items-center">
<ModalButton type={`${title === "Default Activities:" ? "default" : "initiative"}`} handleAddActivity={handleAddActivity}/>
</div>
......
import React from 'react';
import React, {useState} from 'react';
import {useNavigate, Link } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import clearStore from '../../utils/clearStore';
......@@ -6,7 +6,8 @@ import clearStore from '../../utils/clearStore';
function Header() {
const dispatch = useDispatch();
const navigate = useNavigate();
const userDetails = useSelector((state) => state.userDetails.user);
const user = useSelector((state) => state.userDetails.user);
const [open, setOpen] = useState(false)
const handleLogout = () => {
navigate('/');
......@@ -16,14 +17,16 @@ function Header() {
return (
<div className="flex items-center justify-between py-5 px-10">
<img src="/logo.png"/>
<div className="w-[23%]">
<Link to={`/${userDetails?.empId}/dashboard`}><button className="pr-10 hover:text-blue-400">Home</button></Link>
<Link><button className="hover:text-blue-400">Reports</button></Link>
</div>
<div className="flex items-center">
<img src="/power-button.png" width="30px" height="30px"/>
<button className="ml-2 -mt-1 text-2xl" onClick={handleLogout}>
Logout
<div className="flex items-center relative">
<button className=" -mt-1 text-2xl flex" onClick={() => setOpen(!open)}>
<img src="/user.png" width="35px" height="35px" className="mt-2 pr-2" />
<div className="flex flex-col">
<p className="text-lg font-semibold">{user.empName}</p>
<p className="text-xs">{user.designation}</p>
</div>
</button>
<button onClick={handleLogout} className={`${!open && "hidden"} absolute top-[40px] bg-white opacity-100 shadow-md px-5 py-1 bg-opacity-100 rounded border border-gray-400 right-0 hover:bg-blue-400 hover:text-white w-[-webkit-fill-available]`} style={{zIndex: 1}}>
Logout
</button>
</div>
</div>
......
import React from "react";
import { Link } from "react-router-dom";
import { useSelector } from "react-redux";
import { useParams } from "react-router-dom";
function LeftSidebar() {
const reportees = useSelector((state) => state.reportees.reportees);
const {id} = useParams()
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">
{reportees?.map(({ empName, score, empId }) => (
<Link
to={`/${empId}/reports`}
className={`flex items-center bg-${
Number(id) === empId ? "indigo-400" : "white"
} p-2 justify-between mb-1 w-full`}
key={empId}
>
<img src="/man.png" width="18px" height="18px" />
<p className="w-[80%] text-left">{empName}</p>
<p className="w-[10%] bg-blue-200 rounded-sm text-center">
{score}
</p>
</Link>
))}
</div>
</div>
);
}
export default LeftSidebar;
import React from "react";
import {Link} from 'react-router-dom';
import { Link } from "react-router-dom";
import { useSelector } from "react-redux";
import { useParams } from "react-router-dom";
function Sidebar() {
const user = useSelector((state) => state.userDetails.user);
const reportees = useSelector((state) => state.reportees.reportees);
const url = window.location.href;
const {id} = useParams()
const user = useSelector((state) => state.userDetails.user);
return (
<div className="w-[30%] flex items-center flex-col px-4">
<div>
<img src="/generic-male-avatar-rectangular.jpg" width="130px" height="130px" />
</div>
<div className="flex items-center flex-col mt-5">
<p className="text-lg font-semibold">{user.empName}</p>
<p>{user.designation}</p>
</div>
{
url.includes('/reports') && <div className="mt-5 border-t-2 border-gray-300 w-[-webkit-fill-available] flex flex-col ">
<p className="text-xl text-blue-400 font-semibold pl-4 mt-3">My Project Allocations</p>
<div className="p-2 bg-[#E9EDEE] mt-4 max-h-[49vh] overflow-auto">
{
reportees?.map(({empName, score, empId}) => (
<Link to={`/${empId}/reports`} className={`flex items-center bg-${Number(id) === empId ? "indigo-400" : "white"} p-2 justify-between mb-1 w-full`} key={empId}>
<img src="/man.png" width="18px" height="18px" />
<p className="w-[80%] text-left">{empName}</p>
<p className="w-[10%] bg-blue-200 rounded-sm text-center">{score}</p>
</Link>
))
}
</div>
</div>
}
<div className="w-[20%] flex items-center flex-col">
<nav
class="hs-accordion-group p-6 w-full flex flex-col flex-wrap"
data-hs-accordion-always-open
>
<ul class="space-y-1.5">
<li>
<Link
class={`flex items-center gap-x-3.5 py-2 px-2.5 bg-gray-100 text-sm text-slate-700 rounded-lg hover:bg-gray-100 dark:bg-gray-900 dark:text-white dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-gray-600`}
to={`/${user?.empId}/dashboard`}
>
<svg
class="size-4"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="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
class={`flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-slate-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-900 dark:text-slate-400 dark:hover:text-slate-300 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-gray-600`}
>
<svg
class="size-4"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="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>
Reports
</Link>
</li>
</ul>
</nav>
</div>
);
}
......
import React from "react";
import {Link} from 'react-router-dom';
function Table({headers, data, isView}) {
function Table({headers, data, maxHeight}) {
return (
<div className="relative overflow-x-auto sm:rounded-lg p-3">
<table className="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400 bg-transparent justify-center">
<div className={`relative 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">
<thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400 ">
<tr>
<tr className="mb-2">
{headers.map((item) => (
<th scope="col" className="px-6 py-3" >
<th scope="col" className={`px-6 py-4 w-[${item.width}]`} >
{item.title}
</th>
))}
......@@ -16,14 +15,15 @@ function Table({headers, data, isView}) {
</thead>
<tbody>
{
data?.map((item, index) => (
<tr className="bg-white border-b-8 dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600">
{headers?.map((field) => (
field.id !== "action" ?<td className="px-6 py-4 listData" >{field.id==="empName"?<span className="flex items-center"><img className="pr-2" src="/man.png" width="30px" height="30px"/>{item[field.id]}</span> :item[field.id]}</td> : <td className="px-6 py-3 border-l-2"><Link to={`/${item.empId}/reports`}><button type="button" className="bg-blue-400 text-white rounded-md px-3 py-1">View</button></Link></td>
))}
</tr>
))
data?.map((item, index) => (
<tr className="bg-white dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600">
{
headers?.map(({render, id}) => (
<td className="px-6 py-4 listData" >{render ? render(item[id]) : item[id] }</td>
))
}
</tr>
))
}
</tbody>
</table>
......
......@@ -15,6 +15,6 @@ code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
.listData:nth-child(4) {
/* .listData:nth-child(4) {
padding-left: 35px;
}
\ No newline at end of file
} */
\ No newline at end of file
import React, { useEffect } from "react";
import { useParams } from "react-router-dom";
import { useParams, Link } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import { fetchReportees } from "../../redux/reducers/reporteesSlice";
import { fetchUser } from "../../redux/reducers/userSlice";
......@@ -30,16 +30,38 @@ function Dashboard() {
}, [id]);
const headers = [
{title: "Employee Name", id:"empName"},
{title: "Emp.Id", id: "empId"},
{title: "Designation", id: 'designation'},
{title: "score", id:"score"},
{title: "Action", id:"action"},
{
title: "Employee Name",
id:"empName",
render: (value) => <span className="flex items-center"><img className="pr-2" src="/man.png" width="30px" height="30px"/>{value}</span>
},
{
title: "Emp.Id",
id: "empId"
},
{
title: "Designation",
id: 'designation'
},
{
title: "score",
id:"score",
render: (value) => <div className="bg-blue-200 rounded-md text-center p-[4px]">{value}</div>
},
{
title: "Email",
id: 'empEmail'
},
{
title: "Action",
id:"empId",
render: (value) => <Link to={`/${value}/reports`}><button className="bg-blue-400 text-white rounded-md px-3 py-1">View</button></Link>
},
]
return (
<div>
<Table headers={headers} data={reportees} isView={true}/>
<Table headers={headers} data={reportees} maxHeight={88}/>
</div>
)
}
......
import React from 'react'
import Header from '../../components/header';
import Sidebar from '../../components/sidebar';
import LeftSidebar from '../../components/leftSidebar';
function Layout({children}) {
const url = window.location.href;
return (
<div>
<Header/>
......@@ -11,6 +13,7 @@ function Layout({children}) {
<div className="bg-[#E9EDEE] w-full" style={{height:"88vh"}}>
{children}
</div>
{url.includes('/reports') && <LeftSidebar/>}
</div>
</div>
)
......
......@@ -31,7 +31,7 @@ function Reports() {
const getReports=({startDate, endDate})=>{
const getReports=(startDate=null, endDate=null)=>{
const data={"empId":empId,"fromDate":startDate,"toDate":endDate}
dispatch(fetchReports(data))
}
......@@ -82,7 +82,7 @@ function Reports() {
<div className="flex flex-col w-[85%]">
<div className="flex py-4">
<p className="w-[23%]">
<span className="font-medium">Email Id: </span>Null
<span className="font-medium">Email Id: </span>{empDetails?.empEmail}
</p>
<p className="w-[23%]">
<span className="font-medium">Emp.Id: </span>
......
......@@ -25,13 +25,13 @@ const reportSlice = createSlice({
},
calculateDefaultScore:(state, action)=>{
const defaultItems = action.payload?.filter(item => item.type === "default");
const totalDefaultScore = defaultItems.reduce((acc, curr) => acc+ curr.score, 0);
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 totalDefaultScore = defaultItems?.reduce((acc, curr) => acc+ curr.score, 0);
const defaultAvgScore = totalDefaultScore > 0 ? totalDefaultScore / defaultItems.length : 0;
return {...state,initiativeAvgScore :defaultAvgScore.toFixed(1)}
},
......
import { configureStore } from '@reduxjs/toolkit';
import rootReducer from './reducers/rootReducer';
import sessionStorage from 'redux-persist/es/storage/session'
import { persistReducer, persistStore } from 'redux-persist';
const persistConfig={
key: "root",
storage:sessionStorage,
}
const persistState=persistReducer(persistConfig, rootReducer)
const store = configureStore({
reducer: rootReducer,
reducer: persistState,
});
export const persistor = persistStore(store);
export default store;
\ 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