mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-08 06:35:42 +00:00
Fix CSS formatting for bookings table class to ensure proper styling and layout.
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
|||||||
MultiSelect,
|
MultiSelect,
|
||||||
Select,
|
Select,
|
||||||
Stack,
|
Stack,
|
||||||
|
Tabs,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
@@ -32,6 +33,7 @@ import { useNavigate } from "react-router-dom";
|
|||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
import { BookingActionsMenu } from "@/components/bookings/BookingActionsMenu";
|
import { BookingActionsMenu } from "@/components/bookings/BookingActionsMenu";
|
||||||
|
import { BookingApprovalProgressCell } from "@/components/bookings/BookingApprovalProgressCell";
|
||||||
import { BookingPriorityBadge } from "@/components/bookings/BookingPriorityBadge";
|
import { BookingPriorityBadge } from "@/components/bookings/BookingPriorityBadge";
|
||||||
import { BookingStatusBadge } from "@/components/bookings/BookingStatusBadge";
|
import { BookingStatusBadge } from "@/components/bookings/BookingStatusBadge";
|
||||||
// BookingStatusTabs / Operations* queues removed — replaced by booking-kind tabs.
|
// BookingStatusTabs / Operations* queues removed — replaced by booking-kind tabs.
|
||||||
@@ -58,12 +60,10 @@ import {
|
|||||||
type ColumnDef,
|
type ColumnDef,
|
||||||
} from "@edr/ui-common";
|
} from "@edr/ui-common";
|
||||||
|
|
||||||
import "./booking-requests-table.css";
|
/** The two booking-kind tabs: one-time vs general-contract bookings. */
|
||||||
|
type BookingKindTab = "ONE_TIME" | "GENERAL_CONTRACT";
|
||||||
|
|
||||||
/** Booking kind: one-time vs general-contract bookings. Now a filter, not a tab. */
|
const BOOKING_KIND_TABS: { value: BookingKindTab; label: string }[] = [
|
||||||
type BookingKind = "ONE_TIME" | "GENERAL_CONTRACT";
|
|
||||||
|
|
||||||
const BOOKING_KIND_OPTIONS: { value: BookingKind; label: string }[] = [
|
|
||||||
{ value: "ONE_TIME", label: "One-time booking" },
|
{ value: "ONE_TIME", label: "One-time booking" },
|
||||||
{ value: "GENERAL_CONTRACT", label: "General booking" },
|
{ value: "GENERAL_CONTRACT", label: "General booking" },
|
||||||
];
|
];
|
||||||
@@ -128,9 +128,9 @@ export default function BookingRequestsPage() {
|
|||||||
const { pagination, setPagination } = usePagination({ pageSize: 10 });
|
const { pagination, setPagination } = usePagination({ pageSize: 10 });
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
const [debouncedQuery] = useDebouncedValue(query, 300);
|
const [debouncedQuery] = useDebouncedValue(query, 300);
|
||||||
// Booking kind is a filter now — one list holds both kinds (null = "all").
|
// Booking-kind tabs (one-time vs general contract) replace the old status tabs.
|
||||||
const [kindFilter, setKindFilter] = useState<BookingKind | null>(null);
|
const [kindTab, setKindTab] = useState<BookingKindTab>("ONE_TIME");
|
||||||
// Filter controls (empty/null = "all").
|
// Per-tab filter controls (empty/null = "all").
|
||||||
const [statusFilter, setStatusFilter] = useState<string[]>([]);
|
const [statusFilter, setStatusFilter] = useState<string[]>([]);
|
||||||
const [directionFilter, setDirectionFilter] = useState<string | null>(null);
|
const [directionFilter, setDirectionFilter] = useState<string | null>(null);
|
||||||
const [freightTypeFilter, setFreightTypeFilter] = useState<string | null>(null);
|
const [freightTypeFilter, setFreightTypeFilter] = useState<string | null>(null);
|
||||||
@@ -158,9 +158,9 @@ export default function BookingRequestsPage() {
|
|||||||
pageSize: pagination.pageSize,
|
pageSize: pagination.pageSize,
|
||||||
sortBy: "createdAt",
|
sortBy: "createdAt",
|
||||||
sortOrder: "DESC",
|
sortOrder: "DESC",
|
||||||
// React Query cache key per kind selection ("ALL" when unfiltered).
|
// React Query cache key per kind tab.
|
||||||
tab: kindFilter ?? "ALL",
|
tab: kindTab,
|
||||||
...(kindFilter ? { bookingType: kindFilter } : {}),
|
bookingType: kindTab,
|
||||||
// Server-side free-text search (booking ref, customer, contract ref).
|
// Server-side free-text search (booking ref, customer, contract ref).
|
||||||
...(debouncedQuery.trim() ? { search: debouncedQuery.trim() } : {}),
|
...(debouncedQuery.trim() ? { search: debouncedQuery.trim() } : {}),
|
||||||
...(statusFilter.length ? { statuses: statusFilter.join(",") } : {}),
|
...(statusFilter.length ? { statuses: statusFilter.join(",") } : {}),
|
||||||
@@ -182,7 +182,7 @@ export default function BookingRequestsPage() {
|
|||||||
}, [
|
}, [
|
||||||
pagination.pageIndex,
|
pagination.pageIndex,
|
||||||
pagination.pageSize,
|
pagination.pageSize,
|
||||||
kindFilter,
|
kindTab,
|
||||||
debouncedQuery,
|
debouncedQuery,
|
||||||
statusFilter,
|
statusFilter,
|
||||||
directionFilter,
|
directionFilter,
|
||||||
@@ -226,7 +226,6 @@ export default function BookingRequestsPage() {
|
|||||||
}, [setPagination, pagination.pageSize]);
|
}, [setPagination, pagination.pageSize]);
|
||||||
|
|
||||||
const activeFilterCount =
|
const activeFilterCount =
|
||||||
(kindFilter ? 1 : 0) +
|
|
||||||
(statusFilter.length ? 1 : 0) +
|
(statusFilter.length ? 1 : 0) +
|
||||||
(directionFilter ? 1 : 0) +
|
(directionFilter ? 1 : 0) +
|
||||||
(freightTypeFilter ? 1 : 0) +
|
(freightTypeFilter ? 1 : 0) +
|
||||||
@@ -238,7 +237,6 @@ export default function BookingRequestsPage() {
|
|||||||
(scheduledFrom || scheduledTo ? 1 : 0);
|
(scheduledFrom || scheduledTo ? 1 : 0);
|
||||||
|
|
||||||
const clearFilters = useCallback(() => {
|
const clearFilters = useCallback(() => {
|
||||||
setKindFilter(null);
|
|
||||||
setStatusFilter([]);
|
setStatusFilter([]);
|
||||||
setDirectionFilter(null);
|
setDirectionFilter(null);
|
||||||
setFreightTypeFilter(null);
|
setFreightTypeFilter(null);
|
||||||
@@ -284,8 +282,6 @@ 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;
|
||||||
@@ -307,8 +303,6 @@ 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;
|
||||||
@@ -333,29 +327,8 @@ export default function BookingRequestsPage() {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: "bookingKind",
|
|
||||||
size: 60,
|
|
||||||
minSize: 40,
|
|
||||||
header: () => <span className={bookingTable.headerCell}>Type</span>,
|
|
||||||
cell: ({ row }) => {
|
|
||||||
const isGeneral = row.original.bookingKind === "GENERAL_CONTRACT";
|
|
||||||
return (
|
|
||||||
<div className="py-1">
|
|
||||||
<Badge
|
|
||||||
variant={isGeneral ? "secondary" : "outline"}
|
|
||||||
className="h-5 px-1.5 text-[10px] font-medium"
|
|
||||||
>
|
|
||||||
{isGeneral ? "General" : "One-time"}
|
|
||||||
</Badge>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
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;
|
||||||
@@ -386,8 +359,8 @@ export default function BookingRequestsPage() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "status",
|
id: "status",
|
||||||
size: 60,
|
size: 200,
|
||||||
minSize: 40,
|
minSize: 180,
|
||||||
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">
|
||||||
@@ -398,11 +371,20 @@ export default function BookingRequestsPage() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
|
meta: {
|
||||||
|
headerClassName: "min-w-[11rem]",
|
||||||
|
cellClassName: "min-w-[11rem]",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "approval",
|
||||||
|
header: () => (
|
||||||
|
<span className={bookingTable.headerCell}>Approval</span>
|
||||||
|
),
|
||||||
|
cell: ({ row }) => <BookingApprovalProgressCell row={row.original} />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
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">
|
||||||
@@ -413,8 +395,6 @@ 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} />
|
||||||
@@ -422,8 +402,7 @@ export default function BookingRequestsPage() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "actions",
|
id: "actions",
|
||||||
size: 60,
|
size: 140,
|
||||||
minSize: 40,
|
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<BookingActionsMenu
|
<BookingActionsMenu
|
||||||
row={row.original}
|
row={row.original}
|
||||||
@@ -503,6 +482,22 @@ export default function BookingRequestsPage() {
|
|||||||
/>
|
/>
|
||||||
*/}
|
*/}
|
||||||
|
|
||||||
|
<Tabs
|
||||||
|
value={kindTab}
|
||||||
|
onChange={(value) => {
|
||||||
|
setKindTab((value as BookingKindTab) ?? "ONE_TIME");
|
||||||
|
setPagination({ pageIndex: 0, pageSize: pagination.pageSize });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tabs.List>
|
||||||
|
{BOOKING_KIND_TABS.map((t) => (
|
||||||
|
<Tabs.Tab key={t.value} value={t.value}>
|
||||||
|
{t.label}
|
||||||
|
</Tabs.Tab>
|
||||||
|
))}
|
||||||
|
</Tabs.List>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
<Card p={0}>
|
<Card p={0}>
|
||||||
<Stack gap={0}>
|
<Stack gap={0}>
|
||||||
<Box px="md" pt="md" pb="sm" w="100%">
|
<Box px="md" pt="md" pb="sm" w="100%">
|
||||||
@@ -540,18 +535,6 @@ export default function BookingRequestsPage() {
|
|||||||
</Text>
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
<Group gap="sm" wrap="wrap">
|
<Group gap="sm" wrap="wrap">
|
||||||
<Select
|
|
||||||
placeholder="All booking types"
|
|
||||||
data={BOOKING_KIND_OPTIONS}
|
|
||||||
value={kindFilter}
|
|
||||||
onChange={(v) => {
|
|
||||||
setKindFilter((v as BookingKind | null) ?? null);
|
|
||||||
resetPage();
|
|
||||||
}}
|
|
||||||
clearable
|
|
||||||
radius="lg"
|
|
||||||
style={{ minWidth: 190 }}
|
|
||||||
/>
|
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
placeholder={statusFilter.length ? undefined : "All statuses"}
|
placeholder={statusFilter.length ? undefined : "All statuses"}
|
||||||
data={STATUS_OPTIONS}
|
data={STATUS_OPTIONS}
|
||||||
@@ -713,26 +696,28 @@ export default function BookingRequestsPage() {
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
<DataTable
|
<Box style={{ overflowX: "auto" }} w="100%">
|
||||||
columns={columns}
|
<DataTable
|
||||||
data={rows}
|
columns={columns}
|
||||||
status={isLoading ? "loading" : isError ? "error" : "success"}
|
data={rows}
|
||||||
onRowClick={handleRowClick}
|
status={isLoading ? "loading" : isError ? "error" : "success"}
|
||||||
pagination={{
|
onRowClick={handleRowClick}
|
||||||
pageIndex: pagination.pageIndex,
|
pagination={{
|
||||||
pageSize: pagination.pageSize,
|
pageIndex: pagination.pageIndex,
|
||||||
pageCount,
|
pageSize: pagination.pageSize,
|
||||||
totalCount: total,
|
pageCount,
|
||||||
}}
|
totalCount: total,
|
||||||
tableOptions={{
|
}}
|
||||||
state: { pagination },
|
tableOptions={{
|
||||||
onPaginationChange: setPagination,
|
state: { pagination },
|
||||||
manualPagination: true,
|
onPaginationChange: setPagination,
|
||||||
pageCount,
|
manualPagination: true,
|
||||||
}}
|
pageCount,
|
||||||
containerClassName="edr-booking-requests-table border-0 shadow-none bg-transparent"
|
}}
|
||||||
footer={DataTableFooter}
|
containerClassName="border-0 shadow-none bg-transparent"
|
||||||
/>
|
footer={DataTableFooter}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* content-sized columns with a 40px floor, horizontal scroll when the table
|
* content-sized columns with a 40px floor, horizontal scroll when the table
|
||||||
* outgrows the card, and a sticky shadowed action column.
|
* outgrows the card, and a sticky shadowed action column.
|
||||||
*/
|
*/
|
||||||
.edr-bookings-table {
|
.edr-bookings-table {
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user