mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 05:18:11 +00:00
Enhance BookingRequestsPage layout and styling
This commit is contained in:
@@ -58,6 +58,8 @@ import {
|
|||||||
type ColumnDef,
|
type ColumnDef,
|
||||||
} from "@edr/ui-common";
|
} from "@edr/ui-common";
|
||||||
|
|
||||||
|
import "./booking-requests-table.css";
|
||||||
|
|
||||||
/** Booking kind: one-time vs general-contract bookings. Now a filter, not a tab. */
|
/** Booking kind: one-time vs general-contract bookings. Now a filter, not a tab. */
|
||||||
type BookingKind = "ONE_TIME" | "GENERAL_CONTRACT";
|
type BookingKind = "ONE_TIME" | "GENERAL_CONTRACT";
|
||||||
|
|
||||||
@@ -282,6 +284,8 @@ export default function BookingRequestsPage() {
|
|||||||
const columns: ColumnDef<BookingListRow>[] = [
|
const columns: ColumnDef<BookingListRow>[] = [
|
||||||
{
|
{
|
||||||
id: "booking",
|
id: "booking",
|
||||||
|
size: 60,
|
||||||
|
minSize: 40,
|
||||||
header: () => <span className={bookingTable.headerCell}>Booking</span>,
|
header: () => <span className={bookingTable.headerCell}>Booking</span>,
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const b = row.original;
|
const b = row.original;
|
||||||
@@ -303,6 +307,8 @@ export default function BookingRequestsPage() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "contract",
|
id: "contract",
|
||||||
|
size: 60,
|
||||||
|
minSize: 40,
|
||||||
header: () => <span className={bookingTable.headerCell}>Contract</span>,
|
header: () => <span className={bookingTable.headerCell}>Contract</span>,
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const ref = row.original.contractReference;
|
const ref = row.original.contractReference;
|
||||||
@@ -329,6 +335,8 @@ export default function BookingRequestsPage() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "bookingKind",
|
id: "bookingKind",
|
||||||
|
size: 60,
|
||||||
|
minSize: 40,
|
||||||
header: () => <span className={bookingTable.headerCell}>Type</span>,
|
header: () => <span className={bookingTable.headerCell}>Type</span>,
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const isGeneral = row.original.bookingKind === "GENERAL_CONTRACT";
|
const isGeneral = row.original.bookingKind === "GENERAL_CONTRACT";
|
||||||
@@ -346,6 +354,8 @@ export default function BookingRequestsPage() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "route",
|
id: "route",
|
||||||
|
size: 60,
|
||||||
|
minSize: 40,
|
||||||
header: () => <span className={bookingTable.headerCell}>Route</span>,
|
header: () => <span className={bookingTable.headerCell}>Route</span>,
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const b = row.original;
|
const b = row.original;
|
||||||
@@ -376,8 +386,8 @@ export default function BookingRequestsPage() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "status",
|
id: "status",
|
||||||
size: 200,
|
size: 60,
|
||||||
minSize: 180,
|
minSize: 40,
|
||||||
header: () => <span className={bookingTable.headerCell}>Status</span>,
|
header: () => <span className={bookingTable.headerCell}>Status</span>,
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<div className="py-1">
|
<div className="py-1">
|
||||||
@@ -388,13 +398,11 @@ export default function BookingRequestsPage() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
meta: {
|
|
||||||
headerClassName: "min-w-[11rem]",
|
|
||||||
cellClassName: "min-w-[11rem]",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "scheduled",
|
id: "scheduled",
|
||||||
|
size: 60,
|
||||||
|
minSize: 40,
|
||||||
header: () => <span className={bookingTable.headerCell}>Scheduled</span>,
|
header: () => <span className={bookingTable.headerCell}>Scheduled</span>,
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<span className="inline-flex items-center gap-1.5 text-sm text-muted-foreground">
|
<span className="inline-flex items-center gap-1.5 text-sm text-muted-foreground">
|
||||||
@@ -405,6 +413,8 @@ export default function BookingRequestsPage() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "priority",
|
id: "priority",
|
||||||
|
size: 60,
|
||||||
|
minSize: 40,
|
||||||
header: () => <span className={bookingTable.headerCell}>Priority</span>,
|
header: () => <span className={bookingTable.headerCell}>Priority</span>,
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<BookingPriorityBadge score={row.original.priorityScore} />
|
<BookingPriorityBadge score={row.original.priorityScore} />
|
||||||
@@ -412,7 +422,8 @@ export default function BookingRequestsPage() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "actions",
|
id: "actions",
|
||||||
size: 140,
|
size: 60,
|
||||||
|
minSize: 40,
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<BookingActionsMenu
|
<BookingActionsMenu
|
||||||
row={row.original}
|
row={row.original}
|
||||||
@@ -702,28 +713,26 @@ export default function BookingRequestsPage() {
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
<Box style={{ overflowX: "auto" }} w="100%">
|
<DataTable
|
||||||
<DataTable
|
columns={columns}
|
||||||
columns={columns}
|
data={rows}
|
||||||
data={rows}
|
status={isLoading ? "loading" : isError ? "error" : "success"}
|
||||||
status={isLoading ? "loading" : isError ? "error" : "success"}
|
onRowClick={handleRowClick}
|
||||||
onRowClick={handleRowClick}
|
pagination={{
|
||||||
pagination={{
|
pageIndex: pagination.pageIndex,
|
||||||
pageIndex: pagination.pageIndex,
|
pageSize: pagination.pageSize,
|
||||||
pageSize: pagination.pageSize,
|
pageCount,
|
||||||
pageCount,
|
totalCount: total,
|
||||||
totalCount: total,
|
}}
|
||||||
}}
|
tableOptions={{
|
||||||
tableOptions={{
|
state: { pagination },
|
||||||
state: { pagination },
|
onPaginationChange: setPagination,
|
||||||
onPaginationChange: setPagination,
|
manualPagination: true,
|
||||||
manualPagination: true,
|
pageCount,
|
||||||
pageCount,
|
}}
|
||||||
}}
|
containerClassName="edr-booking-requests-table border-0 shadow-none bg-transparent"
|
||||||
containerClassName="border-0 shadow-none bg-transparent"
|
footer={DataTableFooter}
|
||||||
footer={DataTableFooter}
|
/>
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Scoped to .edr-booking-requests-table — the DataTable container div on the
|
||||||
|
* backoffice booking-requests list only; no other DataTable is affected.
|
||||||
|
* Mirrors the portal's /bookings table (bookings-table.css): horizontal
|
||||||
|
* scroll on the container, a sticky header row, and a sticky/shadowed
|
||||||
|
* action column — with a compact 40–60px column width band (content
|
||||||
|
* beyond that is clipped with an ellipsis) instead of the portal's
|
||||||
|
* content-sized columns.
|
||||||
|
*/
|
||||||
|
.edr-booking-requests-table {
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* width: max-content — the table is exactly as wide as its columns need,
|
||||||
|
* never squeezed to fit the viewport; the container scrolls instead.
|
||||||
|
* min-width: 100% keeps it filling the card when content is narrow.
|
||||||
|
*/
|
||||||
|
.edr-booking-requests-table table {
|
||||||
|
table-layout: auto;
|
||||||
|
width: max-content;
|
||||||
|
min-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compact column band: 40px floor, 60px ceiling, ellipsis past that. */
|
||||||
|
.edr-booking-requests-table th,
|
||||||
|
.edr-booking-requests-table td:not([colspan]) {
|
||||||
|
min-width: 40px;
|
||||||
|
max-width: 60px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Full-width rows (loading skeleton / error / empty state) span every
|
||||||
|
* column via colspan — leave their sizing and wrapping alone.
|
||||||
|
*/
|
||||||
|
.edr-booking-requests-table td[colspan] {
|
||||||
|
max-width: none;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sticky header row. */
|
||||||
|
.edr-booking-requests-table thead th {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fixed, sticky action column. Overrides the inline width DataTable stamps
|
||||||
|
* from tanstack's column size (`size: 140` on the actions column) — hence
|
||||||
|
* !important. `:not([colspan])` keeps the full-width error/empty rows out.
|
||||||
|
*/
|
||||||
|
.edr-booking-requests-table th:last-child,
|
||||||
|
.edr-booking-requests-table td:last-child:not([colspan]) {
|
||||||
|
width: 60px !important;
|
||||||
|
min-width: 60px;
|
||||||
|
max-width: 60px;
|
||||||
|
position: sticky;
|
||||||
|
right: 0;
|
||||||
|
box-shadow: -12px 0 16px -6px rgba(16, 32, 47, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sticky cells sit above the scrolling ones, so they need their own opaque
|
||||||
|
* background or the columns underneath show through.
|
||||||
|
*/
|
||||||
|
.edr-booking-requests-table td:last-child:not([colspan]) {
|
||||||
|
background: #f5f8fb;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Row hover uses the tailwind `hover:bg-accent` class on the <tr>. */
|
||||||
|
.edr-booking-requests-table tbody tr:hover td:last-child:not([colspan]) {
|
||||||
|
background: var(--accent, #f4fbf8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header cell is sticky on both axes — it must outrank the body's sticky column. */
|
||||||
|
.edr-booking-requests-table th:last-child {
|
||||||
|
background: #f4f7fa;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user