//! Match history page. use wasm_bindgen_futures::spawn_local; use sycamore::prelude::*; use crate::api; use crate::components::toast::toast; use crate::model::MatchesPage; #[component] pub fn HistoryPage() -> View { let page = create_signal(Option::::None); let error = create_signal(Option::::None); let cursor = create_signal(Option::::None); // Accumulated rows across "load more" clicks. let rows = create_signal(Vec::::new()); let load = move |next: Option| { spawn_local(async move { match api::my_matches(next.as_deref()).await { Ok(p) => { cursor.set(p.next_cursor.clone()); rows.update(|acc| acc.extend(p.results.iter().cloned())); page.set(Some(p)); } Err(e) => error.set(Some(e)), } }); }; let load2 = load; spawn_local(async move { match api::my_matches(None).await { Ok(p) => { cursor.set(p.next_cursor.clone()); rows.set(p.results.clone()); page.set(Some(p)); } Err(e) => error.set(Some(e)), } }); view! { div(class="page") { nav(class="top-nav") { a(href="/") { "← Lobby" } a(href="/leaderboard") { "Leaderboard" } } h1 { "My matches" } (toast(error)) (move || match page.get_clone() { None => view! { p(class="status") { "Loading…" } }, Some(_) if rows.get_clone().is_empty() => view! { p(class="status") { "No matches played yet." } }, Some(_) => { let table_rows = rows .get_clone() .into_iter() .map(|m| { let team_a: String = m .players .iter() .filter(|p| p.team == "A") .map(|p| p.display_name.clone()) .collect::>() .join(" & "); let team_b: String = m .players .iter() .filter(|p| p.team == "B") .map(|p| p.display_name.clone()) .collect::>() .join(" & "); let outcome = if m.you_won { "Won" } else { "Lost" }; let elo_delta = m .your_elo_delta .map(|d| if d >= 0 { format!("+{d}") } else { d.to_string() }) .unwrap_or_else(|| "—".to_string()); view! { tr { td { (m.finished_at.replace('T', " ").chars().take(16).collect::()) } td { (team_a) } td { (team_b) } td { (m.team_a_score) " – " (m.team_b_score) } td { "Team " (m.winner_team) } td(class=if m.you_won { "won" } else { "lost" }) { (outcome) } td(class=if m.you_won { "won" } else { "lost" }) { (elo_delta) } } } }) .collect::>(); view! { table(class="matches") { thead { tr { th { "Finished" } th { "Team A" } th { "Team B" } th { "Score" } th { "Winner" } th { "You" } th { "Elo" } } } tbody { (table_rows) } } (cursor.get_clone().map(|c| view! { button(class="button", on:click=move |_| load2(Some(c.clone()))) { "Load more" } })) } } }) } } }