diff --git a/public/assets/vendor/css/core.css b/public/assets/vendor/css/core.css index b5c63690..e7ebd248 100644 --- a/public/assets/vendor/css/core.css +++ b/public/assets/vendor/css/core.css @@ -3832,7 +3832,7 @@ fieldset:disabled .btn { --bs-dropdown-padding-x: 0; --bs-dropdown-padding-y: 0.5rem; --bs-dropdown-spacer: 0.125rem; - --bs-dropdown-font-size: 0.9375rem; + --bs-dropdown-font-size: 0.8125rem; --bs-dropdown-color: var(--bs-body-color); --bs-dropdown-bg: #fff; --bs-dropdown-border-color: #e4e6e8; diff --git a/src/components/Dashboard/Dashboard.jsx b/src/components/Dashboard/Dashboard.jsx index 617d7f24..b3b9dc68 100644 --- a/src/components/Dashboard/Dashboard.jsx +++ b/src/components/Dashboard/Dashboard.jsx @@ -1,7 +1,7 @@ -import React, { useState } from 'react'; -import HorizontalBarChart from '../Charts/HorizontalBarChart'; -import LineChart from '../Charts/LineChart'; -import { useProjects } from '../../hooks/useProjects'; +import React, { useState } from "react"; +import HorizontalBarChart from "../Charts/HorizontalBarChart"; +import LineChart from "../Charts/LineChart"; +import { useProjects } from "../../hooks/useProjects"; import { useDashboard_Data, useDashboardProjectsCardData, @@ -10,26 +10,34 @@ import { } from "../../hooks/useDashboard_Data"; const Dashboard = () => { - const { projects,loading } = useProjects(); - const [selectedProjectId, setSelectedProjectId] = useState('all'); - const [range, setRange] = useState('1W'); + const { projects, loading } = useProjects(); + const [selectedProjectId, setSelectedProjectId] = useState("all"); + const [range, setRange] = useState("1W"); const getDaysFromRange = (range) => { switch (range) { - case '1D': return 1; - case '1W': return 7; - case '15D': return 15; - case '1M': return 30; - case '3M': return 90; - case '1Y': return 365; - case '5Y': return 1825; - default: return 7; + case "1D": + return 1; + case "1W": + return 7; + case "15D": + return 15; + case "1M": + return 30; + case "3M": + return 90; + case "1Y": + return 365; + case "5Y": + return 1825; + default: + return 7; } }; const days = getDaysFromRange(range); const today = new Date(); - const FromDate = today.toISOString().split('T')[0]; // Always today + const FromDate = today.toISOString().split("T")[0]; // Always today const { projectsCardData } = useDashboardProjectsCardData(); const { teamsCardData } = useDashboardTeamsCardData(); @@ -38,54 +46,66 @@ const Dashboard = () => { const { dashboard_data, loading: isLineChartLoading } = useDashboard_Data({ days, FromDate, - projectId: selectedProjectId === 'all' ? 0 : selectedProjectId, + projectId: selectedProjectId === "all" ? 0 : selectedProjectId, }); // Sort dashboard_data by date ascending - const sortedDashboardData = [...dashboard_data].sort((a, b) => new Date(a.date) - new Date(b.date)); + const sortedDashboardData = [...dashboard_data].sort( + (a, b) => new Date(a.date) - new Date(b.date) + ); // Bar chart logic - const projectNames = projects?.map(p => p.name) || []; - const projectProgress = projects?.map(p => { - const completed = p.completedWork || 0; - const planned = p.plannedWork || 1; - const percent = (completed / planned) * 100; - return Math.min(Math.round(percent), 100); - }) || []; + const projectNames = projects?.map((p) => p.name) || []; + const projectProgress = + projects?.map((p) => { + const completed = p.completedWork || 0; + const planned = p.plannedWork || 1; + const percent = (completed / planned) * 100; + return Math.min(Math.round(percent), 100); + }) || []; // Line chart data const lineChartSeries = [ { - name: 'Planned Work', - data: sortedDashboardData.map(d => d.plannedTask || 0), + name: "Planned Work", + data: sortedDashboardData.map((d) => d.plannedTask || 0), }, { - name: 'Completed Work', - data: sortedDashboardData.map(d => d.completedTask || 0), + name: "Completed Work", + data: sortedDashboardData.map((d) => d.completedTask || 0), }, ]; - const lineChartCategories = sortedDashboardData.map(d => - new Date(d.date).toLocaleDateString('en-US', { month: 'short', day: 'numeric' }) + const lineChartCategories = sortedDashboardData.map((d) => + new Date(d.date).toLocaleDateString("en-US", { + month: "short", + day: "numeric", + }) ); return (
- {/* Projects Card */}
-
Projects
+
+ {" "} + Projects +
-

{projectsCardData.totalProjects?.toLocaleString()}

+

+ {projectsCardData.totalProjects?.toLocaleString()} +

Total
-

{projectsCardData.ongoingProjects?.toLocaleString()}

+

+ {projectsCardData.ongoingProjects?.toLocaleString()} +

Ongoing
@@ -96,15 +116,21 @@ const Dashboard = () => {
-
Teams
+
+ Teams +
-

{teamsCardData.totalEmployees?.toLocaleString()}

+

+ {teamsCardData.totalEmployees?.toLocaleString()} +

Total Employees
-

{teamsCardData.inToday?.toLocaleString()}

+

+ {teamsCardData.inToday?.toLocaleString()} +

In Today
@@ -115,15 +141,21 @@ const Dashboard = () => {
-
Tasks
+
+ Tasks +
-

{tasksCardData.totalTasks?.toLocaleString()}

+

+ {tasksCardData.totalTasks?.toLocaleString()} +

Total
-

{tasksCardData.completedTasks?.toLocaleString()}

+

+ {tasksCardData.completedTasks?.toLocaleString()} +

Completed
@@ -161,28 +193,34 @@ const Dashboard = () => {
- +
  • -
  • {projects?.map((project) => (
  • -
  • @@ -193,12 +231,15 @@ const Dashboard = () => { {/* Row 2: Time Range Buttons */}
    - {['1D', '1W', '15D', '1M', '3M', '1Y', '5Y'].map((key) => ( + {["1D", "1W", "15D", "1M", "3M", "1Y", "5Y"].map((key) => (
- +
-
); diff --git a/src/components/common/DateRangePicker.jsx b/src/components/common/DateRangePicker.jsx index f2d797a7..a8230e95 100644 --- a/src/components/common/DateRangePicker.jsx +++ b/src/components/common/DateRangePicker.jsx @@ -1,22 +1,29 @@ -import React, { useEffect, useRef } from 'react'; +import React, { useEffect, useRef } from "react"; + const DateRangePicker = ({ onRangeChange }) => { const inputRef = useRef(null); useEffect(() => { + + const today = new Date(); + const fifteenDaysAgo = new Date(); + fifteenDaysAgo.setDate(today.getDate() - 15); + + const fp = flatpickr(inputRef.current, { - mode: "range", - dateFormat: "Y-m-d", - static: true, - clickOpens: true, - onChange: (selectedDates, dateStr) => { - const [startDate, endDate] = dateStr.split(" to "); - onRangeChange?.({ startDate, endDate }); - } - }); + mode: "range", + dateFormat: "Y-m-d", + defaultDate: [fifteenDaysAgo, today], // ✅ set default range + static: true, + clickOpens: true, + onChange: (selectedDates, dateStr) => { + const [startDate, endDate] = dateStr.split(" to "); + onRangeChange?.({ startDate, endDate }); + }, + }); return () => { - // Cleanup Flatpickr instance fp.destroy(); }; }, [onRangeChange]); diff --git a/src/hooks/useProjects.js b/src/hooks/useProjects.js index 037aba94..9ee9a330 100644 --- a/src/hooks/useProjects.js +++ b/src/hooks/useProjects.js @@ -1,126 +1,126 @@ -import { useEffect,useState } from "react" -import { - cacheData, - getCachedData, - } from "../slices/apiDataManager" +import { useEffect, useState } from "react"; +import { cacheData, getCachedData } from "../slices/apiDataManager"; import ProjectRepository from "../repositories/ProjectRepository"; import { useProfile } from "./useProfile"; - - -export const useProjects =()=>{ - +export const useProjects = () => { const [projects, setProjects] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(""); const fetchData = async () => { - const projects_cache = getCachedData("projectslist"); - - if (!projects_cache) { - setLoading(true) - ProjectRepository.getProjectList() + const projects_cache = getCachedData("projectslist"); + + if (!projects_cache) { + setLoading(true); + ProjectRepository.getProjectList() .then((response) => { - setProjects(response.data); - - cacheData("projectslist", response.data); + let projects = response.data; + const sortedProject = [...projects].sort((a, b) => + a.name.localeCompare(b.name) + ); + + setProjects(sortedProject); + + cacheData("projectslist", sortedProject); setLoading(false); }) .catch((error) => { - setLoading(false) - console.error(error); + setLoading(false); setError("Failed to fetch data."); }); - - } else { - if (!projects.length) setProjects(projects_cache); + } else { + if (!projects.length) { + let projects = projects_cache; + const sortedProject = [...projects].sort((a, b) => + a.name.localeCompare(b.name) + ); + setProjects(sortedProject); } + } }; - - useEffect(()=>{ - fetchData() - },[]) + useEffect(() => { + fetchData(); + }, []); - return { projects,loading,error,refetch:fetchData} - -} + return { projects, loading, error, refetch: fetchData }; +}; -export const useEmployeesByProjectAllocated = ( selectedProject ) => - { - const [projectEmployees, setEmployeeList] = useState([]); - const[loading,setLoading] = useState(true) - const [projects, setProjects] = useState([]); - - const fetchData = async (projectid) => { - try { - let EmployeeByProject_Cache = getCachedData("empListByProjectAllocated") - if(!EmployeeByProject_Cache || !EmployeeByProject_Cache.projectId === projectid) { - - let response = await ProjectRepository.getProjectAllocation(projectid) - setEmployeeList(response.data); - cacheData("empListByProjectAllocated",{data:response.data,projectId:projectid}); - setLoading(false) - }else{ - setEmployeeList(EmployeeByProject_Cache.data) - setLoading(false) - } - - - } catch (err) { - setError("Failed to fetch data."); - setLoading(false) - } - }; - - - useEffect(()=>{ - if(selectedProject){ +export const useEmployeesByProjectAllocated = (selectedProject) => { + const [projectEmployees, setEmployeeList] = useState([]); + const [loading, setLoading] = useState(true); + const [projects, setProjects] = useState([]); + + const fetchData = async (projectid) => { + try { + let EmployeeByProject_Cache = getCachedData("empListByProjectAllocated"); + if ( + !EmployeeByProject_Cache || + !EmployeeByProject_Cache.projectId === projectid + ) { + let response = await ProjectRepository.getProjectAllocation(projectid); + setEmployeeList(response.data); + cacheData("empListByProjectAllocated", { + data: response.data, + projectId: projectid, + }); + setLoading(false); + } else { + setEmployeeList(EmployeeByProject_Cache.data); + setLoading(false); + } + } catch (err) { + setError("Failed to fetch data."); + setLoading(false); + } + }; + + useEffect(() => { + if (selectedProject) { fetchData(selectedProject); - } - },[selectedProject]) - - - return {projectEmployees,loading,projects} -} - -export const useProjectDetails =(projectId)=>{ - const {profile} = useProfile(); + } + }, [selectedProject]); + + return { projectEmployees, loading, projects }; +}; + +export const useProjectDetails = (projectId) => { + const { profile } = useProfile(); const [projects_Details, setProject_Details] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); const fetchData = async () => { - setLoading( true ) - + setLoading(true); + const project_cache = getCachedData("projectInfo"); if (!project_cache || project_cache?.projectId != projectId) { ProjectRepository.getProjectByprojectId(projectId) - .then( ( response ) => - { - setProject_Details( response.data ); - cacheData("projectInfo", {projectId:projectId,data: response.data} ); - setLoading(false) + .then((response) => { + setProject_Details(response.data); + cacheData("projectInfo", { + projectId: projectId, + data: response.data, + }); + setLoading(false); }) .catch((error) => { console.error(error); - setError( "Failed to fetch data." ); - setLoading(false) + setError("Failed to fetch data."); + setLoading(false); }); } else { - setProject_Details( project_cache.data ); - setLoading(false) - } - -}; - - useEffect(()=>{ - if ( profile && (projectId != undefined) ) - { - fetchData() - } - },[projectId,profile]) + setProject_Details(project_cache.data); + setLoading(false); + } + }; - return { projects_Details,loading,error,refetch:fetchData} - -} \ No newline at end of file + useEffect(() => { + if (profile && projectId != undefined) { + fetchData(); + } + }, [projectId, profile]); + + return { projects_Details, loading, error, refetch: fetchData }; +}; diff --git a/src/pages/Activities/DailyTask.jsx b/src/pages/Activities/DailyTask.jsx index ffd18230..07bf21ee 100644 --- a/src/pages/Activities/DailyTask.jsx +++ b/src/pages/Activities/DailyTask.jsx @@ -91,7 +91,7 @@ const DailyTask = () => {