Asthetic Changes

- Margin on all sides for grid
- Margin for card content
This commit is contained in:
Vikas Nale 2025-09-16 18:33:48 +05:30
parent daa1a29e8a
commit a86c815ca2
9 changed files with 338 additions and 302 deletions

View File

@ -99,9 +99,7 @@ const AttendanceOverview = () => {
};
return (
<div
className="bg-white p-4 rounded shadow d-flex flex-column"
>
<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">
@ -119,18 +117,22 @@ const AttendanceOverview = () => {
<option value={30}>Last 30 Days</option>
</select>
<button
className={`btn btn-sm ${view === "chart" ? "btn-primary" : "btn-outline-primary"}`}
className={`btn btn-sm p-1 ${
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"}`}
className={`btn btn-sm p-1 ${
view === "table" ? "btn-primary" : "btn-outline-primary"
}`}
onClick={() => setView("table")}
title="Table View"
>
<i className="bx bx-task text-success"></i>
<i class="bx bx-list-ul fs-5"></i>
</button>
</div>
</div>

View File

@ -125,18 +125,18 @@ const TenantsList = ({
];
if (isInitialLoading)
return <TenantTableSkeleton columns={TenantColumns} rows={13} />;
if (isError)
if (isError)
return (
<div className="">
<div className="card text-center my-4 p-2">
<i className="fa-solid fa-triangle-exclamation fs-5"></i>
<p>{error.message}</p>
</div>
<div className="text-center my-4 p-2">
<i className="fa-solid fa-triangle-exclamation fs-5"></i>
<p>{error.message}</p>
</div>
</div>
);
return (
<>
<div className="card p-2 mt-3">
<div className="p-2 mt-3">
<div className="card-datatable text-nowrap table-responsive">
<table className="table border-top dataTable text-nowrap">
<thead>

View File

@ -95,11 +95,11 @@ const AttendancePage = () => {
{(modelConfig?.action === 0 ||
modelConfig?.action === 1 ||
modelConfig?.action === 2) && (
<CheckCheckOutmodel
modeldata={modelConfig}
closeModal={closeModal}
/>
)}
<CheckCheckOutmodel
modeldata={modelConfig}
closeModal={closeModal}
/>
)}
{/* For view logs */}
{modelConfig?.action === 6 && (
<AttendLogs Id={modelConfig?.id} closeModal={closeModal} />
@ -118,19 +118,19 @@ const AttendancePage = () => {
]}
></Breadcrumb>
<div className="nav-align-top nav-tabs-shadow">
<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">
<div className="nav-align-top nav-tabs-shadow bg-white border-bottom pt-5">
<div className="row align-items-center g-0 mb-3 mb-md-0 mx-5">
{/* 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`}
className={`nav-link ${
activeTab === "all" ? "active" : ""
} fs-6`}
onClick={() => handleTabChange("all")}
data-bs-toggle="tab"
data-bs-target="#navs-top-home"
@ -141,9 +141,9 @@ const AttendancePage = () => {
<li className="nav-item">
<button
type="button"
className={`nav-link ${
activeTab === "logs" ? "active" : ""
} fs-6`}
className={`nav-link ${
activeTab === "logs" ? "active" : ""
} fs-6`}
onClick={() => handleTabChange("logs")}
data-bs-toggle="tab"
data-bs-target="#navs-top-profile"
@ -155,9 +155,9 @@ const AttendancePage = () => {
<li className={`nav-item ${!DoRegularized ? "d-none" : ""}`}>
<button
type="button"
className={`nav-link ${
activeTab === "regularization" ? "active" : ""
} fs-6`}
className={`nav-link ${
activeTab === "regularization" ? "active" : ""
} fs-6`}
onClick={() => handleTabChange("regularization")}
data-bs-toggle="tab"
data-bs-target="#navs-top-messages"
@ -182,11 +182,11 @@ const AttendancePage = () => {
</div>
</div>
<div className="tab-content attedanceTabs py-0 px-1 px-sm-3">
<div className="tab-content attedanceTabs py-0 px-1 px-sm-3 pb-10">
{selectedProject ? (
<>
{activeTab === "all" && (
<div className="tab-pane fade show active py-0">
<div className="tab-pane fade show active py-0 mx-5">
<Attendance
handleModalData={handleModalData}
getRole={getRole}
@ -214,7 +214,6 @@ const AttendancePage = () => {
</div>
)}
</div>
</div>
</div>
</>

View File

@ -133,119 +133,119 @@ export default function DirectoryPage({ IsPage = true, projectId = null }) {
></Breadcrumb>
)}
<div className="card">
<div className="d-flex-row px-2">
<div className="d-flex justify-content-between align-items-center mb-1">
<ul className="nav nav-tabs">
<li className="nav-item cursor-pointer">
<a
className={`nav-link ${
activeTab === "notes" ? "active" : ""
} fs-6`}
onClick={(e) => handleTabClick("notes", e)}
>
<i className="bx bx-notepad bx-sm me-1_5"></i>
<span className="d-none d-md-inline">Notes</span>
</a>
</li>
<li className="nav-item cursor-pointer">
<a
className={`nav-link ${
activeTab === "contacts" ? "active" : ""
} fs-6`}
onClick={(e) => handleTabClick("contacts", e)}
>
<i className="bx bxs-contact bx-sm me-1_5"></i>
<span className="d-none d-md-inline">Contacts</span>
</a>
</li>
</ul>
</div>
<div className="d-flex-row px-2">
<div className="d-flex justify-content-between align-items-center mb-1">
<ul className="nav nav-tabs">
<li className="nav-item cursor-pointer">
<a
className={`nav-link ${
activeTab === "notes" ? "active" : ""
} fs-6`}
onClick={(e) => handleTabClick("notes", e)}
>
<i className="bx bx-notepad bx-sm me-1_5"></i>
<span className="d-none d-md-inline">Notes</span>
</a>
</li>
<li className="nav-item cursor-pointer">
<a
className={`nav-link ${
activeTab === "contacts" ? "active" : ""
} fs-6`}
onClick={(e) => handleTabClick("contacts", e)}
>
<i className="bx bxs-contact bx-sm me-1_5"></i>
<span className="d-none d-md-inline">Contacts</span>
</a>
</li>
</ul>
</div>
<div className="mb-1 px-2">
<div className="d-flex align-items-center justify-content-between">
<div className="d-flex align-items-center gap-3">
{activeTab === "notes" && (
<input
type="search"
className="form-control form-control-sm"
placeholder="Search notes..."
value={searchNote}
onChange={(e) => setSearchNote(e.target.value)}
/>
)}
<div className="mb-1 px-2 py-3">
<div className="d-flex align-items-center justify-content-between">
<div className="d-flex align-items-center gap-3">
{activeTab === "notes" && (
<input
type="search"
className="form-control form-control-sm"
placeholder="Search notes..."
value={searchNote}
onChange={(e) => setSearchNote(e.target.value)}
/>
)}
{activeTab === "contacts" && (
<div className="d-flex align-items-center gap-3">
<div className="d-flex gap-2 align-items-center">
<input
type="search"
className="form-control form-control-sm"
placeholder="Search contacts..."
value={searchContact}
onChange={(e) => setsearchContact(e.target.value)}
/>
<button
className={`btn btn-sm p-1 ${
!gridView ? "btn-primary" : "btn-outline-primary"
}`}
onClick={() => setGridView(false)}
>
<i className="bx bx-list-ul"></i>
</button>
{activeTab === "contacts" && (
<div className="d-flex align-items-center gap-3">
<div className="d-flex gap-2 align-items-center">
<input
type="search"
className="form-control form-control-sm"
placeholder="Search contacts..."
value={searchContact}
onChange={(e) => setsearchContact(e.target.value)}
/>
<button
className={`btn btn-sm p-1 ${
!gridView ? "btn-primary" : "btn-outline-primary"
}`}
onClick={() => setGridView(false)}
>
<i className="bx bx-list-ul"></i>
</button>
<button
className={`btn btn-sm p-1 ${
gridView ? " btn-primary" : " btn-outline-primary"
}`}
onClick={() => setGridView(true)}
>
<i className="bx bx-grid-alt"></i>
</button>
<button
className={`btn btn-sm p-1 ${
gridView ? " btn-primary" : " btn-outline-primary"
}`}
onClick={() => setGridView(true)}
>
<i className="bx bx-grid-alt"></i>
</button>
</div>
<div className="form-check form-switch d-flex align-items-center">
<input
type="checkbox"
className="form-check-input"
role="switch"
id="inactiveEmployeesCheckbox"
checked={showActive}
onChange={(e) => setShowActive(e.target.checked)}
/>
<label
className="form-check-label ms-2"
htmlFor="inactiveEmployeesCheckbox"
>
{showActive ? "Active" : "Inactive"} Contacts
</label>
</div>
</div>
)}
</div>
<div className="form-check form-switch d-flex align-items-center">
<input
type="checkbox"
className="form-check-input"
role="switch"
id="inactiveEmployeesCheckbox"
checked={showActive}
onChange={(e) => setShowActive(e.target.checked)}
/>
<label
className="form-check-label ms-2"
htmlFor="inactiveEmployeesCheckbox"
<div className="btn-group">
<button
className="btn btn-sm btn-label-secondary dropdown-toggle"
type="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
<i className="bx bx-export me-2 bx-sm"></i>Export
</button>
<ul className="dropdown-menu">
<li>
<a
className="dropdown-item cursor-pointer"
onClick={() => handleExport("csv")}
>
{showActive ? "Active" : "Inactive"} Contacts
</label>
</div>
</div>
)}
</div>
<div className="btn-group">
<button
className="btn btn-sm btn-label-secondary dropdown-toggle"
type="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
<i className="bx bx-export me-2 bx-sm"></i>Export
</button>
<ul className="dropdown-menu">
<li>
<a
className="dropdown-item cursor-pointer"
onClick={() => handleExport("csv")}
>
<i className="bx bx-file me-1"></i> CSV
</a>
</li>
</ul>
<i className="bx bx-file me-1"></i> CSV
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<div>

View File

@ -13,8 +13,6 @@ import "swiper/css/navigation";
import SwaperSlideContent from "./SwaperSlideContent";
import SwaperBlogContent from "./SwaperBlogContent";
const swiperConfig = {
spaceBetween: 30,
centeredSlides: true,
@ -110,7 +108,7 @@ const LandingPage = () => {
</a>
</li>
<li className="nav-item">
<a className="nav-link fw-medium" href="#landingReviews">
<a className="nav-link fw-medium" href="#sectionBlog">
Blogs
</a>
</li>
@ -182,7 +180,7 @@ const LandingPage = () => {
</div>
</div>
<div
<div
id="heroDashboardAnimation"
className="hero-animation-img mt-10"
>
@ -296,10 +294,7 @@ const LandingPage = () => {
<div className="features-icon-wrapper row gx-0 gy-6 g-sm-12">
<div className="col-lg-3 col-sm-4 text-center features-icon-box">
<div className="text-center mb-4">
<img
src="/img/icons/laptop.svg"
alt="laptop charging"
/>
<img src="/img/icons/laptop.svg" alt="laptop charging" />
</div>
<h5 className="mb-2">Project & Task Management</h5>
<p className="features-icon-description">
@ -309,10 +304,7 @@ const LandingPage = () => {
</div>
<div className="col-lg-3 col-sm-4 text-center features-icon-box">
<div className="text-center mb-4">
<img
src="/img/icons/rocket.svg"
alt="transition up"
/>
<img src="/img/icons/rocket.svg" alt="transition up" />
</div>
<h5 className="mb-2">Attendance & Leave Tracking</h5>
<p className="features-icon-description">
@ -332,10 +324,7 @@ const LandingPage = () => {
</div>
<div className="col-lg-3 col-sm-4 text-center features-icon-box">
<div className="text-center mb-4">
<img
src="/img/icons/check.svg"
alt="3d select solid"
/>
<img src="/img/icons/check.svg" alt="3d select solid" />
</div>
<h5 className="mb-2">Expense & Budget Tracking</h5>
<p className="features-icon-description">
@ -355,10 +344,7 @@ const LandingPage = () => {
</div>
<div className="col-lg-3 col-sm-4 text-center features-icon-box">
<div className="text-center mb-4">
<img
src="/img/icons/keyboard.svg"
alt="keyboard"
/>
<img src="/img/icons/keyboard.svg" alt="keyboard" />
</div>
<h5 className="mb-2">Document Management</h5>
<p className="features-icon-description">
@ -368,10 +354,7 @@ const LandingPage = () => {
</div>
<div className="col-lg-3 col-sm-4 text-center features-icon-box">
<div className="text-center mb-4">
<img
src="/img/icons/keyboard.svg"
alt="keyboard"
/>
<img src="/img/icons/keyboard.svg" alt="keyboard" />
</div>
<h5 className="mb-2">
Service Provider & Subcontractor Tracking
@ -383,10 +366,7 @@ const LandingPage = () => {
</div>{" "}
<div className="col-lg-3 col-sm-4 text-center features-icon-box">
<div className="text-center mb-4">
<img
src="/img/icons/inventory.svg"
alt="keyboard"
/>
<img src="/img/icons/inventory.svg" alt="keyboard" />
</div>
<h5 className="mb-2">Inventory Management</h5>
<p className="features-icon-description">
@ -396,10 +376,7 @@ const LandingPage = () => {
</div>
<div className="col-lg-3 col-sm-4 text-center features-icon-box">
<div className="text-center mb-4">
<img
src="/img/icons/keyboard.svg"
alt="keyboard"
/>
<img src="/img/icons/keyboard.svg" alt="keyboard" />
</div>
<h5 className="mb-2">Directory</h5>
<p className="features-icon-description">
@ -411,10 +388,11 @@ const LandingPage = () => {
</section>
{/* Useful features: End */}
{/* <!-- Real customers reviews: Start --> */}
{/* <!-- Real blog/ case studies: Start --> */}
<section
id="landingReviews"
id="sectionBlog"
class="section-py bg-body landing-reviews pb-0"
hidden
>
{/* <!-- What people say slider: Start --> */}
<div class="container">
@ -1186,7 +1164,7 @@ const LandingPage = () => {
href="tel:+1234-568-963"
className="text-heading"
>
+1234 568 963
+91 70288 83755
</a>
</h6>
</div>
@ -1516,10 +1494,7 @@ const LandingPage = () => {
<div className="col-lg-6 col-md-6 d-flex gap-3 align-items-center justify-content-end">
<h6 className="footer-title mt-3">Download our app</h6>
<a href="javascript:void(0);">
<img
src="/img/icons/apple-icon.png"
alt="apple icon"
/>
<img src="/img/icons/apple-icon.png" alt="apple icon" />
</a>
<a
href="https://play.google.com/store/apps/details?id=com.marco.aiotstage&pcampaignid=web_share"
@ -1554,26 +1529,17 @@ const LandingPage = () => {
className="me-4"
target="_blank"
>
<img
src="/img/icons/facebook.svg"
alt="facebook icon"
/>
<img src="/img/icons/facebook.svg" alt="facebook icon" />
</a>
<a
href="https://twitter.com/marcoaiot"
className="me-4"
target="_blank"
>
<img
src="/img/icons/twitter.svg"
alt="twitter icon"
/>
<img src="/img/icons/twitter.svg" alt="twitter icon" />
</a>
<a href="https://www.instagram.com/marcoaiot/" target="_blank">
<img
src="/img/icons/instagram.svg"
alt="google icon"
/>
<img src="/img/icons/instagram.svg" alt="google icon" />
</a>
</div>
</div>

View File

@ -121,66 +121,67 @@ const TenantPage = () => {
{ label: "Tenant", link: null },
]}
/>
<div className="card text-center my-4 p-5 pb-10">
{/* Super Tenant Actions */}
{isSuperTenant && (
<div className="p-0">
<div className="row align-items-center">
{/* Search */}
<div className="col-6 col-md-6 col-lg-3 mb-md-0">
<input
type="search"
value={searchText}
onChange={(e) => setSearchText(e.target.value)}
className="form-control form-control"
placeholder="Search Tenant"
/>
</div>
{/* Super Tenant Actions */}
{isSuperTenant && (
<div className="card d-flex p-2">
<div className="row align-items-center">
{/* Search */}
<div className="col-6 col-md-6 col-lg-3 mb-md-0">
<input
type="search"
value={searchText}
onChange={(e) => setSearchText(e.target.value)}
className="form-control form-control-sm"
placeholder="Search Tenant"
/>
</div>
{/* Actions */}
<div className="col-6 col-md-6 col-lg-9 text-end">
<span
className="text-tiny text-muted p-1 border-0 bg-none lead mx-3 cursor-pointer"
disabled={isRefetching}
onClick={() => refetchFn && refetchFn()}
>
Refresh{" "}
<i
className={`bx bx-refresh ms-1 ${
isRefetching ? "bx-spin" : ""
}`}
></i>
</span>
{/* Actions */}
<div className="col-6 col-md-6 col-lg-9 text-end">
<span
className="text-tiny text-muted p-1 border-0 bg-none lead mx-3 cursor-pointer"
disabled={isRefetching}
onClick={() => refetchFn && refetchFn()}
>
Refresh{" "}
<i
className={`bx bx-refresh ms-1 ${
isRefetching ? "bx-spin" : ""
}`}
></i>
</span>
<button
type="button"
title="Add New Tenant"
className="p-1 bg-primary rounded-circle cursor-pointer"
onClick={handleNewTenant}
>
<i className="bx bx-plus fs-4 text-white"></i>
</button>
<button
type="button"
title="Add New Tenant"
className="p-1 bg-primary rounded-circle cursor-pointer"
onClick={handleNewTenant}
>
<i className="bx bx-plus fs-4 text-white"></i>
</button>
</div>
</div>
</div>
</div>
)}
)}
{/* Tenant List or Access Denied */}
{isSuperTenant ? (
<TenantsList
filters={filters}
searchText={debouncedSearch}
setIsRefetching={setIsRefetching}
setRefetchFn={setRefetchFn}
/>
) : !isSelfTenant ? (
<div className="card text-center my-4 p-2">
<i className="fa-solid fa-triangle-exclamation fs-5"></i>
<p>
Access Denied: You don't have permission to perform this action!
</p>
</div>
) : null}
{/* Tenant List or Access Denied */}
{isSuperTenant ? (
<TenantsList
filters={filters}
searchText={debouncedSearch}
setIsRefetching={setIsRefetching}
setRefetchFn={setRefetchFn}
/>
) : !isSelfTenant ? (
<div className="text-center my-4 p-2">
<i className="fa-solid fa-triangle-exclamation fs-5"></i>
<p>
Access Denied: You don't have permission to perform this action!
</p>
</div>
) : null}
</div>
</div>
</TenantContext.Provider>
);

View File

@ -176,10 +176,12 @@ const EmployeeList = () => {
useEffect(() => {
if (!loading && Array.isArray(employees)) {
const sorted = [...employees].sort((a, b) => {
const nameA = `${a.firstName || ""}${a.middleName || ""}${a.lastName || ""
}`.toLowerCase();
const nameB = `${b.firstName || ""}${b.middleName || ""}${b.lastName || ""
}`.toLowerCase();
const nameA = `${a.firstName || ""}${a.middleName || ""}${
a.lastName || ""
}`.toLowerCase();
const nameB = `${b.firstName || ""}${b.middleName || ""}${
b.lastName || ""
}`.toLowerCase();
return nameA?.localeCompare(nameB);
});
@ -266,8 +268,9 @@ const EmployeeList = () => {
? "Suspend Employee"
: "Reactivate Employee"
}
message={`Are you sure you want to ${selectedEmpFordelete?.isActive ? "suspend" : "reactivate"
} this employee?`}
message={`Are you sure you want to ${
selectedEmpFordelete?.isActive ? "suspend" : "reactivate"
} this employee?`}
onSubmit={(id) =>
suspendEmployee({
employeeId: id,
@ -291,11 +294,11 @@ const EmployeeList = () => {
{ViewTeamMember ? (
// <div className="row">
<div className="card p-1">
<div className="card-datatable table-responsive pt-2">
<div className="card-datatable table-responsive pt-5 mx-5 py-10">
<div
id="DataTables_Table_0_wrapper"
className="dataTables_wrapper dt-bootstrap5 no-footer"
style={{ width: "98%" }}
style={{ width: "100%" }}
>
<div className="d-flex flex-wrap align-items-center justify-content-between gap-3 mb-3">
{/* Switches: All Employees + Inactive */}
@ -315,7 +318,7 @@ const EmployeeList = () => {
className="form-check-label ms-0"
htmlFor="allEmployeesCheckbox"
>
All Employees
Show All Employees
</label>
</div>
)}
@ -351,7 +354,7 @@ const EmployeeList = () => {
value={searchText}
onChange={handleSearch}
className="form-control form-control-sm"
placeholder="Search User"
placeholder="Search Employee"
aria-controls="DataTables_Table_0"
/>
</label>
@ -499,8 +502,9 @@ const EmployeeList = () => {
Status
</th>
<th
className={`sorting_disabled ${!Manage_Employee && "d-none"
}`}
className={`sorting_disabled ${
!Manage_Employee && "d-none"
}`}
rowSpan="1"
colSpan="1"
style={{ width: "50px" }}
@ -520,9 +524,9 @@ const EmployeeList = () => {
)}
{/* Conditional messages for no data or no search results */}
{!loading &&
displayData?.length === 0 &&
searchText &&
!showAllEmployees ? (
displayData?.length === 0 &&
searchText &&
!showAllEmployees ? (
<tr>
<td colSpan={8}>
<small className="muted">
@ -532,8 +536,8 @@ const EmployeeList = () => {
</tr>
) : null}
{!loading &&
displayData?.length === 0 &&
(!searchText || showAllEmployees) ? (
displayData?.length === 0 &&
(!searchText || showAllEmployees) ? (
<tr>
<td
colSpan={8}
@ -578,7 +582,7 @@ const EmployeeList = () => {
</span>
) : (
<span className="text-truncate text-italic">
NA
-
</span>
)}
</td>
@ -627,7 +631,9 @@ const EmployeeList = () => {
<div className="dropdown-menu dropdown-menu-end">
{/* View always visible */}
<button
onClick={() => navigate(`/employee/${item.id}`)}
onClick={() =>
navigate(`/employee/${item.id}`)
}
className="dropdown-item py-1"
>
<i className="bx bx-detail bx-sm"></i> View
@ -638,9 +644,12 @@ const EmployeeList = () => {
<>
<button
className="dropdown-item py-1"
onClick={() => handleEmployeeModel(item.id)}
onClick={() =>
handleEmployeeModel(item.id)
}
>
<i className="bx bx-edit bx-sm"></i> Edit
<i className="bx bx-edit bx-sm"></i>{" "}
Edit
</button>
{/* Suspend only when active */}
@ -649,7 +658,8 @@ 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 bx-sm"></i>{" "}
Suspend
</button>
)}
@ -658,11 +668,13 @@ const EmployeeList = () => {
type="button"
data-bs-toggle="modal"
data-bs-target="#managerole-modal"
onClick={() => setEmpForManageRole(item.id)}
onClick={() =>
setEmpForManageRole(item.id)
}
>
<i className="bx bx-cog bx-sm"></i> Manage Role
<i className="bx bx-cog bx-sm"></i>{" "}
Manage Role
</button>
</>
)}
@ -672,7 +684,8 @@ 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 bx-sm me-1"></i>{" "}
Re-activate
</button>
)}
</div>
@ -691,8 +704,9 @@ const EmployeeList = () => {
<nav aria-label="Page">
<ul className="pagination pagination-sm justify-content-end py-1">
<li
className={`page-item ${currentPage === 1 ? "disabled" : ""
}`}
className={`page-item ${
currentPage === 1 ? "disabled" : ""
}`}
>
<button
className="page-link btn-xs"
@ -705,8 +719,9 @@ const EmployeeList = () => {
{[...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"
@ -718,8 +733,9 @@ const EmployeeList = () => {
))}
<li
className={`page-item ${currentPage === totalPages ? "disabled" : ""
}`}
className={`page-item ${
currentPage === totalPages ? "disabled" : ""
}`}
>
<button
className="page-link"

View File

@ -5,7 +5,10 @@ import Breadcrumb from "../../components/common/Breadcrumb";
import MasterModal from "../../components/master/MasterModal";
import ConfirmModal from "../../components/common/ConfirmModal";
import MasterTable from "./MasterTable";
import useMaster, { useDeleteMasterItem, useMasterMenu } from "../../hooks/masterHook/useMaster";
import useMaster, {
useDeleteMasterItem,
useMasterMenu,
} from "../../hooks/masterHook/useMaster";
import { changeMaster } from "../../slices/localVariablesSlice";
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
import { MANAGE_MASTER } from "../../utils/constants";
@ -14,11 +17,22 @@ import GlobalModel from "../../components/common/GlobalModel";
const MasterPage = () => {
const dispatch = useDispatch();
const queryClient = useQueryClient();
const selectedMaster = useSelector((store) => store.localVariables.selectedMaster);
const selectedMaster = useSelector(
(store) => store.localVariables.selectedMaster
);
const hasMasterPermission = useHasUserPermission(MANAGE_MASTER);
const { data: menuData, isLoading: menuLoading, isError: menuErrorFlag, error: menuError } = useMasterMenu();
const { data: masterData = [], loading, isError: isMasterError } = useMaster();
const {
data: menuData,
isLoading: menuLoading,
isError: menuErrorFlag,
error: menuError,
} = useMasterMenu();
const {
data: masterData = [],
loading,
isError: isMasterError,
} = useMaster();
const { mutate: DeleteMaster, isPending: isDeleting } = useDeleteMasterItem();
const [modalConfig, setModalConfig] = useState(null);
@ -26,7 +40,8 @@ const MasterPage = () => {
const [searchTerm, setSearchTerm] = useState("");
const displayData = useMemo(() => {
const dataSource = queryClient.getQueryData(["masterData", selectedMaster]) || masterData;
const dataSource =
queryClient.getQueryData(["masterData", selectedMaster]) || masterData;
if (!searchTerm) return dataSource;
return dataSource.filter((item) =>
Object.values(item).some((val) =>
@ -37,7 +52,10 @@ const MasterPage = () => {
const columns = useMemo(() => {
if (!displayData.length) return [];
return Object.keys(displayData[0]).map((key) => ({ key, label: key.toUpperCase() }));
return Object.keys(displayData[0]).map((key) => ({
key,
label: key.toUpperCase(),
}));
}, [displayData]);
const handleModalData = (type, item = null, masterType = selectedMaster) => {
@ -47,18 +65,24 @@ const MasterPage = () => {
const handleDeleteSubmit = () => {
if (!deleteData) return;
DeleteMaster({ masterType: deleteData.masterType, item: deleteData.item }, {
onSuccess: () => setDeleteData(null),
});
DeleteMaster(
{ masterType: deleteData.masterType, item: deleteData.item },
{
onSuccess: () => setDeleteData(null),
}
);
};
if (menuErrorFlag || isMasterError)
return (
<div className="d-flex flex-column align-items-center justify-content-center py-5">
<h4 className="mb-3">
<i className="fa-solid fa-triangle-exclamation fs-5" /> Oops, an error occurred
<i className="fa-solid fa-triangle-exclamation fs-5" /> Oops, an error
occurred
</h4>
<p className="text-muted">{menuError?.message || "Error fetching master data"}</p>
<p className="text-muted">
{menuError?.message || "Error fetching master data"}
</p>
</div>
);
@ -66,11 +90,20 @@ const MasterPage = () => {
<>
{modalConfig && (
<GlobalModel
size={["Application Role", "Edit-Application Role"].includes(modalConfig.masterType) ? "lg" : "md"}
size={
["Application Role", "Edit-Application Role"].includes(
modalConfig.masterType
)
? "lg"
: "md"
}
isOpen={!!modalConfig}
closeModal={() => setModalConfig(null)}
>
<MasterModal modaldata={modalConfig} closeModal={() => setModalConfig(null)} />
<MasterModal
modaldata={modalConfig}
closeModal={() => setModalConfig(null)}
/>
</GlobalModel>
)}
@ -85,40 +118,58 @@ const MasterPage = () => {
/>
<div className="container-fluid">
<Breadcrumb data={[{ label: "Home", link: "/dashboard" }, { label: "Masters" }]} />
<Breadcrumb
data={[{ label: "Home", link: "/dashboard" }, { label: "Masters" }]}
/>
<div className="row">
<div className="card">
<div className="card-datatable table-responsive py-4">
<div
className="card-datatable table-responsive py-10 mx-5 "
style={{ overflow: "hidden" }}
>
<div className="row mb-2">
<div className="col-md-3 col-sm-6">
<select
className="form-select py-1 px-2"
style={{ fontSize: "0.875rem", height: "32px", width: "190px" }}
style={{
fontSize: "0.875rem",
height: "32px",
width: "190px",
}}
value={selectedMaster}
onChange={(e) => dispatch(changeMaster(e.target.value))}
>
{menuLoading ? (
<option value="">Loading...</option>
) : (
menuData?.map((item) => <option key={item.id} value={item.name}>{item.name}</option>)
menuData?.map((item) => (
<option key={item.id} value={item.name}>
{item.name}
</option>
))
)}
</select>
</div>
<div className="col-md-9 col-sm-6 d-flex justify-content-end align-items-center gap-2">
<div className="w-25"><input
type="search"
className="form-control form-control-sm"
placeholder="Search"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/></div>
<div className="w-25">
<input
type="search"
className="form-control form-control-sm"
placeholder="Search"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
</div>
{hasMasterPermission && (
<button
className="btn btn-sm btn-primary"
onClick={() => handleModalData(selectedMaster, null, selectedMaster)}
onClick={() =>
handleModalData(selectedMaster, null, selectedMaster)
}
>
<i className="bx bx-plus-circle me-2"></i>Add {selectedMaster}
<i className="bx bx-plus-circle me-2"></i>Add{" "}
{selectedMaster}
</button>
)}
</div>

View File

@ -179,8 +179,9 @@ const MasterTable = ({ data, columns, loading, handleModalData }) => {
aria-label="Delete"
type="button"
className="btn p-0 dropdown-toggle hide-arrow"
onClick={() => handleModalData("delete", item, selectedMaster)}
onClick={() =>
handleModalData("delete", item, selectedMaster)
}
>
<i className="bx bx-trash me-1 text-danger"></i>
</button>