From 8aaccf3f367cfe72041d543a7eae394b4d0e1f94 Mon Sep 17 00:00:00 2001 From: marshalyordanos Date: Mon, 20 Jul 2026 22:10:48 +0300 Subject: [PATCH] Enhance BookingRequestsPage layout and styling --- .../pages/bookings/BookingRequestsPage.tsx | 67 ++++++++------- .../pages/bookings/booking-requests-table.css | 84 +++++++++++++++++++ 2 files changed, 122 insertions(+), 29 deletions(-) create mode 100644 apps/edr-freight-web/backoffice/src/pages/bookings/booking-requests-table.css diff --git a/apps/edr-freight-web/backoffice/src/pages/bookings/BookingRequestsPage.tsx b/apps/edr-freight-web/backoffice/src/pages/bookings/BookingRequestsPage.tsx index 8ca532819..1345d2855 100644 --- a/apps/edr-freight-web/backoffice/src/pages/bookings/BookingRequestsPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/bookings/BookingRequestsPage.tsx @@ -58,6 +58,8 @@ import { type ColumnDef, } from "@edr/ui-common"; +import "./booking-requests-table.css"; + /** Booking kind: one-time vs general-contract bookings. Now a filter, not a tab. */ type BookingKind = "ONE_TIME" | "GENERAL_CONTRACT"; @@ -282,6 +284,8 @@ export default function BookingRequestsPage() { const columns: ColumnDef[] = [ { id: "booking", + size: 60, + minSize: 40, header: () => Booking, cell: ({ row }) => { const b = row.original; @@ -303,6 +307,8 @@ export default function BookingRequestsPage() { }, { id: "contract", + size: 60, + minSize: 40, header: () => Contract, cell: ({ row }) => { const ref = row.original.contractReference; @@ -329,6 +335,8 @@ export default function BookingRequestsPage() { }, { id: "bookingKind", + size: 60, + minSize: 40, header: () => Type, cell: ({ row }) => { const isGeneral = row.original.bookingKind === "GENERAL_CONTRACT"; @@ -346,6 +354,8 @@ export default function BookingRequestsPage() { }, { id: "route", + size: 60, + minSize: 40, header: () => Route, cell: ({ row }) => { const b = row.original; @@ -376,8 +386,8 @@ export default function BookingRequestsPage() { }, { id: "status", - size: 200, - minSize: 180, + size: 60, + minSize: 40, header: () => Status, cell: ({ row }) => (
@@ -388,13 +398,11 @@ export default function BookingRequestsPage() { />
), - meta: { - headerClassName: "min-w-[11rem]", - cellClassName: "min-w-[11rem]", - }, }, { id: "scheduled", + size: 60, + minSize: 40, header: () => Scheduled, cell: ({ row }) => ( @@ -405,6 +413,8 @@ export default function BookingRequestsPage() { }, { id: "priority", + size: 60, + minSize: 40, header: () => Priority, cell: ({ row }) => ( @@ -412,7 +422,8 @@ export default function BookingRequestsPage() { }, { id: "actions", - size: 140, + size: 60, + minSize: 40, cell: ({ row }) => ( ) : ( - - - + )} diff --git a/apps/edr-freight-web/backoffice/src/pages/bookings/booking-requests-table.css b/apps/edr-freight-web/backoffice/src/pages/bookings/booking-requests-table.css new file mode 100644 index 000000000..d5bb8df5d --- /dev/null +++ b/apps/edr-freight-web/backoffice/src/pages/bookings/booking-requests-table.css @@ -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 . */ +.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; +}