import { useMemo } from "react"; import { Activity, AlertTriangle, Clock, Pause, Play, Zap } from "lucide-react"; import { useExecutorStats } from "../hooks/useExecutorStats"; import type { ExecutorState } from "../api"; interface ExecutorStatusBarProps { /** Project ID for fetching project-specific stats */ projectId?: string; } /** * Format a relative time string (e.g., "2m ago", "1h ago") */ function formatRelativeTime(timestamp: string | undefined): string { if (!timestamp) return "no activity"; const now = Date.now(); const then = new Date(timestamp).getTime(); const diffMs = now - then; const seconds = Math.floor(diffMs / 1000); const minutes = Math.floor(seconds / 60); const hours = Math.floor(minutes / 60); const days = Math.floor(hours / 24); if (days > 0) return `${days}d ago`; if (hours > 0) return `${hours}h ago`; if (minutes > 0) return `${minutes}m ago`; if (seconds > 10) return `${seconds}s ago`; return "just now"; } /** * Get display configuration for an executor state */ function getStateDisplay(state: ExecutorState): { label: string; color: string; icon: typeof Play } { switch (state) { case "running": return { label: "Running", color: "var(--color-success)", icon: Play }; case "paused": return { label: "Paused", color: "var(--triage)", icon: Pause }; case "idle": default: return { label: "Idle", color: "var(--text-muted)", icon: Zap }; } } /** * Footer status bar component that displays real-time executor statistics. * * Shows: * - Running tasks count with pulsing animation when > 0 * - Blocked tasks count with warning color when > 0 * - Queued tasks count * - Executor state badge (idle/running/paused) * - Last activity timestamp */ export function ExecutorStatusBar({ projectId }: ExecutorStatusBarProps) { const { stats, loading, error } = useExecutorStats(projectId); const stateDisplay = useMemo(() => getStateDisplay(stats.executorState), [stats.executorState]); const relativeTime = useMemo(() => formatRelativeTime(stats.lastActivityAt), [stats.lastActivityAt]); const StateIcon = stateDisplay.icon; if (error) { return (
{error}
); } if (loading && stats.runningTaskCount === 0) { return (
Loading...
); } return (
{/* Running tasks */}
0 ? "executor-status-bar__indicator--active" : ""}`} aria-hidden="true" /> Running {stats.runningTaskCount} {stats.maxConcurrent}
{/* Separator */}