refactor: radio button group
This commit is contained in:
parent
7d95e48941
commit
9b15daaf6d
@ -2,7 +2,6 @@ use super::icons::Icon;
|
||||
use crate::components::outlined_box::OutlinedBox;
|
||||
use crate::gradient::Gradient;
|
||||
use leptos::prelude::*;
|
||||
use web_sys::MouseEvent;
|
||||
|
||||
#[component]
|
||||
pub fn Button(
|
||||
@ -13,8 +12,6 @@ pub fn Button(
|
||||
#[prop(optional)] color: Gradient,
|
||||
|
||||
#[prop(into, optional)] highlight: MaybeProp<bool>,
|
||||
|
||||
onclick: impl FnMut(MouseEvent) + 'static,
|
||||
) -> impl IntoView {
|
||||
let margin = "mx-2 my-1 sm:mx-5 sm:my-2.5";
|
||||
|
||||
@ -48,7 +45,7 @@ pub fn Button(
|
||||
};
|
||||
|
||||
view! {
|
||||
<button on:click=onclick type="button" class="hover:brightness-125 active:brightness-90">
|
||||
<button type="button" class="hover:brightness-125 active:brightness-90">
|
||||
<OutlinedBox color highlight>
|
||||
<div class="flex items-stretch">{icon_view} {separator} {text_view}</div>
|
||||
</OutlinedBox>
|
||||
@ -65,7 +62,7 @@ mod tests {
|
||||
let text = "foo";
|
||||
let onclick = |_| {};
|
||||
|
||||
view! { <Button text onclick /> };
|
||||
view! { <Button text on:click=onclick /> };
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -74,6 +71,6 @@ mod tests {
|
||||
let text = "foo";
|
||||
let onclick = |_| {};
|
||||
|
||||
view! { <Button icon text onclick /> };
|
||||
view! { <Button icon text on:click=onclick /> };
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ pub mod v4 {
|
||||
|
||||
pub mod v3 {
|
||||
use super::v2;
|
||||
use derive_more::Display;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use std::collections::BTreeMap;
|
||||
@ -54,7 +55,7 @@ pub mod v3 {
|
||||
pub is_saved: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Copy)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Copy, Display)]
|
||||
pub enum Attempt {
|
||||
/// Tried to climb problem, but was not able to.
|
||||
Attempt,
|
||||
|
@ -4,7 +4,7 @@ use chrono::Utc;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
impl UserInteraction {
|
||||
pub fn new(wall_uid: WallUid, problem_uid: ProblemUid) -> Self {
|
||||
pub(crate) fn new(wall_uid: WallUid, problem_uid: ProblemUid) -> Self {
|
||||
Self {
|
||||
wall_uid,
|
||||
problem_uid,
|
||||
@ -14,11 +14,11 @@ impl UserInteraction {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn latest_attempt(&self) -> Option<DatedAttempt> {
|
||||
pub(crate) fn latest_attempt(&self) -> Option<DatedAttempt> {
|
||||
self.attempted_on.last_key_value().map(Into::into)
|
||||
}
|
||||
|
||||
pub fn todays_attempt(&self) -> Option<Attempt> {
|
||||
pub(crate) fn todays_attempt(&self) -> Option<Attempt> {
|
||||
self.latest_attempt()
|
||||
.filter(|latest_attempt| {
|
||||
let today_local_naive = chrono::Local::now().date_naive();
|
||||
@ -28,12 +28,12 @@ impl UserInteraction {
|
||||
.map(|dated_attempt| dated_attempt.attempt)
|
||||
}
|
||||
|
||||
pub fn best_attempt(&self) -> Option<DatedAttempt> {
|
||||
pub(crate) fn best_attempt(&self) -> Option<DatedAttempt> {
|
||||
self.attempted_on.iter().max_by_key(|(_date_time, attempt)| *attempt).map(Into::into)
|
||||
}
|
||||
|
||||
pub fn attempted_on(&self) -> impl IntoIterator<Item = DatedAttempt> {
|
||||
self.attempted_on.iter().map(Into::into)
|
||||
pub(crate) fn attempted_on(&self) -> impl IntoIterator<Item = DatedAttempt> {
|
||||
self.attempted_on.iter().rev().map(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,19 +59,19 @@ impl From<(&DateTime<Utc>, &Attempt)> for DatedAttempt {
|
||||
}
|
||||
|
||||
impl WallUid {
|
||||
pub fn create() -> Self {
|
||||
pub(crate) fn create() -> Self {
|
||||
Self(uuid::Uuid::new_v4())
|
||||
}
|
||||
}
|
||||
|
||||
impl ProblemUid {
|
||||
pub fn create() -> Self {
|
||||
pub(crate) fn create() -> Self {
|
||||
Self(uuid::Uuid::new_v4())
|
||||
}
|
||||
pub fn min() -> Self {
|
||||
pub(crate) fn min() -> Self {
|
||||
Self(uuid::Uuid::nil())
|
||||
}
|
||||
pub fn max() -> Self {
|
||||
pub(crate) fn max() -> Self {
|
||||
Self(uuid::Uuid::max())
|
||||
}
|
||||
}
|
||||
@ -87,7 +87,18 @@ impl Image {
|
||||
}
|
||||
|
||||
impl ImageUid {
|
||||
pub fn create() -> Self {
|
||||
pub(crate) fn create() -> Self {
|
||||
Self(uuid::Uuid::new_v4())
|
||||
}
|
||||
}
|
||||
|
||||
impl Attempt {
|
||||
pub(crate) fn icon(&self) -> crate::components::icons::Icon {
|
||||
use crate::components::icons::Icon;
|
||||
match self {
|
||||
Attempt::Attempt => Icon::ArrowTrendingUp,
|
||||
Attempt::Send => Icon::Trophy,
|
||||
Attempt::Flash => Icon::BoltSolid,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,35 +1,3 @@
|
||||
// +--------------- Filter ----------- ↓ -+
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// +--------------------------------------+
|
||||
|
||||
// +---------------------------+
|
||||
// | Next Problem |
|
||||
// +---------------------------+
|
||||
|
||||
// +--------------- Problem --------------+
|
||||
// | Name: ... |
|
||||
// | Method: ... |
|
||||
// | Set by: ... |
|
||||
// | |
|
||||
// | | Flash | Top | Attempt | |
|
||||
// | |
|
||||
// +--------------------------------------+
|
||||
|
||||
// +---------+ +---------+ +---------+
|
||||
// | Flash | | Send | | Attempt |
|
||||
// +---------+ +---------+ +---------+
|
||||
|
||||
// +---------- <Latest attempt> ----------+
|
||||
// | Today: <Attempt> |
|
||||
// | 14 days ago: <Attempt> |
|
||||
// +--------------------------------------+
|
||||
|
||||
use crate::codec::ron::RonEncoded;
|
||||
use crate::components::OnHoverRed;
|
||||
use crate::components::ProblemInfo;
|
||||
@ -48,7 +16,6 @@ use leptos::prelude::*;
|
||||
use leptos_router::params::Params;
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::BTreeSet;
|
||||
use web_sys::MouseEvent;
|
||||
|
||||
#[derive(Params, PartialEq, Clone)]
|
||||
struct RouteParams {
|
||||
@ -323,7 +290,7 @@ fn WithWall(
|
||||
<Button
|
||||
icon=Icon::ArrowPath
|
||||
text="Next problem"
|
||||
onclick=move |_| fn_next_problem()
|
||||
on:click=move |_| fn_next_problem()
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -367,11 +334,13 @@ fn WithUserInteraction(
|
||||
) -> impl IntoView {
|
||||
tracing::debug!("Enter WithUserInteraction");
|
||||
|
||||
let user_interaction_rw = RwSignal::new(None);
|
||||
let parent_user_interaction = user_interaction;
|
||||
|
||||
let user_interaction = RwSignal::new(None);
|
||||
Effect::new(move || {
|
||||
let i = user_interaction.get();
|
||||
let i = parent_user_interaction.get();
|
||||
tracing::info!("setting user interaction to parent user interaction value: {i:?}");
|
||||
user_interaction_rw.set(i);
|
||||
user_interaction.set(i);
|
||||
});
|
||||
|
||||
let submit_attempt = ServerAction::<RonEncoded<server_functions::UpsertTodaysAttempt>>::new();
|
||||
@ -380,53 +349,67 @@ fn WithUserInteraction(
|
||||
tracing::info!("flaf");
|
||||
if let Some(Ok(v)) = submit_attempt_value.get() {
|
||||
tracing::info!("setting user interaction to action return value: {v:?}");
|
||||
user_interaction_rw.set(Some(v.into_inner()));
|
||||
user_interaction.set(Some(v.into_inner()));
|
||||
}
|
||||
});
|
||||
|
||||
let latest_attempt = signals::latest_attempt(user_interaction_rw.into());
|
||||
let todays_attempt = signals::todays_attempt(user_interaction_rw.into());
|
||||
let todays_attempt = signals::todays_attempt(user_interaction.into());
|
||||
|
||||
let ui_is_flash = RwSignal::new(false);
|
||||
let ui_is_send = RwSignal::new(false);
|
||||
let ui_is_attempt = RwSignal::new(false);
|
||||
let ui_is_favorite = RwSignal::new(false);
|
||||
let mut attempt_radio_buttons = vec![];
|
||||
for variant in [models::Attempt::Flash, models::Attempt::Send, models::Attempt::Attempt] {
|
||||
let ui_toggle = Signal::derive(move || todays_attempt.get() == Some(variant));
|
||||
let onclick = move |_| {
|
||||
let attempt = if ui_toggle.get() { None } else { Some(variant) };
|
||||
submit_attempt.dispatch(RonEncoded(server_functions::UpsertTodaysAttempt {
|
||||
wall_uid: wall_uid.get(),
|
||||
problem_uid: problem_uid.get(),
|
||||
attempt,
|
||||
}));
|
||||
};
|
||||
attempt_radio_buttons.push(view! { <AttemptRadioButton on:click=onclick variant selected=ui_toggle /> });
|
||||
}
|
||||
|
||||
Effect::new(move || {
|
||||
let attempt = todays_attempt.get();
|
||||
ui_is_flash.set(matches!(attempt, Some(models::Attempt::Flash)));
|
||||
ui_is_send.set(matches!(attempt, Some(models::Attempt::Send)));
|
||||
ui_is_attempt.set(matches!(attempt, Some(models::Attempt::Attempt)));
|
||||
});
|
||||
view! {
|
||||
<AttemptRadio>{attempt_radio_buttons}</AttemptRadio>
|
||||
<Separator />
|
||||
<History user_interaction />
|
||||
}
|
||||
}
|
||||
|
||||
let onclick_flash = move |_| {
|
||||
let attempt = if ui_is_flash.get() { None } else { Some(models::Attempt::Flash) };
|
||||
submit_attempt.dispatch(RonEncoded(server_functions::UpsertTodaysAttempt {
|
||||
wall_uid: wall_uid.get(),
|
||||
problem_uid: problem_uid.get(),
|
||||
attempt,
|
||||
}));
|
||||
};
|
||||
let onclick_send = move |_| {
|
||||
let attempt = if ui_is_send.get() { None } else { Some(models::Attempt::Send) };
|
||||
submit_attempt.dispatch(RonEncoded(server_functions::UpsertTodaysAttempt {
|
||||
wall_uid: wall_uid.get(),
|
||||
problem_uid: problem_uid.get(),
|
||||
attempt,
|
||||
}));
|
||||
};
|
||||
let onclick_attempt = move |_| {
|
||||
let attempt = if ui_is_attempt.get() { None } else { Some(models::Attempt::Attempt) };
|
||||
submit_attempt.dispatch(RonEncoded(server_functions::UpsertTodaysAttempt {
|
||||
wall_uid: wall_uid.get(),
|
||||
problem_uid: problem_uid.get(),
|
||||
attempt,
|
||||
}));
|
||||
#[component]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn AttemptRadio(children: Children) -> impl IntoView {
|
||||
tracing::debug!("Enter");
|
||||
|
||||
view! {
|
||||
<div class="gap-2 flex flex-row justify-evenly md:flex-col 2xl:flex-row">{children()}</div>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn AttemptRadioButton(variant: models::Attempt, #[prop(into)] selected: Signal<bool>) -> impl IntoView {
|
||||
tracing::debug!("Enter");
|
||||
|
||||
let text = variant.to_string();
|
||||
let icon = variant.icon();
|
||||
let color = match variant {
|
||||
models::Attempt::Attempt => Gradient::PinkOrange,
|
||||
models::Attempt::Send => Gradient::TealLime,
|
||||
models::Attempt::Flash => Gradient::CyanBlue,
|
||||
};
|
||||
view! { <Button text icon color highlight=selected /> }
|
||||
}
|
||||
|
||||
// TODO: loop over attempts in user_interaction
|
||||
let v = move || {
|
||||
user_interaction_rw
|
||||
#[component]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn History(#[prop(into)] user_interaction: Signal<Option<models::UserInteraction>>) -> impl IntoView {
|
||||
tracing::debug!("Enter");
|
||||
|
||||
let latest_attempt = signals::latest_attempt(user_interaction);
|
||||
|
||||
let attempts = move || {
|
||||
user_interaction
|
||||
.read()
|
||||
.as_ref()
|
||||
.iter()
|
||||
@ -446,61 +429,7 @@ fn WithUserInteraction(
|
||||
})
|
||||
};
|
||||
|
||||
view! {
|
||||
<AttemptRadio
|
||||
flash=ui_is_flash
|
||||
send=ui_is_send
|
||||
attempt=ui_is_attempt
|
||||
onclick_flash
|
||||
onclick_send
|
||||
onclick_attempt
|
||||
/>
|
||||
|
||||
<Separator />
|
||||
|
||||
<Section title="History">{placeholder} {v}</Section>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn AttemptRadio(
|
||||
#[prop(into)] flash: Signal<bool>,
|
||||
#[prop(into)] send: Signal<bool>,
|
||||
#[prop(into)] attempt: Signal<bool>,
|
||||
onclick_flash: impl FnMut(MouseEvent) + 'static,
|
||||
onclick_send: impl FnMut(MouseEvent) + 'static,
|
||||
onclick_attempt: impl FnMut(MouseEvent) + 'static,
|
||||
) -> impl IntoView {
|
||||
tracing::debug!("Enter");
|
||||
|
||||
view! {
|
||||
<div class="gap-2 flex flex-row justify-evenly md:flex-col 2xl:flex-row">
|
||||
<Button
|
||||
onclick=onclick_flash
|
||||
text="Flash"
|
||||
icon=Icon::BoltSolid
|
||||
color=Gradient::CyanBlue
|
||||
highlight=Signal::derive(move || { flash.get() })
|
||||
/>
|
||||
|
||||
<Button
|
||||
onclick=onclick_send
|
||||
text="Send"
|
||||
icon=Icon::Trophy
|
||||
color=Gradient::TealLime
|
||||
highlight=Signal::derive(move || { send.get() })
|
||||
/>
|
||||
|
||||
<Button
|
||||
onclick=onclick_attempt
|
||||
text="Attempt"
|
||||
icon=Icon::ArrowTrendingUp
|
||||
color=Gradient::PinkOrange
|
||||
highlight=Signal::derive(move || { attempt.get() })
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
view! { <Section title="History">{placeholder} {attempts}</Section> }
|
||||
}
|
||||
|
||||
#[component]
|
||||
|
Loading…
x
Reference in New Issue
Block a user