From e21e3949f50594a39bc700c3b25ff7895dcb532f Mon Sep 17 00:00:00 2001 From: Yashas Date: Wed, 9 Sep 2026 12:01:46 +0530 Subject: [PATCH] console: state before numbers; frame optional actions; flatten the overview band MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Applying the lens from the status-strip critique across the surfaces. LEAD PAGE - "What is happening now" lifts above the metrics. An operator's first question is what is going on / what do I do, not what the premium is — so the status strip (an alert when blocked or stalled, the live state otherwise) sits directly under the header, before the four numbers, full-width. - The optional "Add a document" action stopped floating: with no required step it read like the next move and sat under "nothing is waiting on you". A quiet "Optional" tag now frames it. OVERVIEW - The "right now" band was four heavy dark-navy shadowed cards — the cards-on-canvas language removed everywhere else, clashing on the flat white page. Flattened to light tiles read by a coloured left rule (blue AI, amber person, teal customer, grey risk), the figure taking that colour; a live person-queue or lapsed renewal warms its whole tile. Prominence from the big number and the accent, not a dark fill. Co-Authored-By: Claude Opus 4.8 --- src/screens/Lead.jsx | 154 +++++++++++++++++++++------------------- src/screens/screens.css | 65 +++++++++++------ 2 files changed, 127 insertions(+), 92 deletions(-) diff --git a/src/screens/Lead.jsx b/src/screens/Lead.jsx index c36bc72..e32a890 100644 --- a/src/screens/Lead.jsx +++ b/src/screens/Lead.jsx @@ -300,6 +300,82 @@ export default function Lead() { // are still looked up on the state's own uid; only the presentation moves. const stage = phaseOf(STAGES.find((s) => s.name === stateName), row) const holds = holdsOf(stage) + + /* WHAT IS HAPPENING NOW, lifted above the numbers. An operator's first + question about a lead is "what is going on / what do I do", not "what is + the premium" — so the status strip (an alert when blocked or stalled, the + live state otherwise) sits directly under the header, before the metrics. + Rendered full-width there rather than inside the narrow work column. */ + const statusStrip = ( +blocked ? ( +
+
+ ) : stalled ? ( +
+
+ ) : stage?.kind === 'customer' && stage.doing ? ( + /* Not an agent working, and not a task of yours either — the lead + is with someone outside the business. Without this the screen + went blank at exactly the stage where an operator is most likely + to wonder whether something has broken. */ +
+
+ ) : stage?.kind === 'auto' ? ( +
+
+ ) : null + ) // Only what THIS user may run. The workflow refuses the rest server-side // anyway; showing them a row of buttons that all 403 reads as a broken app // rather than as a control. @@ -441,6 +517,8 @@ export default function Lead() { ) : null} + {statusStrip} + {/* Measures, not fields. Age and dwell time are computed — neither is on the record — and they are the two that answer "is this lead moving?", which no label/value pair on the page could. */} @@ -497,78 +575,6 @@ export default function Lead() { ) : null} - {/* An AI-carried stage has no empty action bar and no idle screen: it - says what is happening and who is doing it. The activities below it - stay available — ops can run them by hand — but they are not the - answer to "why is nothing moving?". */} - {blocked ? ( -
-
- ) : stalled ? ( -
-
- ) : stage?.kind === 'customer' && stage.doing ? ( - /* Not an agent working, and not a task of yours either — the lead - is with someone outside the business. Without this the screen - went blank at exactly the stage where an operator is most likely - to wonder whether something has broken. */ -
-
- ) : stage?.kind === 'auto' ? ( -
-
- ) : null} {/* WHAT TO DO NEXT, not what is permitted. Every action carries a role: `do` is the step this stage is @@ -661,6 +667,10 @@ export default function Lead() { {again.length ? (
+ {/* With no required step, these optional actions floated at + the top of the column reading like the next step. A quiet + tag frames them as optional without repeating the status. */} + {!step.length ? Optional : null} {again.map((a) => (