fix: clear cockpit state on session switch and add loading placeholders
- Reset triageMeta, psaTicketId, steps, and completedSteps when activeChatId changes (prevents stale triage data from previous session showing while AI processes the new one) - Split the activeChatId and activeActions reset effects so triage only resets on session switch, not on every new action set - Add loading placeholders to cockpit work zone: spinner + "analyzing" text in steps panel, "questions will appear here" in right panel - Add centered "Starting session..." loader to FlowPilot page when loading with no messages yet (prefill creation period) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -87,11 +87,23 @@ export default function CockpitPage() {
|
|||||||
prevMessageCountRef.current = session.messages.length
|
prevMessageCountRef.current = session.messages.length
|
||||||
}, [session.messages.length, showOnboarding])
|
}, [session.messages.length, showOnboarding])
|
||||||
|
|
||||||
// Reset local step UI when switching cases or when a new action set arrives.
|
// Reset all cockpit-local state when switching cases.
|
||||||
|
// Triage data gets repopulated via onSessionLoadedRef after the async fetch.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setActiveStepIndex(0)
|
setActiveStepIndex(0)
|
||||||
setCompletedSteps(new Set())
|
setCompletedSteps(new Set())
|
||||||
}, [session.activeChatId, session.activeActions])
|
setTriageMeta({
|
||||||
|
client_name: null, asset_name: null, issue_category: null,
|
||||||
|
triage_hypothesis: null, evidence_items: [],
|
||||||
|
})
|
||||||
|
setPsaTicketId(null)
|
||||||
|
}, [session.activeChatId])
|
||||||
|
|
||||||
|
// Reset step UI when a new action set arrives from AI.
|
||||||
|
useEffect(() => {
|
||||||
|
setActiveStepIndex(0)
|
||||||
|
setCompletedSteps(new Set())
|
||||||
|
}, [session.activeActions])
|
||||||
|
|
||||||
// ── Triage handlers ──
|
// ── Triage handlers ──
|
||||||
|
|
||||||
@@ -306,28 +318,44 @@ export default function CockpitPage() {
|
|||||||
<div className="flex min-h-0 overflow-hidden" style={{ height: `${workZonePct}%` }}>
|
<div className="flex min-h-0 overflow-hidden" style={{ height: `${workZonePct}%` }}>
|
||||||
{/* Left: Steps panel */}
|
{/* Left: Steps panel */}
|
||||||
<div className="flex-[55] min-w-0 p-3 overflow-y-auto border-r border-default">
|
<div className="flex-[55] min-w-0 p-3 overflow-y-auto border-r border-default">
|
||||||
<StepsPanel
|
{session.loading && session.activeActions.length === 0 ? (
|
||||||
actions={session.activeActions}
|
<div className="flex flex-col items-center justify-center h-full text-center gap-2">
|
||||||
activeIndex={activeStepIndex}
|
<Loader2 size={20} className="animate-spin text-accent" />
|
||||||
completedSteps={completedSteps}
|
<p className="text-xs text-muted-foreground">FlowPilot is analyzing the issue...</p>
|
||||||
onStepComplete={handleStepComplete}
|
</div>
|
||||||
onStepSelect={handleStepSelect}
|
) : (
|
||||||
/>
|
<StepsPanel
|
||||||
|
actions={session.activeActions}
|
||||||
|
activeIndex={activeStepIndex}
|
||||||
|
completedSteps={completedSteps}
|
||||||
|
onStepComplete={handleStepComplete}
|
||||||
|
onStepSelect={handleStepSelect}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{/* Right: FlowPilot Asks + What We Know */}
|
{/* Right: FlowPilot Asks + What We Know */}
|
||||||
<div className="flex-[45] min-w-0 p-3 overflow-y-auto flex flex-col gap-3">
|
<div className="flex-[45] min-w-0 p-3 overflow-y-auto flex flex-col gap-3">
|
||||||
<FlowPilotAsks
|
{session.loading && session.activeQuestions.length === 0 && triageMeta.evidence_items.length === 0 ? (
|
||||||
questions={session.activeQuestions}
|
<div className="flex flex-col items-center justify-center h-full text-center gap-2">
|
||||||
onAnswer={(answer) => {
|
<Sparkles size={18} className="text-muted" />
|
||||||
void session.sendMessage(answer, { clearComposer: false })
|
<p className="text-xs text-muted-foreground">Questions and evidence will appear here</p>
|
||||||
}}
|
</div>
|
||||||
loading={session.loading}
|
) : (
|
||||||
/>
|
<>
|
||||||
<WhatWeKnow
|
<FlowPilotAsks
|
||||||
items={triageMeta.evidence_items}
|
questions={session.activeQuestions}
|
||||||
onAdd={handleEvidenceAdd}
|
onAnswer={(answer) => {
|
||||||
onEdit={handleEvidenceEdit}
|
void session.sendMessage(answer, { clearComposer: false })
|
||||||
/>
|
}}
|
||||||
|
loading={session.loading}
|
||||||
|
/>
|
||||||
|
<WhatWeKnow
|
||||||
|
items={triageMeta.evidence_items}
|
||||||
|
onAdd={handleEvidenceAdd}
|
||||||
|
onEdit={handleEvidenceEdit}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -149,6 +149,12 @@ export default function FlowPilotPage() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{session.messages.length === 0 && session.loading && (
|
||||||
|
<div className="flex flex-col items-center justify-center h-full text-center gap-3">
|
||||||
|
<Loader2 size={24} className="animate-spin text-primary" />
|
||||||
|
<p className="text-sm text-muted-foreground">Starting session...</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{session.messages.map((msg, i) => (
|
{session.messages.map((msg, i) => (
|
||||||
<ChatMessage
|
<ChatMessage
|
||||||
key={i}
|
key={i}
|
||||||
|
|||||||
Reference in New Issue
Block a user