diff --git a/package-lock.json b/package-lock.json
index 39e9a3b4..75c151b9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -18,6 +18,7 @@
"apexcharts": "^4.5.0",
"axios": "^1.7.9",
"axios-retry": "^4.5.0",
+ "date-fns": "^4.1.0",
"dotenv": "^16.4.7",
"dotenv-webpack": "^8.1.0",
"eventemitter3": "^5.0.1",
@@ -2455,6 +2456,16 @@
"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": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
diff --git a/package.json b/package.json
index 3f4d52fe..33e1f019 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
"apexcharts": "^4.5.0",
"axios": "^1.7.9",
"axios-retry": "^4.5.0",
+ "date-fns": "^4.1.0",
"dotenv": "^16.4.7",
"dotenv-webpack": "^8.1.0",
"eventemitter3": "^5.0.1",
diff --git a/public/assets/css/core-extend.css b/public/assets/css/core-extend.css
index c017c963..327febfa 100644
--- a/public/assets/css/core-extend.css
+++ b/public/assets/css/core-extend.css
@@ -3,10 +3,6 @@
--bs-nav-link-font-size: 0.7375rem;
}
-.nav {
- --bs-nav-link-font-size: 0.7375rem;
-}
-
.card-header {
padding: 0.5rem var(--bs-card-cap-padding-x);
}
diff --git a/public/assets/img/avatars/avatar_f_01.png b/public/assets/img/avatars/avatar_f_01.png
new file mode 100644
index 00000000..978d2438
Binary files /dev/null and b/public/assets/img/avatars/avatar_f_01.png differ
diff --git a/public/assets/img/avatars/avatar_f_02.png b/public/assets/img/avatars/avatar_f_02.png
new file mode 100644
index 00000000..38958cb6
Binary files /dev/null and b/public/assets/img/avatars/avatar_f_02.png differ
diff --git a/public/assets/img/avatars/avatar_m_01.png b/public/assets/img/avatars/avatar_m_01.png
new file mode 100644
index 00000000..30dfa72d
Binary files /dev/null and b/public/assets/img/avatars/avatar_m_01.png differ
diff --git a/public/assets/img/avatars/avatar_m_02.png b/public/assets/img/avatars/avatar_m_02.png
new file mode 100644
index 00000000..b43e1c74
Binary files /dev/null and b/public/assets/img/avatars/avatar_m_02.png differ
diff --git a/public/img/favicon.ico b/public/img/favicon.ico
new file mode 100644
index 00000000..be94d1b7
Binary files /dev/null and b/public/img/favicon.ico differ
diff --git a/public/img/favicon/favicon.ico b/public/img/favicon/favicon.ico
index 1ccd2aea..be94d1b7 100644
Binary files a/public/img/favicon/favicon.ico and b/public/img/favicon/favicon.ico differ
diff --git a/src/components/Dashboard/AttendanceChart.jsx b/src/components/Dashboard/AttendanceChart.jsx
index 7fcc862e..df99b07d 100644
--- a/src/components/Dashboard/AttendanceChart.jsx
+++ b/src/components/Dashboard/AttendanceChart.jsx
@@ -6,180 +6,198 @@ import flatColors from "../Charts/flatColor";
import ChartSkeleton from "../Charts/Skelton";
const formatDate = (dateStr) => {
- const date = new Date(dateStr);
- return date.toLocaleDateString("en-GB", {
- day: "2-digit",
- month: "long",
- });
+ const date = new Date(dateStr);
+ return date.toLocaleDateString("en-GB", {
+ day: "2-digit",
+ month: "long",
+ });
};
const AttendanceOverview = () => {
- const [dayRange, setDayRange] = useState(7);
- const [view, setView] = useState("chart");
+ const [dayRange, setDayRange] = useState(7);
+ const [view, setView] = useState("chart");
- const projectId = useSelector((store) => store.localVariables.projectId);
- const { attendanceOverviewData, loading, error } = useAttendanceOverviewData(projectId, dayRange);
+ const projectId = useSelector((store) => store.localVariables.projectId);
+ const { attendanceOverviewData, loading, error } = useAttendanceOverviewData(
+ projectId,
+ dayRange
+ );
- const { tableData, roles, dates } = useMemo(() => {
- const map = new Map();
+ const { tableData, roles, dates } = useMemo(() => {
+ const map = new Map();
- attendanceOverviewData.forEach((entry) => {
- const date = formatDate(entry.date);
- if (!map.has(date)) map.set(date, {});
- map.get(date)[entry.role.trim()] = entry.present;
- });
+ attendanceOverviewData.forEach((entry) => {
+ const date = formatDate(entry.date);
+ if (!map.has(date)) map.set(date, {});
+ map.get(date)[entry.role.trim()] = entry.present;
+ });
- const uniqueRoles = [...new Set(attendanceOverviewData.map((e) => e.role.trim()))];
- const sortedDates = [...map.keys()];
- const data = sortedDates.map((date) => {
- const row = { date };
- uniqueRoles.forEach((role) => {
- row[role] = map.get(date)?.[role] ?? 0;
- });
- return row;
- });
+ const uniqueRoles = [
+ ...new Set(attendanceOverviewData.map((e) => e.role.trim())),
+ ];
+ const sortedDates = [...map.keys()];
+ const data = sortedDates.map((date) => {
+ const row = { date };
+ uniqueRoles.forEach((role) => {
+ row[role] = map.get(date)?.[role] ?? 0;
+ });
+ return row;
+ });
- return {
- tableData: data,
- roles: uniqueRoles,
- dates: sortedDates,
- };
- }, [attendanceOverviewData]);
-
- const chartSeries = roles.map((role) => ({
- name: role,
- data: tableData.map((row) => row[role]),
- }));
-
- const chartOptions = {
- chart: {
- type: "bar",
- stacked: true,
- height: 400,
- toolbar: { show: false },
- },
- plotOptions: {
- bar: {
- borderRadius: 2,
- columnWidth: "60%",
- },
- },
- xaxis: {
- categories: tableData.map((row) => row.date),
- },
- yaxis: {
- show: true,
- axisBorder: {
- show: true,
- color: '#78909C',
- offsetX: 0,
- offsetY: 0
- },
- axisTicks: {
- show: true,
- borderType: 'solid',
- color: '#78909C',
- width: 6,
- offsetX: 0,
- offsetY: 0
- },
- },
- legend: {
- position: "bottom",
- },
- fill: {
- opacity: 1,
- },
- colors: roles.map((_, i) => flatColors[i % flatColors.length]),
+ return {
+ tableData: data,
+ roles: uniqueRoles,
+ dates: sortedDates,
};
+ }, [attendanceOverviewData]);
- return (
-
- {/* Header */}
-
-
-
Attendance Overview
-
Role-wise present count
-
-
-
-
-
-
-
+ const chartSeries = roles.map((role) => ({
+ name: role,
+ data: tableData.map((row) => row[role]),
+ }));
- {/* Content */}
-
- {loading ? (
-
- ) : error ? (
-
{error}
- ) : view === "chart" ? (
-
-
-
- ) : (
-
-
-
-
- Role |
- {dates.map((date, idx) => (
- {date} |
- ))}
-
-
+ const chartOptions = {
+ chart: {
+ type: "bar",
+ stacked: true,
+ height: 400,
+ toolbar: { show: false },
+ },
+ plotOptions: {
+ bar: {
+ borderRadius: 2,
+ columnWidth: "60%",
+ },
+ },
+ xaxis: {
+ categories: tableData.map((row) => row.date),
+ },
+ yaxis: {
+ show: true,
+ axisBorder: {
+ show: true,
+ color: "#78909C",
+ offsetX: 0,
+ offsetY: 0,
+ },
+ axisTicks: {
+ show: true,
+ borderType: "solid",
+ color: "#78909C",
+ width: 6,
+ offsetX: 0,
+ offsetY: 0,
+ },
+ },
+ legend: {
+ position: "bottom",
+ },
+ fill: {
+ opacity: 1,
+ },
+ colors: roles.map((_, i) => flatColors[i % flatColors.length]),
+ };
-
- {roles.map((role) => (
-
- {role} |
- {tableData.map((row, idx) => {
- const value = row[role];
- const cellStyle = value > 0 ? { backgroundColor: '#d5d5d5' } : {};
- return (
-
- {value}
- |
- );
- })}
-
- ))}
-
-
-
- )}
-
+ return (
+
+ {/* Header */}
+
+
+
Attendance Overview
+
Role-wise present count
- );
+
+
+
+
+
+
+
+ {/* Content */}
+
+ {loading ? (
+
+ ) : error ? (
+
{error}
+ ) : view === "chart" ? (
+
+
+
+ ) : (
+
+
+
+
+
+ Role
+ |
+ {dates.map((date, idx) => (
+
+ {date}
+ |
+ ))}
+
+
+
+
+ {roles.map((role) => (
+
+ {role} |
+ {tableData.map((row, idx) => {
+ const value = row[role];
+ const cellStyle =
+ value > 0 ? { backgroundColor: "#d5d5d5" } : {};
+ return (
+
+ {value}
+ |
+ );
+ })}
+
+ ))}
+
+
+
+ )}
+
+
+ );
};
-export default AttendanceOverview;
\ No newline at end of file
+export default AttendanceOverview;
diff --git a/src/components/Employee/EmpActivities.jsx b/src/components/Employee/EmpActivities.jsx
new file mode 100644
index 00000000..f5d9e8c2
--- /dev/null
+++ b/src/components/Employee/EmpActivities.jsx
@@ -0,0 +1,161 @@
+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
Loading...
+ return (
+ <>
+
+
+
+
+
+
+ {data?.map((activity)=>(
+ -
+
+
+
+
{activity.projectName}
+
+ {useFormattedDate(activity.assignmentDate, "dd-MMM-yyyy")}
+
+
+
Activity:{activity.activityName}
+
+ Location: {activity.location}
+
+
+ Planned: {activity.plannedTask}
+ Completed : {activity.completedTask}
+
+
+
+ ))}
+
+
+ {/* -
+
+
+
+
Client Meeting
+ 45 min ago
+
+
Project meeting with john @10:15am
+
+
+
+

+
+
+
+ Lester McCarthy (Client)
+
+
CEO of ThemeSelection
+
+
+
+
+
+ -
+
+
+
+
Create a new project for client
+ 2 Day Ago
+
+
6 team members in a project
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+ +3
+
+
+
+
+
+
+
+ */}
+
+
+
+ >
+ );
+};
+
+export default EmpActivities;
diff --git a/src/pages/employee/AttendancesEmployeeRecords.jsx b/src/components/Employee/EmpAttendance.jsx
similarity index 83%
rename from src/pages/employee/AttendancesEmployeeRecords.jsx
rename to src/components/Employee/EmpAttendance.jsx
index 9b3b7b06..d3cbe817 100644
--- a/src/pages/employee/AttendancesEmployeeRecords.jsx
+++ b/src/components/Employee/EmpAttendance.jsx
@@ -1,24 +1,30 @@
import React, { useState, useEffect } from "react";
import moment from "moment";
-import DateRangePicker from "../../components/common/DateRangePicker";
+import DateRangePicker from "../common/DateRangePicker";
import { useDispatch, useSelector } from "react-redux";
import { fetchEmployeeAttendanceData } from "../../slices/apiSlice/employeeAttendanceSlice";
import usePagination from "../../hooks/usePagination";
-import Avatar from "../../components/common/Avatar";
+import Avatar from "../common/Avatar";
import { convertShortTime } from "../../utils/dateUtils";
-import RenderAttendanceStatus from "../../components/Activities/RenderAttendanceStatus";
-import AttendLogs from "../../components/Activities/AttendLogs";
+import RenderAttendanceStatus from "../Activities/RenderAttendanceStatus";
+import AttendLogs from "../Activities/AttendLogs";
import { useAttendanceByEmployee } from "../../hooks/useAttendance";
-import GlobalModel from "../../components/common/GlobalModel";
+import GlobalModel from "../common/GlobalModel";
import { ITEMS_PER_PAGE } from "../../utils/constants";
-const AttendancesEmployeeRecords = ({ employee }) => {
+const EmpAttendance = ({ employee }) => {
const [attendances, setAttendnaces] = useState([]);
const [selectedDate, setSelectedDate] = useState("");
const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" });
const [isModalOpen, setIsModalOpen] = useState(false);
const [attendanceId, setAttendanecId] = useState();
- const {data =[],isLoading:loading,isFetching,error,refetch} = useAttendanceByEmployee(employee,dateRange.startDate, dateRange.endDate)
+ const {
+ data = [],
+ isLoading: loading,
+ isFetching,
+ error,
+ refetch,
+ } = useAttendanceByEmployee(employee, dateRange.startDate, dateRange.endDate);
const dispatch = useDispatch();
// const { data, loading, error } = useSelector(
@@ -75,16 +81,24 @@ const AttendancesEmployeeRecords = ({ employee }) => {
const uniqueMap = new Map();
[...group1, ...group2, ...group3, ...group4, ...group5].forEach((rec) => {
- const date = moment(rec.checkInTime || rec.checkOutTime).format("YYYY-MM-DD");
+ const date = moment(rec.checkInTime || rec.checkOutTime).format(
+ "YYYY-MM-DD"
+ );
const key = `${rec.employeeId}-${date}`;
const existing = uniqueMap.get(key);
- if (!existing || new Date(rec.checkInTime || rec.checkOutTime) > new Date(existing.checkInTime || existing.checkOutTime)) {
+ if (
+ !existing ||
+ new Date(rec.checkInTime || rec.checkOutTime) >
+ new Date(existing.checkInTime || existing.checkOutTime)
+ ) {
uniqueMap.set(key, rec);
}
});
- const sortedFinalList = [...uniqueMap.values()].sort((a, b) =>
- new Date(b.checkInTime || b.checkOutTime) - new Date(a.checkInTime || a.checkOutTime)
+ const sortedFinalList = [...uniqueMap.values()].sort(
+ (a, b) =>
+ new Date(b.checkInTime || b.checkOutTime) -
+ new Date(a.checkInTime || a.checkOutTime)
);
const currentDate = new Date().toLocaleDateString("en-CA");
@@ -93,8 +107,6 @@ const AttendancesEmployeeRecords = ({ employee }) => {
ITEMS_PER_PAGE
);
-
-
const openModal = (id) => {
setAttendanecId(id);
setIsModalOpen(true);
@@ -103,25 +115,28 @@ const AttendancesEmployeeRecords = ({ employee }) => {
return (
<>
-
-
{isModalOpen && (
-
-
+
+
)}
-
+
-
+
refetch()}
@@ -214,8 +229,9 @@ const AttendancesEmployeeRecords = ({ employee }) => {
{[...Array(totalPages)].map((_, index) => (
))}