diff --git a/src/components/Activities/AttendcesLogs.jsx b/src/components/Activities/AttendcesLogs.jsx index 267bec1d..e58565e8 100644 --- a/src/components/Activities/AttendcesLogs.jsx +++ b/src/components/Activities/AttendcesLogs.jsx @@ -226,7 +226,7 @@ const AttendanceLog = ({ handleModalData, searchTerm, organizationId }) => { return ( <>
@@ -234,7 +234,7 @@ const AttendanceLog = ({ handleModalData, searchTerm, organizationId }) => { onRangeChange={setDateRange} defaultStartDate={yesterday} /> -
+
{ +const Regularization = ({ + handleRequest, + searchTerm, + projectId, + organizationId, + IncludeInActive, +}) => { const queryClient = useQueryClient(); // var selectedProject = useSelector((store) => store.localVariables.projectId); const selectedProject = useSelectedProject(); const [regularizesList, setregularizedList] = useState([]); - const { regularizes, loading, error, refetch } = - useRegularizationRequests(selectedProject, organizationId, IncludeInActive); + const { regularizes, loading, error, refetch } = useRegularizationRequests( + selectedProject, + organizationId, + IncludeInActive + ); useEffect(() => { setregularizedList(regularizes); @@ -54,48 +68,15 @@ const Regularization = ({ handleRequest, searchTerm,projectId, organizationId, I } const lowercasedSearchTerm = searchTerm.toLowerCase(); return sortedList.filter((item) => { - const fullName = `${item.firstName} ${item.lastName}`.toLowerCase(); + const fullName = `${item?.firstName} ${item?.lastName}`.toLowerCase(); return fullName.includes(lowercasedSearchTerm); }); }, [regularizesList, searchTerm]); - // const filteredSearchData = useMemo(() => { - // let sortedList = [...regularizesList].sort(sortByName); - - // // Search filter - // if (searchTerm) { - // const lowercasedSearchTerm = searchTerm.toLowerCase(); - // sortedList = sortedList.filter((item) => { - // const fullName = `${item.firstName} ${item.lastName}`.toLowerCase(); - // return fullName.includes(lowercasedSearchTerm); - // }); - // } - - // // Organization filter - // if (filters?.selectedOrganization) { - // sortedList = sortedList.filter( - // (item) => item.organization?.name === filters.selectedOrganization - // ); - // } - - // // Services filter - // if (filters?.selectedServices?.length > 0) { - // sortedList = sortedList.filter((item) => - // filters.selectedServices.includes(item.service?.name) - // ); - // } - - // return sortedList; - // }, [regularizesList, searchTerm, filters]); - - - const { currentPage, totalPages, currentItems, paginate } = - usePagination(filteredSearchData, 20); - - // Reset pagination when the search term or data changes - useEffect(() => { - - }, [filteredSearchData]); + const { currentPage, totalPages, currentItems, paginate } = usePagination( + filteredSearchData, + 20 + ); useEffect(() => { eventBus.on("regularization", handler); @@ -117,9 +98,15 @@ const Regularization = ({ handleRequest, searchTerm,projectId, organizationId, I }, [employeeHandler]); return ( -
+
{loading ? ( -
+

Loading...

) : currentItems?.length > 0 ? ( @@ -143,10 +130,7 @@ const Regularization = ({ handleRequest, searchTerm,projectId, organizationId, I diff --git a/src/components/DailyProgressRport/TaskReportList.jsx b/src/components/DailyProgressRport/TaskReportList.jsx index 27323b51..78af8df3 100644 --- a/src/components/DailyProgressRport/TaskReportList.jsx +++ b/src/components/DailyProgressRport/TaskReportList.jsx @@ -192,7 +192,7 @@ const TaskReportList = () => { if (isLoading) return ; if (isError) return
Loading....
; return ( -
+
diff --git a/src/components/Directory/ListViewContact.jsx b/src/components/Directory/ListViewContact.jsx index 16e737a7..16fd9a14 100644 --- a/src/components/Directory/ListViewContact.jsx +++ b/src/components/Directory/ListViewContact.jsx @@ -179,7 +179,7 @@ const ListViewContact = ({ data, Pagination }) => { diff --git a/src/components/Employee/ManageEmployee.jsx b/src/components/Employee/ManageEmployee.jsx index b3aad4b4..5ee82674 100644 --- a/src/components/Employee/ManageEmployee.jsx +++ b/src/components/Employee/ManageEmployee.jsx @@ -18,7 +18,7 @@ import { defatEmployeeObj, employeeSchema } from "./EmployeeSchema"; import { useOrganizationsList } from "../../hooks/useOrganization"; import { ITEMS_PER_PAGE } from "../../utils/constants"; -const ManageEmployee = ({ employeeId, onClosed, IsAllEmployee }) => { +const ManageEmployee = ({ employeeId, onClosed }) => { const dispatch = useDispatch(); const { mutate: updateEmployee, isPending } = useUpdateEmployee(); const { @@ -72,7 +72,7 @@ const ManageEmployee = ({ employeeId, onClosed, IsAllEmployee }) => { data.email = null; } - const payload = { ...data, IsAllEmployee }; + const payload = { ...data }; if (employeeId) { payload.id = employeeId; diff --git a/src/components/Expenses/ExpenseFilterPanel.jsx b/src/components/Expenses/ExpenseFilterPanel.jsx index 250f5de4..c04a0981 100644 --- a/src/components/Expenses/ExpenseFilterPanel.jsx +++ b/src/components/Expenses/ExpenseFilterPanel.jsx @@ -117,6 +117,7 @@ const ExpenseFilterPanel = ({ onApply, handleGroupBy }) => { endField="endDate" resetSignal={resetKey} defaultRange={false} + maxDate={new Date()} /> diff --git a/src/components/Layout/Header.jsx b/src/components/Layout/Header.jsx index 54d5f8aa..ae72921a 100644 --- a/src/components/Layout/Header.jsx +++ b/src/components/Layout/Header.jsx @@ -189,7 +189,8 @@ const Header = () => { className="navbar-nav-right d-flex align-items-center justify-content-between" id="navbar-collapse" > - {showProjectDropdown(location.pathname) && ( +
+ {showProjectDropdown(location.pathname) && (
@@ -247,6 +248,7 @@ const Header = () => {
)} +
  • diff --git a/src/components/Organization/OrganizationsList.jsx b/src/components/Organization/OrganizationsList.jsx index af981025..dc2e977e 100644 --- a/src/components/Organization/OrganizationsList.jsx +++ b/src/components/Organization/OrganizationsList.jsx @@ -142,7 +142,7 @@ const OrganizationsList = ({searchText}) => { colSpan={organizationsColumns.length + 1} className="text-center" > -

    Not Found

    +

    {isLoading ? "Loading....":"Not Found Organization"}

)} diff --git a/src/components/Project/AssignTask.jsx b/src/components/Project/AssignTask.jsx index 8c8aab22..187b1cc0 100644 --- a/src/components/Project/AssignTask.jsx +++ b/src/components/Project/AssignTask.jsx @@ -12,6 +12,7 @@ import showToast from "../../services/toastService"; import { useEmployeeForTaskAssign, useProjectAssignedOrganizations, + useProjectAssignedServices, useProjectDetails, } from "../../hooks/useProjects"; import eventBus from "../../services/eventBus"; @@ -95,7 +96,7 @@ const AssignTask = ({ assignData, onClose, setAssigned }) => { }, []); const selectedProject = useSelectedProject(); - const { data: serviceList, isLoading: isServiceLoading } = useServices(); + const { data: serviceList, isLoading: isServiceLoading } = useProjectAssignedServices(selectedProject); const { data: organizationList, isLoading: isOrgLoading } = useProjectAssignedOrganizations(selectedProject); const { data: employees, isLoading: isEmployeeLoading } = @@ -274,7 +275,7 @@ const AssignTask = ({ assignData, onClose, setAssigned }) => { ) : ( <> - {serviceList?.data?.map((service,index) => ( + {serviceList?.map((service,index) => ( diff --git a/src/components/Project/Infrastructure/WorkArea.jsx b/src/components/Project/Infrastructure/WorkArea.jsx index 71e34d0e..59f281be 100644 --- a/src/components/Project/Infrastructure/WorkArea.jsx +++ b/src/components/Project/Infrastructure/WorkArea.jsx @@ -108,7 +108,7 @@ const WorkArea = ({ workArea, floor, forBuilding }) => { diff --git a/src/components/Project/ManageProjectInfo.jsx b/src/components/Project/ManageProjectInfo.jsx index d6eec199..547cf4cb 100644 --- a/src/components/Project/ManageProjectInfo.jsx +++ b/src/components/Project/ManageProjectInfo.jsx @@ -327,7 +327,7 @@ const ManageProjectInfo = ({ project, onClose }) => { Not found PMC and Pomoter, find through SPRID or create new - + @@ -367,14 +367,14 @@ const ManageProjectInfo = ({ project, onClose }) => { className="btn btn-label-secondary btn-sm me-2" onClick={handleCancel} aria-label="Close" - disabled={isPending || isCreating} + disabled={isPending || isCreating || loading} > Cancel diff --git a/src/components/Project/ProjectListView.jsx b/src/components/Project/ProjectListView.jsx index 2e717163..3bf9b160 100644 --- a/src/components/Project/ProjectListView.jsx +++ b/src/components/Project/ProjectListView.jsx @@ -132,11 +132,15 @@ const ProjectListView = ({ return (
+ +
No contacts found
- + {projectColumns.map((col) => ( - ))} @@ -217,6 +221,7 @@ const ProjectListView = ({ ))}
+ {col.label}
+
{isLoading && (
diff --git a/src/components/Project/Team/TeamEmployeeList.jsx b/src/components/Project/Team/TeamEmployeeList.jsx index a800df3f..4ce995c9 100644 --- a/src/components/Project/Team/TeamEmployeeList.jsx +++ b/src/components/Project/Team/TeamEmployeeList.jsx @@ -6,6 +6,7 @@ import { useOrganizationEmployees } from "../../../hooks/useOrganization"; import { useEmployeesByProjectAllocated, useManageProjectAllocation, + useProjectAssignedServices, } from "../../../hooks/useProjects"; import useMaster, { useServices } from "../../../hooks/masterHook/useMaster"; import showToast from "../../../services/toastService"; @@ -29,7 +30,7 @@ const TeamEmployeeList = ({ organizationId, searchTerm, closeModal }) => { useEmployeesByProjectAllocated(selectedProject, null); const { data: jobRoles } = useMaster(); - const { data: services } = useServices(); + const { data: services } = useProjectAssignedServices(selectedProject); const [employees, setEmployees] = useState([]); @@ -187,7 +188,7 @@ if (employees.length === 0) { }`} > - {services?.data?.map((s) => ( + {services?.map((s) => ( diff --git a/src/components/common/DateRangePicker.jsx b/src/components/common/DateRangePicker.jsx index 8e53b5e6..3a93853d 100644 --- a/src/components/common/DateRangePicker.jsx +++ b/src/components/common/DateRangePicker.jsx @@ -3,8 +3,8 @@ import { useController, useFormContext, useWatch } from "react-hook-form"; import { useSelector } from "react-redux"; const DateRangePicker = ({ - md, - sm, + md=12, + sm=6, onRangeChange, DateDifference = 7, endDateMode = "yesterday", @@ -63,21 +63,22 @@ const DateRangePicker = ({ }; return ( -
- +
+ + + +
+ - -
); }; diff --git a/src/components/common/ProgressBar.jsx b/src/components/common/ProgressBar.jsx index 947c6a00..cb6e7b8a 100644 --- a/src/components/common/ProgressBar.jsx +++ b/src/components/common/ProgressBar.jsx @@ -3,35 +3,65 @@ import React from "react"; const ProgressBar = ({ plannedWork = 100, completedWork = 0, - height = "8px", + height = "6px", className = "mb-4", rounded = true, + showLabel = true, }) => { const getProgress = (planned, completed) => { - if (!planned || planned === 0) return "0%"; - return `${Math.min((completed / planned) * 100, 100).toFixed(2)}%`; + if (!planned || planned === 0) return 0; + return Math.min((completed / planned) * 100, 100); }; - const progressStyle = { - width: getProgress(plannedWork, completedWork), + const percentage = getProgress(plannedWork, completedWork); + + const progressBarStyle = { + width: ` ${percentage.toFixed(2)}%`, + transition: "width 0.4s ease", + }; + + const containerStyle = { + height, + display: "flex", + alignItems: "center", + gap: "8px", }; return (
-
+
+
+
+
+
+ + {showLabel && ( + + {percentage.toFixed(2)}% + + )}
); }; export default ProgressBar; - diff --git a/src/components/gallary/GalleryFilterPanel.jsx b/src/components/gallary/GalleryFilterPanel.jsx index e91ba9d1..fadcf135 100644 --- a/src/components/gallary/GalleryFilterPanel.jsx +++ b/src/components/gallary/GalleryFilterPanel.jsx @@ -60,6 +60,7 @@ const GalleryFilterPanel = ({ onApply }) => { endField="endDate" resetSignal={resetKey} defaultRange={false} + maxDate={new Date()} />
diff --git a/src/hooks/useAuth.jsx b/src/hooks/useAuth.jsx index c52854f4..5b6621e9 100644 --- a/src/hooks/useAuth.jsx +++ b/src/hooks/useAuth.jsx @@ -84,6 +84,7 @@ export const useAuthModal = () => { export const useLogout = () => { const queryClient = useQueryClient(); + const naviget = useNavigate() return useMutation({ mutationFn: async () => { @@ -96,9 +97,11 @@ export const useLogout = () => { }, onSuccess: (data) => { + queryClient.clear() removeSession(); - window.location.href = "/auth/login"; + // window.location.href = "/auth/login"; + naviget("/auth/login",{replace:true}) if (onSuccessCallBack) onSuccessCallBack(); }, diff --git a/src/hooks/useEmployees.js b/src/hooks/useEmployees.js index 2b37e0de..e33084a6 100644 --- a/src/hooks/useEmployees.js +++ b/src/hooks/useEmployees.js @@ -12,14 +12,14 @@ import { queryClient } from "../layouts/AuthLayout"; // Query --------------------------------------------------------------------------- export const useEmployee = (employeeId) => { - return useQuery({ + return useQuery({ queryKey: ["employeeProfile", employeeId], queryFn: async () => { - const res = await EmployeeRepository.getEmployeeProfile(employeeId) + const res = await EmployeeRepository.getEmployeeProfile(employeeId); return res.data; }, - enabled:!!employeeId - }); + enabled: !!employeeId, + }); }; export const useAllEmployees = (showInactive) => { @@ -137,7 +137,6 @@ export const useEmployeesAllOrByProjectId = ( return res.data; } }; - const { data: employees = [], isLoading, @@ -158,6 +157,18 @@ export const useEmployeesAllOrByProjectId = ( }; }; +// New Employee get list by CureentOrganization + +export const useEmployeesByOrganization = (showInactive) => { + return useQuery({ + queryKey: ["employeesByOrganization", showInactive], + queryFn: async () => { + const res = await EmployeeRepository.getAllEmployeeList(showInactive); + return res.data; + }, + }); +}; + // ManageEmployee.jsx export const useEmployeeProfile = (employeeId) => { const isEnabled = !!employeeId; @@ -184,11 +195,11 @@ export const useEmployeeProfile = (employeeId) => { }; }; -export const useEmployeesName = (projectId, search,allEmployee) => { +export const useEmployeesName = (projectId, search, allEmployee) => { return useQuery({ - queryKey: ["employees", projectId, search,allEmployee], + queryKey: ["employees", projectId, search, allEmployee], queryFn: async () => - await EmployeeRepository.getEmployeeName(projectId, search,allEmployee), + await EmployeeRepository.getEmployeeName(projectId, search, allEmployee), staleTime: 5 * 60 * 1000, // Optional: cache for 5 minutes }); @@ -208,9 +219,6 @@ export const useEmployeesNameByProject = (projectId) => { // Mutation------------------------------------------------------------------ - - - export const useUpdateEmployee = () => { const selectedProject = useSelector( (store) => store.localVariables.projectId @@ -225,7 +233,7 @@ export const useUpdateEmployee = () => { const isAllEmployee = variables.IsAllEmployee; // Cache invalidation - queryClient.invalidateQueries({ queryKey: ["employeeProfile",id] }); + queryClient.invalidateQueries({ queryKey: ["employeeProfile", id] }); queryClient.invalidateQueries({ queryKey: ["allEmployees"] }); // queryClient.invalidateQueries(['employeeProfile', id]); queryClient.invalidateQueries({ queryKey: ["projectEmployees"] }); @@ -247,7 +255,6 @@ export const useUpdateEmployee = () => { }); }; - export const useSuspendEmployee = ({ setIsDeleteModalOpen, setemployeeLodaing, @@ -300,7 +307,6 @@ export const useSuspendEmployee = ({ }); }; - export const useUpdateEmployeeRoles = ({ onClose, resetForm, @@ -334,4 +340,4 @@ export const useUpdateEmployeeRoles = ({ isError: mutation.isError, error: mutation.error, }; -}; \ No newline at end of file +}; diff --git a/src/hooks/useOrganization.js b/src/hooks/useOrganization.js index e99d8ccb..ca356936 100644 --- a/src/hooks/useOrganization.js +++ b/src/hooks/useOrganization.js @@ -139,7 +139,7 @@ export const useAssignOrgToProject = (onSuccessCallback) => { queryKey: ["projectAssignedOrganiztions"], }); useClient.invalidateQueries({ - queryKey: ["projectAssignedOrganization", projectId], + queryKey: ["projectAssignedServices", projectId], }); showToast("Organization successfully", "success"); if (onSuccessCallback) onSuccessCallback(); diff --git a/src/hooks/useProjects.js b/src/hooks/useProjects.js index 9f5c48b9..803f17b7 100644 --- a/src/hooks/useProjects.js +++ b/src/hooks/useProjects.js @@ -296,7 +296,7 @@ export const useProjectAssignedOrganizations = (projectId) => { }; export const useProjectAssignedServices = (projectId) => { return useQuery({ - queryKey: ["projectAssignedOrganization", projectId], + queryKey: ["projectAssignedServices", projectId], queryFn: async () => { const resp = await ProjectRepository.getProjectAssignedServices( projectId diff --git a/src/pages/Activities/AttendancePage.jsx b/src/pages/Activities/AttendancePage.jsx index b55592bc..e07be1f5 100644 --- a/src/pages/Activities/AttendancePage.jsx +++ b/src/pages/Activities/AttendancePage.jsx @@ -131,7 +131,7 @@ const AttendancePage = () => {
{/* Tabs */}
-
+
{/* Tabs */}
    @@ -181,9 +181,10 @@ const AttendancePage = () => { {/* Search + Organization filter */}
    {/* Organization Dropdown */} - setAppliedFilters((prev) => ({ @@ -200,16 +201,21 @@ const AttendancePage = () => { ))} - - {/* Search Input */} +
    +
    + {/* Search Input */} setSearchTerm(e.target.value)} - style={{ minWidth: "200px" }} /> +
    +
+ + +
diff --git a/src/pages/DailyProgressReport/DailyProgrssReport.jsx b/src/pages/DailyProgressReport/DailyProgrssReport.jsx index 2e027935..1985db38 100644 --- a/src/pages/DailyProgressReport/DailyProgrssReport.jsx +++ b/src/pages/DailyProgressReport/DailyProgrssReport.jsx @@ -8,6 +8,8 @@ import ReportTask from "../../components/Activities/ReportTask"; import TaskReportFilterPanel from "../../components/DailyProgressRport/TaskReportFilterPanel"; import { useFab } from "../../Context/FabContext"; import SubTask from "../../components/Activities/SubTask"; +import { useProjectAssignedServices } from "../../hooks/useProjects"; +import { useSelectedProject } from "../../slices/apiDataManager"; const DailyProgrssContext = createContext(); export const useDailyProgrssContext = () => { @@ -21,10 +23,11 @@ export const useDailyProgrssContext = () => { }; const DailyProgrssReport = () => { + const selectedProject = useSelectedProject() const [service, setService] = useState(""); const [filter,setFilter] = useState('') const { setOffcanvasContent, setShowTrigger } = useFab(); - const { data, isLoading, isError, error } = useServices(); + const { data, isLoading, isError, error } = useProjectAssignedServices(selectedProject); const [modal, setModal] = useState({ type: null, data: null }); @@ -86,7 +89,7 @@ const DailyProgrssReport = () => { />
- {data?.data?.length > 0 && (
+ {data?.length > 0 && (
- -
- )} {/* Show Inactive Employees Switch */} - {showAllEmployees && ( -
- setShowInactive(e.target.checked)} - /> - -
- )} + +
+ setShowInactive(e.target.checked)} + /> + +
{/* Right side: Search + Export + Add Employee */} -
+
{/* Search Input - ALWAYS ENABLED */}
diff --git a/src/utils/appUtils.js b/src/utils/appUtils.js index 0611d9c8..f9be1ebd 100644 --- a/src/utils/appUtils.js +++ b/src/utils/appUtils.js @@ -91,4 +91,47 @@ const date = new Date( Date.UTC(Number(year), Number(month) - 1, Number(day), 0, 0, 0) ); return isNaN(date.getTime()) ? null : date.toISOString(); -} \ No newline at end of file +} + + +/** + * Flexible number formatter for currency, numbers, or percentages. + * + * @param {number} amount - The value to format. + * @param {Object} options - Formatting options. + * @param {"currency"|"number"|"percent"} [options.type="number"] - Type of format. + * @param {string} [options.currency="INR"] - Currency code (only used when type="currency"). + * @param {string} [options.locale="en-US"] - Locale for formatting. + * @param {"short"|"long"|"standard"} [options.notation="compact"] - Display style for large numbers. + * @param {number} [options.minimumFractionDigits=0] - Minimum decimal places. + * @param {number} [options.maximumFractionDigits=2] - Maximum decimal places. + * @returns {string} Formatted number string. + */ +export const formatFigure = ( + amount, + { + type = "number", + currency = "INR", + locale = "en-US", + notation = "compact", + compactDisplay = "short", + minimumFractionDigits = 0, + maximumFractionDigits = 2, + } = {} +) => { + if (amount == null || isNaN(amount)) return "-"; + + const formatterOptions = { + style: type === "currency" ? "currency" : type === "percent" ? "percent" : "decimal", + notation: notation, + compactDisplay, + minimumFractionDigits, + maximumFractionDigits, + }; + + if (type === "currency") { + formatterOptions.currency = currency; + } + + return new Intl.NumberFormat(locale, formatterOptions).format(amount); +}; diff --git a/src/utils/constants.jsx b/src/utils/constants.jsx index 62c686c9..8d190f15 100644 --- a/src/utils/constants.jsx +++ b/src/utils/constants.jsx @@ -3,6 +3,11 @@ export const DURATION_TIME = 10; // minutes export const ITEMS_PER_PAGE = 20; export const OTP_EXPIRY_SECONDS = 300; // OTP time + +export const BASE_URL = process.env.VITE_BASE_URL; + +// export const BASE_URL = "https://api.marcoaiot.com"; + export const MANAGE_MASTER = "588a8824-f924-4955-82d8-fc51956cf323"; export const VIEW_MASTER = "5ffbafe0-7ab0-48b1-bb50-c1bf76b65f9d"; @@ -142,6 +147,3 @@ export const PROJECT_STATUS = [ ]; export const DEFAULT_EMPTY_STATUS_ID = "00000000-0000-0000-0000-000000000000"; -export const BASE_URL = process.env.VITE_BASE_URL; - -// export const BASE_URL = "https://api.marcoaiot.com";