/// StatusBar — bottom bar showing agent fleet state, cost, and attention. /// /// Mirrors the Svelte app's StatusBar.svelte (Mission Control bar). use dioxus::prelude::*; use crate::components::pulsing_dot::{PulsingDot, DotState}; #[derive(Clone, PartialEq)] pub struct FleetState { pub running: usize, pub idle: usize, pub stalled: usize, pub total_cost: f64, pub total_tokens: u64, pub project_count: usize, } #[component] pub fn StatusBar(fleet: FleetState) -> Element { rsx! { div { class: "status-bar", // Left section: agent counts div { class: "status-bar-left", // Running div { class: "status-item", PulsingDot { state: DotState::Running, size: "6px".to_string() } span { class: "status-count running", "{fleet.running}" } span { "running" } } // Idle div { class: "status-item", PulsingDot { state: DotState::Idle, size: "6px".to_string() } span { class: "status-count idle", "{fleet.idle}" } span { "idle" } } // Stalled if fleet.stalled > 0 { div { class: "status-item", PulsingDot { state: DotState::Stalled, size: "6px".to_string() } span { class: "status-count stalled", "{fleet.stalled}" } span { "stalled" } } } // Separator span { style: "color: var(--ctp-surface1);", "|" } // Projects div { class: "status-item", span { "{fleet.project_count} projects" } } } // Right section: cost + tokens div { class: "status-bar-right", div { class: "status-item", span { class: "status-cost", "${fleet.total_cost:.4}" } } div { class: "status-item", span { "{format_tokens(fleet.total_tokens)} tokens" } } } } } } fn format_tokens(tokens: u64) -> String { if tokens >= 1_000_000 { format!("{:.1}M", tokens as f64 / 1_000_000.0) } else if tokens >= 1_000 { format!("{:.1}K", tokens as f64 / 1_000.0) } else { tokens.to_string() } }