← back to Dw Boardroom Governance
frontend/src/components/EscalationQueue.tsx
58 lines
import { api } from '../api';
import { useApi } from '../hooks/useApi';
export default function EscalationQueue() {
const { data: escalations, refresh } = useApi(() => api.getActiveEscalations(), []);
async function triggerCheck() {
try {
await api.triggerEscalationCheck();
refresh();
} catch (err: any) {
console.error('[EscalationQueue] triggerCheck failed:', err.message);
}
}
return (
<div style={styles.card}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
<h3 style={styles.cardTitle}>Escalation Queue</h3>
<button style={styles.checkBtn} onClick={triggerCheck}>Run Check</button>
</div>
<div style={styles.list}>
{(!escalations || escalations.length === 0) && (
<div style={styles.empty}>No active escalations. Decisions past the threshold will appear here.</div>
)}
{escalations?.map((e: any) => (
<div key={e.id} style={styles.item}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<span style={{ fontWeight: 600, fontSize: 13 }}>{e.topic || 'Unknown topic'}</span>
<span style={styles.timeBadge}>{e.hours_elapsed}h elapsed</span>
</div>
<div style={{ fontSize: 11, color: '#7a7f96', marginTop: 4 }}>
Owner: {e.owner} | Type: {e.escalation_type} | Action: {e.action_taken}
</div>
{e.decision_status && (
<span style={{ ...styles.statusBadge, marginTop: 6, display: 'inline-block' }}>
Decision: {e.decision_status}
</span>
)}
</div>
))}
</div>
</div>
);
}
const styles: Record<string, React.CSSProperties> = {
card: { background: '#1a1a2e', borderRadius: 12, padding: 20, border: '1px solid #252540' },
cardTitle: { margin: 0, fontSize: 15, fontWeight: 700 },
checkBtn: { padding: '6px 14px', borderRadius: 6, border: 'none', background: '#ef444433', color: '#ef4444', fontWeight: 600, fontSize: 11, cursor: 'pointer', fontFamily: 'inherit' },
list: { display: 'flex', flexDirection: 'column', gap: 8 },
empty: { color: '#7a7f96', fontSize: 13, textAlign: 'center' as const, padding: 30 },
item: { background: '#12121f', borderRadius: 8, padding: 12, border: '1px solid #ef444433' },
timeBadge: { padding: '2px 10px', borderRadius: 4, fontSize: 11, fontWeight: 700, background: '#ef444422', color: '#ef4444' },
statusBadge: { padding: '2px 8px', borderRadius: 4, fontSize: 10, fontWeight: 600, background: '#f59e0b22', color: '#f59e0b' },
};