Adding Spinners in all files.

This commit is contained in:
Kartik Sharma 2025-10-31 15:06:11 +05:30
parent 4a08394015
commit 1c64fac499
20 changed files with 164 additions and 122 deletions

View File

@ -24,8 +24,7 @@ import { useProfile } from "../../hooks/useProfile";
import { refreshData, setProjectId } from "../../slices/localVariablesSlice";
import InfraTable from "../Project/Infrastructure/InfraTable";
import { useSelectedProject } from "../../slices/apiDataManager";
import Loader from "../common/Loader";
import { SpinnerLoader } from "../common/Loader";
const InfraPlanning = () => {
const { profile: LoggedUser, refetch: fetchData } = useProfile();
const dispatch = useDispatch();
@ -57,7 +56,14 @@ const InfraPlanning = () => {
}
if (isLoading) {
return <Loader />;
return (
<div
className="d-flex justify-content-center align-items-center"
style={{ height: "60vh" }}
>
<SpinnerLoader />
</div>
);
}
if (isFetched && (!projectInfra || projectInfra.length === 0)) {

View File

@ -30,7 +30,6 @@ const HorizontalBarChart = ({
>
<SpinnerLoader />
</div>
{/* Replace this with a skeleton or spinner if you prefer */}
</div>
);
}

View File

@ -99,7 +99,7 @@ const ExpenseAnalysis = () => {
{isLoading && (
<div
className="d-flex justify-content-center align-items-center"
style={{ height: "200px" }}
style={{ minHeight: "50vh" }}
>
<SpinnerLoader />
</div>

View File

@ -7,6 +7,7 @@ import { formatCurrency } from "../../utils/appUtils";
import { formatDate_DayMonth } from "../../utils/dateUtils";
import { useProjectName } from "../../hooks/useProjects";
import { useSelectedProject } from "../../slices/apiDataManager";
import { SpinnerLoader } from "../common/Loader";
const ExpenseByProject = () => {
const projectId = useSelector((store) => store.localVariables.projectId);
@ -161,14 +162,17 @@ const ExpenseByProject = () => {
</div>
{/* Chart */}
<div className="card-body bg-white text-dark p-3 rounded" style={{ minHeight: "210px" }}>
<div className="card-body bg-white text-dark p-3 rounded" style={{ minHeight: "210px" }}>
{isLoading ? (
<p>Loading chart...</p>
<div className="d-flex justify-content-center align-items-center py-5">
<SpinnerLoader />
</div>
) : !expenseApiData || expenseApiData.length === 0 ? (
<div className="text-center text-muted py-5">No data found</div>
) : (
<Chart options={options} series={series} type="bar" height={235} />
)}
</div>
</div>

View File

@ -12,13 +12,13 @@ const EmpActivities = ({ employee }) => {
const {
data,
isError,
isLoading,
error,
isError,
isLoading,
error,
refetch,
} = useProjectTasksByEmployee(employee?.id,dateRange.startDate,dateRange.endDate);
} = useProjectTasksByEmployee(employee?.id, dateRange.startDate, dateRange.endDate);
if(isLoading) return <div>Loading...</div>
if (isLoading) return <div>Loading...</div>
return (
<>
<div className="card h-100 mt-4">
@ -31,28 +31,28 @@ error,
/>
</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>
{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>
<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>
))}
{/* <li className="timeline-item timeline-item-transparent">
<span className="timeline-point timeline-point-success"></span>

View File

@ -15,6 +15,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { localToUtc } from "../../utils/appUtils";
import { useParams } from "react-router-dom";
import { SpinnerLoader } from "../common/Loader";
const EmpAttendance = () => {
const { employeeId } = useParams();
@ -82,21 +83,19 @@ const EmpAttendance = () => {
</FormProvider>
</>
</div>
<div className="col-md-2 m-0 text-end">
<i
className={`bx bx-refresh cursor-pointer fs-4 ${
isFetching ? "spin" : ""
}`}
data-toggle="tooltip"
title="Refresh"
onClick={() => refetch()}
/>
</div>
</div>
<div className="table-responsive text-nowrap">
{!loading && data.length === 0 && <span>No employee logs</span>}
{!loading && data.length === 0 && (
<div className="text-center py-5">No employee logs</div>
)}
{isError && <div className="text-center">{error.message}</div>}
{loading && !data && <div className="text-center">Loading...</div>}
{loading && (
<div className="d-flex justify-content-center align-items-center" style={{ minHeight: "200px" }}>
<SpinnerLoader />
</div>
)}
{data && data.length > 0 && (
<table className="table mb-0">
<thead>
@ -179,9 +178,8 @@ const EmpAttendance = () => {
{[...Array(totalPages)].map((_, index) => (
<li
key={index}
className={`page-item ${
currentPage === index + 1 ? "active" : ""
}`}
className={`page-item ${currentPage === index + 1 ? "active" : ""
}`}
>
<button
className="page-link "
@ -192,9 +190,8 @@ const EmpAttendance = () => {
</li>
))}
<li
className={`page-item ${
currentPage === totalPages ? "disabled" : ""
}`}
className={`page-item ${currentPage === totalPages ? "disabled" : ""
}`}
>
<button
className="page-link "

View File

@ -16,6 +16,7 @@ import { useParams } from "react-router-dom";
import ProgressBar from "../../common/ProgressBar";
import { formatNumber } from "../../../utils/dateUtils";
import { useServices } from "../../../hooks/masterHook/useMaster";
import { SpinnerLoader } from "../../common/Loader";
const WorkArea = ({ workArea, floor, forBuilding }) => {
const selectedProject = useSelectedProject()
@ -120,9 +121,14 @@ const WorkArea = ({ workArea, floor, forBuilding }) => {
className="accordion-collapse collapse"
aria-labelledby={`heading-${workArea.id}`}
>
<div className="accordion-body px-6">
<div className="accordion-body px-6">
{isLoading || ProjectTaskList === undefined ? (
<div className="text-center py-2 text-muted">Loading activities...</div>
<div
className="d-flex justify-content-center align-items-center text-muted"
style={{ height: "120px" }}
>
<SpinnerLoader />
</div>
) : ProjectTaskList?.length === 0 ? (
<div className="text-center py-2 text-muted">No activities available for this work area.</div>
) : ProjectTaskList?.length > 0 ? (

View File

@ -29,6 +29,7 @@ import eventBus from "../../services/eventBus";
import { useParams } from "react-router-dom";
import GlobalModel from "../common/GlobalModel";
import { setService } from "../../slices/globalVariablesSlice";
import { SpinnerLoader } from "../common/Loader";
const ProjectInfra = ({ data, onDataChange, eachSiteEngineer }) => {
const projectId = useSelectedProject();
@ -186,18 +187,20 @@ const ProjectInfra = ({ data, onDataChange, eachSiteEngineer }) => {
)}
</div>
</div>
<div className="row ">
{isLoading && <p>Loading....</p>}
{projectInfra && projectInfra?.length > 0 && (
<div className="row modal-min-h">
{isLoading ? (
<div className="d-flex justify-content-center align-items-center py-5">
<SpinnerLoader />
</div>
) : projectInfra && projectInfra.length > 0 ? (
<InfraTable
buildings={projectInfra}
projectId={projectId}
serviceId={selectedService}
/>
)}
{!isLoading && projectInfra?.length == 0 && (
<div className="mt-5">
<p>No Infra Avaiable</p>
) : (
<div className="text-center py-5">
<p className="text-muted fs-6">No infrastructure data available.</p>
</div>
)}
</div>

View File

@ -2,6 +2,7 @@ import React from "react";
import { useProjectAssignedOrganizations } from "../../../hooks/useProjects";
import { useSelectedProject } from "../../../slices/apiDataManager";
import { formatUTCToLocalTime } from "../../../utils/dateUtils";
import { SpinnerLoader } from "../../common/Loader";
const ProjectAssignedOrgs = () => {
const selectedProject = useSelectedProject();
@ -25,12 +26,12 @@ const ProjectAssignedOrgs = () => {
),
align: "text-start",
},
{
{
key: "service",
label: "Service Name",
getValue: (org) => (
<div className="d-flex gap-2 py-1 ">
{org?.service?.name}
{org?.service?.name}
</div>
),
align: "text-start",
@ -49,7 +50,7 @@ const ProjectAssignedOrgs = () => {
align: "text-center",
},
{
{
key: "organizationType",
label: "Organization Type",
getValue: (org) => (
@ -62,7 +63,7 @@ const ProjectAssignedOrgs = () => {
),
align: "text-center",
},
{
{
key: "assignedDate",
label: "Assigned Date",
getValue: (org) => (
@ -78,7 +79,12 @@ const ProjectAssignedOrgs = () => {
},
];
if (isLoading) return <div>Loading...</div>;
if (isLoading)
return (
<div className="d-flex justify-content-center align-items-center py-5">
<SpinnerLoader />
</div>
);
if (isError) return <div>{error.message}</div>;
return (

View File

@ -21,7 +21,7 @@ const ProjectOrganizations = () => {
</div>
</div>
<div className="row">
<div className="row modal-min-h">
<ProjectAssignedOrgs />
</div>
</div>

View File

@ -21,6 +21,7 @@ import {
import { useSelectedProject } from "../../../slices/apiDataManager";
import GlobalModel from "../../common/GlobalModel";
import TeamAssignToProject from "./TeamAssignToProject";
import { SpinnerLoader } from "../../common/Loader";
const Teams = () => {
const selectedProject = useSelectedProject();
@ -158,16 +159,8 @@ const Teams = () => {
<div>
{!servicesLoading && (
<>
{(!assignedServices || assignedServices.length === 0) && (
<span className="badge bg-label-secondary">
Not Service Assigned
</span>
)}
{assignedServices?.length === 1 && (
<span className="badge bg-label-secondary">
{assignedServices[0].name}
</span>
<h5 className="mb-2">{assignedServices[0].name}</h5>
)}
{assignedServices?.length > 1 && (
@ -232,7 +225,11 @@ const Teams = () => {
</div>
<div className="table-responsive text-nowrap modal-min-h">
{employeeLodaing && <p>Loading..</p>}
{employeeLodaing && (
<div className="d-flex justify-content-center align-items-center py-5" style={{ minHeight: "50vh" }}>
<SpinnerLoader />
</div>
)}
{projectEmployees && projectEmployees.length > 0 && (
<table className="table ">
<thead>
@ -290,8 +287,8 @@ const Teams = () => {
<td>
{emp.reAllocationDate
? moment(emp.reAllocationDate).format(
"DD-MMM-YYYY"
)
"DD-MMM-YYYY"
)
: "Present"}
</td>
)}

View File

@ -7,8 +7,7 @@ import { useSelectedProject } from "../../slices/apiDataManager";
import { ITEMS_PER_PAGE } from "../../utils/constants";
import Pagination from "../common/Pagination";
import { formatUTCToLocalTime } from "../../utils/dateUtils";
import Loader from "../common/Loader";
import { SpinnerLoader } from "../common/Loader";
const ImageGalleryListView = ({filter}) => {
const [hoveredImage, setHoveredImage] = useState(null);
const selectedProject = useSelectedProject();
@ -44,10 +43,10 @@ const ImageGalleryListView = ({filter}) => {
}
if (isLoading) {
if (isLoading) {
return (
<div className="page-min-h d-flex justify-content-center align-items-center">
<Loader />
<SpinnerLoader />
</div>
);
}

View File

@ -11,8 +11,7 @@ import { defaultContactFilter } from "../../components/Directory/DirectorySchema
import { useDebounce } from "../../utils/appUtils";
import Pagination from "../../components/common/Pagination";
import ListViewContact from "../../components/Directory/ListViewContact";
import Loader from "../../components/common/Loader";
import { SpinnerLoader } from "../../components/common/Loader";
// Utility for CSV export
const formatExportData = (contacts) => {
return contacts.map((contact) => ({
@ -113,7 +112,14 @@ const ContactsPage = ({ projectId, searchText, onExport }) => {
{/* Grid / List View */}
{gridView ? (
<>
{isLoading && <Loader />}
{isLoading && (
<div
className="d-flex justify-content-center align-items-center"
style={{ height: "50vh" }}
>
<SpinnerLoader />
</div>
)}
{data?.data?.length === 0 && (
<div className="py-4 text-center">

View File

@ -3,7 +3,7 @@ import { useProfile } from "../../hooks/useProfile";
import TenantDetails from "./TenantDetails";
import { VIEW_TENANTS } from "../../utils/constants";
import { useNavigate } from "react-router-dom";
import Loader from "../../components/common/Loader";
import { SpinnerLoader } from "../../components/common/Loader";
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
const SelfTenantDetails = () => {
@ -19,7 +19,7 @@ const SelfTenantDetails = () => {
}, [isSelfTenantView, navigate]);
if (loading || !tenantId) {
return <Loader/>;
return <SpinnerLoader />;
}
return (

View File

@ -7,7 +7,7 @@ import { ComingSoonPage } from "../Misc/ComingSoonPage";
import GlobalModel from "../../components/common/GlobalModel";
import EditProfile from "../../components/Tenant/EditProfile";
import SubScriptionHistory from "../../components/Tenant/SubScriptionHistory";
import Loader from "../../components/common/Loader";
import { SpinnerLoader } from "../../components/common/Loader";
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
import { MANAGE_TENANTS, SUPPER_TENANT } from "../../utils/constants";
@ -71,8 +71,11 @@ const TenantDetails = ({
if (!activeTenantId) return <div className="my-4">No tenant selected.</div>;
if (isLoading)
return (
<div className="my-4">
<Loader />
<div
className="page-min-h d-flex justify-content-center align-items-center"
style={{ minHeight: "80vh" }}
>
<SpinnerLoader />
</div>
);
if (isError)
@ -110,14 +113,14 @@ const TenantDetails = ({
data={
iTSelf
? [
{ label: "Home", link: "/dashboard" },
{ label: "Tenant Details", link: null },
]
{ label: "Home", link: "/dashboard" },
{ label: "Tenant Details", link: null },
]
: [
{ label: "Home", link: "/dashboard" },
{ label: "Tenant", link: "/tenants" },
{ label: "Tenant Details", link: null },
]
{ label: "Home", link: "/dashboard" },
{ label: "Tenant", link: "/tenants" },
{ label: "Tenant Details", link: null },
]
}
/>
)}
@ -128,9 +131,8 @@ const TenantDetails = ({
<li key={tab.id} className="nav-item">
<button
type="button"
className={`nav-link d-flex align-items-center text-tiny gap-2 ${
index === 0 ? "active" : ""
}`}
className={`nav-link d-flex align-items-center text-tiny gap-2 ${index === 0 ? "active" : ""
}`}
role="tab"
data-bs-toggle="tab"
data-bs-target={`#${tab.id}`}
@ -150,9 +152,8 @@ const TenantDetails = ({
{tabs.map((tab, index) => (
<div
key={tab.id}
className={`tab-pane fade ${
index === 0 ? "show active" : ""
} text-start`}
className={`tab-pane fade ${index === 0 ? "show active" : ""
} text-start`}
id={tab.id}
>
{tab.content}

View File

@ -4,8 +4,7 @@ import { useAuthModal, useSelectTenant, useTenants } from "../../hooks/useAuth";
import { useProfile } from "../../hooks/useProfile";
import { useQueryClient } from "@tanstack/react-query";
import AuthRepository from "../../repositories/AuthRepository";
import Loader from "../../components/common/Loader";
import { SpinnerLoader } from "../../components/common/Loader";
const SwitchTenant = () => {
const queryClient = useQueryClient();
const { profile } = useProfile();
@ -99,7 +98,7 @@ const SwitchTenant = () => {
</div>
</div>
);
return <Modal isOpen={isOpen} onClose={onClose} body={isLoading ? <Loader/>:contentBody} />;
return <Modal isOpen={isOpen} onClose={onClose} body={isLoading ? <SpinnerLoader/>:contentBody} />;
};
export default SwitchTenant;

View File

@ -2,7 +2,7 @@ import { useEffect, useState } from "react";
import { useTenants, useSelectTenant, useLogout } from "../../hooks/useAuth.jsx";
import { Link, useNavigate } from "react-router-dom";
import Dashboard from "../../components/Dashboard/Dashboard.jsx";
import Loader from "../../components/common/Loader.jsx";
import { SpinnerLoader } from "../../components/common/Loader.jsx";
const TenantSelectionPage = () => {
const [pendingTenant, setPendingTenant] = useState(null);
@ -45,7 +45,7 @@ const TenantSelectionPage = () => {
isPending ||
(data?.data?.length === 1 && pendingTenant !== null)
) {
return <Loader />;
return <SpinnerLoader />;
}
if (!data?.data?.length) {

View File

@ -39,6 +39,7 @@ import { setProjectId } from "../../slices/localVariablesSlice";
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
import Pagination from "../../components/common/Pagination";
import handleEmployeeExport from "../../components/Employee/handleEmployeeExport";
import { SpinnerLoader } from "../../components/common/Loader";
const EmployeeList = () => {
const selectedProjectId = useSelector(
@ -468,12 +469,15 @@ const EmployeeList = () => {
<tbody>
{loading && (
<tr>
<td colSpan={8}>
<p>Loading...</p>
<td colSpan={8} className="text-center py-5">
<div className="d-flex justify-content-center align-items-center py-5" style={{ minHeight: "50vh" }}>
<SpinnerLoader />
</div>
</td>
</tr>
)}
{!loading &&
displayData?.length === 0 &&
(!searchText) ? (
@ -649,16 +653,16 @@ const EmployeeList = () => {
</tr>
))}
</tbody>
</table>
</table>
</div>
</div>
{displayData?.length > 0 && (
<Pagination
currentPage={currentPage}
totalPages={totalPages}
onPageChange={paginate}
/>
)}
{displayData?.length > 0 && (
<Pagination
currentPage={currentPage}
totalPages={totalPages}
onPageChange={paginate}
/>
)}
</div>
) : (
<div className="card">

View File

@ -7,7 +7,7 @@ import AboutProject from "../../components/Project/AboutProject";
import ProjectNav from "../../components/Project/ProjectNav";
import Teams from "../../components/Project/Team/Teams";
import ProjectInfra from "../../components/Project/ProjectInfra";
import Loader from "../../components/common/Loader";
import { SpinnerLoader } from "../../components/common/Loader";
import WorkPlan from "../../components/Project/WorkPlan";
import Breadcrumb from "../../components/common/Breadcrumb";
import { useSelectedProject } from "../../slices/apiDataManager";
@ -20,7 +20,7 @@ import { setProjectId } from "../../slices/localVariablesSlice";
import ProjectDocuments from "../../components/Project/ProjectDocuments";
import ProjectSetting from "../../components/Project/ProjectSetting";
import DirectoryPage from "../Directory/DirectoryPage";
import { useProjectAccess } from "../../hooks/useProjectAccess";
import { useProjectAccess } from "../../hooks/useProjectAccess";
import "./ProjectDetails.css";
import ProjectOrganizations from "../../components/Project/ProjectOrganizations";
@ -65,7 +65,14 @@ const ProjectDetails = () => {
};
if (projectLoading || permsLoading || !projects_Details) {
return <Loader />;
return (
<div
className="d-flex justify-content-center align-items-center"
style={{ height: "80vh" }}
>
<SpinnerLoader />
</div>
);
}
const renderContent = () => {

View File

@ -7,8 +7,8 @@ import ManageProjectInfo from "../../components/Project/ManageProjectInfo";
import ProjectCardView from "../../components/Project/ProjectCardView";
import usePagination from "../../hooks/usePagination";
import { useProjects } from "../../hooks/useProjects";
import Loader from "../../components/common/Loader";
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
import { SpinnerLoader } from "../../components/common/Loader";
const ProjectContext = createContext();
export const useProjectContext = () => {
@ -95,8 +95,16 @@ const ProjectPage = () => {
}
}, [data, isLoading, selectedStatuses]);
if (isLoading)
return (
<div
className="page-min-h d-flex justify-content-center align-items-center"
style={{ minHeight: "80vh" }}
>
<SpinnerLoader />
</div>
);
if (isLoading) return <div className="page-min-h"><Loader /></div>
if (isError) return <div className="page-min-h d-flex justify-content-center align-items-center"><p>{error.message}</p></div>
return (
<ProjectContext.Provider value={contextDispatcher}>