From 6bb0fb1da50b4f68751477a121bbe985bf799ae5 Mon Sep 17 00:00:00 2001 From: DEls Date: Mon, 21 Sep 2026 01:19:15 +0200 Subject: [PATCH] feat(po): colour the whole line, and give over-supply its own colour A single coloured number at the far right of seven columns is easy to miss. The description now carries the same tone as the outstanding figure, so a line that still owes reads as one thing at a glance. Over-supply moves from amber to blue, in the row and on the summary tile. Amber sat next to red as another shade of "behind", which is the opposite of what over-supply is: nothing is owed, something arrived that was not ordered, and it is queried with the supplier rather than chased. Co-Authored-By: Claude Opus 5 --- .../purchase-orders/[poId]/po-detail-view.tsx | 54 ++++++++++++------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/src/app/dashboard/financial/purchase-orders/[poId]/po-detail-view.tsx b/src/app/dashboard/financial/purchase-orders/[poId]/po-detail-view.tsx index 5f5bc3b..a750245 100644 --- a/src/app/dashboard/financial/purchase-orders/[poId]/po-detail-view.tsx +++ b/src/app/dashboard/financial/purchase-orders/[poId]/po-detail-view.tsx @@ -97,12 +97,21 @@ function amberTile( value: React.ReactNode, sub: string, Icon: React.ComponentType<{ className?: string }>, - tone?: "warning", + // "info" is over-supply: a discrepancy to raise with the supplier, not + // a shortfall to chase. Blue keeps it distinct from what is still owed. + tone?: "warning" | "info", ) { - const strip = - tone === "warning" ? "from-red-500 to-amber-500" : "from-[#F2B165] to-[#E08A3C]"; - const iconBg = tone === "warning" ? "bg-red-500/15" : "bg-[#F2B165]/15"; - const iconFg = tone === "warning" ? "text-red-600 dark:text-red-400" : "text-[#F2B165]"; + const strip = tone === "warning" + ? "from-red-500 to-amber-500" + : tone === "info" + ? "from-blue-500 to-sky-400" + : "from-[#F2B165] to-[#E08A3C]"; + const iconBg = tone === "warning" ? "bg-red-500/15" : tone === "info" ? "bg-blue-500/15" : "bg-[#F2B165]/15"; + const iconFg = tone === "warning" + ? "text-red-600 dark:text-red-400" + : tone === "info" + ? "text-blue-600 dark:text-blue-400" + : "text-[#F2B165]"; return ( 0 ? "warning" : undefined, + overSuppliedLines > 0 ? "info" : undefined, )} {amberTile( "Verified", @@ -308,7 +317,17 @@ export function PoDetailView({ - {state.items.map((it) => ( + {state.items.map((it) => { + // One tone per row, carried by the description and the + // outstanding figure, so a line that still owes reads + // as one thing at a glance rather than a lone coloured + // number at the far right of seven columns. + const tone = it.qtyOutstanding > 0 + ? "text-destructive" + : it.qtyOutstanding < 0 + ? "text-blue-700 dark:text-blue-300" + : ""; + return (

{it.materialCode || "—"}

@@ -316,7 +335,9 @@ export function PoDetailView({ {it.costCode || "—"}

- {it.description || "—"} + + {it.description || "—"} + {formatNumber(it.qtyOrdered)} {it.unit} @@ -333,16 +354,10 @@ export function PoDetailView({ {/* Outstanding is ordered minus delivered, so it goes negative once a supplier over-delivers. - Still owed and over-supplied are different - problems and read differently: a bare "-5" in - the same amber as a shortfall says neither. */} - 0 && "text-destructive", - it.qtyOutstanding < 0 && "text-amber-700 dark:text-amber-300", - )} - > + Still owed and over-supplied are opposite + problems: one is chased, the other is queried. + A bare "-5" in the same colour says neither. */} + {it.qtyOutstanding < 0 ? ( <>{formatNumber(Math.abs(it.qtyOutstanding))} {it.unit} over ) : ( @@ -356,7 +371,8 @@ export function PoDetailView({ {formatCurrency(it.amount)} - ))} + ); + })}