Files
resolutionflow/frontend/src/components/dashboard/PendingEscalations.tsx
Michael Chihlas 912075cd43 refactor: dashboard design critique — eliminate redundancy, differentiate sections
- Remove GreetingStatStrip (duplicated PerformanceCards data)
- Strip left-border accent from stat cards (AI slop pattern)
- Redesign KnowledgeBaseCards: icon grid → compact row list with icon badges
- Redesign TeamSummary: distinct inline-row layout, no longer identical twin
- Differentiate hover: stat cards use subtle border-hover, sessions keep springy lift
- Add loading skeletons to PerformanceCards, KnowledgeBaseCards, TeamSummary
- Add error state to PerformanceCards
- Extract timeAgo() to shared lib/timeAgo.ts (replaced 4 duplicates)
- Fix Skeleton bg-brand-border (undefined CSS var) → border-default
- Fix double text-xs text-[0.5625rem] class conflicts across dashboard

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 17:06:30 -04:00

79 lines
2.9 KiB
TypeScript

import { useState, useEffect } from 'react'
import { Link, useNavigate } from 'react-router-dom'
import { AlertTriangle } from 'lucide-react'
import { aiSessionsApi } from '@/api/aiSessions'
import type { AISessionSummary } from '@/types/ai-session'
import { timeAgo } from '@/lib/timeAgo'
export function PendingEscalations() {
const [escalations, setEscalations] = useState<AISessionSummary[]>([])
const navigate = useNavigate()
useEffect(() => {
aiSessionsApi.getEscalationQueue()
.then(setEscalations)
.catch(() => {})
}, [])
if (escalations.length === 0) return null
return (
<div
className="card-flat overflow-hidden"
style={{ borderColor: 'rgba(234, 179, 8, 0.2)' }}
>
<div
className="flex items-center justify-between px-5 py-3"
style={{ borderBottom: '1px solid var(--color-border-default)' }}
>
<div className="flex items-center gap-2">
<AlertTriangle size={14} className="text-amber-400" />
<h3 className="font-heading text-sm font-bold text-foreground">
Pending Escalations
<span className="ml-2 inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-amber-400/10 px-1.5 text-[0.625rem] font-bold text-amber-400">
{escalations.length}
</span>
</h3>
</div>
<Link
to="/escalations"
className="text-[0.6875rem] text-muted-foreground hover:text-foreground transition-colors"
>
View all
</Link>
</div>
<div>
{escalations.slice(0, 3).map((esc, i) => (
<div
key={esc.id}
className="flex items-center gap-3 px-5 py-3"
style={{
borderBottom: i < Math.min(escalations.length, 3) - 1
? '1px solid var(--color-border-default)'
: undefined,
}}
>
<span className="h-2 w-2 shrink-0 rounded-full bg-amber-400 animate-pulse" />
<div className="flex-1 min-w-0">
<div className="text-sm text-foreground truncate">
{esc.problem_summary || 'Escalated session'}
</div>
<div className="text-[0.6875rem] text-muted-foreground">
{esc.problem_domain || 'General'}
<span className="mx-1.5 text-[var(--text-dimmed)]">&middot;</span>
<span className="font-sans text-xs">{timeAgo(esc.created_at)}</span>
</div>
</div>
<button
onClick={() => navigate(`/pilot/${esc.id}?pickup=true`)}
className="shrink-0 rounded-lg border border-amber-400/30 bg-amber-400/10 px-3 py-1 text-[0.6875rem] font-medium text-amber-400 hover:bg-amber-400/20 transition-colors"
>
Pick up
</button>
</div>
))}
</div>
</div>
)
}