import { useNavigate } from 'react-router'; import { StatusDot, MonoText, Badge } from '@cameleer/design-system'; import { useCorrelationChain } from '../../api/queries/correlation'; import type { ExecutionDetail } from '../../components/ExecutionDiagram/types'; import styles from './ExchangeHeader.module.css'; interface ExchangeHeaderProps { detail: ExecutionDetail; } type StatusVariant = 'success' | 'error' | 'running' | 'warning'; function statusVariant(s: string): StatusVariant { switch (s) { case 'COMPLETED': return 'success'; case 'FAILED': return 'error'; case 'RUNNING': return 'running'; default: return 'warning'; } } function statusLabel(s: string): string { switch (s) { case 'COMPLETED': return 'OK'; case 'FAILED': return 'ERR'; case 'RUNNING': return 'RUN'; default: return s; } } function formatDuration(ms: number): string { if (ms >= 60_000) return `${(ms / 1000).toFixed(0)}s`; if (ms >= 1000) return `${(ms / 1000).toFixed(2)}s`; return `${ms}ms`; } export function ExchangeHeader({ detail }: ExchangeHeaderProps) { const navigate = useNavigate(); const { data: chainResult } = useCorrelationChain(detail.correlationId ?? null); const chain = chainResult?.data; const showChain = chain && chain.length > 1; const attrs = Object.entries(detail.attributes ?? {}); return (
{/* Exchange info — always shown */}
{attrs.length > 0 && ( <> {attrs.map(([k, v]) => ( ))} )} {detail.applicationName} {detail.routeId} {detail.agentId && ( <> Agent {detail.agentId} )} {formatDuration(detail.durationMs)}
{/* Correlation chain — only when multiple correlated exchanges exist */} {showChain && (
Correlated {chain.map((ce: any, i: number) => { const isCurrent = ce.executionId === detail.executionId; const variant = statusVariant(ce.status); const statusCls = variant === 'success' ? styles.chainNodeSuccess : variant === 'error' ? styles.chainNodeError : variant === 'running' ? styles.chainNodeRunning : styles.chainNodeWarning; return ( {i > 0 && } ); })}
)}
); }