pagination added

parent dc7f4018
import React from 'react';
const PaginationComponent = ({ currentPage, totalPages, onPageChange }) => {
const pageNumbers = [];
for (let i = 1; i <= totalPages; i++) {
pageNumbers.push(i);
}
return (
<nav className="flex justify-center ">
<ul className="pagination flex">
{pageNumbers.map(number => (
<li key={number} className={`page-item ${number === currentPage ? 'active' : ''}` }>
<button onClick={() => onPageChange(number)} className=" w-[22px] font-bold h-[22px] ">
{number}
</button>
</li>
))}
</ul>
</nav>
);
};
export default PaginationComponent;
......@@ -28,7 +28,7 @@ function AccordionTable({ headers, data }) {
header.id === "aName" ? "[#D9D9D9]" : "white"
}`}
>
{header?.id === 'recorded_date' ? <span>{getDate(item[header?.id])}</span> : <span>{item[header?.id]}</span>}
{header?.id === 'recorded_date' ? <span>{getDate(item[header?.id])}</span> : <span className="truncate overflow-hidden whitespace-nowrap overflow-ellipsis">{item[header?.id]}</span>}
</td>
))}
</tr>
......
......@@ -42,7 +42,7 @@ function Accordion({ title, data ,handleAddActivity,open,handleAccordian}) {
const headers = [
{ title: "Activity Name", id: "aName", width: "30%" },
{ 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: "Score", id: "score", width: "10%", render: (value) => <div className="w-[35px] bg-blue-400 rounded-full text-white font-bold text-center p-[4px]">{value}</div> },
{ title: "Comments", id: "comments", width: "40%" },
];
......
......@@ -24,9 +24,9 @@ const DateRangePicker = ({getReports}) => {
return (
<div>
<label htmlFor="start" className="font-bold ps-2">From:</label>
<input type="date" id="start" name="start" placeholder="MM-DD-YYYY" className="rounded-md font-semibold ms-1 ps-2 text-[#555]" onChange={(e)=>handleStartChange(e.target.value)} />
<input type="date" id="start" name="start" placeholder="MM-DD-YYYY" className="rounded-md font-semibold text-sm ms-1 ps-2 text-[#555]" onChange={(e)=>handleStartChange(e.target.value)} />
<label htmlFor="end" className="font-bold ps-2">To:</label>
<input type="date" id="end" name="end" placeholder="MM-DD-YYYY" className="rounded-md font-semibold ms-1 ps-2 text-[#555]" onChange={(e)=>handleEndChange(e.target.value)}/>
<input type="date" id="end" name="end" placeholder="MM-DD-YYYY" className="rounded-md font-semibold text-sm ms-1 ps-2 text-[#555]" onChange={(e)=>handleEndChange(e.target.value)}/>
</div>
)
......
import React,{useEffect,useState} from "react";
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,loading} = useSelector((state) => state.reportees);
const {id} = useParams()
const { reportees, loading } = useSelector((state) => state.reportees);
const { id } = useParams()
return (
<div className="mt-2 w-[30%] flex flex-col px-[5px]">
<div className=" w-[33%] flex flex-col px-[5px]">
<p className="text-xl text-blue-400 font-semibold pl-4 mt-3">
My Reportees
</p>
{
(loading)? <Loading/>:
(loading) ? <Loading /> :
<div className="p-2 bg-[#E9EDEE] mt-4 max-h-[80vh] overflow-auto">
{reportees?.map(({ empName, score, empId }) => (
<Link
to={`/viewreportee/${empId}`}
className={`flex items-center bg-${
Number(id) === empId ? "blue-200" : "white"
className={`flex items-center bg-${Number(id) === empId ? "blue-200" : "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">
<p className={`w-[30px] h-[30px] rounded-full flex items-center text-white justify-center
${score === 0 ? 'bg-red-500 ' : ''}
${score >= 1 && score < 2 ? 'bg-red-500' : ''}
${score >= 2 && score < 3 ? 'bg-yellow-500' : ''}
${score >= 3 && score < 4 ? 'bg-green-500 ' : ''}
${score >= 4 && score < 5 ? 'bg-green-600 ' : ''}
${score >= 5 ? 'bg-green-600 ' : ''}`}>
{score}
</p>
</Link>
......
......@@ -66,30 +66,30 @@ export default function MyModal({ visible, onClose ,type,handleAddActivity}) {
return (
<div className="absolute w-full h-full inset-0 bg-black bg-opacity-25 backdrop-blur-sm flex items-center justify-center" onClick={(e) => e.stopPropagation()}>
<div className="bg-white rounded lg:w-4/12 sm:w-100">
<div className=" text-white py-3 pl-2 bg-blue-500 ">{activityType} Activity</div>
<div className="bg-white rounded-md lg:w-4/12 sm:w-100">
<div className=" text-white py-3 pl-2 bg-blue-500 rounded-md">{activityType} Activity</div>
<div>
<div>
<form className=" p-2 max-w-sm mx-auto" onClick={(e) => e.stopPropagation()}>
<form className=" p-2 max-w-sm mx-auto text-[12px]" onClick={(e) => e.stopPropagation()}>
<div className="flex items-center my-5">
<label htmlFor="countries">Select Activity: </label>
<label htmlFor="countries">SELECT ACTIVITY: </label>
<select className="bg-gray-50 ml-2 w-7/12 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" onChange={(e)=>handleActivityName(e)}>
<option id="" value="" className="text-[16px]">Select</option>
<option id="" value="">Select</option>
{
activitiesList && activitiesList.map((activity)=><option className="text-[16px] w-7/12" key={activity.aId} id={activity.aId} value={activity.aName}>{activity.aName}</option>)
activitiesList && activitiesList.map((activity)=><option className=" w-7/12" key={activity.aId} id={activity.aId} value={activity.aName}>{activity.aName}</option>)
}
</select>
</div>
<div className="flex items-center mb-4 ">
<label htmlFor="appreciate" className=" text-sm font-medium text-gray-900 dark:text-gray-300">Appreciation:</label>
<label htmlFor="appreciate" className=" font-medium dark:text-gray-300">APPRECIATION:</label>
<input id="appreciate" type="radio" value="appreciate" name="performance" className="w-4 h-4 m-3 text-blue-600 bg-gray-100 border-gray-300 dark:bg-gray-700 dark:border-gray-600" onChange={()=>handlePerformance(1)}/>
<label htmlFor="depreciate" className="ms-2 text-sm font-medium text-gray-900 dark:text-gray-300">Depreciation:</label>
<label htmlFor="depreciate" className="ms-2 font-medium dark:text-gray-300">DEPRECIATION:</label>
<input id="depreciate" type="radio" value="depreciate" name="performance" className="w-4 h-4 m-3 text-blue-600 bg-gray-100 border-gray-300 dark:bg-gray-700 dark:border-gray-600" onChange={()=>handlePerformance(-1)} />
</div>
<div className="flex ">
<span>Score</span>
<select className="border w-1/5" onChange={(e)=>handleScoreChange(e.target.value)}>
<span>SCORE: </span>
<select className="border w-1/5 ms-1" onChange={(e)=>handleScoreChange(e.target.value)}>
<option value={0}>Select</option>
<option value={1}>1</option>
<option value={2}>2</option>
......@@ -100,8 +100,8 @@ export default function MyModal({ visible, onClose ,type,handleAddActivity}) {
</div>
<div className="flex items-center my-5">
<label htmlFor="comments" className="block w-3/12 mb-20 text-sm font-medium text-gray-900 dark:text-white">Comments :</label>
<textarea id="comments" rows="4" className="block ml-2 p-2.5 w-9/12 text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="activity comments" onChange={(e)=>handleComments(e)}
<label htmlFor="comments" className="block w-3/12 mb-20 text-start font-medium dark:text-white">COMMENTS :</label>
<textarea id="comments" style={{resize:"none"}} rows="4" className="block ml-2 p-2.5 w-9/12 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="Activity comments (optional)" onChange={(e)=>handleComments(e)}
onClick={(e) => e.stopPropagation()}
onKeyDown={(e) => {
// Prevent propagation of space key press
......@@ -119,9 +119,9 @@ export default function MyModal({ visible, onClose ,type,handleAddActivity}) {
}}></textarea>
</div>
<div className="flex items-center justify-end mb-3">
<button onClick={onClose} className="px-3 py-2 bg-gray-700 text-white rounded">Cancel</button>
<button onClick={onClose} className="px-3 py-2 rounded-md bg-gray-700 text-white ">Cancel</button>
{
enableSubmit?<button type="button" className="px-3 py-2 ml-5 bg-green-700 text-white rounded" onClick={handleSubmit}>Submit</button>:
enableSubmit?<button type="button" className="px-3 py-2 ml-5 bg-blue-500 text-white rounded-md" onClick={handleSubmit}>Submit</button>:
<button type="button" className="px-3 py-2 ml-5 bg-gray-400 text-white rounded" disabled={!enableSubmit} title="Please fill all fileds to submit">Submit</button>
}
......
......@@ -10,7 +10,7 @@ export default function ModalButton({type,handleAddActivity}) {
<button
onClick={() => setShowMyModal(true)}
className="bg-blue-400 text-white px-2 py-1 rounded hover:scale-95 transition text-sm">
Add Activity
Add Score
</button>
<MyModal onClose={handleOnClose} visible={showMyModal} handleAddActivity={handleAddActivity} type={type}/>
</div>
......
......@@ -5,7 +5,7 @@ function Table({headers, data,loading, maxHeight}) {
if(loading) return <Loading/>
if(data?.length)
return (
<div className={` overflow-x-auto sm:rounded-lg p-4 max-h-[${maxHeight}vh] bg-gray-100`}>
<div className={` overflow-auto sm:rounded-lg p-4 max-h-[${maxHeight}vh] bg-gray-100`}>
<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-white">
<tr className="mb-2">
......
@tailwind base;
@tailwind components;
@tailwind utilities;
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
......@@ -18,3 +18,8 @@ code {
/* .listData:nth-child(4) {
padding-left: 35px;
} */
.active{
background: rgb(96 165 250);
color:white;
border-radius:50%
}
import React, { useEffect, useState } from "react";
import { Link ,useNavigate} from "react-router-dom";
import { Link, useNavigate } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import { fetchReportees } from "../../redux/reducers/reporteesSlice";
import Table from '../../components/table';
import PaginationComponent from "../../components/Pagenation/Pagenation";
function Dashboard() {
const dispatch = useDispatch();
const navigate=useNavigate();
const {reportees,loading} = useSelector((state) => state.reportees);
const navigate = useNavigate();
const { reportees, loading, totalCount } = useSelector((state) => state.reportees);
const userDetails = useSelector((state) => state.userDetails);
const [reporteIds,setReporteIds] =useState([]);
const [reporteIds, setReporteIds] = useState([]);
const [currPage, setCurrPage] = useState(1)
const [pagesCount, setPagesCount] = useState(1)
// userDetails.user.reportees || [];
const handlePageChange = (currPage) => {
let data = {
reportees: userDetails.user.reportees,
page: currPage,
perPage: 10
}
setCurrPage(currPage)
dispatch(fetchReportees(data))
}
// useEffect(() => {
// let data={
// reportees:reportees,
// ["page"]:page,
// }
// dispatch(fetchReportees(data))
// } ,[page]);
useEffect(() => {
setPagesCount(Math.ceil((totalCount) / (10)))
}, [totalCount])
useEffect(() => {
if (reporteIds.length > 0) {
const data = {
reportees: userDetails.user.reportees,
sort: { type: "empId", order: 1 },
page: 1,
perPage: 10,
// sort: { type: "empId", order: 1 },
page: currPage,
perPage: 10
};
dispatch(fetchReportees(data));
}
}, [reporteIds]);
useEffect(() => {
if(userDetails.user){
if (userDetails.user) {
setReporteIds(userDetails.user.reportees)
navigate("/dashboard")
}else{
} else {
navigate("/")
}
}, [userDetails]);
......@@ -36,8 +60,8 @@ function Dashboard() {
const headers = [
{
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>
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",
......@@ -49,8 +73,15 @@ function Dashboard() {
},
{
title: "score",
id:"score",
render: (value) => <div className="bg-blue-200 rounded-md text-center p-[4px]">{value}</div>
id: "score",
render: (value) => <span className={`w-[30px] h-[30px] rounded-full flex items-center text-white justify-center
${value === 0 ? 'bg-red-500 ' : ''}
${value >= 1 && value < 2 ? 'bg-red-500' : ''}
${value >= 2 && value < 3 ? 'bg-yellow-500' : ''}
${value >= 3 && value < 4 ? 'bg-green-400 ' : ''}
${value >= 4 && value < 5 ? 'bg-green-600 ' : ''}
${value >= 5 ? 'bg-green-600 ' : ''}
`}>{value}</span>
},
{
title: "Email",
......@@ -58,14 +89,33 @@ function Dashboard() {
},
{
title: "Action",
id:"empId",
id: "empId",
render: (value) => <Link to={`/viewreportee/${value}`}><button className="bg-blue-400 text-white rounded-md px-3 py-1">View</button></Link>
},
]
return (
<div className="max-h-[87vh] ">
<Table headers={headers} data={reportees} loading={loading} maxHeight={88}/>
<div className="">
<div className="mb-2">
<Table headers={headers} data={reportees} loading={loading} maxHeight={88} />
<div className="">
{reportees && (
<div className="flex justify-end mt-2">
{/* <div className="text-blue-500">Total Results: {pagesCount}</div> */}
{pagesCount > 1 && (
<PaginationComponent
currentPage={currPage}
totalPages={pagesCount}
onPageChange={handlePageChange}
/>
)}
</div>
)}
</div>
</div>
</div>
)
}
......
......@@ -6,7 +6,7 @@ import LeftSidebar from '../../components/leftSidebar';
function Layout({children}) {
const url = window.location.href;
return (
<div>
<div className='max-h-[84vh]'>
<Header/>
<div className="flex">
<Sidebar/>
......
import React, { useState, useEffect, useMemo } from "react";
import { useSelector, useDispatch } from "react-redux";
import { useParams,useNavigate } from "react-router";
import { useParams, useNavigate } from "react-router";
import { base_url } from "../../utils/constants";
import axios from 'axios';
import { fetchReports } from "../../redux/reducers/reportSlice";
......@@ -10,14 +10,14 @@ import DateRangePicker from "../../components/dateRangePicker/DateRangePicker";
function Reports() {
const dispatch = useDispatch();
const navigate=useNavigate();
const navigate = useNavigate();
const { id } = useParams();
const empId = Number(id)
const reportees = useSelector((state) => state.reportees.reportees);
const user=useSelector((state)=>state.userDetails.user)
const user = useSelector((state) => state.userDetails.user)
const [empDetails, setEmpDetails] = useState(null);
const { reports ,loading,error} = useSelector((state) => state.reports);
const [open, setOpen] = useState({"accordianOne":false,"accordianTwo":false});
const { reports, loading, error } = useSelector((state) => state.reports);
const [open, setOpen] = useState({ "accordianOne": false, "accordianTwo": false });
......@@ -33,7 +33,7 @@ function Reports() {
const filtered = Object.groupBy(reports, ({ type }) => type);
return filtered;
}
}, [reports,id]);
}, [reports, id]);
const handleAccordian = (value) => {
switch (value) {
......@@ -52,8 +52,8 @@ function Reports() {
const data = { "empId": empId, "fromDate": startDate, "toDate": endDate }
dispatch(fetchReports(data))
}
const fetchLatestReporteesData=()=>{
if(user){
const fetchLatestReporteesData = () => {
if (user) {
const data = {
reportees: user.reportees,
sort: { type: "empId", order: 1 },
......@@ -65,7 +65,7 @@ function Reports() {
}
const handleAddActivity = async(activityData) => {
const handleAddActivity = async (activityData) => {
if (id) {
let newData = {
"empId": empId,
......@@ -83,7 +83,7 @@ function Reports() {
}
useEffect(() => {
if (id !== undefined || null && reportees.length>0) {
if (id !== undefined || null && reportees.length > 0) {
const emp = reportees?.filter((item) => item.empId === Number(id));
setEmpDetails(emp[0]);
const data = {
......@@ -96,45 +96,64 @@ function Reports() {
return (() => {
setEmpDetails(null)
})
}, [id,reportees]);
}, [id, reportees]);
useEffect(() => {
if(user){
if (user) {
navigate(`/viewreportee/${id}`)
}else{
} else {
navigate("/")
}
}, [id]);
if( empDetails && reportees.length)
return (
if (empDetails && reportees.length)
return (
<div className="p-4" >
<div className="bg-white p-3">
<div className="flex">
<div className="bg-white p-3 rounded-md">
<div className="flex justify-between">
{/* <img src="/generic-male-avatar-rectangular.jpg" width="100px" height="100px" /> */}
<div className="w-1/2">
<div className="my-1">
<p>
<span className="font-medium">Employee Name : </span> {empDetails?.empName}
</p>
<p>
<span className="font-medium">Designation : </span> {empDetails?.designation}
</p>
<p>
{/* <p>
<span className="font-medium">Email Id: </span> {empDetails?.empEmail}
</p>
</p> */}
</div>
<div className="w-1/2">
<div className="my-1">
<p>
<span className="font-medium">Employee Id: </span> {empDetails?.empId}
<span className="font-medium">Email : </span> {empDetails?.empEmail}
</p>
<p>
<span className="font-medium">Average Score : </span> {empDetails?.score}
<span className="font-medium">Employee Id: </span> {empDetails?.empId}
</p>
<p>
{/* <p>
<span className="font-medium">Total Score : </span> {empDetails?.score}
</p> */}
{/* <p>
<span className="font-medium">Allocated To : </span> {empDetails?.project}
</p>
</p> */}
</div>
<div className="flex flex-col justify-center items-center">
<div className={`w-[40px] h-[40px] rounded-full flex items-center text-white justify-center
${empDetails?.score === 0 ? 'bg-red-500 ' : ''}
${empDetails?.score >= 1 && empDetails?.score < 2 ? 'bg-red-500' : ''}
${empDetails?.score >= 2 && empDetails?.score < 3 ? 'bg-yellow-500' : ''}
${empDetails?.score >= 3 && empDetails?.score < 4 ? 'bg-green-500 ' : ''}
${empDetails?.score >= 4 && empDetails?.score < 5 ? 'bg-green-600 ' : ''}
${empDetails?.score >= 5 ? 'bg-green-600 ' : ''}
`}>
<span className="text-lg font-bold">{empDetails?.score}</span>
</div>
<div className="">
<span className="text-blue-400 font-semibold">Total Score</span>
</div>
</div>
</div>
</div>
<div className="max-h-[70vh] overflow-auto">
......@@ -149,11 +168,11 @@ return (
</div>
</div>
</div>
);
else
return <div className="w-full h-full">
<p className="text-center align-middle pt-14 pb-14 text-blue-500 font-bold">Employee Details Not Found</p>
</div>
);
else
return <div className="w-full h-full">
<p className="text-center align-middle pt-14 pb-14 text-blue-500 font-bold">Employee Details Not Found</p>
</div>
}
......
......@@ -4,6 +4,7 @@ import axios from "axios";
const initialState = {
reportees: [],
totalCount:0,
loading: false,
error: null,
};
......@@ -29,6 +30,7 @@ const reporteesSlice = createSlice({
builder.addCase(fetchReportees.fulfilled, (state, action) => {
state.loading = false;
state.reportees = action.payload.data;
state.totalCount = action.payload.totalCount.count;
state.error = "";
});
builder.addCase(fetchReportees.rejected, (state, action) => {
......
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