use leptos::wasm_bindgen::JsCast; use leptos::*; #[component] pub fn Sidebar() -> impl IntoView { let store = use_context::().expect("store not provided"); let total_count = move || store.torrents.get().len(); let downloading_count = move || { store .torrents .get() .iter() .filter(|t| t.status == shared::TorrentStatus::Downloading) .count() }; let seeding_count = move || { store .torrents .get() .iter() .filter(|t| t.status == shared::TorrentStatus::Seeding) .count() }; let completed_count = move || { store .torrents .get() .iter() .filter(|t| { t.status == shared::TorrentStatus::Seeding || (t.status == shared::TorrentStatus::Paused && t.percent_complete >= 100.0) }) .count() }; let paused_count = move || { store .torrents .get() .iter() .filter(|t| t.status == shared::TorrentStatus::Paused) .count() }; let inactive_count = move || { store .torrents .get() .iter() .filter(|t| { t.status == shared::TorrentStatus::Paused || t.status == shared::TorrentStatus::Error }) .count() }; let close_drawer = move || { if let Some(element) = document().get_element_by_id("my-drawer") { if let Ok(input) = element.dyn_into::() { input.set_checked(false); } } }; let set_filter = move |f: crate::store::FilterStatus| { store.filter.set(f); close_drawer(); }; let filter_class = move |f: crate::store::FilterStatus| { if store.filter.get() == f { "active" } else { "" } }; let handle_logout = move |_| { spawn_local(async move { let client = gloo_net::http::Request::post("/api/auth/logout"); if let Ok(resp) = client.send().await { if resp.ok() { // Force full reload to clear state let _ = window().location().set_href("/login"); } } }); }; let username = move || { store.user.get().unwrap_or_else(|| "User".to_string()) }; let first_letter = move || { username().chars().next().unwrap_or('?').to_uppercase().to_string() }; view! {
{first_letter}
{username}
"Online"
}}