import { useState, useMemo } from 'react'; import type { ExecutionSummary } from '../../api/schema-types'; import { StatusPill } from '../../components/shared/StatusPill'; import { DurationBar } from '../../components/shared/DurationBar'; import { AppBadge } from '../../components/shared/AppBadge'; import { ProcessorTree } from './ProcessorTree'; import { ExchangeDetail } from './ExchangeDetail'; import styles from './ResultsTable.module.css'; interface ResultsTableProps { results: ExecutionSummary[]; loading: boolean; } type SortColumn = 'startTime' | 'status' | 'agentId' | 'routeId' | 'correlationId' | 'durationMs'; type SortDir = 'asc' | 'desc'; function formatTime(iso: string) { return new Date(iso).toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3, }); } function compareFn(a: ExecutionSummary, b: ExecutionSummary, col: SortColumn, dir: SortDir): number { let cmp = 0; switch (col) { case 'startTime': cmp = a.startTime.localeCompare(b.startTime); break; case 'status': cmp = a.status.localeCompare(b.status); break; case 'agentId': cmp = a.agentId.localeCompare(b.agentId); break; case 'routeId': cmp = a.routeId.localeCompare(b.routeId); break; case 'correlationId': cmp = (a.correlationId ?? '').localeCompare(b.correlationId ?? ''); break; case 'durationMs': cmp = a.durationMs - b.durationMs; break; } return dir === 'asc' ? cmp : -cmp; } interface SortableThProps { label: string; column: SortColumn; activeColumn: SortColumn | null; direction: SortDir; onSort: (col: SortColumn) => void; style?: React.CSSProperties; } function SortableTh({ label, column, activeColumn, direction, onSort, style }: SortableThProps) { const isActive = activeColumn === column; return (