fixed PmsGrid header

This commit is contained in:
pramod.mahajan 2025-10-31 09:57:28 +05:30
parent 7329319417
commit 73f437e911
5 changed files with 79 additions and 45 deletions

View File

@ -480,6 +480,24 @@ th {
border-style: solid;
border-width: 0;
}
.vs-th {
position: relative;
border: none;
background-color: #f8f9fa;
padding: 0.75rem 1rem;
vertical-align: middle;
}
.vs-th::after {
content: "";
position: absolute;
left: 0;
top: 6px;
bottom: 6px;
width: 1px;
background-color: #dee2e6;
}
label {
display: inline-block;

View File

@ -26,14 +26,18 @@ import { useNavigate } from "react-router-dom";
const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
const [deletingId, setDeletingId] = useState(null);
const [IsDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const { setViewExpense, setManageExpenseModal, filterData, removeFilterChip } = useExpenseContext();
const {
setViewExpense,
setManageExpenseModal,
filterData,
removeFilterChip,
} = useExpenseContext();
const IsExpenseEditable = useHasUserPermission();
const IsExpesneApprpve = useHasUserPermission(APPROVE_EXPENSE);
const [currentPage, setCurrentPage] = useState(1);
const debouncedSearch = useDebounce(searchText, 500);
const navigate = useNavigate();
const { mutate: DeleteExpense, isPending } = useDeleteExpense();
const { data, isLoading, isError, isInitialLoading, error } = useExpenseList(
ITEMS_PER_PAGE,
@ -80,8 +84,9 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
displayField = "Status";
break;
case "submittedBy":
key = `${item?.createdBy?.firstName ?? ""} ${item.createdBy?.lastName ?? ""
}`.trim();
key = `${item?.createdBy?.firstName ?? ""} ${
item.createdBy?.lastName ?? ""
}`.trim();
displayField = "Submitted By";
break;
case "project":
@ -139,11 +144,14 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
label: "Submitted By",
align: "text-start",
getValue: (e) =>
`${e.createdBy?.firstName ?? ""} ${e.createdBy?.lastName ?? ""
}`.trim() || "N/A",
`${e.createdBy?.firstName ?? ""} ${
e.createdBy?.lastName ?? ""
}`.trim() || "N/A",
customRender: (e) => (
<div className="d-flex align-items-center cursor-pointer"
onClick={() => navigate(`/employee/${e.createdBy?.id}`)}>
<div
className="d-flex align-items-center cursor-pointer"
onClick={() => navigate(`/employee/${e.createdBy?.id}`)}
>
<Avatar
size="xs"
classAvatar="m-0"
@ -151,8 +159,9 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
lastName={e.createdBy?.lastName}
/>
<span className="text-truncate">
{`${e.createdBy?.firstName ?? ""} ${e.createdBy?.lastName ?? ""
}`.trim() || "N/A"}
{`${e.createdBy?.firstName ?? ""} ${
e.createdBy?.lastName ?? ""
}`.trim() || "N/A"}
</span>
</div>
),
@ -176,10 +185,9 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
align: "text-center",
getValue: (e) => (
<span
className={`badge bg-label-${getColorNameFromHex(e?.status?.color) || "secondary"
}`}
className={`badge bg-label-${getColorNameFromHex(e?.status?.color) || "secondary"
}`}
className={`badge bg-label-${
getColorNameFromHex(e?.status?.color) || "secondary"
}`}
>
{e.status?.name || "Unknown"}
</span>

View File

@ -107,8 +107,8 @@ const router = createBrowserRouter(
{ path: "/tenant/self", element: <SelfTenantDetails /> },
{ path: "/organizations", element: <OrganizationPage /> },
{ path: "/help/support", element: <Support /> },
{ path: "/help/docs", element: <Documentation /> },
{ path: "/help/connect", element: <DemoBOQGrid /> },
{ path: "/help/docs", element: <DemoBOQGrid /> },
],
},
],

View File

@ -190,7 +190,6 @@ const boqColumns = [
*/
export default function DemoBOQGrid() {
useEffect(() => {
// 🔥 Initialize Bootstrap popovers after first render
initPopover();
}, []);
const wrapperRef = useRef()
@ -204,15 +203,7 @@ useEffect(() => {
}, []);
return (
<div className="container-fluid py-3">
<button
type="button"
className="btn btn-outline-primary"
data-bs-toggle="popover"
data-bs-placement="right"
data-bs-content="This is a popover via CDN!"
>
Click me
</button>
<div className="card p-3">
<PmsGrid

View File

@ -135,16 +135,20 @@ export default function PmsGrid({
return (
<div className="pms-grid">
<div className="d-flex justify-content-between mb-2">
<div className="d-flex gap-2 align-items-center">
{features.search && (
<div className="row mb-2">
<div className="col-8">
<div className="d-flex flex-row gap-2 gap-2 ">
<div>
{features.search && (
<input
type="search"
className="form-control form-control-sm"
placeholder="Search..."
value={search}
onChange={(e) => setSearch(e.target.value)}
/>
)}
</div>
{features.export && (
<button
className="btn btn-sm btn-outline-secondary"
@ -159,8 +163,9 @@ export default function PmsGrid({
</button>
)}
</div>
<div className="d-flex gap-2">
</div>
<div className="col-4 ">
<div className="d-flex justify-content-end gap-2">
{features.columnVisibility && (
<ColumnVisibilityPanel
columns={colState}
@ -186,15 +191,16 @@ export default function PmsGrid({
</select>
)}
</div>
</div>
</div>
<div
ref={wrapperRef}
className="grid-wrapper"
className="grid-wrapper text-nowrap"
style={{ maxHeight: features.maxHeight || "60vh" }}
>
<table className="table table-sm table-bordered mb-0">
<table className="table table-sm mb-0">
<thead
className="table-light"
className="bg-light-secondary"
style={{ position: "sticky", top: 0, zIndex: 3 }}
>
<tr>
@ -202,7 +208,7 @@ export default function PmsGrid({
<th style={{ width: 32 }} className="text-center">
<input
type="checkbox"
className="form-check-input"
className="form-check-input mx-3"
checked={
currentRows.length > 0 &&
currentRows.every((r) => selected.has(r[rowKey]))
@ -232,19 +238,25 @@ export default function PmsGrid({
onDragStart={(e) => onDragStart(e, col.key)}
onDragOver={(e) => e.preventDefault()}
onDrop={(e) => onDrop(e, col.key)}
className={`pms-col-header ${col.pinned ? "pinned" : ""}`}
className={`pms-col-header vs-th ${
col.pinned ? "pinned" : ""
}`}
style={style}
>
<div className="d-flex align-items-center justify-content-between">
<div className="d-flex align-items-center justify-content-between px-1">
<div
onClick={() => col.sortable && changeSort(col.key)}
style={{ cursor: col.sortable ? "pointer" : "default" }}
>
<strong>{col.title}</strong>
{sortBy.key === col.key && (
<small className="ms-2 text-muted">
[{sortBy.dir}]
</small>
<i
className={`bx bx-sm ${
sortBy.dir === "asc"
? "bxs-chevron-up"
: "bxs-chevron-down"
}`}
></i>
)}
</div>
<div className="d-flex align-items-center gap-1">
@ -270,7 +282,7 @@ export default function PmsGrid({
})}
{features.actions && (
<th
className="text-center sticky-action-column"
className="text-center sticky-action-column vs-th bg-white"
style={{ position: "sticky", right: 0, zIndex: 5 }}
>
Actions
@ -357,12 +369,12 @@ export default function PmsGrid({
function renderRow(row) {
return (
<React.Fragment key={row[rowKey]}>
<tr>
<tr className={`${selected.has(row[rowKey]) ? "bg-light" : ""}`}>
{features.selection && (
<td className="text-center p-2">
<input
type="checkbox"
className="form-check-input"
className="form-check-input"
checked={selected.has(row[rowKey])}
onChange={() => toggleSelect(row[rowKey])}
/>
@ -379,13 +391,17 @@ export default function PmsGrid({
if (col.pinned === "right")
style.right = `${getRightOffset(colState, col.key)}px`;
return (
<td key={col.key} style={style}>
<td
key={col.key}
style={style}
className={col.pinned ? "bg-white" : ""}
>
{col.render ? col.render(row) : row[col.key] ?? ""}
</td>
);
})}
{features.actions && (
<td className="text-center sticky-action-column">
<td className="text-center sticky-action-column bg-white">
{features.actions(row, toggleExpand)}
</td>
)}
@ -461,3 +477,4 @@ function ColumnVisibilityPanel({ columns, onToggle }) {
</div>
);
}