feat(pilot): EscalateInterceptDialog popover
Anchored above the Escalate button, captures fix outcome before the engineer hands off the ticket. Defaults to 'didn't work' on Enter (the common case). Alternatives: 'worked, escalating for another reason' (preserves success) and 'never actually applied' (dismiss). Task 11 will wire this to AssistantChatPage's Escalate handler. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
76
frontend/src/components/pilot/EscalateInterceptDialog.tsx
Normal file
76
frontend/src/components/pilot/EscalateInterceptDialog.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* EscalateInterceptDialog — popover anchored above the Escalate button.
|
||||
*
|
||||
* Fires when the engineer clicks Escalate while a fix is in Verifying or
|
||||
* Partial state. Captures the fix outcome before the escalation so the
|
||||
* handoff narrative is honest for whoever picks up the ticket.
|
||||
*
|
||||
* Visual reference: docs/FlowAssist_Migration/mockups/07-verify-states.html
|
||||
* (panel C).
|
||||
*/
|
||||
import { X, AlertCircle, Check } from 'lucide-react'
|
||||
import type { FixOutcome } from '@/api/sessionSuggestedFixes'
|
||||
|
||||
export type InterceptChoice = FixOutcome | 'never_applied'
|
||||
|
||||
export interface EscalateInterceptDialogProps {
|
||||
fixTitle: string
|
||||
onChoose: (choice: InterceptChoice) => void
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
export function EscalateInterceptDialog({
|
||||
fixTitle,
|
||||
onChoose,
|
||||
onClose,
|
||||
}: EscalateInterceptDialogProps) {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className="fixed inset-0 z-40"
|
||||
onClick={onClose}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<div
|
||||
role="dialog"
|
||||
aria-label="Capture fix outcome before escalating"
|
||||
className="absolute bottom-full mb-2 left-0 z-50 w-[340px] rounded-lg border border-white/15 bg-card p-3.5 shadow-[0_18px_40px_rgba(0,0,0,0.55)]"
|
||||
>
|
||||
<div className="font-heading font-semibold text-[13px] text-heading mb-1">
|
||||
Before escalating — what happened with the fix?
|
||||
</div>
|
||||
<div className="text-[12px] text-muted-foreground leading-[1.5] mb-3">
|
||||
“{fixTitle}” is still in the Verifying state. Tag its outcome so
|
||||
the senior picking this up knows what's been tried.
|
||||
</div>
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<button
|
||||
autoFocus
|
||||
onClick={() => onChoose('applied_failed')}
|
||||
className="flex items-center gap-2.5 px-3 py-2.5 rounded-lg border border-danger/30 bg-danger-dim text-[12.5px] text-primary hover:bg-danger-dim/80 hover:border-danger transition-colors text-left"
|
||||
>
|
||||
<X size={13} strokeWidth={2.5} className="text-danger" />
|
||||
<span className="flex-1">The fix didn't work</span>
|
||||
<span className="text-[10.5px] text-muted-foreground font-mono px-1.5 py-[2px] rounded bg-white/[0.05]">↵</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => onChoose('applied_success')}
|
||||
className="flex items-center gap-2.5 px-3 py-2.5 rounded-lg border border-white/10 bg-elevated text-[12.5px] text-primary hover:bg-sidebar transition-colors text-left"
|
||||
>
|
||||
<Check size={13} strokeWidth={2} />
|
||||
<span className="flex-1">It worked — escalating for another reason</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => onChoose('never_applied')}
|
||||
className="flex items-center gap-2.5 px-3 py-2.5 rounded-lg border border-white/10 bg-elevated text-[12.5px] text-primary hover:bg-sidebar transition-colors text-left"
|
||||
>
|
||||
<AlertCircle size={13} strokeWidth={2} />
|
||||
<span className="flex-1">Never actually applied it</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default EscalateInterceptDialog
|
||||
Reference in New Issue
Block a user