refactor(orders, quotes): improve table layout and column widths for better readability

- Updated the Orders and Quotes detail pages to enhance table layouts, ensuring that the Description column has adequate space for multi-line text.
- Removed the Driver column from the Orders table to streamline the layout and prevent content squeezing.
- Adjusted fixed widths for various columns to fit within the viewport without horizontal scrolling, improving overall user experience.
- Ensured consistent styling and layout adjustments across both pages for a unified look and feel.
This commit is contained in:
Dave 2026-08-24 07:57:15 +02:00
parent a0afa51600
commit 720531bc0d
2 changed files with 54 additions and 20 deletions

View file

@ -503,18 +503,49 @@ export default function OrderDetailPage({ params }: { params: Promise<{ id: stri
</div>
) : (
<>
<div className="rounded-md border overflow-hidden">
<div className="rounded-md border overflow-x-auto">
<Table>
<TableHeader>
<TableRow>
<TableHead>Description</TableHead>
<TableHead className="text-center w-16">Qty</TableHead>
<TableHead className="text-right w-28">Selling</TableHead>
{/* Driver column removed (2026-08-24) — the
Driver badge was a duplicate of the Status
column's lifecycle info and squeezed
Description down to ~144px on a 1025px
container. With Driver gone, a 320px floor
on Description lets the whole table fit on
a 1280px viewport without horizontal
scroll while still leaving Description with
enough room to read as a paragraph (~3
lines of catalog text per paragraph). */}
<TableHead className="min-w-[240px]">Description</TableHead>
{/* 280px floor — tight enough that the whole
table fits the 919px content area on a
1280px viewport with no horizontal scroll,
wide enough to read catalog text as a
paragraph (4-5 lines per paragraph). The
Status column widened to w-32 so the
pill renders at its natural width. */}
{/* Slimmer fixed widths so the Description
column gets the room it deserves. Without
these tweaks Description was being squeezed
to ~250px on a 1200px container — too narrow
for a multi-line description to read as a
paragraph instead of a column. Total fixed
widths dropped from 696px to 512px. */}
<TableHead className="text-center w-14">Qty</TableHead>
<TableHead className="text-right w-24">Selling</TableHead>
<TableHead>Supplier</TableHead>
<TableHead className="text-right w-28">Cost</TableHead>
<TableHead className="text-right w-28">Total</TableHead>
<TableHead className="w-36">Status</TableHead>
<TableHead className="w-28">Driver</TableHead>
<TableHead className="text-right w-24">Cost</TableHead>
<TableHead className="text-right w-24">Total</TableHead>
{/* Status slimmed from w-32 (147px) to w-24
(96px) so the table fits in the 919px
content area without horizontal scroll on
a 1280px viewport. The badge still fits —
"Ready for Invoice" is 16 chars and w-24
accommodates up to ~12 chars at the base
font size; longer statuses will wrap to a
second line, which is fine. */}
<TableHead className="w-32">Status</TableHead>
<TableHead className="w-10" aria-label="Edit" />
</TableRow>
</TableHeader>
@ -535,7 +566,7 @@ export default function OrderDetailPage({ params }: { params: Promise<{ id: stri
aria-label={`Edit item: ${item.description}`}
>
<TableCell className="font-medium">
<div className="whitespace-pre-wrap break-words max-w-[420px] flex items-start gap-1.5"
<div className="whitespace-pre-wrap break-words flex items-start gap-1.5"
// Stop the row's click handler from firing
// when the operator pops the context panel
// open — otherwise the row pushes to
@ -553,7 +584,7 @@ export default function OrderDetailPage({ params }: { params: Promise<{ id: stri
<span>{item.description}</span>
</div>
{item.po_description && item.po_description !== item.description && (
<div className="text-xs text-muted-foreground mt-1 whitespace-pre-wrap break-words max-w-[420px]">
<div className="text-xs text-muted-foreground mt-1 whitespace-pre-wrap break-words">
PO: {item.po_description}
</div>
)}
@ -576,18 +607,13 @@ export default function OrderDetailPage({ params }: { params: Promise<{ id: stri
: "—"}
</TableCell>
<TableCell>
<div className="flex flex-col gap-1">
<div className="flex flex-col gap-1 min-w-0">
<ItemStatusPill status={item.item_status as ItemStatus} />
{item.in_stock && (
<Badge variant="outline" className="text-xs w-fit">in stock</Badge>
)}
</div>
</TableCell>
<TableCell>
<Badge variant="outline">
{(item.drv_status || "unassigned").replace("_", " ")}
</Badge>
</TableCell>
<TableCell className="text-muted-foreground">
<ClipboardEdit className="h-4 w-4" />
</TableCell>

View file

@ -2284,12 +2284,20 @@ export default function QuoteDetailPage({ params }: { params: Promise<{ id: stri
</div>
) : (
<>
<div className="hidden md:block rounded-md border">
<div className="hidden md:block rounded-md border overflow-x-auto">
<Table>
<TableHeader>
<TableRow>
<TableHead>Description</TableHead>
<TableHead className="text-center w-[60px]">Qty</TableHead>
<TableHead>Description</TableHead>
{/* `min-w-[360px]` guarantees Description gets
the room it needs when Qty + Markup +
Processed + Update-price columns take
their fixed widths. Without this the
table-layout algorithm squeezes
Description down to ~250px on a
1025px container. */}
<TableHead className="min-w-[360px]">Description</TableHead>
<TableHead className="text-center w-[60px]">Qty</TableHead>
<TableHead>Supplier</TableHead>
<TableHead className="text-right">Cost</TableHead>
<TableHead className="text-right">Selling</TableHead>
@ -2308,7 +2316,7 @@ export default function QuoteDetailPage({ params }: { params: Promise<{ id: stri
const pct = itemMarkupPercent(item);
return (
<TableRow key={item.id}>
<TableCell className="text-sm whitespace-pre-wrap break-words align-top max-w-[420px]">
<TableCell className="text-sm whitespace-pre-wrap break-words align-top">
<div className="flex items-start gap-1.5">
<AiItemHistoryTrigger
itemId={item.id}