fix(console): blank lead page — statusStrip const used blocked/stalled before they existed
The lifted status strip (e21e394) was defined right after `holds`, but its JSX
references `blocked` and `stalled`, which are declared ~80 lines lower. A const
that reads a const declared below it throws "Cannot access before
initialization" at render — a temporal dead zone the bundler does not catch, so
the build passed and the lead page rendered blank.
Moved the statusStrip definition to just after `stalled`, so every value it
reads exists first. The lifted-above-the-metrics position is unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
e21e3949f5
commit
fda1247ee9
@ -301,81 +301,6 @@ export default function Lead() {
|
|||||||
const stage = phaseOf(STAGES.find((s) => s.name === stateName), row)
|
const stage = phaseOf(STAGES.find((s) => s.name === stateName), row)
|
||||||
const holds = holdsOf(stage)
|
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 ? (
|
|
||||||
<div className="doing doing--blocked">
|
|
||||||
<span className="doing__stop" aria-hidden="true" />
|
|
||||||
<div>
|
|
||||||
<strong>Stopped — {blocked.what}</strong>
|
|
||||||
<span>
|
|
||||||
{blocked.fix} The agents will pick the lead up again on their own once it
|
|
||||||
is there; nothing else is running in the meantime.
|
|
||||||
</span>
|
|
||||||
<button
|
|
||||||
type="button" className="doing__fix"
|
|
||||||
onClick={() => setOpen(blocked.via)}
|
|
||||||
>
|
|
||||||
Open Collect Documents
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : stalled ? (
|
|
||||||
<div className="doing doing--stalled">
|
|
||||||
<span className="doing__stop" aria-hidden="true" />
|
|
||||||
<div>
|
|
||||||
<strong>{stage.doing} — nothing for {stalled.mins} minutes</strong>
|
|
||||||
<span>
|
|
||||||
{stage.by} has not come back. That is usually the model provider being
|
|
||||||
slow or dropping a request, not a problem with this lead — the work so far
|
|
||||||
is safe and nothing has been lost.
|
|
||||||
{stalled.nudge
|
|
||||||
? ` Running ${stalled.nudge.label.toLowerCase()} wakes ${stalled.nudge.by} to try again.`
|
|
||||||
: ' There is no step to re-run from here; the actions below are the way on.'}
|
|
||||||
</span>
|
|
||||||
{stalled.nudge ? (
|
|
||||||
<button
|
|
||||||
type="button" className="doing__fix"
|
|
||||||
onClick={() => setOpen(stalled.nudge.uid)}
|
|
||||||
>
|
|
||||||
{stalled.nudge.label}
|
|
||||||
</button>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : 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. */
|
|
||||||
<div className="doing doing--waiting">
|
|
||||||
<span className="doing__wait" aria-hidden="true" />
|
|
||||||
<div>
|
|
||||||
<strong>{stage.doing}</strong>
|
|
||||||
<span>
|
|
||||||
Their answer comes back to this lead on its own — Engage reads it and
|
|
||||||
records the acceptance. Nothing is waiting on you.
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : stage?.kind === 'auto' ? (
|
|
||||||
<div className="doing">
|
|
||||||
<span className="doing__pulse" aria-hidden="true" />
|
|
||||||
<div>
|
|
||||||
<strong>{stage.doing}</strong>
|
|
||||||
<span>
|
|
||||||
Handled by {stage.by}.
|
|
||||||
{stage.after ? ` The lead stays in ${stateName} until a quote exists — nothing is waiting on you.` : ''}
|
|
||||||
{' '}Typically completes within two minutes; this view refreshes automatically.
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : null
|
|
||||||
)
|
|
||||||
// Only what THIS user may run. The workflow refuses the rest server-side
|
// 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
|
// anyway; showing them a row of buttons that all 403 reads as a broken app
|
||||||
// rather than as a control.
|
// rather than as a control.
|
||||||
@ -454,6 +379,83 @@ blocked ? (
|
|||||||
// the way out rather than going on promising two minutes.
|
// the way out rather than going on promising two minutes.
|
||||||
const stillFor = row.updated_at ? now - Date.parse(row.updated_at) : 0
|
const stillFor = row.updated_at ? now - Date.parse(row.updated_at) : 0
|
||||||
const stalled = !blocked && stage?.kind === 'auto' && stillFor > STALL_AFTER_MS
|
const stalled = !blocked && stage?.kind === 'auto' && stillFor > STALL_AFTER_MS
|
||||||
|
|
||||||
|
/* 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 ? (
|
||||||
|
<div className="doing doing--blocked">
|
||||||
|
<span className="doing__stop" aria-hidden="true" />
|
||||||
|
<div>
|
||||||
|
<strong>Stopped — {blocked.what}</strong>
|
||||||
|
<span>
|
||||||
|
{blocked.fix} The agents will pick the lead up again on their own once it
|
||||||
|
is there; nothing else is running in the meantime.
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
type="button" className="doing__fix"
|
||||||
|
onClick={() => setOpen(blocked.via)}
|
||||||
|
>
|
||||||
|
Open Collect Documents
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : stalled ? (
|
||||||
|
<div className="doing doing--stalled">
|
||||||
|
<span className="doing__stop" aria-hidden="true" />
|
||||||
|
<div>
|
||||||
|
<strong>{stage.doing} — nothing for {stalled.mins} minutes</strong>
|
||||||
|
<span>
|
||||||
|
{stage.by} has not come back. That is usually the model provider being
|
||||||
|
slow or dropping a request, not a problem with this lead — the work so far
|
||||||
|
is safe and nothing has been lost.
|
||||||
|
{stalled.nudge
|
||||||
|
? ` Running ${stalled.nudge.label.toLowerCase()} wakes ${stalled.nudge.by} to try again.`
|
||||||
|
: ' There is no step to re-run from here; the actions below are the way on.'}
|
||||||
|
</span>
|
||||||
|
{stalled.nudge ? (
|
||||||
|
<button
|
||||||
|
type="button" className="doing__fix"
|
||||||
|
onClick={() => setOpen(stalled.nudge.uid)}
|
||||||
|
>
|
||||||
|
{stalled.nudge.label}
|
||||||
|
</button>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : 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. */
|
||||||
|
<div className="doing doing--waiting">
|
||||||
|
<span className="doing__wait" aria-hidden="true" />
|
||||||
|
<div>
|
||||||
|
<strong>{stage.doing}</strong>
|
||||||
|
<span>
|
||||||
|
Their answer comes back to this lead on its own — Engage reads it and
|
||||||
|
records the acceptance. Nothing is waiting on you.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : stage?.kind === 'auto' ? (
|
||||||
|
<div className="doing">
|
||||||
|
<span className="doing__pulse" aria-hidden="true" />
|
||||||
|
<div>
|
||||||
|
<strong>{stage.doing}</strong>
|
||||||
|
<span>
|
||||||
|
Handled by {stage.by}.
|
||||||
|
{stage.after ? ` The lead stays in ${stateName} until a quote exists — nothing is waiting on you.` : ''}
|
||||||
|
{' '}Typically completes within two minutes; this view refreshes automatically.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : null
|
||||||
|
)
|
||||||
|
|
||||||
? { mins: Math.round(stillFor / 60000), nudge: nudgeFor(stage, row) }
|
? { mins: Math.round(stillFor / 60000), nudge: nudgeFor(stage, row) }
|
||||||
: null
|
: null
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user