Compare commits
No commits in common. "1772a2fcd118b26a757e1a4250e775033eef1681" and "f9e9e2b326038147e986946e502d2afb8d8700fd" have entirely different histories.
1772a2fcd1
...
f9e9e2b326
11
package-lock.json
generated
@ -18,7 +18,6 @@
|
|||||||
"apexcharts": "^4.5.0",
|
"apexcharts": "^4.5.0",
|
||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
"axios-retry": "^4.5.0",
|
"axios-retry": "^4.5.0",
|
||||||
"date-fns": "^4.1.0",
|
|
||||||
"dotenv": "^16.4.7",
|
"dotenv": "^16.4.7",
|
||||||
"dotenv-webpack": "^8.1.0",
|
"dotenv-webpack": "^8.1.0",
|
||||||
"eventemitter3": "^5.0.1",
|
"eventemitter3": "^5.0.1",
|
||||||
@ -2456,16 +2455,6 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/date-fns": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/kossnocorp"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.4.0",
|
"version": "4.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
||||||
|
|||||||
@ -21,7 +21,6 @@
|
|||||||
"apexcharts": "^4.5.0",
|
"apexcharts": "^4.5.0",
|
||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
"axios-retry": "^4.5.0",
|
"axios-retry": "^4.5.0",
|
||||||
"date-fns": "^4.1.0",
|
|
||||||
"dotenv": "^16.4.7",
|
"dotenv": "^16.4.7",
|
||||||
"dotenv-webpack": "^8.1.0",
|
"dotenv-webpack": "^8.1.0",
|
||||||
"eventemitter3": "^5.0.1",
|
"eventemitter3": "^5.0.1",
|
||||||
|
|||||||
@ -3,6 +3,10 @@
|
|||||||
--bs-nav-link-font-size: 0.7375rem;
|
--bs-nav-link-font-size: 0.7375rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav {
|
||||||
|
--bs-nav-link-font-size: 0.7375rem;
|
||||||
|
}
|
||||||
|
|
||||||
.card-header {
|
.card-header {
|
||||||
padding: 0.5rem var(--bs-card-cap-padding-x);
|
padding: 0.5rem var(--bs-card-cap-padding-x);
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 376 KiB |
|
Before Width: | Height: | Size: 426 KiB |
|
Before Width: | Height: | Size: 364 KiB |
|
Before Width: | Height: | Size: 376 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
@ -18,10 +18,7 @@ const AttendanceOverview = () => {
|
|||||||
const [view, setView] = useState("chart");
|
const [view, setView] = useState("chart");
|
||||||
|
|
||||||
const projectId = useSelector((store) => store.localVariables.projectId);
|
const projectId = useSelector((store) => store.localVariables.projectId);
|
||||||
const { attendanceOverviewData, loading, error } = useAttendanceOverviewData(
|
const { attendanceOverviewData, loading, error } = useAttendanceOverviewData(projectId, dayRange);
|
||||||
projectId,
|
|
||||||
dayRange
|
|
||||||
);
|
|
||||||
|
|
||||||
const { tableData, roles, dates } = useMemo(() => {
|
const { tableData, roles, dates } = useMemo(() => {
|
||||||
const map = new Map();
|
const map = new Map();
|
||||||
@ -32,9 +29,7 @@ const AttendanceOverview = () => {
|
|||||||
map.get(date)[entry.role.trim()] = entry.present;
|
map.get(date)[entry.role.trim()] = entry.present;
|
||||||
});
|
});
|
||||||
|
|
||||||
const uniqueRoles = [
|
const uniqueRoles = [...new Set(attendanceOverviewData.map((e) => e.role.trim()))];
|
||||||
...new Set(attendanceOverviewData.map((e) => e.role.trim())),
|
|
||||||
];
|
|
||||||
const sortedDates = [...map.keys()];
|
const sortedDates = [...map.keys()];
|
||||||
const data = sortedDates.map((date) => {
|
const data = sortedDates.map((date) => {
|
||||||
const row = { date };
|
const row = { date };
|
||||||
@ -76,17 +71,17 @@ const AttendanceOverview = () => {
|
|||||||
show: true,
|
show: true,
|
||||||
axisBorder: {
|
axisBorder: {
|
||||||
show: true,
|
show: true,
|
||||||
color: "#78909C",
|
color: '#78909C',
|
||||||
offsetX: 0,
|
offsetX: 0,
|
||||||
offsetY: 0,
|
offsetY: 0
|
||||||
},
|
},
|
||||||
axisTicks: {
|
axisTicks: {
|
||||||
show: true,
|
show: true,
|
||||||
borderType: "solid",
|
borderType: 'solid',
|
||||||
color: "#78909C",
|
color: '#78909C',
|
||||||
width: 6,
|
width: 6,
|
||||||
offsetX: 0,
|
offsetX: 0,
|
||||||
offsetY: 0,
|
offsetY: 0
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
@ -99,7 +94,9 @@ const AttendanceOverview = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-white p-4 rounded shadow d-flex flex-column">
|
<div
|
||||||
|
className="bg-white p-4 rounded shadow d-flex flex-column"
|
||||||
|
>
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="d-flex justify-content-between align-items-center mb-3">
|
<div className="d-flex justify-content-between align-items-center mb-3">
|
||||||
<div className="card-title mb-0 text-start">
|
<div className="card-title mb-0 text-start">
|
||||||
@ -108,7 +105,7 @@ const AttendanceOverview = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="d-flex gap-2">
|
<div className="d-flex gap-2">
|
||||||
<select
|
<select
|
||||||
className="form-select form-select-sm w-auto"
|
className="form-select form-select-sm"
|
||||||
value={dayRange}
|
value={dayRange}
|
||||||
onChange={(e) => setDayRange(Number(e.target.value))}
|
onChange={(e) => setDayRange(Number(e.target.value))}
|
||||||
>
|
>
|
||||||
@ -117,20 +114,16 @@ const AttendanceOverview = () => {
|
|||||||
<option value={30}>Last 30 Days</option>
|
<option value={30}>Last 30 Days</option>
|
||||||
</select>
|
</select>
|
||||||
<button
|
<button
|
||||||
className={`btn btn-sm p-1 ${
|
className={`btn btn-sm ${view === "chart" ? "btn-primary" : "btn-outline-primary"}`}
|
||||||
view === "chart" ? "btn-primary" : "btn-outline-primary"
|
|
||||||
}`}
|
|
||||||
onClick={() => setView("chart")}
|
onClick={() => setView("chart")}
|
||||||
>
|
>
|
||||||
<i class="bx bx-bar-chart fs-5"></i>
|
📊
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className={`btn btn-sm p-1 ${
|
className={`btn btn-sm ${view === "table" ? "btn-primary" : "btn-outline-primary"}`}
|
||||||
view === "table" ? "btn-primary" : "btn-outline-primary"
|
|
||||||
}`}
|
|
||||||
onClick={() => setView("table")}
|
onClick={() => setView("table")}
|
||||||
>
|
>
|
||||||
<i class="bx bx-table fs-5"></i>
|
📋
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -156,21 +149,11 @@ const AttendanceOverview = () => {
|
|||||||
style={{ maxHeight: "350px", overflowY: "auto" }}
|
style={{ maxHeight: "350px", overflowY: "auto" }}
|
||||||
>
|
>
|
||||||
<table className="table table-bordered table-sm text-start align-middle mb-0">
|
<table className="table table-bordered table-sm text-start align-middle mb-0">
|
||||||
<thead
|
<thead className="table-light" style={{ position: "sticky", top: 0, zIndex: 1 }}>
|
||||||
className="table-light"
|
|
||||||
style={{ position: "sticky", top: 0, zIndex: 1 }}
|
|
||||||
>
|
|
||||||
<tr>
|
<tr>
|
||||||
<th style={{ background: "#f8f9fa", textTransform: "none" }}>
|
<th style={{ background: "#f8f9fa", textTransform: "none" }}>Role</th>
|
||||||
Role
|
|
||||||
</th>
|
|
||||||
{dates.map((date, idx) => (
|
{dates.map((date, idx) => (
|
||||||
<th
|
<th key={idx} style={{ background: "#f8f9fa", textTransform: "none" }}>{date}</th>
|
||||||
key={idx}
|
|
||||||
style={{ background: "#f8f9fa", textTransform: "none" }}
|
|
||||||
>
|
|
||||||
{date}
|
|
||||||
</th>
|
|
||||||
))}
|
))}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -181,8 +164,7 @@ const AttendanceOverview = () => {
|
|||||||
<td>{role}</td>
|
<td>{role}</td>
|
||||||
{tableData.map((row, idx) => {
|
{tableData.map((row, idx) => {
|
||||||
const value = row[role];
|
const value = row[role];
|
||||||
const cellStyle =
|
const cellStyle = value > 0 ? { backgroundColor: '#d5d5d5' } : {};
|
||||||
value > 0 ? { backgroundColor: "#d5d5d5" } : {};
|
|
||||||
return (
|
return (
|
||||||
<td key={idx} style={cellStyle}>
|
<td key={idx} style={cellStyle}>
|
||||||
{value}
|
{value}
|
||||||
|
|||||||
@ -1,161 +0,0 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
|
||||||
import moment from "moment";
|
|
||||||
import DateRangePicker from "../common/DateRangePicker";
|
|
||||||
import useFormattedDate from "../../hooks/useFormattedDate";
|
|
||||||
import { useProjectTasksByEmployee } from "../../hooks/useProjects";
|
|
||||||
|
|
||||||
const EmpActivities = ({ employee }) => {
|
|
||||||
const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" });
|
|
||||||
const myDate = new Date("2025-08-06T10:30:00Z");
|
|
||||||
const formattedToday = useFormattedDate(myDate, "dd-MMM-yyyy");
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
data,
|
|
||||||
isError,
|
|
||||||
isLoading,
|
|
||||||
error,
|
|
||||||
refetch,
|
|
||||||
} = useProjectTasksByEmployee(employee?.id,dateRange.startDate,dateRange.endDate);
|
|
||||||
|
|
||||||
if(isLoading) return <div>Loading...</div>
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="card h-100 mt-4">
|
|
||||||
<div className="card-body">
|
|
||||||
<div className="my-0 text-start">
|
|
||||||
<DateRangePicker
|
|
||||||
DateDifference="30"
|
|
||||||
onRangeChange={setDateRange}
|
|
||||||
endDateMode="today"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<ul className="timeline mb-0 mt-5 text-start">
|
|
||||||
{data?.map((activity)=>(
|
|
||||||
<li className="timeline-item timeline-item-transparent">
|
|
||||||
<span className="timeline-point timeline-point-primary"></span>
|
|
||||||
<div className="timeline-event">
|
|
||||||
<div className="timeline-header mb-3">
|
|
||||||
<h6 className="mb-0">{activity.projectName}</h6>
|
|
||||||
<small className="text-body-secondary">
|
|
||||||
{useFormattedDate(activity.assignmentDate, "dd-MMM-yyyy")}
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
<p className="mb-2"><span className="fw-semibold">Activity:</span>{activity.activityName}</p>
|
|
||||||
<p className="mb-2">
|
|
||||||
<span className="fw-semibold">Location:</span> {activity.location}
|
|
||||||
</p>
|
|
||||||
<p className="mb-2">
|
|
||||||
<span className="fw-semibold">Planned: {activity.plannedTask}</span>
|
|
||||||
<span className="ms-2">Completed : {activity.completedTask}</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
|
|
||||||
|
|
||||||
{/* <li className="timeline-item timeline-item-transparent">
|
|
||||||
<span className="timeline-point timeline-point-success"></span>
|
|
||||||
<div className="timeline-event">
|
|
||||||
<div className="timeline-header mb-3">
|
|
||||||
<h6 className="mb-0">Client Meeting</h6>
|
|
||||||
<small className="text-body-secondary">45 min ago</small>
|
|
||||||
</div>
|
|
||||||
<p className="mb-2">Project meeting with john @10:15am</p>
|
|
||||||
<div className="d-flex justify-content-between flex-wrap gap-2 mb-2">
|
|
||||||
<div className="d-flex flex-wrap align-items-center mb-50">
|
|
||||||
<div className="avatar avatar-sm me-2">
|
|
||||||
<img
|
|
||||||
src="../../assets/img/avatars/1.png"
|
|
||||||
alt="Avatar"
|
|
||||||
className="rounded-circle"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="mb-0 small fw-medium">
|
|
||||||
Lester McCarthy (Client)
|
|
||||||
</p>
|
|
||||||
<small>CEO of ThemeSelection</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li className="timeline-item timeline-item-transparent">
|
|
||||||
<span className="timeline-point timeline-point-info"></span>
|
|
||||||
<div className="timeline-event">
|
|
||||||
<div className="timeline-header mb-3">
|
|
||||||
<h6 className="mb-0">Create a new project for client</h6>
|
|
||||||
<small className="text-body-secondary">2 Day Ago</small>
|
|
||||||
</div>
|
|
||||||
<p className="mb-2">6 team members in a project</p>
|
|
||||||
<ul className="list-group list-group-flush">
|
|
||||||
<li className="list-group-item d-flex justify-content-between align-items-center flex-wrap border-top-0 p-0">
|
|
||||||
<div className="d-flex flex-wrap align-items-center">
|
|
||||||
<ul className="list-unstyled users-list d-flex align-items-center avatar-group m-0 me-2">
|
|
||||||
<li
|
|
||||||
data-bs-toggle="tooltip"
|
|
||||||
data-popup="tooltip-custom"
|
|
||||||
data-bs-placement="top"
|
|
||||||
className="avatar pull-up"
|
|
||||||
aria-label="Vinnie Mostowy"
|
|
||||||
data-bs-original-title="Vinnie Mostowy"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
className="rounded-circle"
|
|
||||||
src="../../assets/img/avatars/5.png"
|
|
||||||
alt="Avatar"
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
data-bs-toggle="tooltip"
|
|
||||||
data-popup="tooltip-custom"
|
|
||||||
data-bs-placement="top"
|
|
||||||
className="avatar pull-up"
|
|
||||||
aria-label="Allen Rieske"
|
|
||||||
data-bs-original-title="Allen Rieske"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
className="rounded-circle"
|
|
||||||
src="../../assets/img/avatars/12.png"
|
|
||||||
alt="Avatar"
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
data-bs-toggle="tooltip"
|
|
||||||
data-popup="tooltip-custom"
|
|
||||||
data-bs-placement="top"
|
|
||||||
className="avatar pull-up"
|
|
||||||
aria-label="Julee Rossignol"
|
|
||||||
data-bs-original-title="Julee Rossignol"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
className="rounded-circle"
|
|
||||||
src="../../assets/img/avatars/6.png"
|
|
||||||
alt="Avatar"
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
<li className="avatar">
|
|
||||||
<span
|
|
||||||
className="avatar-initial rounded-circle pull-up"
|
|
||||||
data-bs-toggle="tooltip"
|
|
||||||
data-bs-placement="bottom"
|
|
||||||
data-bs-original-title="3 more"
|
|
||||||
>
|
|
||||||
+3
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</li> */}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default EmpActivities;
|
|
||||||
@ -1,115 +0,0 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
|
||||||
|
|
||||||
import { useChangePassword } from "../../components/Context/ChangePasswordContext";
|
|
||||||
import GlobalModel from "../common/GlobalModel";
|
|
||||||
import ManageEmployee from "./ManageEmployee";
|
|
||||||
|
|
||||||
const EmpBanner = ({ profile, loggedInUser }) => {
|
|
||||||
const { openChangePassword } = useChangePassword();
|
|
||||||
const [showModal, setShowModal] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{showModal && (
|
|
||||||
<GlobalModel
|
|
||||||
size="lg"
|
|
||||||
isOpen={showModal}
|
|
||||||
closeModal={() => setShowModal(false)}
|
|
||||||
>
|
|
||||||
<ManageEmployee
|
|
||||||
employeeId={profile.id}
|
|
||||||
onClosed={() => setShowModal(false)}
|
|
||||||
/>
|
|
||||||
</GlobalModel>
|
|
||||||
)}
|
|
||||||
<div className="user-profile-header d-flex flex-column flex-lg-row text-sm-start text-center mb-8">
|
|
||||||
<div className="flex-shrink-0 mt-1 mx-sm-0 mx-auto">
|
|
||||||
{profile?.gender?.toLowerCase() == "male" && (
|
|
||||||
<img
|
|
||||||
width={125}
|
|
||||||
src="../../assets/img/avatars/avatar_m_01.png"
|
|
||||||
alt="user image"
|
|
||||||
className="d-block h-auto ms-0 ms-sm-6 rounded-3 user-profile-img"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{profile?.gender?.toLowerCase() == "female" && (
|
|
||||||
<img
|
|
||||||
width={125}
|
|
||||||
src="../../assets/img/avatars/avatar_f_02.png"
|
|
||||||
alt="user image"
|
|
||||||
className="d-block h-auto ms-0 ms-sm-6 rounded-3 user-profile-img"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="flex-grow-1 mt-1 mt-lg-1">
|
|
||||||
<div className="d-flex align-items-md-end align-items-sm-start align-items-center justify-content-md-between justify-content-start mx-5 flex-md-row flex-column gap-4">
|
|
||||||
<div className="user-profile-info">
|
|
||||||
<h4 className="mb-2">
|
|
||||||
<span>{profile?.firstName}</span>
|
|
||||||
{profile?.middleName ? (
|
|
||||||
<span className="ms-1">{profile?.middleName}</span>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{profile?.lastName ? (
|
|
||||||
<span className="ms-1">{profile?.lastName}</span>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</h4>
|
|
||||||
<ul className="list-inline mb-0 d-flex align-items-center flex-wrap justify-content-sm-start justify-content-center gap-4 mt-4">
|
|
||||||
<li className="list-inline-item">
|
|
||||||
<i className="icon-base bx bx-crown me-2 align-top"></i>
|
|
||||||
<span className="fw-medium">
|
|
||||||
{profile?.jobRole || <em>NA</em>}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li className="list-inline-item">
|
|
||||||
<i className="icon-base bx bx-phone me-2 align-top"></i>
|
|
||||||
<span className="fw-medium">
|
|
||||||
{" "}
|
|
||||||
{profile?.phoneNumber || <em>NA</em>}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li className="list-inline-item">
|
|
||||||
<i className="icon-base bx bx-calendar me-2 align-top"></i>
|
|
||||||
<span className="fw-medium">
|
|
||||||
{" "}
|
|
||||||
Joined on{" "}
|
|
||||||
{profile?.joiningDate ? (
|
|
||||||
new Date(profile.joiningDate).toLocaleDateString()
|
|
||||||
) : (
|
|
||||||
<em>NA</em>
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<ul className="list-inline mb-0 d-flex align-items-center flex-wrap justify-content-sm-start justify-content-center mt-4">
|
|
||||||
<li className="list-inline-item">
|
|
||||||
<button
|
|
||||||
className="btn btn-sm btn-primary btn-block"
|
|
||||||
onClick={() => setShowModal(true)}
|
|
||||||
>
|
|
||||||
Edit Profile
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li className="list-inline-item">
|
|
||||||
{profile?.id == loggedInUser?.employeeInfo?.id && (
|
|
||||||
<button
|
|
||||||
className="btn btn-sm btn-outline-primary btn-block"
|
|
||||||
onClick={() => openChangePassword()}
|
|
||||||
>
|
|
||||||
Change Password
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default EmpBanner;
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
|
||||||
import EmpOverview from "./EmpOverview";
|
|
||||||
import { useProjectsAllocationByEmployee } from "../../hooks/useProjects";
|
|
||||||
|
|
||||||
const EmpDashboard = ({ profile }) => {
|
|
||||||
const {
|
|
||||||
projectList,
|
|
||||||
loading: selectedProjectLoding,
|
|
||||||
refetch,
|
|
||||||
} = useProjectsAllocationByEmployee(profile?.id);
|
|
||||||
|
|
||||||
console.log(projectList);
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="row">
|
|
||||||
<div className="col-12 col-sm-6 pt-5">
|
|
||||||
{" "}
|
|
||||||
<EmpOverview profile={profile}></EmpOverview>
|
|
||||||
</div>
|
|
||||||
<div className="col col-sm-6 pt-5">
|
|
||||||
<div className="card ">
|
|
||||||
<div className="card-body">
|
|
||||||
<small className="card-text text-uppercase text-body-secondary small">
|
|
||||||
My Projects
|
|
||||||
</small>{" "}
|
|
||||||
<ul className="list-unstyled text-start my-3 py-1">
|
|
||||||
{selectedProjectLoding && <span>Loading</span>}
|
|
||||||
{projectList.map((project) => (
|
|
||||||
<li
|
|
||||||
className="d-flex mb-4 align-items-start flex-wrap"
|
|
||||||
key={project.id}
|
|
||||||
>
|
|
||||||
{/* Project Info */}
|
|
||||||
<div className="flex-grow-1">
|
|
||||||
<div className="d-flex flex-wrap align-items-center justify-content-between gap-2">
|
|
||||||
<div className="d-flex">
|
|
||||||
<div className="avatar flex-shrink-0 me-3">
|
|
||||||
<span className="avatar-initial rounded bg-label-primary">
|
|
||||||
<i className="icon-base bx bx-buildings icon-lg"></i>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h6 className="mb-0">{project.projectShortName}</h6>
|
|
||||||
<small className="text-muted">{project.projectName}</small>
|
|
||||||
<div className="label-secondary">
|
|
||||||
Assigned:{" "}
|
|
||||||
{project.assignedDate ? (
|
|
||||||
new Date(project.assignedDate).toLocaleDateString()
|
|
||||||
) : (
|
|
||||||
<em>NA</em>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span className="badge bg-label-secondary">
|
|
||||||
{project.designation}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Dates */}
|
|
||||||
{project.removedDate && (
|
|
||||||
<div className="mt-2 d-flex flex-column flex-sm-row justify-content-between">
|
|
||||||
<div className="label-secondary">
|
|
||||||
Unassigned:{" "}
|
|
||||||
{new Date(project.removedDate).toLocaleDateString()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default EmpDashboard;
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
|
||||||
import { ComingSoonPage } from "../../pages/Misc/ComingSoonPage";
|
|
||||||
|
|
||||||
const EmpDocuments = ({ profile, loggedInUser }) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ComingSoonPage/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default EmpDocuments;
|
|
||||||
@ -1,109 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import Avatar from "../common/Avatar";
|
|
||||||
import { useProfile } from "../../hooks/useProfile";
|
|
||||||
|
|
||||||
const EmpOverview = ({ profile }) => {
|
|
||||||
const { loggedInUserProfile } = useProfile();
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{" "}
|
|
||||||
<div className="row">
|
|
||||||
<div className="col-12 mb-4">
|
|
||||||
<div className="card">
|
|
||||||
<div className="card-body">
|
|
||||||
<small className="card-text text-uppercase text-body-secondary small">
|
|
||||||
About
|
|
||||||
</small>
|
|
||||||
<ul className="list-unstyled my-3 py-1">
|
|
||||||
<li className="d-flex align-items-center mb-4">
|
|
||||||
<i className="icon-base bx bx-user"></i>
|
|
||||||
<span className="fw-medium mx-2">Full Name:</span>{" "}
|
|
||||||
<span>{`${profile?.firstName} ${profile?.lastName}`}</span>
|
|
||||||
</li>
|
|
||||||
<li className="d-flex align-items-center mb-4">
|
|
||||||
<i className="icon-base bx bx-check"></i>
|
|
||||||
<span className="fw-medium mx-2">Status:</span>{" "}
|
|
||||||
<span>Active</span>
|
|
||||||
</li>
|
|
||||||
<li className="d-flex align-items-center mb-4">
|
|
||||||
<i className="icon-base bx bx-crown"></i>
|
|
||||||
<span className="fw-medium mx-2">Role:</span>{" "}
|
|
||||||
<span> {profile?.jobRole || <em>NA</em>}</span>
|
|
||||||
</li>
|
|
||||||
<li className="d-flex align-items-center mb-4">
|
|
||||||
<i className="icon-base bx bx-flag"></i>
|
|
||||||
<span className="fw-medium mx-2">Gender:</span>{" "}
|
|
||||||
<span> {profile?.gender || <em>NA</em>}</span>
|
|
||||||
</li>{" "}
|
|
||||||
<li className="d-flex align-items-center mb-2">
|
|
||||||
<i className="icon-base bx bx-calendar "></i>
|
|
||||||
<span className="fw-medium mx-2">Birth Date:</span>{" "}
|
|
||||||
<span>
|
|
||||||
{profile?.birthDate ? (
|
|
||||||
new Date(profile.birthDate).toLocaleDateString()
|
|
||||||
) : (
|
|
||||||
<em>NA</em>
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li className="d-flex align-items-center mb-2">
|
|
||||||
<i className="icon-base bx bx-calendar "></i>
|
|
||||||
<span className="fw-medium mx-2">Joining Date:</span>{" "}
|
|
||||||
<span>
|
|
||||||
{profile?.joiningDate ? (
|
|
||||||
new Date(profile.joiningDate).toLocaleDateString()
|
|
||||||
) : (
|
|
||||||
<em>NA</em>
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<small className="card-text text-uppercase text-body-secondary small">
|
|
||||||
Contacts
|
|
||||||
</small>
|
|
||||||
<ul className="list-unstyled my-3 py-1">
|
|
||||||
<li className="d-flex align-items-center mb-4">
|
|
||||||
<i className="icon-base bx bx-phone"></i>
|
|
||||||
<span className="fw-medium mx-2">Contact:</span>{" "}
|
|
||||||
<span> {profile?.phoneNumber || <em>NA</em>}</span>
|
|
||||||
</li>
|
|
||||||
<li className="d-flex align-items-center mb-4">
|
|
||||||
<i className="icon-base bx bx-envelope"></i>
|
|
||||||
<span className="fw-medium mx-2">Email:</span>{" "}
|
|
||||||
<a href={`mailto:${profile?.email}`}>
|
|
||||||
{" "}
|
|
||||||
{profile?.email || <em>NA</em>}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li className="d-flex align-items-center mb-4">
|
|
||||||
<i className="icon-base bx bx-user"></i>
|
|
||||||
<span className="fw-medium mx-2">
|
|
||||||
{" "}
|
|
||||||
Emergency Contact:
|
|
||||||
</span>{" "}
|
|
||||||
<span> {profile?.emergencyContactPerson || <em>NA</em>}</span>
|
|
||||||
</li>
|
|
||||||
<li className="d-flex align-items-center mb-4">
|
|
||||||
<i className="icon-base bx bx-phone"></i>
|
|
||||||
<span className="fw-medium mx-2"> Emergency Phone:</span>{" "}
|
|
||||||
<span> {profile?.emergencyPhoneNumber || <em>NA</em>}</span>
|
|
||||||
</li>
|
|
||||||
<li className="d-flex align-items-center ">
|
|
||||||
<div className="container p-0">
|
|
||||||
<div className="fw-medium text-start">
|
|
||||||
<i className="icon-base bx bx-map "></i> Address:
|
|
||||||
</div>
|
|
||||||
<div className="text-start ms-7">
|
|
||||||
{profile?.currentAddress || <em>NA</em>}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
export default EmpOverview;
|
|
||||||
@ -1,36 +1,53 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
const EmployeeNav = ({ onPillClick, activePill }) => {
|
|
||||||
const tabs = [
|
|
||||||
{ key: "profile", icon: "bx bx-user", label: "Profile" },
|
|
||||||
{ key: "attendance", icon: "bx bx-group", label: "Attendances" },
|
|
||||||
{ key: "documents", icon: "bx bx-user", label: "Documents" },
|
|
||||||
{ key: "activities", icon: "bx bx-grid-alt", label: "Activities" },
|
|
||||||
];
|
|
||||||
|
|
||||||
|
const EmployeeNav = ({ onPillClick, activePill }) => {
|
||||||
return (
|
return (
|
||||||
<div className="col-md-12">
|
<div className="col-md-12">
|
||||||
<div className="nav-align-top">
|
<div className="nav-align-top ">
|
||||||
<ul className="nav nav-tabs overflow-auto" id="horizontal-example">
|
<ul className="nav nav-tabs">
|
||||||
{tabs.map(({ key, icon, label }) => (
|
<li className="nav-item" style={{ padding: "10px 10px 0 10px" }}>
|
||||||
<li
|
|
||||||
key={key}
|
|
||||||
className="nav-item"
|
|
||||||
style={{ padding: "10px 10px 0 10px" }}
|
|
||||||
>
|
|
||||||
<a
|
<a
|
||||||
href="#"
|
|
||||||
className={`nav-link py-1 px-2 small ${
|
className={`nav-link py-1 px-2 small ${
|
||||||
activePill === key ? "active" : ""
|
activePill === "attendance" ? "active" : ""
|
||||||
}`}
|
}`}
|
||||||
|
href="#"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault(); // Prevent page reload
|
||||||
onPillClick(key);
|
onPillClick("attendance");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<i className={`icon-base ${icon} icon-sm me-1_5`}></i> {label}
|
<i className="bx bx-group bx-sm me-1_5"></i> Attendances
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li className="nav-item" style={{ padding: "10px 10px 0 10px" }}>
|
||||||
|
<a
|
||||||
|
className={`nav-link py-1 px-2 small ${
|
||||||
|
activePill === "account" ? "active" : ""
|
||||||
|
}`}
|
||||||
|
href="#"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault(); // Prevent page reload
|
||||||
|
onPillClick("account");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i className="bx bx-user bx-sm me-1_5"></i> Documents
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li className="nav-item" style={{ padding: "10px 10px 0 10px" }}>
|
||||||
|
<a
|
||||||
|
className={`nav-link py-1 px-2 small ${
|
||||||
|
activePill === "activities" ? "active" : ""
|
||||||
|
}`}
|
||||||
|
href="#"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault(); // Prevent page reload
|
||||||
|
onPillClick("activities");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i className="bx bx-grid-alt bx-sm me-1_5"></i> Activities
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
))}
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -27,25 +27,12 @@ const Header = () => {
|
|||||||
const { data, loading } = useMaster();
|
const { data, loading } = useMaster();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const HasManageProjectPermission = useHasUserPermission(MANAGE_PROJECT);
|
const HasManageProjectPermission = useHasUserPermission(MANAGE_PROJECT);
|
||||||
// {
|
|
||||||
// console.log(location.pathname);
|
|
||||||
// }
|
|
||||||
|
|
||||||
const isDashboardPath =
|
const isDirectoryPath = /^\/directory$/.test(location.pathname);
|
||||||
/^\/dashboard$/.test(location.pathname) || /^\/$/.test(location.pathname);
|
|
||||||
const isProjectPath = /^\/projects$/.test(location.pathname);
|
const isProjectPath = /^\/projects$/.test(location.pathname);
|
||||||
|
const isDashboard =
|
||||||
|
/^\/dashboard$/.test(location.pathname) || /^\/$/.test(location.pathname);
|
||||||
|
|
||||||
const showProjectDropdown = (pathname) => {
|
|
||||||
const isDirectoryPath = /^\/directory$/.test(pathname);
|
|
||||||
|
|
||||||
// const isProfilePage = /^\/employee$/.test(location.pathname);
|
|
||||||
const isProfilePage =
|
|
||||||
/^\/employee\/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(
|
|
||||||
pathname
|
|
||||||
);
|
|
||||||
|
|
||||||
return !(isDirectoryPath || isProfilePage);
|
|
||||||
};
|
|
||||||
const allowedProjectStatusIds = [
|
const allowedProjectStatusIds = [
|
||||||
"603e994b-a27f-4e5d-a251-f3d69b0498ba",
|
"603e994b-a27f-4e5d-a251-f3d69b0498ba",
|
||||||
"cdad86aa-8a56-4ff4-b633-9c629057dfef",
|
"cdad86aa-8a56-4ff4-b633-9c629057dfef",
|
||||||
@ -95,16 +82,16 @@ const Header = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleProfilePage = () => {
|
const handleProfilePage = () => {
|
||||||
navigate(`/employee/${profile?.employeeInfo?.id}`);
|
navigate(`/employee/${profile?.employeeInfo?.id}?for=attendance`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const { projectNames, loading: projectLoading, fetchData } = useProjectName();
|
const { projectNames, loading: projectLoading, fetchData } = useProjectName();
|
||||||
|
|
||||||
const selectedProject = useSelectedproject();
|
const selectedProject = useSelectedproject();
|
||||||
|
|
||||||
const projectsForDropdown = isDashboardPath
|
const projectsForDropdown = isDashboard
|
||||||
? projectNames
|
? projectNames
|
||||||
: projectNames?.filter((project) =>
|
: projectNames?.filter(project =>
|
||||||
allowedProjectStatusIds.includes(project.projectStatusId)
|
allowedProjectStatusIds.includes(project.projectStatusId)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -122,9 +109,7 @@ const Header = () => {
|
|||||||
const selectedProjectObj = projectNames.find(
|
const selectedProjectObj = projectNames.find(
|
||||||
(p) => p?.id === selectedProject
|
(p) => p?.id === selectedProject
|
||||||
);
|
);
|
||||||
currentProjectDisplayName = selectedProjectObj
|
currentProjectDisplayName = selectedProjectObj ? selectedProjectObj.name : "All Projects";
|
||||||
? selectedProjectObj.name
|
|
||||||
: "All Projects";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,17 +125,16 @@ const Header = () => {
|
|||||||
if (projectNames.length === 1) {
|
if (projectNames.length === 1) {
|
||||||
dispatch(setProjectId(projectNames[0]?.id || null));
|
dispatch(setProjectId(projectNames[0]?.id || null));
|
||||||
} else {
|
} else {
|
||||||
if (isDashboardPath) {
|
if (isDashboard) {
|
||||||
dispatch(setProjectId(null));
|
dispatch(setProjectId(null));
|
||||||
} else {
|
} else {
|
||||||
const firstAllowedProject = projectNames.find((project) =>
|
const firstAllowedProject = projectNames.find(project => allowedProjectStatusIds.includes(project.projectStatusId));
|
||||||
allowedProjectStatusIds.includes(project.projectStatusId)
|
|
||||||
);
|
|
||||||
dispatch(setProjectId(firstAllowedProject?.id || null));
|
dispatch(setProjectId(firstAllowedProject?.id || null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [projectNames, selectedProject, dispatch, isDashboardPath]);
|
}, [projectNames, selectedProject, dispatch, isDashboard]);
|
||||||
|
|
||||||
|
|
||||||
const handler = useCallback(
|
const handler = useCallback(
|
||||||
async (data) => {
|
async (data) => {
|
||||||
@ -220,7 +204,7 @@ const Header = () => {
|
|||||||
className="navbar-nav-right d-flex align-items-center justify-content-between"
|
className="navbar-nav-right d-flex align-items-center justify-content-between"
|
||||||
id="navbar-collapse"
|
id="navbar-collapse"
|
||||||
>
|
>
|
||||||
{showProjectDropdown(location.pathname) && (
|
{projectNames && !isDirectoryPath && (
|
||||||
<div className="align-items-center">
|
<div className="align-items-center">
|
||||||
<i className="rounded-circle bx bx-building-house bx-sm-lg bx-md me-2"></i>
|
<i className="rounded-circle bx bx-building-house bx-sm-lg bx-md me-2"></i>
|
||||||
<div className="btn-group">
|
<div className="btn-group">
|
||||||
@ -239,14 +223,12 @@ const Header = () => {
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{shouldShowDropdown &&
|
{shouldShowDropdown && projectsForDropdown && projectsForDropdown.length > 0 && (
|
||||||
projectsForDropdown &&
|
|
||||||
projectsForDropdown.length > 0 && (
|
|
||||||
<ul
|
<ul
|
||||||
className="dropdown-menu"
|
className="dropdown-menu"
|
||||||
style={{ overflow: "auto", maxHeight: "300px" }}
|
style={{ overflow: "auto", maxHeight: "300px" }}
|
||||||
>
|
>
|
||||||
{isDashboardPath && (
|
{isDashboard && (
|
||||||
<li>
|
<li>
|
||||||
<button
|
<button
|
||||||
className="dropdown-item"
|
className="dropdown-item"
|
||||||
|
|||||||
@ -27,7 +27,8 @@ const DateRangePicker = ({
|
|||||||
altInput: true,
|
altInput: true,
|
||||||
altFormat: "d-m-Y",
|
altFormat: "d-m-Y",
|
||||||
defaultDate: [startDate, endDate],
|
defaultDate: [startDate, endDate],
|
||||||
static: true,
|
static: false,
|
||||||
|
// appendTo: document.body,
|
||||||
clickOpens: true,
|
clickOpens: true,
|
||||||
maxDate: endDate,
|
maxDate: endDate,
|
||||||
onChange: (selectedDates, dateStr) => {
|
onChange: (selectedDates, dateStr) => {
|
||||||
|
|||||||
@ -1,26 +0,0 @@
|
|||||||
import { format } from "date-fns";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A custom hook to format a date string, object, or number.
|
|
||||||
* @param {string | Date | number} date - The date to be formatted.
|
|
||||||
* @param {string} formatString - The format string (e.g., 'MMMM do, yyyy').
|
|
||||||
* @returns {string} The formatted date string.
|
|
||||||
*/
|
|
||||||
const useFormattedDate = (date, formatString) => {
|
|
||||||
// Return early if no date is provided
|
|
||||||
if (!date) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const dateObj = new Date(date);
|
|
||||||
// You could also add error handling for invalid dates
|
|
||||||
// if (!isValid(dateObj)) return 'Invalid Date';
|
|
||||||
return format(dateObj, formatString);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error formatting date:", error);
|
|
||||||
return ""; // Return an empty string or a default value on error
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useFormattedDate;
|
|
||||||
@ -96,7 +96,7 @@ export const useProjectDetails = (projectId, isAuto = true) => {
|
|||||||
|
|
||||||
export const useProjectsByEmployee = (employeeId) => {
|
export const useProjectsByEmployee = (employeeId) => {
|
||||||
const {
|
const {
|
||||||
data: projectList = [],
|
data: projectNameList = [],
|
||||||
isLoading,
|
isLoading,
|
||||||
error,
|
error,
|
||||||
refetch,
|
refetch,
|
||||||
@ -117,36 +117,6 @@ export const useProjectsByEmployee = (employeeId) => {
|
|||||||
return { projectList, loading: isLoading, error, refetch };
|
return { projectList, loading: isLoading, error, refetch };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useProjectsAllocationByEmployee = (employeeId) => {
|
|
||||||
const {
|
|
||||||
data: projectList = [],
|
|
||||||
isLoading,
|
|
||||||
error,
|
|
||||||
refetch,
|
|
||||||
} = useQuery({
|
|
||||||
queryKey: ["ProjectsAllocationByEmployee", employeeId],
|
|
||||||
queryFn: async () => {
|
|
||||||
const res = await ProjectRepository.getProjectsAllocationByEmployee(
|
|
||||||
employeeId
|
|
||||||
);
|
|
||||||
const sortedProjects = [...res.data].sort((a, b) =>
|
|
||||||
a.projectName.localeCompare(b.projectName)
|
|
||||||
);
|
|
||||||
return sortedProjects || res;
|
|
||||||
|
|
||||||
//return res.data || res;
|
|
||||||
},
|
|
||||||
enabled: !!employeeId,
|
|
||||||
onError: (error) => {
|
|
||||||
showToast(
|
|
||||||
error.message || "Error while Fetching project Employee",
|
|
||||||
"error"
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return { projectList, loading: isLoading, error, refetch };
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useProjectName = () => {
|
export const useProjectName = () => {
|
||||||
const {
|
const {
|
||||||
data = [],
|
data = [],
|
||||||
@ -206,29 +176,6 @@ export const useProjectTasks = (workAreaId, IsExpandedArea = false) => {
|
|||||||
return { ProjectTaskList, isLoading, error };
|
return { ProjectTaskList, isLoading, error };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useProjectTasksByEmployee = (
|
|
||||||
employeeId,
|
|
||||||
fromDate,
|
|
||||||
toDate,
|
|
||||||
) => {
|
|
||||||
|
|
||||||
return useQuery({
|
|
||||||
queryKey: ["TasksByEmployee", employeeId],
|
|
||||||
queryFn: async () => {
|
|
||||||
const res = await ProjectRepository.getProjectTasksByEmployee(
|
|
||||||
employeeId,
|
|
||||||
fromDate,
|
|
||||||
toDate
|
|
||||||
);
|
|
||||||
return res.data;
|
|
||||||
},
|
|
||||||
enabled: !!employeeId && !!fromDate && !!toDate,
|
|
||||||
onError: (error) => {
|
|
||||||
showToast(error.message || "Error while Fetching project Tasks", "error");
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// -- -------------Mutation-------------------------------
|
// -- -------------Mutation-------------------------------
|
||||||
|
|
||||||
export const useCreateProject = ({ onSuccessCallback }) => {
|
export const useCreateProject = ({ onSuccessCallback }) => {
|
||||||
|
|||||||
@ -1,30 +1,24 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import DateRangePicker from "../common/DateRangePicker";
|
import DateRangePicker from "../../components/common/DateRangePicker";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { fetchEmployeeAttendanceData } from "../../slices/apiSlice/employeeAttendanceSlice";
|
import { fetchEmployeeAttendanceData } from "../../slices/apiSlice/employeeAttendanceSlice";
|
||||||
import usePagination from "../../hooks/usePagination";
|
import usePagination from "../../hooks/usePagination";
|
||||||
import Avatar from "../common/Avatar";
|
import Avatar from "../../components/common/Avatar";
|
||||||
import { convertShortTime } from "../../utils/dateUtils";
|
import { convertShortTime } from "../../utils/dateUtils";
|
||||||
import RenderAttendanceStatus from "../Activities/RenderAttendanceStatus";
|
import RenderAttendanceStatus from "../../components/Activities/RenderAttendanceStatus";
|
||||||
import AttendLogs from "../Activities/AttendLogs";
|
import AttendLogs from "../../components/Activities/AttendLogs";
|
||||||
import { useAttendanceByEmployee } from "../../hooks/useAttendance";
|
import { useAttendanceByEmployee } from "../../hooks/useAttendance";
|
||||||
import GlobalModel from "../common/GlobalModel";
|
import GlobalModel from "../../components/common/GlobalModel";
|
||||||
import { ITEMS_PER_PAGE } from "../../utils/constants";
|
import { ITEMS_PER_PAGE } from "../../utils/constants";
|
||||||
|
|
||||||
const EmpAttendance = ({ employee }) => {
|
const AttendancesEmployeeRecords = ({ employee }) => {
|
||||||
const [attendances, setAttendnaces] = useState([]);
|
const [attendances, setAttendnaces] = useState([]);
|
||||||
const [selectedDate, setSelectedDate] = useState("");
|
const [selectedDate, setSelectedDate] = useState("");
|
||||||
const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" });
|
const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" });
|
||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
const [attendanceId, setAttendanecId] = useState();
|
const [attendanceId, setAttendanecId] = useState();
|
||||||
const {
|
const {data =[],isLoading:loading,isFetching,error,refetch} = useAttendanceByEmployee(employee,dateRange.startDate, dateRange.endDate)
|
||||||
data = [],
|
|
||||||
isLoading: loading,
|
|
||||||
isFetching,
|
|
||||||
error,
|
|
||||||
refetch,
|
|
||||||
} = useAttendanceByEmployee(employee, dateRange.startDate, dateRange.endDate);
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
// const { data, loading, error } = useSelector(
|
// const { data, loading, error } = useSelector(
|
||||||
@ -81,24 +75,16 @@ const EmpAttendance = ({ employee }) => {
|
|||||||
const uniqueMap = new Map();
|
const uniqueMap = new Map();
|
||||||
|
|
||||||
[...group1, ...group2, ...group3, ...group4, ...group5].forEach((rec) => {
|
[...group1, ...group2, ...group3, ...group4, ...group5].forEach((rec) => {
|
||||||
const date = moment(rec.checkInTime || rec.checkOutTime).format(
|
const date = moment(rec.checkInTime || rec.checkOutTime).format("YYYY-MM-DD");
|
||||||
"YYYY-MM-DD"
|
|
||||||
);
|
|
||||||
const key = `${rec.employeeId}-${date}`;
|
const key = `${rec.employeeId}-${date}`;
|
||||||
const existing = uniqueMap.get(key);
|
const existing = uniqueMap.get(key);
|
||||||
if (
|
if (!existing || new Date(rec.checkInTime || rec.checkOutTime) > new Date(existing.checkInTime || existing.checkOutTime)) {
|
||||||
!existing ||
|
|
||||||
new Date(rec.checkInTime || rec.checkOutTime) >
|
|
||||||
new Date(existing.checkInTime || existing.checkOutTime)
|
|
||||||
) {
|
|
||||||
uniqueMap.set(key, rec);
|
uniqueMap.set(key, rec);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const sortedFinalList = [...uniqueMap.values()].sort(
|
const sortedFinalList = [...uniqueMap.values()].sort((a, b) =>
|
||||||
(a, b) =>
|
new Date(b.checkInTime || b.checkOutTime) - new Date(a.checkInTime || a.checkOutTime)
|
||||||
new Date(b.checkInTime || b.checkOutTime) -
|
|
||||||
new Date(a.checkInTime || a.checkOutTime)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const currentDate = new Date().toLocaleDateString("en-CA");
|
const currentDate = new Date().toLocaleDateString("en-CA");
|
||||||
@ -107,6 +93,8 @@ const EmpAttendance = ({ employee }) => {
|
|||||||
ITEMS_PER_PAGE
|
ITEMS_PER_PAGE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const openModal = (id) => {
|
const openModal = (id) => {
|
||||||
setAttendanecId(id);
|
setAttendanecId(id);
|
||||||
setIsModalOpen(true);
|
setIsModalOpen(true);
|
||||||
@ -115,27 +103,24 @@ const EmpAttendance = ({ employee }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
||||||
|
|
||||||
{isModalOpen && (
|
{isModalOpen && (
|
||||||
<GlobalModel size="lg" isOpen={isModalOpen} closeModal={closeModal}>
|
<GlobalModel size="lg" isOpen={isModalOpen} closeModal={closeModal}>
|
||||||
<AttendLogs Id={attendanceId} />
|
<AttendLogs Id={attendanceId} />
|
||||||
</GlobalModel>
|
</GlobalModel>
|
||||||
)}
|
)}
|
||||||
<div className="card px-4 mt-5 py-2 " style={{ minHeight: "500px" }}>
|
<div className="px-4 py-2 " style={{ minHeight: "500px" }}>
|
||||||
<div
|
<div
|
||||||
className="dataTables_length text-start py-2 d-flex justify-content-between "
|
className="dataTables_length text-start py-2 d-flex justify-content-between "
|
||||||
id="DataTables_Table_0_length"
|
id="DataTables_Table_0_length"
|
||||||
>
|
>
|
||||||
<div className="col-md-3 my-0 ">
|
<div className="col-md-3 my-0 ">
|
||||||
<DateRangePicker
|
<DateRangePicker onRangeChange={setDateRange} endDateMode="yesterday" />
|
||||||
DateDifference="30"
|
|
||||||
onRangeChange={setDateRange}
|
|
||||||
endDateMode="today"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-2 m-0 text-end">
|
<div className="col-md-2 m-0 text-end">
|
||||||
<i
|
<i
|
||||||
className={`bx bx-refresh cursor-pointer fs-4 ${
|
className={`bx bx-refresh cursor-pointer fs-4 ${isFetching ? "spin" : ""
|
||||||
isFetching ? "spin" : ""
|
|
||||||
}`}
|
}`}
|
||||||
data-toggle="tooltip"
|
data-toggle="tooltip"
|
||||||
title="Refresh"
|
title="Refresh"
|
||||||
@ -229,8 +214,7 @@ const EmpAttendance = ({ employee }) => {
|
|||||||
{[...Array(totalPages)].map((_, index) => (
|
{[...Array(totalPages)].map((_, index) => (
|
||||||
<li
|
<li
|
||||||
key={index}
|
key={index}
|
||||||
className={`page-item ${
|
className={`page-item ${currentPage === index + 1 ? "active" : ""
|
||||||
currentPage === index + 1 ? "active" : ""
|
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
@ -242,8 +226,7 @@ const EmpAttendance = ({ employee }) => {
|
|||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
<li
|
<li
|
||||||
className={`page-item ${
|
className={`page-item ${currentPage === totalPages ? "disabled" : ""
|
||||||
currentPage === totalPages ? "disabled" : ""
|
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
@ -261,4 +244,4 @@ const EmpAttendance = ({ employee }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default EmpAttendance;
|
export default AttendancesEmployeeRecords;
|
||||||
@ -51,8 +51,7 @@ const EmployeeList = () => {
|
|||||||
|
|
||||||
const { employees, loading, setLoading, error, recallEmployeeData } =
|
const { employees, loading, setLoading, error, recallEmployeeData } =
|
||||||
useEmployeesAllOrByProjectId(
|
useEmployeesAllOrByProjectId(
|
||||||
showAllEmployees,
|
showAllEmployees ,selectedProjectId,
|
||||||
selectedProjectId,
|
|
||||||
showInactive
|
showInactive
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -154,6 +153,8 @@ const EmployeeList = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleAllEmployeesToggle = (e) => {
|
const handleAllEmployeesToggle = (e) => {
|
||||||
const isChecked = e.target.checked;
|
const isChecked = e.target.checked;
|
||||||
setShowInactive(false);
|
setShowInactive(false);
|
||||||
@ -294,12 +295,12 @@ const EmployeeList = () => {
|
|||||||
|
|
||||||
{ViewTeamMember ? (
|
{ViewTeamMember ? (
|
||||||
// <div className="row">
|
// <div className="row">
|
||||||
<div className="card p-1">
|
<div className="card px-0 px-sm-4">
|
||||||
<div className="card-datatable table-responsive pt-2">
|
<div className="card-datatable table-responsive pt-2">
|
||||||
<div
|
<div
|
||||||
id="DataTables_Table_0_wrapper"
|
id="DataTables_Table_0_wrapper"
|
||||||
className="dataTables_wrapper dt-bootstrap5 no-footer"
|
className="dataTables_wrapper no-footer px-2 "
|
||||||
style={{ width: "98%" }}
|
|
||||||
>
|
>
|
||||||
<div className="d-flex flex-wrap align-items-center justify-content-between gap-3 mb-3">
|
<div className="d-flex flex-wrap align-items-center justify-content-between gap-3 mb-3">
|
||||||
{/* Switches: All Employees + Inactive */}
|
{/* Switches: All Employees + Inactive */}
|
||||||
@ -333,7 +334,7 @@ const EmployeeList = () => {
|
|||||||
role="switch"
|
role="switch"
|
||||||
id="inactiveEmployeesCheckbox"
|
id="inactiveEmployeesCheckbox"
|
||||||
checked={showInactive}
|
checked={showInactive}
|
||||||
onChange={(e) => setShowInactive(e.target.checked)}
|
onChange={(e)=> setShowInactive(e.target.checked)}
|
||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
className="form-check-label ms-0"
|
className="form-check-label ms-0"
|
||||||
@ -479,9 +480,7 @@ const EmployeeList = () => {
|
|||||||
aria-label="User: activate to sort column ascending"
|
aria-label="User: activate to sort column ascending"
|
||||||
aria-sort="descending"
|
aria-sort="descending"
|
||||||
>
|
>
|
||||||
<div className="text-start ms-5">
|
<div className="text-start ms-5">Official Designation</div>
|
||||||
Official Designation
|
|
||||||
</div>
|
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
<th
|
<th
|
||||||
@ -565,7 +564,9 @@ const EmployeeList = () => {
|
|||||||
<div className="d-flex flex-column">
|
<div className="d-flex flex-column">
|
||||||
<a
|
<a
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
navigate(`/employee/${item.id}`)
|
navigate(
|
||||||
|
`/employee/${item.id}?for=attendance`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
className="text-heading text-truncate cursor-pointer"
|
className="text-heading text-truncate cursor-pointer"
|
||||||
>
|
>
|
||||||
@ -580,7 +581,7 @@ const EmployeeList = () => {
|
|||||||
<td className="text-start d-none d-sm-table-cell">
|
<td className="text-start d-none d-sm-table-cell">
|
||||||
{item.email ? (
|
{item.email ? (
|
||||||
<span className="text-truncate">
|
<span className="text-truncate">
|
||||||
<i className="bx bxs-envelope text-primary me-2"></i>
|
<i className="bx bxs-envelope text-primary text-truncate me-2"></i>
|
||||||
{item.email}
|
{item.email}
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
@ -638,7 +639,8 @@ const EmployeeList = () => {
|
|||||||
}
|
}
|
||||||
className="dropdown-item py-1"
|
className="dropdown-item py-1"
|
||||||
>
|
>
|
||||||
<i className="bx bx-detail bx-sm"></i> View
|
<i className="bx bx-detail bx-sm"></i>{" "}
|
||||||
|
View
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="dropdown-item py-1"
|
className="dropdown-item py-1"
|
||||||
@ -735,8 +737,8 @@ const EmployeeList = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
|
||||||
// </div>
|
// </div>
|
||||||
|
) : (
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<i className="fa-solid fa-triangle-exclamation fs-5"></i>
|
<i className="fa-solid fa-triangle-exclamation fs-5"></i>
|
||||||
|
|||||||
@ -1,27 +1,26 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { useSearchParams, useParams, useNavigate } from "react-router-dom";
|
import EmpProfile from "../../components/Employee/EmpProfile";
|
||||||
import { useSelector } from "react-redux";
|
import axios from "axios";
|
||||||
|
import Breadcrumb from "../../components/common/Breadcrumb";
|
||||||
|
import EmployeeNav from "../../components/Employee/EmployeeNav";
|
||||||
|
import { useSearchParams, useParams } from "react-router-dom";
|
||||||
|
import { getCachedData } from "../../slices/apiDataManager";
|
||||||
import {
|
import {
|
||||||
useEmployeeProfile,
|
useEmployeeProfile,
|
||||||
useEmployees,
|
useEmployees,
|
||||||
useEmployeesByProject,
|
useEmployeesByProject,
|
||||||
} from "../../hooks/useEmployees";
|
} from "../../hooks/useEmployees";
|
||||||
import { useProfile } from "../../hooks/useProfile";
|
import { useProfile } from "../../hooks/useProfile";
|
||||||
import { getCachedData } from "../../slices/apiDataManager";
|
|
||||||
|
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
import EmployeeRepository from "../../repositories/EmployeeRepository";
|
import EmployeeRepository from "../../repositories/EmployeeRepository";
|
||||||
import { ComingSoonPage } from "../Misc/ComingSoonPage";
|
import { ComingSoonPage } from "../Misc/ComingSoonPage";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
import Breadcrumb from "../../components/common/Breadcrumb";
|
import Avatar from "../../components/common/Avatar";
|
||||||
import EmployeeNav from "../../components/Employee/EmployeeNav";
|
import AttendancesEmployeeRecords from "./AttendancesEmployeeRecords";
|
||||||
import EmpProfile from "../../components/Employee/EmpProfile";
|
|
||||||
import EmpAttendance from "../../components/Employee/EmpAttendance";
|
|
||||||
import ManageEmployee from "../../components/Employee/ManageEmployee";
|
import ManageEmployee from "../../components/Employee/ManageEmployee";
|
||||||
import EmpBanner from "../../components/Employee/EmpBanner";
|
import { useChangePassword } from "../../components/Context/ChangePasswordContext";
|
||||||
import EmpDashboard from "../../components/Employee/EmpDashboard";
|
import GlobalModel from "../../components/common/GlobalModel";
|
||||||
import EmpDocuments from "../../components/Employee/EmpDocuments";
|
|
||||||
import EmpActivities from "../../components/Employee/EmpActivities";
|
|
||||||
|
|
||||||
const EmployeeProfile = () => {
|
const EmployeeProfile = () => {
|
||||||
const { profile } = useProfile();
|
const { profile } = useProfile();
|
||||||
@ -33,7 +32,7 @@ const EmployeeProfile = () => {
|
|||||||
|
|
||||||
const [SearchParams] = useSearchParams();
|
const [SearchParams] = useSearchParams();
|
||||||
const tab = SearchParams.get("for");
|
const tab = SearchParams.get("for");
|
||||||
const [activePill, setActivePill] = useState(tab || "profile");
|
const [activePill, setActivePill] = useState(tab);
|
||||||
const [currentEmployee, setCurrentEmployee] = useState();
|
const [currentEmployee, setCurrentEmployee] = useState();
|
||||||
const [showModal, setShowModal] = useState(false);
|
const [showModal, setShowModal] = useState(false);
|
||||||
|
|
||||||
@ -41,6 +40,8 @@ const EmployeeProfile = () => {
|
|||||||
setActivePill(pillKey);
|
setActivePill(pillKey);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const fetchEmployeeProfile = async (employeeID) => {
|
const fetchEmployeeProfile = async (employeeID) => {
|
||||||
try {
|
try {
|
||||||
const resp = await EmployeeRepository.getEmployeeProfile(employeeID);
|
const resp = await EmployeeRepository.getEmployeeProfile(employeeID);
|
||||||
@ -61,24 +62,17 @@ const EmployeeProfile = () => {
|
|||||||
const renderContent = () => {
|
const renderContent = () => {
|
||||||
if (loading) return <div>Loading</div>;
|
if (loading) return <div>Loading</div>;
|
||||||
switch (activePill) {
|
switch (activePill) {
|
||||||
case "profile": {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<EmpDashboard profile={currentEmployee} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
case "attendance": {
|
case "attendance": {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<EmpAttendance employee={employeeId} />
|
<AttendancesEmployeeRecords employee={employeeId} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case "documents": {
|
case "dcoument": {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<EmpDocuments />
|
<ComingSoonPage />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@ -86,7 +80,7 @@ const EmployeeProfile = () => {
|
|||||||
case "activities": {
|
case "activities": {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<EmpActivities employee={currentEmployee} />
|
<ComingSoonPage />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@ -104,8 +98,14 @@ const EmployeeProfile = () => {
|
|||||||
if (loading) {
|
if (loading) {
|
||||||
return <div>Loading...</div>;
|
return <div>Loading...</div>;
|
||||||
}
|
}
|
||||||
|
const { openChangePassword } = useChangePassword();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{showModal && (
|
||||||
|
<GlobalModel size="lg" isOpen={showModal} closeModal={() => setShowModal(false)}>
|
||||||
|
<ManageEmployee employeeId={employeeId} onClosed={() => setShowModal(false)} />
|
||||||
|
</GlobalModel>
|
||||||
|
)}
|
||||||
<div className="container-fluid">
|
<div className="container-fluid">
|
||||||
<Breadcrumb
|
<Breadcrumb
|
||||||
data={[
|
data={[
|
||||||
@ -114,24 +114,151 @@ const EmployeeProfile = () => {
|
|||||||
{ label: "Profile", link: null },
|
{ label: "Profile", link: null },
|
||||||
]}
|
]}
|
||||||
></Breadcrumb>
|
></Breadcrumb>
|
||||||
|
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-12 ">
|
<div className="col-12 col-md-8 col-lg-4 order-1 order-lg-1">
|
||||||
<EmpBanner
|
<div className="row">
|
||||||
profile={currentEmployee}
|
<div className="col-12 mb-4">
|
||||||
loggedInUser={profile}
|
<div className="card">
|
||||||
></EmpBanner>
|
<div className="card-body">
|
||||||
|
<div className="d-flex flex-row flex-lg-column">
|
||||||
|
<div className="d-flex flex-column justify-content-center align-items-center text-center">
|
||||||
|
<Avatar
|
||||||
|
firstName={`${currentEmployee?.firstName}`}
|
||||||
|
lastName={`${currentEmployee?.lastName}`}
|
||||||
|
size={"lg"}
|
||||||
|
/>
|
||||||
|
<div className="py-2">
|
||||||
|
<p className="h6">{`${currentEmployee?.firstName} ${currentEmployee?.lastName}`}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>{" "}
|
</div>
|
||||||
|
<div className="w-100 d-flex flex-column justify-content-start">
|
||||||
|
<div className="mt-3 w-100">
|
||||||
|
<h6 className="mb-2 text-muted text-start">
|
||||||
|
Employee Info
|
||||||
|
</h6>
|
||||||
|
<table className="table table-borderless mb-3">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td className="fw-medium text-start">Email:</td>
|
||||||
|
<td className="text-start">
|
||||||
|
{currentEmployee?.email || <em>NA</em>}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="fw-medium text-start text-nowrap">
|
||||||
|
Phone Number:
|
||||||
|
</td>
|
||||||
|
<td className="text-start">
|
||||||
|
{currentEmployee?.phoneNumber || <em>NA</em>}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="fw-medium text-start" style={{ width: '120px' }}>
|
||||||
|
Emergency Contact Person:
|
||||||
|
</td>
|
||||||
|
<td className="text-start align-bottom">
|
||||||
|
{currentEmployee?.emergencyContactPerson || <em>NA</em>}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="fw-medium text-start">
|
||||||
|
Emergency Contact Number:
|
||||||
|
</td>
|
||||||
|
<td className="text-start align-bottom">
|
||||||
|
{currentEmployee?.emergencyPhoneNumber || <em>NA</em>}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="fw-medium text-start">
|
||||||
|
Gender:
|
||||||
|
</td>
|
||||||
|
<td className="text-start">
|
||||||
|
{currentEmployee?.gender || <em>NA</em>}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="fw-medium text-start">
|
||||||
|
Birth Date:
|
||||||
|
</td>
|
||||||
|
<td className="text-start">
|
||||||
|
{currentEmployee?.birthDate ? (
|
||||||
|
new Date(
|
||||||
|
currentEmployee.birthDate
|
||||||
|
).toLocaleDateString()
|
||||||
|
) : (
|
||||||
|
<em>NA</em>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td className="fw-medium text-start">
|
||||||
|
Joining Date:
|
||||||
|
</td>
|
||||||
|
<td className="text-start">
|
||||||
|
{currentEmployee?.joiningDate ? (
|
||||||
|
new Date(
|
||||||
|
currentEmployee.joiningDate
|
||||||
|
).toLocaleDateString()
|
||||||
|
) : (
|
||||||
|
<em>NA</em>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="fw-medium text-start">
|
||||||
|
Job Role:
|
||||||
|
</td>
|
||||||
|
<td className="text-start">
|
||||||
|
{currentEmployee?.jobRole || <em>NA</em>}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="fw-medium text-start align-top" >
|
||||||
|
Address:
|
||||||
|
</td>
|
||||||
|
<td className="text-start">
|
||||||
|
{currentEmployee?.currentAddress || <em>NA</em>}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
className="btn btn-primary btn-block"
|
||||||
|
onClick={() => setShowModal(true)}
|
||||||
|
>
|
||||||
|
Edit Profile
|
||||||
|
</button>
|
||||||
|
{currentEmployee?.id == profile?.employeeInfo?.id && (
|
||||||
|
<button
|
||||||
|
className="btn btn-outline-primary btn-block mt-2"
|
||||||
|
onClick={() => openChangePassword()}
|
||||||
|
>
|
||||||
|
Change Password
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-12 col-lg-8 order-2 order-lg-2 mb-4">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-12 ">
|
|
||||||
<EmployeeNav
|
<EmployeeNav
|
||||||
onPillClick={handlePillClick}
|
onPillClick={handlePillClick}
|
||||||
activePill={activePill}
|
activePill={activePill}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="card">
|
||||||
|
<div className="row row-bordered g-0">{renderContent()}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="row">
|
|
||||||
<div className=" ">{renderContent()}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -6,41 +6,32 @@ const ProjectRepository = {
|
|||||||
api.get(`/api/project/details/${projetid}`),
|
api.get(`/api/project/details/${projetid}`),
|
||||||
|
|
||||||
getProjectAllocation: (projetid) =>
|
getProjectAllocation: (projetid) =>
|
||||||
api.get(`api/project/allocation/${projetid}`),
|
api.get( `api/project/allocation/${ projetid }` ),
|
||||||
|
|
||||||
getEmployeesByProject: (projectId) =>
|
getEmployeesByProject:(projectId)=>api.get(`/api/Project/employees/get/${projectId}`),
|
||||||
api.get(`/api/Project/employees/get/${projectId}`),
|
|
||||||
|
|
||||||
manageProject: (data) => api.post("/api/project", data),
|
manageProject: (data) => api.post("/api/project", data),
|
||||||
// updateProject: (data) => api.post("/api/project/update", data),
|
// updateProject: (data) => api.post("/api/project/update", data),
|
||||||
|
|
||||||
manageProjectAllocation: (data) => api.post("/api/project/allocation", data),
|
manageProjectAllocation: ( data ) => api.post( "/api/project/allocation", data ),
|
||||||
|
|
||||||
manageProjectInfra: (data) => api.post("/api/project/manage-infra", data),
|
manageProjectInfra: (data) => api.post("/api/project/manage-infra", data),
|
||||||
manageProjectTasks: (data) => api.post("/api/project/task", data),
|
manageProjectTasks: ( data ) => api.post( "/api/project/task", data ),
|
||||||
deleteProjectTask: (id) => api.delete(`/api/project/task/${id}`),
|
deleteProjectTask:(id)=> api.delete(`/api/project/task/${id}`),
|
||||||
|
|
||||||
updateProject: (id, data) => api.put(`/api/project/update/${id}`, data),
|
updateProject: (id, data) => api.put(`/api/project/update/${id}`, data),
|
||||||
deleteProject: (id) => api.delete(`/projects/${id}`),
|
deleteProject: ( id ) => api.delete( `/projects/${ id }` ),
|
||||||
getProjectsByEmployee: (id) =>
|
getProjectsByEmployee: ( id ) => api.get( `/api/project/assigned-projects/${ id }` ),
|
||||||
api.get(`/api/project/assigned-projects/${id}`),
|
updateProjectsByEmployee:(id,data)=>api.post(`/api/project/assign-projects/${id}`,data),
|
||||||
getProjectsAllocationByEmployee: (id) =>
|
projectNameList: () => api.get( "/api/project/list/basic" ),
|
||||||
api.get(`/api/project/allocation-histery/${id}`),
|
|
||||||
updateProjectsByEmployee: (id, data) =>
|
|
||||||
api.post(`/api/project/assign-projects/${id}`, data),
|
|
||||||
projectNameList: () => api.get("/api/project/list/basic"),
|
|
||||||
|
|
||||||
getProjectDetails: (id) => api.get(`/api/project/details/${id}`),
|
getProjectDetails:(id)=>api.get(`/api/project/details/${id}`),
|
||||||
getProjectInfraByproject: (id) => api.get(`/api/project/infra-details/${id}`),
|
getProjectInfraByproject: ( id ) => api.get( `/api/project/infra-details/${ id }` ),
|
||||||
getProjectTasksByWorkArea: (id) => api.get(`/api/project/tasks/${id}`),
|
getProjectTasksByWorkArea:(id)=>api.get(`/api/project/tasks/${id}`)
|
||||||
getProjectTasksByEmployee: (id, fromDate, toDate) =>
|
|
||||||
api.get(
|
|
||||||
`/api/project/tasks-employee/${id}?fromDate=${fromDate}&toDate=${toDate}`
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TasksRepository = {
|
export const TasksRepository = {
|
||||||
assignTask: (data) => api.post("/api/task/assign", data),
|
assignTask: ( data ) => api.post( "/api/task/assign", data ),
|
||||||
// reportTask:(data)=>api.post("/api/task/report",data)
|
// reportTask:(data)=>api.post("/api/task/report",data)
|
||||||
};
|
}
|
||||||
export default ProjectRepository;
|
export default ProjectRepository;
|
||||||
|
|||||||