diff --git a/src/components/Charts/Circle.jsx b/src/components/Charts/Circle.jsx new file mode 100644 index 00000000..6b0669bf --- /dev/null +++ b/src/components/Charts/Circle.jsx @@ -0,0 +1,80 @@ +import React from "react"; +import ReactApexChart from "react-apexcharts"; + +const ApexChart = ({ completed = 0, planned = 1 }) => { +const percentage = planned > 0 ? Math.round((completed / planned) * 100) : 0; + +const options = { +chart: { +height: 200, +type: "radialBar", +toolbar: { show: false }, +}, +plotOptions: { +radialBar: { +startAngle: -135, +endAngle: 225, +hollow: { +margin: 0, +size: "60%", +background: "#fff", +dropShadow: { +enabled: true, +top: 2, +left: 0, +blur: 3, +opacity: 0.45, +}, +}, +track: { +background: "#f5f5f5", +strokeWidth: "67%", +dropShadow: { enabled: false }, +}, +dataLabels: { +show: true, +name: { +offsetY: -10, +color: "#888", +fontSize: "14px", +}, +value: { +formatter: (val) => `${val}%`, +color: "#111", +fontSize: "24px", +show: true, +}, +}, +}, +}, +fill: { +type: "gradient", +gradient: { +shade: "dark", +type: "horizontal", +shadeIntensity: 0.5, +gradientToColors: ["#ABE5A1"], +opacityFrom: 1, +opacityTo: 1, +stops: [0, 100], +}, +}, +stroke: { +lineCap: "round", +}, +labels: ["Progress"], +}; + +return ( +
+ +
+); +}; + +export default ApexChart; \ No newline at end of file diff --git a/src/components/Dashboard/Attendance.jsx b/src/components/Dashboard/Attendance.jsx new file mode 100644 index 00000000..b7e5a3b2 --- /dev/null +++ b/src/components/Dashboard/Attendance.jsx @@ -0,0 +1,188 @@ +import React, { useState, useEffect } from "react"; +import LineChart from "../Charts/LineChart"; +import { useProjects } from "../../hooks/useProjects"; +import { useDashboard_AttendanceData } from "../../hooks/useDashboard_Data"; +import ApexChart from "../Charts/Circle"; + +const LOCAL_STORAGE_PROJECT_KEY = "selectedAttendanceProjectId"; + +const Attendance = () => { + const { projects } = useProjects(); + const today = new Date().toISOString().split("T")[0]; // Format: YYYY-MM-DD + const [selectedDate, setSelectedDate] = useState(today); + const storedProjectId = localStorage.getItem(LOCAL_STORAGE_PROJECT_KEY); + const initialProjectId = storedProjectId || "all"; + const [selectedProjectId, setSelectedProjectId] = useState(initialProjectId); + const [displayedProjectName, setDisplayedProjectName] = useState("Select Project"); + const [activeTab, setActiveTab] = useState("all"); + + const { dashboard_Attendancedata: AttendanceData, isLoading, error: isError } = + useDashboard_AttendanceData(selectedDate, selectedProjectId); + + useEffect(() => { + if (selectedProjectId === "all") { + setDisplayedProjectName("All Projects"); + } else if (projects) { + const foundProject = projects.find((p) => p.id === selectedProjectId); + setDisplayedProjectName(foundProject ? foundProject.name : "Select Project"); + } else { + setDisplayedProjectName("Select Project"); + } + + localStorage.setItem(LOCAL_STORAGE_PROJECT_KEY, selectedProjectId); + }, [selectedProjectId, projects]); + + const handleProjectSelect = (projectId) => { + setSelectedProjectId(projectId); + }; + + const handleDateChange = (e) => { + setSelectedDate(e.target.value); + }; + + return ( +
+
+
+
+
Attendance
+

Attendance Progress Chart

+
+ +
+ +
    +
  • + +
  • + {projects?.map((project) => ( +
  • + +
  • + ))} +
+
+
+
+ + {/* ✅ Date Picker Aligned Left with Padding */} +
+
+ +
+
+ + + {/* Tabs */} + + +
+ {activeTab === "Summary" && ( +
+
+ {isLoading ? ( +

Loading Attendance data...

+ ) : isError ? ( +

No data available.

+ ) : ( + AttendanceData && ( + <> +
+ Attendance +
+

+ {AttendanceData.checkedInEmployee?.toLocaleString()}/ + {AttendanceData.assignedEmployee?.toLocaleString()} +

+ Checked-In / Assigned +
+ +
+ + ) + )} +
+
+ + )} + + {activeTab === "Details" && ( +
+ + + + + + + + + + {AttendanceData?.attendanceTable && AttendanceData.attendanceTable.length > 0 ? ( + AttendanceData.attendanceTable.map((record, index) => ( + + + + + + + )) + ) : ( + + + + )} + +
NameCheckinCheckout
{record.firstName} {record.lastName}{new Date(record.inTime).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}{new Date(record.outTime).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
No attendance data available
+
+ )} + +
+
+ ); +}; + +export default Attendance; diff --git a/src/components/Dashboard/Dashboard.jsx b/src/components/Dashboard/Dashboard.jsx index 93e9f18e..6bbdd11f 100644 --- a/src/components/Dashboard/Dashboard.jsx +++ b/src/components/Dashboard/Dashboard.jsx @@ -9,14 +9,13 @@ import Teams from "./Teams"; import TasksCard from "./Tasks"; import ProjectCompletionChart from "./ProjectCompletionChart"; import ProjectProgressChart from "./ProjectProgressChart"; -import Activity from "./Activity"; +import Attendance from "./Attendance"; const Dashboard = () => { const { projectsCardData } = useDashboardProjectsCardData(); const { teamsCardData } = useDashboardTeamsCardData(); const { tasksCardData } = useDashboardTasksCardData(); - // const { ActivityData } = useDashboardActivityData(); - + return (
@@ -46,7 +45,7 @@ const Dashboard = () => {
- +
diff --git a/src/hooks/useDashboard_Data.jsx b/src/hooks/useDashboard_Data.jsx index c3e357ec..a46aa0c8 100644 --- a/src/hooks/useDashboard_Data.jsx +++ b/src/hooks/useDashboard_Data.jsx @@ -37,8 +37,9 @@ export const useDashboard_Data = ({ days, FromDate, projectId }) => { return { dashboard_data, loading: isLineChartLoading, error }; }; -export const useDashboard_ActivityData = (date, projectId) => { - const [dashboard_Activitydata, setDashboard_ActivityData] = useState([]); + +export const useDashboard_AttendanceData = (date, projectId) => { + const [dashboard_Attendancedata, setDashboard_AttendanceData] = useState([]); const [isLineChartLoading, setLoading] = useState(false); const [error, setError] = useState(""); @@ -48,8 +49,8 @@ export const useDashboard_ActivityData = (date, projectId) => { setError(""); try { - const response = await GlobalRepository.getDashboardActivityData(date,projectId); // date in 2nd param - setDashboard_ActivityData(response.data); + const response = await GlobalRepository.getDashboardAttendanceData(date,projectId); // date in 2nd param + setDashboard_AttendanceData(response.data); } catch (err) { setError("Failed to fetch dashboard data."); console.error(err); @@ -63,7 +64,7 @@ export const useDashboard_ActivityData = (date, projectId) => { } }, [date, projectId]); - return { dashboard_Activitydata, isLineChartLoading: isLineChartLoading, error }; + return { dashboard_Attendancedata, isLineChartLoading: isLineChartLoading, error }; }; @@ -150,31 +151,3 @@ export const useDashboardTasksCardData = () => { return { tasksCardData, loading, error }; }; - - -// export const useDashboardActivityData = () => { -// const [ActivityData, setActivityData] = useState([]); -// const [loading, setLoading] = useState(false); -// const [error, setError] = useState(""); - -// useEffect(() => { -// const fetchTasksData = async () => { -// setLoading(true); -// setError(""); - -// try { -// const response = await GlobalRepository.getDashboardActivityData(); -// setActivityData(response.data); -// } catch (err) { -// setError("Failed to fetch tasks card data."); -// console.error(err); -// } finally { -// setLoading(false); -// } -// }; - -// fetchTasksData(); -// }, []); - -// return { ActivityData, loading, error }; -// }; diff --git a/src/repositories/GlobalRepository.jsx b/src/repositories/GlobalRepository.jsx index eb84be2a..eda5312e 100644 --- a/src/repositories/GlobalRepository.jsx +++ b/src/repositories/GlobalRepository.jsx @@ -19,22 +19,10 @@ const GlobalRepository = { return api.get(`/api/Dashboard/Progression?${params.toString()}`); }, - - getDashboardActivityData: ( date,projectId ) => { + getDashboardAttendanceData: ( date,projectId ) => { - return api.get(`/api/Dashboard/activities/${projectId}?date=${date}`); + return api.get(`/api/Dashboard/project-attendance/${projectId}?date=${date}`); }, - -// getDashboardActivityData: (date, projectId) => { -// let url = `/api/Dashboard/activities`; -// if (projectId) { -// url += `/${projectId}?date=${date}`; -// } else { -// url += `?date=${date}`; // Fetch for all projects -// } -// return api.get(url); -// }, - getDashboardProjectsCardData: () => { return api.get(`/api/Dashboard/projects`); }, @@ -44,9 +32,6 @@ const GlobalRepository = { getDashboardTasksCardData: () => { return api.get(`/api/Dashboard/tasks`); }, -getDashboardPendingAttendence: () => { - return api.get(`/api/dashboard/pending-attendance`); - }, };