Commit b7edf93b authored by Shiva Komirishetti's avatar Shiva Komirishetti

Added modal changes

parent 4d019a8d
...@@ -3767,104 +3767,6 @@ ...@@ -3767,104 +3767,6 @@
"tailwindcss": "^1.5.0" "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": { "node_modules/@testing-library/jest-dom": {
"version": "5.17.0", "version": "5.17.0",
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz", "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz",
...@@ -17505,19 +17407,6 @@ ...@@ -17505,19 +17407,6 @@
"is-typedarray": "^1.0.0" "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": { "node_modules/unbox-primitive": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
......
...@@ -198,13 +198,13 @@ const moment = require("moment"); ...@@ -198,13 +198,13 @@ const moment = require("moment");
{ {
"empId":41689, "empId":41689,
"fromDate":"2024-03-10", "fromDate":"2024-03-10",
"toDate":"2024-03-11" "toDate":"2024-03-14"
} }
*/ */
app.post("/getActivities", (req, res) => { app.post("/getActivities", (req, res) => {
let { empId, fromDate, toDate, today } = req.body; let { empId, fromDate, toDate, today } = req.body;
if (!empId) { if (!empId || typeof empId=="string") {
res.status(401).json({ message: "Employee id is missing" }); res.status(401).json({ message: "Employee id is missing/ EmpId should be string only" });
return; return;
} else { } else {
let query = { let query = {
...@@ -223,8 +223,7 @@ app.post("/getActivities", (req, res) => { ...@@ -223,8 +223,7 @@ app.post("/getActivities", (req, res) => {
}; };
} }
db.collection("performance_master") db.collection("performance_master")
.find(query) .findOne(query)
.toArray()
.then((results) => { .then((results) => {
res.json(results); res.json(results);
}) })
......
...@@ -2,6 +2,7 @@ import {BrowserRouter, Routes, Route} from 'react-router-dom'; ...@@ -2,6 +2,7 @@ import {BrowserRouter, Routes, Route} from 'react-router-dom';
import Home from "./pages/home"; import Home from "./pages/home";
import Dashboard from './pages/dashboard'; import Dashboard from './pages/dashboard';
import Layout from './pages/layout'; import Layout from './pages/layout';
import Reports from './pages/reports';
import './App.css'; import './App.css';
function App() { function App() {
...@@ -10,6 +11,7 @@ function App() { ...@@ -10,6 +11,7 @@ function App() {
<Routes> <Routes>
<Route path='/' element={<Home />}/> <Route path='/' element={<Home />}/>
<Route path=":id/dashboard" element={<Layout><Dashboard/></Layout>}/> <Route path=":id/dashboard" element={<Layout><Dashboard/></Layout>}/>
<Route path=":id/reports" element={<Layout><Reports/></Layout>}/>
</Routes> </Routes>
</BrowserRouter> </BrowserRouter>
); );
......
import React from 'react'; import React from 'react';
import {Link} from 'react-router-dom'; import {useNavigate} from 'react-router-dom';
import { useDispatch } from 'react-redux';
import clearStore from '../../utils/clearStore';
function Header() { function Header() {
const dispatch = useDispatch();
const navigate = useNavigate()
const handleLogout = () => {
navigate('/');
clearStore(dispatch)
}
return ( return (
<div className="flex items-center justify-between py-5 px-10"> <div className="flex items-center justify-between py-5 px-10">
<img src="/logo.png"/> <img src="/logo.png"/>
<div className="flex items-center"> <div className="flex items-center">
<img src="/power-button.png" width="30px" height="30px"/> <img src="/power-button.png" width="30px" height="30px"/>
<button className="ml-2 -mt-1 text-2xl" > <button className="ml-2 -mt-1 text-2xl" onClick={handleLogout}>
<Link to="/">
Logout Logout
</Link>
</button> </button>
</div> </div>
</div> </div>
......
import React, { useState } from "react";
export default function MyModal({ visible, onClose }) {
const [aId,setAId]=useState("");
const [aName,setAName]=useState("");
const [valueType,setvalueType]=useState("");
const [score,setScore]=useState(0);
const [comments,setComments]=useState('');
if (!visible) return null;
return (
<div className="fixed inset-0 bg-black bg-opacity-25 backdrop-blur-sm flex items-center justify-center">
<div className="bg-white rounded w-4/12">
<div className=" text-white py-3 pl-2 bg-blue-500">Default Activity</div>
<div>
<div>
<form class=" p-2 max-w-sm mx-auto">
<div className="flex items-center my-5">
<label for="countries">Default Activity List : </label>
<select id="countries" class="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">
<option selected>List Types</option>
<option value="US">United States</option>
<option value="CA">Canada</option>
<option value="FR">France</option>
<option value="DE">Germany</option>
</select>
</div>
<div class="flex items-center mb-4 ">
<label for="default-radio-1" class=" text-sm font-medium text-gray-900 dark:text-gray-300">Appreciation:</label>
<input id="default-radio-1" type="radio" value="" name="default-radio" class="w-4 h-4 m-3 text-blue-600 bg-gray-100 border-gray-300 dark:bg-gray-700 dark:border-gray-600" />
<label for="default-radio-1" class="ms-2 text-sm font-medium text-gray-900 dark:text-gray-300">Depreciation:</label>
<input id="default-radio-1" type="radio" value="" name="default-radio" class="w-4 h-4 m-3 text-blue-600 bg-gray-100 border-gray-300 dark:bg-gray-700 dark:border-gray-600" />
</div>
<div className="flex ">
<span>Score</span>
<select className="border w-1/5">
<option value={1} selected>1</option>
<option value={2}>2</option>
<option value={3}>3</option>
<option value={4}>4</option>
<option value={5}>5</option>
</select>
</div>
<div className="flex items-center my-5">
<label for="message" class="block w-3/12 mb-20 text-sm font-medium text-gray-900 dark:text-white">Comments :</label>
<textarea id="message" rows="4" class="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="..."></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 className="px-3 py-2 ml-5 bg-gray-700 text-white rounded">Save</button>
</div>
</form>
</div>
</div>
</div>
</div>
);
}
\ No newline at end of file
import React from "react"; import React from "react";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { useParams } from "react-router-dom";
function Sidebar() { function Sidebar() {
const user = useSelector((state) => state.userDetails.user); const user = useSelector((state) => state.userDetails.user);
const reportees = useSelector((state) => state.reportees.reportees);
const url = window.location.href
return ( return (
<div className="w-[30%] flex items-center flex-col"> <div className="w-[30%] flex items-center flex-col px-4">
<div> <div>
<img src="/user.png" width="130px" height="130px" /> <img src="/user.png" width="130px" height="130px" />
</div> </div>
...@@ -12,6 +17,23 @@ function Sidebar() { ...@@ -12,6 +17,23 @@ function Sidebar() {
<p className="text-lg font-semibold">{user.empName}</p> <p className="text-lg font-semibold">{user.empName}</p>
<p>{user.designation}</p> <p>{user.designation}</p>
</div> </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-[50vh] overflow-auto">
{
reportees?.map(({empName, score, empId}) => (
<div className="flex items-center bg-white p-2 justify-between mb-1" key={empId}>
<img src="/man.png" width="18px" height="18px" />
<p className="w-[80%]">{empName}</p>
<p className="w-[10%] bg-blue-200 rounded-sm text-center">{score}</p>
</div>
))
}
</div>
</div>
}
</div> </div>
); );
} }
......
import React from "react"; import React from "react";
import {Link} from 'react-router-dom';
function Table({headers, data, isView}) { function Table({headers, data, isView}) {
return ( return (
<div class="relative overflow-x-auto shadow-md sm:rounded-lg"> <div className="relative overflow-x-auto shadow-md sm:rounded-lg p-3">
<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400"> <table className="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400 bg-transparent justify-center">
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400"> <thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400 ">
<tr> <tr>
{headers.map((item) => ( {headers.map((item) => (
<th scope="col" class="px-6 py-3 font-bold"> <th scope="col" className="px-6 py-3" >
{item.title} {item.title}
</th> </th>
))} ))}
...@@ -16,9 +17,9 @@ function Table({headers, data, isView}) { ...@@ -16,9 +17,9 @@ function Table({headers, data, isView}) {
<tbody> <tbody>
{ {
data?.map((item, index) => ( data?.map((item, index) => (
<tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600"> <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) => ( {headers?.map((field) => (
field.id !== "action" ? <td class="px-6 py-4">{item[field.id]}</td> : <td class="px-6 py-4"><button>View</button></td> field.id !== "action" ?<td className="px-6 py-4 listData" >{field.id==="empName"?<span className="flex items-center"><img className="pr-2" src="/user.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> </tr>
......
...@@ -15,3 +15,6 @@ code { ...@@ -15,3 +15,6 @@ code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace; monospace;
} }
.listData:nth-child(4) {
padding-left: 35px;
}
\ No newline at end of file
...@@ -10,7 +10,7 @@ function Dashboard() { ...@@ -10,7 +10,7 @@ function Dashboard() {
const reportees = useSelector((state) => state.reportees.reportees); const reportees = useSelector((state) => state.reportees.reportees);
const userDetails = useSelector((state) => state.userDetails); const userDetails = useSelector((state) => state.userDetails);
const { id } = useParams(); const { id } = useParams();
const reporteIds = userDetails.user.reportees || {}; const reporteIds = userDetails.user.reportees || [];
useEffect(() => { useEffect(() => {
if (reporteIds.length > 0) { if (reporteIds.length > 0) {
...@@ -25,11 +25,12 @@ function Dashboard() { ...@@ -25,11 +25,12 @@ function Dashboard() {
}, [reporteIds]); }, [reporteIds]);
useEffect(() => { useEffect(() => {
if(id !== undefined ||null)
dispatch(fetchUser(id)); dispatch(fetchUser(id));
}, []); }, [id]);
const headers = [ const headers = [
{title: "Name", id:"empName"}, {title: "Employee Name", id:"empName"},
{title: "Emp.Id", id: "empId"}, {title: "Emp.Id", id: "empId"},
{title: "Designation", id: 'designation'}, {title: "Designation", id: 'designation'},
{title: "score", id:"score"}, {title: "score", id:"score"},
...@@ -38,7 +39,7 @@ function Dashboard() { ...@@ -38,7 +39,7 @@ function Dashboard() {
] ]
return ( return (
<div> <div>
<Table headers={headers} data={reportees.data} isView={true}/> <Table headers={headers} data={reportees} isView={true}/>
</div> </div>
) )
} }
......
import React, {useState, useEffect} from 'react';
import { useSelector,useDispatch } from 'react-redux';
import { useParams } from 'react-router';
import { fetchReports } from "../../redux/reducers/reportSlice";
function Reports() {
const {id} = useParams();
const dispatch = useDispatch();
const reportees = useSelector((state) => state.reportees.reportees);
const [empDetails, setEmpDetails] = useState(null);
const { report, loading, error}=useSelector((state)=>state.reports)
/*Example post data
{
"empId":41689,
"fromDate":"2024-03-10",
"toDate":"2024-03-11"
}
*/
useEffect(() => {
if(id) {
const emp = reportees?.filter((item) => item.empId === Number(id));
setEmpDetails(emp[0]);
const data = {
"empId":Number(id),
"fromDate":"2024-03-10",
"toDate":"2024-03-15"
}
dispatch(fetchReports(data))
}
return (() => {
setEmpDetails(null)
})
},[id]);
useEffect(()=>{console.log( report, loading, error)},[ report, loading, error])
return (
<div>This Perots</div>
)
}
export default Reports
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import { base_url } from "../../utils/constants";
import axios from "axios";
const initialState = {
reports: [],
loading: false,
error: null,
};
export const fetchReports = createAsyncThunk("getReports", async (data) => {
return await axios
.post(`${base_url}/getActivities`, data)
.then((response) => response.data);
});
const reportSlice = createSlice({
name: "reportees",
initialState,
reducers: {
resetReports:() => {
return initialState
}
},
extraReducers: (builder) => {
builder.addCase(fetchReports.pending, (state) => {
state.loading = true;
state.error = "pending";
});
builder.addCase(fetchReports.fulfilled, (state, action) => {
state.loading = false;
state.reports = action.payload.activities;
state.error = "";
});
builder.addCase(fetchReports.rejected, (state, action) => {
state.loading = false;
state.reports = [];
state.error = action.error || "Something went wrong!";
});
},
});
export const {resetReports} = reportSlice.actions;
export default reportSlice.reducer;
...@@ -15,9 +15,13 @@ export const fetchReportees = createAsyncThunk("getReportees", async (data) => { ...@@ -15,9 +15,13 @@ export const fetchReportees = createAsyncThunk("getReportees", async (data) => {
}); });
const reporteesSlice = createSlice({ const reporteesSlice = createSlice({
name: "counter", name: "reportees",
initialState, initialState,
reducers: {}, reducers: {
resetReportees:() => {
return initialState
}
},
extraReducers: (builder) => { extraReducers: (builder) => {
builder.addCase(fetchReportees.pending, (state) => { builder.addCase(fetchReportees.pending, (state) => {
state.loading = true; state.loading = true;
...@@ -25,7 +29,7 @@ const reporteesSlice = createSlice({ ...@@ -25,7 +29,7 @@ const reporteesSlice = createSlice({
}); });
builder.addCase(fetchReportees.fulfilled, (state, action) => { builder.addCase(fetchReportees.fulfilled, (state, action) => {
state.loading = false; state.loading = false;
state.reportees = action.payload; state.reportees = action.payload.data;
state.error = ""; state.error = "";
}); });
builder.addCase(fetchReportees.rejected, (state, action) => { builder.addCase(fetchReportees.rejected, (state, action) => {
...@@ -36,6 +40,6 @@ const reporteesSlice = createSlice({ ...@@ -36,6 +40,6 @@ const reporteesSlice = createSlice({
}, },
}); });
export const {} = reporteesSlice.actions; export const {resetReportees} = reporteesSlice.actions;
export default reporteesSlice.reducer; export default reporteesSlice.reducer;
import { combineReducers } from 'redux'; import { combineReducers } from 'redux';
import reporteesReducer from './reporteesSlice'; import reporteesReducer from './reporteesSlice';
import userReducer from './userSlice'; import userReducer from './userSlice';
import reportReducer from './reportSlice';
const rootReducer = combineReducers({ const rootReducer = combineReducers({
userDetails: userReducer, userDetails: userReducer,
reportees: reporteesReducer reportees: reporteesReducer,
reports: reportReducer
}); });
export default rootReducer; export default rootReducer;
\ No newline at end of file
...@@ -15,9 +15,13 @@ export const fetchUser = createAsyncThunk("getUser", async (id) => { ...@@ -15,9 +15,13 @@ export const fetchUser = createAsyncThunk("getUser", async (id) => {
}); });
const userSlice = createSlice({ const userSlice = createSlice({
name: "counter", name: "user",
initialState, initialState,
reducers: {}, reducers: {
resetUser:() => {
return initialState
}
},
extraReducers: (builder) => { extraReducers: (builder) => {
// fetch user // fetch user
builder.addCase(fetchUser.pending, (state) => { builder.addCase(fetchUser.pending, (state) => {
...@@ -37,6 +41,6 @@ const userSlice = createSlice({ ...@@ -37,6 +41,6 @@ const userSlice = createSlice({
}, },
}); });
export const {} = userSlice.actions; export const {resetUser} = userSlice.actions;
export default userSlice.reducer; export default userSlice.reducer;
import {resetUser} from '../redux/reducers/userSlice';
import {resetReportees} from '../redux/reducers/reporteesSlice';
const clearStore = (dispatch) => {
dispatch(resetUser());
dispatch(resetReportees());
};
export default clearStore;
\ 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