feat: problem filtering
This commit is contained in:
parent
9898af1bf7
commit
83bd8e0e5e
@ -23,7 +23,7 @@ pub fn ProblemInfo(#[prop(into)] problem: Signal<models::Problem>) -> impl IntoV
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn NameValue(#[prop(into)] name: Signal<String>, #[prop(into)] value: Signal<String>) -> impl IntoView {
|
||||
view! {
|
||||
<p class="text-sm font-light mr-4 text-right text-orange-300">{name.get()}</p>
|
||||
<p class="font-light mr-4 text-right text-orange-300">{name.get()}</p>
|
||||
<p class="text-white">{value.get()}</p>
|
||||
}
|
||||
}
|
||||
|
@ -94,13 +94,6 @@ pub mod v2 {
|
||||
pub holds: BTreeMap<v1::HoldPosition, Hold>,
|
||||
pub problems: BTreeSet<ProblemUid>,
|
||||
}
|
||||
impl Wall {
|
||||
pub fn random_problem(&self) -> Option<ProblemUid> {
|
||||
use rand::seq::IteratorRandom;
|
||||
let mut rng = rand::rng();
|
||||
self.problems.iter().choose(&mut rng).copied()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct WallDimensions {
|
||||
|
@ -70,6 +70,7 @@ pub fn Wall() -> impl IntoView {
|
||||
});
|
||||
|
||||
let wall = crate::resources::wall_by_uid(wall_uid);
|
||||
let problems = crate::resources::problems_for_wall(wall_uid);
|
||||
|
||||
let header_items = move || HeaderItems {
|
||||
left: vec![],
|
||||
@ -98,7 +99,8 @@ pub fn Wall() -> impl IntoView {
|
||||
{move || Suspend::new(async move {
|
||||
tracing::info!("executing main suspend");
|
||||
let wall = wall.await?;
|
||||
let v = view! { <WithWall wall /> };
|
||||
let problems = problems.await?;
|
||||
let v = view! { <WithWall wall problems /> };
|
||||
Ok::<_, ServerFnError>(v)
|
||||
})}
|
||||
</Transition>
|
||||
@ -117,7 +119,7 @@ fn WithProblem(#[prop(into)] problem: Signal<models::Problem>) -> impl IntoView
|
||||
|
||||
#[component]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn WithWall(#[prop(into)] wall: Signal<models::Wall>) -> impl IntoView {
|
||||
fn WithWall(#[prop(into)] wall: Signal<models::Wall>, #[prop(into)] problems: Signal<Vec<models::Problem>>) -> impl IntoView {
|
||||
tracing::trace!("Enter");
|
||||
|
||||
let wall_uid = Signal::derive(move || wall.read().uid);
|
||||
@ -137,18 +139,36 @@ fn WithWall(#[prop(into)] wall: Signal<models::Wall>) -> impl IntoView {
|
||||
});
|
||||
};
|
||||
|
||||
let filtered_problems = Memo::new(move |_prev_val| {
|
||||
let filter_holds = filter_holds.get();
|
||||
problems.with(|problems| {
|
||||
problems
|
||||
.iter()
|
||||
.filter(|problem| filter_holds.iter().all(|hold_pos| problem.holds.contains_key(hold_pos)))
|
||||
.cloned()
|
||||
.collect::<Vec<models::Problem>>()
|
||||
})
|
||||
});
|
||||
|
||||
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());
|
||||
|
||||
let fn_next_problem = move |wall: &models::Wall| {
|
||||
set_problem_uid.set(wall.random_problem());
|
||||
let fn_next_problem = move || {
|
||||
let problems = filtered_problems.read();
|
||||
|
||||
use rand::seq::IteratorRandom;
|
||||
let mut rng = rand::rng();
|
||||
let problem = problems.iter().choose(&mut rng);
|
||||
let problem_uid = problem.map(|p| p.uid);
|
||||
|
||||
set_problem_uid.set(problem_uid);
|
||||
};
|
||||
|
||||
// Set a problem when wall is set (loaded)
|
||||
Effect::new(move |_prev_value| {
|
||||
if problem_uid.get().is_none() {
|
||||
tracing::debug!("Setting next problem");
|
||||
fn_next_problem(&wall.read());
|
||||
fn_next_problem();
|
||||
}
|
||||
});
|
||||
|
||||
@ -156,6 +176,7 @@ fn WithWall(#[prop(into)] wall: Signal<models::Wall>) -> impl IntoView {
|
||||
let problem_signal = Signal::derive(move || problem.get().transpose().map(Option::flatten));
|
||||
|
||||
let on_click_hold = move |hold_position: models::HoldPosition| {
|
||||
// Add/Remove hold position to problem filter
|
||||
set_filter_holds.update(|set| {
|
||||
if !set.remove(&hold_position) {
|
||||
set.insert(hold_position);
|
||||
@ -163,26 +184,18 @@ fn WithWall(#[prop(into)] wall: Signal<models::Wall>) -> impl IntoView {
|
||||
});
|
||||
};
|
||||
|
||||
let grid = {
|
||||
let wall = wall.clone();
|
||||
view! {
|
||||
let grid = view! {
|
||||
<Transition fallback=|| ()>
|
||||
{
|
||||
let wall = wall.clone();
|
||||
move || {
|
||||
let wall = wall.clone();
|
||||
{move || {
|
||||
Suspend::new(async move {
|
||||
let wall = wall.clone();
|
||||
tracing::info!("executing grid suspend");
|
||||
tracing::debug!("executing grid suspend");
|
||||
let view = view! {
|
||||
<Grid wall=wall.get() problem=problem_signal on_click_hold />
|
||||
};
|
||||
Ok::<_, ServerFnError>(view)
|
||||
})
|
||||
}
|
||||
}
|
||||
}}
|
||||
</Transition>
|
||||
}
|
||||
};
|
||||
|
||||
let filter = move || {
|
||||
@ -205,14 +218,30 @@ fn WithWall(#[prop(into)] wall: Signal<models::Wall>) -> impl IntoView {
|
||||
}
|
||||
}
|
||||
|
||||
view! { <div class="grid grid-cols-4 gap-2">{cells}</div> }
|
||||
let problems_counter = {
|
||||
let name = view! { <p class="font-light mr-4 text-right text-orange-300">{"Problems:"}</p> };
|
||||
let value = view! { <p class="text-white">{filtered_problems.read().len()}</p> };
|
||||
view! {
|
||||
<div class="grid grid-rows-none gap-y-1 gap-x-0.5 grid-cols-[auto,1fr]">
|
||||
{name} {value}
|
||||
</div>
|
||||
}
|
||||
};
|
||||
|
||||
let sep = (!cells.is_empty()).then_some(view! { <Separator /> });
|
||||
|
||||
view! {
|
||||
<div class="grid grid-cols-5 gap-1">{cells}</div>
|
||||
{sep}
|
||||
{problems_counter}
|
||||
}
|
||||
};
|
||||
|
||||
view! {
|
||||
<div class="inline-grid grid-cols-1 gap-8 md:grid-cols-[auto,1fr]">
|
||||
<div>{grid}</div>
|
||||
|
||||
<div class="flex flex-col w-screen-sm">
|
||||
<div class="flex flex-col" style="width:38rem">
|
||||
<Section title="Filter">{filter}</Section>
|
||||
|
||||
<Separator />
|
||||
@ -222,7 +251,7 @@ fn WithWall(#[prop(into)] wall: Signal<models::Wall>) -> impl IntoView {
|
||||
<Button
|
||||
icon=Icon::ArrowPath
|
||||
text="Next problem"
|
||||
onclick=move |_| fn_next_problem(&wall.read())
|
||||
onclick=move |_| fn_next_problem()
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user