diff --git a/crates/ascend/src/pages/wall.rs b/crates/ascend/src/pages/wall.rs index 46c2b2e..3f18733 100644 --- a/crates/ascend/src/pages/wall.rs +++ b/crates/ascend/src/pages/wall.rs @@ -45,6 +45,7 @@ use crate::server_functions; use leptos::Params; use leptos::prelude::*; use leptos_router::params::Params; +use std::collections::BTreeSet; use web_sys::MouseEvent; #[derive(Params, PartialEq, Clone)] @@ -122,6 +123,19 @@ fn WithWall(#[prop(into)] wall: Signal) -> impl IntoView { let (problem_uid, set_problem_uid) = leptos_router::hooks::query_signal::("problem"); + // Filter + let (filter_holds, set_filter_holds) = signal(BTreeSet::new()); + let filter_add_hold = move |hold_pos: models::HoldPosition| { + set_filter_holds.update(move |set| { + set.insert(hold_pos); + }); + }; + let filter_remove_hold = move |hold_pos: models::HoldPosition| { + set_filter_holds.update(move |set| { + set.remove(&hold_pos); + }); + }; + let problem = crate::resources::problem_by_uid_optional(wall_uid, problem_uid.into()); let user_interaction = crate::resources::user_interaction(wall_uid, problem_uid.into()); @@ -140,6 +154,14 @@ fn WithWall(#[prop(into)] wall: Signal) -> impl IntoView { // merge outer option (resource hasn't resolved yet) with inner option (there is no problem for the wall) let problem_signal = Signal::derive(move || problem.get().transpose().map(Option::flatten)); + let on_click_hold = move |hold_position: models::HoldPosition| { + set_filter_holds.update(|set| { + if !set.remove(&hold_position) { + set.insert(hold_position); + } + }); + }; + let grid = { let wall = wall.clone(); view! { @@ -151,7 +173,9 @@ fn WithWall(#[prop(into)] wall: Signal) -> impl IntoView { Suspend::new(async move { let wall = wall.clone(); tracing::info!("executing grid suspend"); - let view = view! { }; + let view = view! { + + }; Ok::<_, ServerFnError>(view) }) } @@ -160,12 +184,25 @@ fn WithWall(#[prop(into)] wall: Signal) -> impl IntoView { } }; + let filter = move || { + let mut cells = vec![]; + for hold_pos in filter_holds.get() { + let w = &*wall.read(); + if let Some(hold) = w.holds.get(&hold_pos).cloned() { + let v = view! { }; + cells.push(v); + } + } + + view! {
{cells}
} + }; + view! {
{grid}
-
-
{}
+
+
{filter}
@@ -369,14 +406,27 @@ fn AttemptRadio( #[component] #[tracing::instrument(skip_all)] -fn Grid(wall: models::Wall, #[prop(into)] problem: Signal, ServerFnError>>) -> impl IntoView { +fn Grid( + wall: models::Wall, + #[prop(into)] problem: Signal, ServerFnError>>, + on_click_hold: impl Fn(models::HoldPosition) + 'static, +) -> impl IntoView { tracing::debug!("Enter"); + let on_click_hold = std::rc::Rc::new(on_click_hold); + let mut cells = vec![]; for (&hold_position, hold) in &wall.holds { let role = move || problem.get().map(|o| o.and_then(|p| p.holds.get(&hold_position).copied())); let role = Signal::derive(role); - let cell = view! { }; + + let on_click = { + let on_click_hold = std::rc::Rc::clone(&on_click_hold); + move |_| { + on_click_hold(hold_position); + } + }; + let cell = view! { }; cells.push(cell); } let grid_classes = format!("grid grid-rows-{} grid-cols-{} gap-1", wall.rows, wall.cols,); @@ -393,13 +443,20 @@ fn Grid(wall: models::Wall, #[prop(into)] problem: Signal, ServerFnError>>) -> impl IntoView { +fn Hold( + hold: models::Hold, + + #[prop(optional)] + #[prop(into)] + role: Option, ServerFnError>>>, +) -> impl IntoView { tracing::trace!("Enter"); move || { - let role = role.get()?; + let mut class = "bg-sky-100 aspect-square rounded hover:brightness-125".to_string(); + if let Some(role) = role { + let role = role.get()?; - let class = { let role_classes = match role { Some(HoldRole::Start) => Some("outline outline-offset-2 outline-green-500"), Some(HoldRole::Normal) => Some("outline outline-offset-2 outline-blue-500"), @@ -407,13 +464,11 @@ fn Hold(hold: models::Hold, role: Signal, ServerFnError> Some(HoldRole::End) => Some("outline outline-offset-2 outline-red-500"), None => Some("brightness-50"), }; - let mut s = "bg-sky-100 aspect-square rounded hover:brightness-125".to_string(); if let Some(c) = role_classes { - s.push(' '); - s.push_str(c); + class.push(' '); + class.push_str(c); } - s - }; + } let img = hold.image.as_ref().map(|img| { let srcset = img.srcset();