Merge branch 'UI_Changes_PMS' of https://git.marcoaiot.com/admin/marco.pms.web into UI_Changes_PMS

This commit is contained in:
pramod mahajan 2025-09-08 11:57:30 +05:30
commit 0194c4427a
20 changed files with 218 additions and 173 deletions

View File

@ -114,7 +114,10 @@ const Attendance = ({ getRole, handleModalData, searchTerm }) => {
return (
<>
<div className="table-responsive text-nowrap h-100" >
<div
className="table-responsive text-nowrap h-100"
style={{ minHeight: "200px" }} // 🔹 Ensures fixed height
>
<div className="d-flex text-start align-items-center py-2">
<strong>Date : {formatUTCToLocalTime(todayDate)}</strong>
<div className="form-check form-switch text-start m-0 ms-5">
@ -209,7 +212,11 @@ const Attendance = ({ getRole, handleModalData, searchTerm }) => {
</tr>
))}
{!attendance && (
<span className="text-secondary m-4">No employees assigned to the project!</span>
<tr>
<td colSpan={6} className="text-center text-secondary" style={{ height: "200px" }}>
No employees assigned to the project!
</td>
</tr>
)}
</tbody>
</table>
@ -258,7 +265,10 @@ const Attendance = ({ getRole, handleModalData, searchTerm }) => {
)}
</>
) : (
<div className="text-muted my-4">
<div
className="d-flex justify-content-center align-items-center text-muted"
style={{ height: "200px" }}
>
{searchTerm
? "No results found for your search."
: attendanceList.length === 0

View File

@ -42,7 +42,7 @@ const AttendanceLog = ({ handleModalData, searchTerm }) => {
const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" });
const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const [showPending,setShowPending] = useState(false)
const [showPending, setShowPending] = useState(false)
const [isRefreshing, setIsRefreshing] = useState(false);
const [processedData, setProcessedData] = useState([]);
@ -245,17 +245,16 @@ const AttendanceLog = ({ handleModalData, searchTerm }) => {
</div>
<div className="col-md-2 m-0 text-end">
<i
className={`bx bx-refresh cursor-pointer fs-4 ${
isFetching ? "spin" : ""
}`}
className={`bx bx-refresh cursor-pointer fs-4 ${isFetching ? "spin" : ""
}`}
title="Refresh"
onClick={() => refetch()}
/>
</div>
</div>
<div className="table-responsive text-nowrap">
<div className="table-responsive text-nowrap" style={{ minHeight: "200px" }}>
{isLoading ? (
<div>
<div className="d-flex justify-content-center align-items-center" style={{ height: "200px" }}>
<p className="text-secondary">Loading...</p>
</div>
) : filteredSearchData?.length > 0 ? (
@ -284,9 +283,9 @@ const AttendanceLog = ({ handleModalData, searchTerm }) => {
const previousAttendance = arr[index - 1];
const previousDate = previousAttendance
? moment(
previousAttendance.checkInTime ||
previousAttendance.checkOutTime
).format("YYYY-MM-DD")
previousAttendance.checkInTime ||
previousAttendance.checkOutTime
).format("YYYY-MM-DD")
: null;
if (!previousDate || currentDate !== previousDate) {
@ -346,12 +345,15 @@ const AttendanceLog = ({ handleModalData, searchTerm }) => {
</tbody>
</table>
) : (
<div className="my-4"><span className="text-secondary">No Record Available !</span></div>
<div className="my-4"><span className="text-secondary">No Record Available !</span></div>
)}
</div>
{paginatedAttendances?.length == 0 && filteredSearchData?.length > 0 && (
<div className="my-4">
<span className="text-secondary">No Pending Record Available !</span>
<div
className="d-flex justify-content-center align-items-center text-secondary"
style={{ height: "200px" }}
>
No Record Available !
</div>
)}
{filteredSearchData.length > ITEMS_PER_PAGE && (
@ -369,9 +371,8 @@ const AttendanceLog = ({ handleModalData, searchTerm }) => {
(pageNumber) => (
<li
key={pageNumber}
className={`page-item ${
currentPage === pageNumber ? "active" : ""
}`}
className={`page-item ${currentPage === pageNumber ? "active" : ""
}`}
>
<button
className="page-link"
@ -383,9 +384,8 @@ const AttendanceLog = ({ handleModalData, searchTerm }) => {
)
)}
<li
className={`page-item ${
currentPage === totalPages ? "disabled" : ""
}`}
className={`page-item ${currentPage === totalPages ? "disabled" : ""
}`}
>
<button
className="page-link"

View File

@ -87,9 +87,9 @@ const Regularization = ({ handleRequest, searchTerm }) => {
}, [employeeHandler]);
return (
<div className="table-responsive text-nowrap pb-4">
<div className="table-responsive text-nowrap pb-4" style={{ minHeight: "200px" }}>
{loading ? (
<div className="my-2">
<div className="d-flex justify-content-center align-items-center" style={{ height: "200px" }}>
<p className="text-secondary">Loading...</p>
</div>
) : currentItems?.length > 0 ? (
@ -143,9 +143,14 @@ const Regularization = ({ handleRequest, searchTerm }) => {
</tbody>
</table>
) : (
<div className="my-4">
<div
className="d-flex justify-content-center align-items-center"
style={{ height: "200px" }}
>
<span className="text-secondary">
{searchTerm ? "No results found for your search." : "No Requests Found !"}
{searchTerm
? "No results found for your search."
: "No Requests Found !"}
</span>
</div>
)}
@ -163,9 +168,8 @@ const Regularization = ({ handleRequest, searchTerm }) => {
{[...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 "
@ -176,9 +180,8 @@ const Regularization = ({ handleRequest, searchTerm }) => {
</li>
))}
<li
className={`page-item ${
currentPage === totalPages ? "disabled" : ""
}`}
className={`page-item ${currentPage === totalPages ? "disabled" : ""
}`}
>
<button
className="page-link "

View File

@ -98,42 +98,42 @@ const AttendanceOverview = () => {
colors: roles.map((_, i) => flatColors[i % flatColors.length]),
};
return (
<div
className="bg-white p-4 rounded shadow d-flex flex-column"
>
{/* Header */}
<div className="d-flex justify-content-between align-items-center mb-3">
<div className="card-title mb-0 text-start">
<h5 className="mb-1">Attendance Overview</h5>
<p className="card-subtitle">Role-wise present count</p>
</div>
<div className="d-flex gap-2">
<select
className="form-select form-select-sm"
value={dayRange}
onChange={(e) => setDayRange(Number(e.target.value))}
>
<option value={7}>Last 7 Days</option>
<option value={15}>Last 15 Days</option>
<option value={30}>Last 30 Days</option>
</select>
<button
className={`btn btn-sm ${view === "chart" ? "btn-primary" : "btn-outline-primary"}`}
onClick={() => setView("chart")}
title="Chart View"
>
<i className="bx bx-bar-chart-alt-2"></i>
</button>
<button
className={`btn btn-sm ${view === "table" ? "btn-primary" : "btn-outline-primary"}`}
onClick={() => setView("table")}
title="Table View"
>
<i className="bx bx-task text-success"></i>
</button>
</div>
</div>
return (
<div
className="bg-white p-4 rounded shadow d-flex flex-column"
>
{/* Header */}
<div className="d-flex justify-content-between align-items-center mb-3">
<div className="card-title mb-0 text-start">
<h5 className="mb-1 fw-bold">Attendance Overview</h5>
<p className="card-subtitle">Role-wise present count</p>
</div>
<div className="d-flex gap-2">
<select
className="form-select form-select-sm"
value={dayRange}
onChange={(e) => setDayRange(Number(e.target.value))}
>
<option value={7}>Last 7 Days</option>
<option value={15}>Last 15 Days</option>
<option value={30}>Last 30 Days</option>
</select>
<button
className={`btn btn-sm ${view === "chart" ? "btn-primary" : "btn-outline-primary"}`}
onClick={() => setView("chart")}
title="Chart View"
>
<i className="bx bx-bar-chart-alt-2"></i>
</button>
<button
className={`btn btn-sm ${view === "table" ? "btn-primary" : "btn-outline-primary"}`}
onClick={() => setView("table")}
title="Table View"
>
<i className="bx bx-task text-success"></i>
</button>
</div>
</div>
{/* Content */}
<div className="flex-grow-1 d-flex align-items-center justify-content-center">

View File

@ -19,7 +19,7 @@ const ProjectCompletionChart = () => {
<div className="card h-100">
<div className="card-header d-flex align-items-start justify-content-between">
<div className="card-title mb-0 text-start">
<h5 className="mb-1">Projects</h5>
<h5 className="mb-1 fw-bold ">Projects</h5>
<p className="card-subtitle">Projects Completion Status</p>
</div>
</div>

View File

@ -90,7 +90,7 @@ const ProjectProgressChart = ({
<div className="d-flex flex-wrap justify-content-between align-items-start mb-2">
{/* Left: Title */}
<div className="card-title text-start">
<h5 className="mb-1">Project Progress</h5>
<h5 className="mb-1 fw-bold">Project Progress</h5>
<p className="card-subtitle">Progress Overview by Project</p>
</div>
</div>

View File

@ -18,6 +18,7 @@ import {
import { clearApiCacheKey } from "../../slices/apiCacheSlice";
import { useMutation } from "@tanstack/react-query";
import Label from "../common/Label";
import DatePicker from "../common/DatePicker";
const mobileNumberRegex = /^[0-9]\d{9}$/;
@ -371,41 +372,43 @@ const ManageEmployee = ({ employeeId, onClosed, IsAllEmployee }) => {
)}
</div>
<div className="col-sm-4">
<Label className="form-text text-start" required>Birth Date</Label>
<Label className="form-text text-start" required>
Birth Date
</Label>
<div className="input-group">
<input
className="form-control form-control-sm"
type="date"
{...register("birthDate")}
id="birthDate"
<DatePicker
name="birthDate"
control={control} // from useForm()
placeholder="DD-MM-YYYY"
maxDate={new Date()} // restrict future dates (e.g., birth date must be today or past)
className="w-100"
/>
</div>
{errors.birthDate && (
<div
className="danger-text text-start"
style={{ fontSize: "12px" }}
>
<div className="danger-text text-start" style={{ fontSize: "12px" }}>
{errors.birthDate.message}
</div>
)}
</div>
<div className="col-sm-4">
<Label className="form-text text-start" required>Joining Date</Label>
<Label className="form-text text-start" required>
Joining Date
</Label>
<div className="input-group">
<input
className="form-control form-control-sm"
type="date"
{...register("joiningDate")}
id="joiningDate"
<DatePicker
name="joiningDate"
control={control} // from useForm()
placeholder="DD-MM-YYYY"
// For joining date, we dont block future dates
className="w-100"
/>
</div>
{errors.joiningDate && (
<div
className="danger-text text-start"
style={{ fontSize: "12px" }}
>
<div className="danger-text text-start" style={{ fontSize: "12px" }}>
{errors.joiningDate.message}
</div>
)}

View File

@ -51,13 +51,13 @@ const AboutProject = () => {
)}
{projects_Details && (
<>
<div className="card mb-6">
<div className="card mb-4">
<div className="card-header text-start">
<h6 className="card-action-title mb-0 ps-1">
<h5 className="card-action-title mb-0 ps-1">
{" "}
<i className="fa fa-building rounded-circle text-primary"></i>
<span className="ms-2">Project Profile</span>
</h6>
<span className="ms-2 fw-bold">Project Profile</span>
</h5>
</div>
<div className="card-body">
<ul className="list-unstyled my-3 ps-0">

View File

@ -0,0 +1,19 @@
/* For Webkit browsers (Chrome, Edge, Safari) */
.modal-dialog-scrollable::-webkit-scrollbar {
width: 6px; /* smaller width */
}
.modal-dialog-scrollable::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.3); /* scrollbar color */
border-radius: 10px;
}
.modal-dialog-scrollable::-webkit-scrollbar-track {
background: transparent;
}
/* For Firefox */
.modal-dialog-scrollable {
scrollbar-width: thin; /* shrinks scrollbar */
scrollbar-color: rgba(0, 0, 0, 0.3) transparent;
}

View File

@ -4,6 +4,7 @@ import { useAllEmployees } from "../../hooks/useEmployees";
import useSearch from "../../hooks/useSearch";
import AssignEmployeeTable from "./AssignEmployeeTable";
import showToast from "../../services/toastService";
import "./MapUser.css";
const MapUsers = ({
projectId,

View File

@ -93,7 +93,7 @@ const ProjectInfra = ( {data, onDataChange, eachSiteEngineer} ) =>
>
<button
type="button"
className="link-button link-button-sm m-1 "
className="link-button link-button-sm m-1 btn-primary"
onClick={()=>setshowModalBuilding(true)}
>
<i className="bx bx-plus-circle me-2"></i>
@ -101,7 +101,7 @@ const ProjectInfra = ( {data, onDataChange, eachSiteEngineer} ) =>
</button>
<button
type="button"
className="link-button m-1"
className="link-button m-1 btn-primary"
onClick={()=>setshowModalFloor(true)}
>
<i className="bx bx-plus-circle me-2"></i>
@ -109,7 +109,7 @@ const ProjectInfra = ( {data, onDataChange, eachSiteEngineer} ) =>
</button>
<button
type="button"
className="link-button m-1"
className="link-button m-1 btn-primary"
onClick={() => setshowModalWorkArea(true)}
>
<i className="bx bx-plus-circle me-2"></i>
@ -117,7 +117,7 @@ const ProjectInfra = ( {data, onDataChange, eachSiteEngineer} ) =>
</button>
<button
type="button"
className="link-button m-1"
className="link-button m-1 btn-primary"
onClick={()=>setshowModalTask(true)}
>
<i className="bx bx-plus-circle me-2"></i>

View File

@ -167,11 +167,11 @@ const ProjectOverview = ({ project }) => {
return (
<div className="card" style={{ minHeight: "490px" }}>
<div className="card-header text-start">
<h6 className="card-action-title mb-0">
<h5 className="card-action-title mb-0">
{" "}
<i className="fa fa-line-chart rounded-circle text-primary"></i>
<span className="ms-2">Project Statistics</span>
</h6>
<span className="ms-2 fw-bold">Project Statistics</span>
</h5>
</div>
<div className="card-body">
<ul className="list-unstyled m-0 p-0">

View File

@ -276,12 +276,13 @@ const EditMaster = ({ master, onClose }) => {
<div className="col-12 text-end">
<div className="col-12 text-end mt-3">
<button
type="button"
className="btn btn-sm btn-label-secondary me-3"
data-bs-dismiss="modal"
aria-label="Close"
onClick={onClose}
>
Cancel
</button>

View File

@ -116,17 +116,18 @@ const EditWorkCategory = ({ data, onClose }) => {
</div>
<div className="col-12 text-center">
<button type="submit" className="btn btn-sm btn-primary me-3">
{isLoading ? "Please Wait..." : "Submit"}
</button>
<div className="col-12 text-center mt-3">
<button
type="button"
className="btn btn-sm btn-label-secondary"
className="btn btn-sm btn-label-secondary me-3"
onClick={onClose}
>
Cancel
</button>
<button type="submit" className="btn btn-sm btn-primary">
{isLoading ? "Please Wait..." : "Submit"}
</button>
</div>

View File

@ -86,7 +86,7 @@ const ManagePaymentMode = ({ data = null, onClose }) => {
className="btn btn-sm btn-primary"
disabled={isPending || Updating}
>
{isPending || Updating? "Please Wait..." : Updating ? "Update" : "Submit"}
{isPending || Updating ? "Please Wait..." : Updating ? "Update" : "Submit"}
</button>
</div>

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect, useCallback } from "react";
import React, { useState, useEffect } from "react";
import {
cacheData,
clearCacheKey,
@ -26,7 +26,7 @@ import { useQueryClient } from "@tanstack/react-query";
const AttendancePage = () => {
const [activeTab, setActiveTab] = useState("all");
const [ShowPending, setShowPending] = useState(false);
const [searchTerm, setSearchTerm] = useState("");
const [searchTerm, setSearchTerm] = useState("");
const queryClient = useQueryClient();
const loginUser = getCachedProfileData();
@ -117,60 +117,70 @@ const AttendancePage = () => {
{ label: "Attendance", link: null },
]}
></Breadcrumb>
<div className="nav-align-top nav-tabs-shadow" >
<ul className="nav nav-tabs" role="tablist">
<li className="nav-item">
<button
type="button"
<div className="nav-align-top nav-tabs-shadow">
{/* Tabs */}
<div className="nav-align-top nav-tabs-shadow bg-white border-bottom">
<div className="row align-items-center g-0 mb-3 mb-md-0">
{/* Tabs */}
<div className="col-12 col-md">
<ul className="nav nav-tabs" role="tablist">
<li className="nav-item">
<button
type="button"
className={`nav-link ${
activeTab === "all" ? "active" : ""
} fs-6`}
onClick={() => handleTabChange("all")}
data-bs-toggle="tab"
data-bs-target="#navs-top-home"
>
Today's
</button>
</li>
<li className="nav-item">
<button
type="button"
onClick={() => handleTabChange("all")}
data-bs-toggle="tab"
data-bs-target="#navs-top-home"
>
Today's
</button>
</li>
<li className="nav-item">
<button
type="button"
className={`nav-link ${
activeTab === "logs" ? "active" : ""
} fs-6`}
onClick={() => handleTabChange("logs")}
data-bs-toggle="tab"
data-bs-target="#navs-top-profile"
>
Logs
</button>
</li>
<li className={`nav-item ${!DoRegularized && "d-none"}`}>
<button
type="button"
onClick={() => handleTabChange("logs")}
data-bs-toggle="tab"
data-bs-target="#navs-top-profile"
>
Logs
</button>
</li>
<li className={`nav-item ${!DoRegularized ? "d-none" : ""}`}>
<button
type="button"
className={`nav-link ${
activeTab === "regularization" ? "active" : ""
} fs-6`}
onClick={() => handleTabChange("regularization")}
data-bs-toggle="tab"
data-bs-target="#navs-top-messages"
>
Regularization
</button>
</li>
onClick={() => handleTabChange("regularization")}
data-bs-toggle="tab"
data-bs-target="#navs-top-messages"
>
Regularization
</button>
</li>
</ul>
</div>
{/* 🔹 Search box placed after Regularization tab */}
<li className="nav-item ms-auto me-3">
<input
type="text"
className="form-control form-control-sm mt-1"
placeholder="Search Employee..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
style={{ minWidth: "200px" }}
/>
</li>
</ul>
{/* Single search input that moves */}
<div className="col-12 col-md-auto mt-2 mt-md-0 ms-md-auto px-2">
<input
type="text"
className="form-control form-control-sm"
placeholder="Search Employee..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
style={{ minWidth: "200px" }}
/>
</div>
</div>
</div>
<div className="tab-content attedanceTabs py-0 px-1 px-sm-3">
{selectedProject ? (

View File

@ -173,12 +173,12 @@ const DailyTask = () => {
currentSelectedBuilding={filters.selectedBuilding}
currentSelectedFloors={filters.selectedFloors}
currentSelectedActivities={filters.selectedActivities}
selectedProject={selectedProject}
selectedProject={selectedProject}
/>
</div>
{/* --- Table --- */}
<div className="table-responsive text-nowrap mt-3">
<div className="table-responsive text-nowrap mt-3" style={{ minHeight: "200px" }}>
<table className="table">
<thead>
<tr>
@ -193,14 +193,16 @@ const DailyTask = () => {
<tbody>
{taskLoading && (
<tr>
<td colSpan={6} className="text-center">
<Loader/>
<td colSpan={6} className="text-center align-middle" style={{ height: "200px" }}>
<Loader />
</td>
</tr>
)}
{!taskLoading && groupedTasks.length === 0 && (
<tr>
<td colSpan={6} className="text-center">No Reports Found</td>
<td colSpan={6} className="text-center align-middle" style={{ height: "200px" }}>
No Reports Found
</td>
</tr>
)}
{!taskLoading &&
@ -211,7 +213,7 @@ const DailyTask = () => {
</tr>
{tasks.map((task, idx) => (
<tr key={task.id || idx}>
<td className="flex-wrap text-start">
<td className="flex-wrap text-start">
<div>{task.workItem.activityMaster?.activityName || "No Activity Name"}</div>
<div className="text-sm">
{task.workItem.workArea?.floor?.building?.name} {task.workItem.workArea?.floor?.floorName} {task.workItem.workArea?.areaName}
@ -239,6 +241,7 @@ const DailyTask = () => {
</tbody>
</table>
</div>
</div>
</div>
</div>

View File

@ -414,14 +414,11 @@ const EmployeeList = () => {
{/* Add Employee Button */}
{Manage_Employee && (
<button
className="btn btn-sm btn-primary"
className="p-1 me-1 m-sm-0 bg-primary rounded-circle"
type="button"
onClick={() => handleEmployeeModel(null)}
>
<i className="bx bx-plus-circle me-2"></i>
<span className="d-none d-md-inline-block">
Add New Employee
</span>
<i className="bx bx-plus fs-4 text-white"></i>
</button>
)}
</div>
@ -636,7 +633,7 @@ const EmployeeList = () => {
}
className="dropdown-item py-1"
>
<i className="bx bx-detail bx-sm"></i> View
<i className="bx bx-show text-primary bx-sm"></i> View
</button>
{/* If ACTIVE employee */}
@ -648,8 +645,7 @@ const EmployeeList = () => {
handleEmployeeModel(item.id)
}
>
<i className="bx bx-edit bx-sm"></i>{" "}
Edit
<i className="bx bx-edit text-secondary bx-sm"></i> Edit
</button>
{/* Suspend only when active */}
@ -658,8 +654,7 @@ const EmployeeList = () => {
className="dropdown-item py-1"
onClick={() => handleOpenDelete(item)}
>
<i className="bx bx-task-x bx-sm"></i>{" "}
Suspend
<i className="bx bx-task-x text-danger bx-sm"></i> Suspend
</button>
)}
@ -684,8 +679,7 @@ const EmployeeList = () => {
className="dropdown-item py-1"
onClick={() => handleOpenDelete(item)}
>
<i className="bx bx-refresh bx-sm me-1"></i>{" "}
Re-activate
<i className="bx bx-refresh text-danger bx-sm me-0"></i> Re-activate
</button>
)}
</div>

View File

@ -163,7 +163,7 @@ useEffect(() => {
name="DataTables_Table_0_length"
aria-controls="DataTables_Table_0"
className="form-select py-1 px-2"
style={{ fontSize: "0.875rem", height: "32px", width: "150px" }}
style={{ fontSize: "0.875rem", height: "32px", width: "170px" }}
value={selectedMaster}
>
{isLoading && (

View File

@ -83,7 +83,7 @@ const ProjectDetails = () => {
return (
<>
<div className="row">
<div className="col-lg-4 col-md-5 mt-5">
<div className="col-lg-4 col-md-5 mt-2">
<AboutProject></AboutProject>
<ProjectOverview project={projectId} />
</div>