Skip to content

Commit

Permalink
Improve representation of sets per muscle
Browse files Browse the repository at this point in the history
  • Loading branch information
treiher committed Jun 2, 2024
1 parent a52f6bc commit e44179e
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 47 deletions.
12 changes: 12 additions & 0 deletions frontend/assets/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -193,3 +193,15 @@ div.is-calendar {
.is-scrollbar-width-none {
scrollbar-width: none;
}

// Tags

.tags.has-addons .tag:not(:first-child) {
border-left: 1px solid;
}

// Dropdown menu

.dropdown-menu.has-no-min-width {
min-width: auto;
}
88 changes: 66 additions & 22 deletions frontend/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1087,32 +1087,76 @@ where
]
}

pub fn view_sets_per_muscle<Ms>(stimulus_per_muscle: &[(&str, u32)]) -> Node<Ms>
pub fn view_sets_per_muscle<Ms>(stimulus_per_muscle: &[(domain::Muscle, u32)]) -> Vec<Node<Ms>>
where
Ms: 'static,
{
let mut stimulus_per_muscle = stimulus_per_muscle.to_vec();
stimulus_per_muscle.sort_by(|a, b| b.1.cmp(&a.1));
let mut groups = vec![vec![], vec![], vec![], vec![]];
for (muscle, stimulus) in stimulus_per_muscle {
let name = domain::Muscle::name(muscle);
let description = domain::Muscle::description(muscle);
let sets = f64::from(stimulus) / 100.0;
let sets_str = format!("{:.1$}", sets, usize::from(sets.fract() != 0.0));
if sets > 10.0 {
groups[0].push((name, description, sets_str, vec!["is-dark"]));
} else if sets >= 3.0 {
groups[1].push((name, description, sets_str, vec!["is-dark", "is-link"]));
} else if sets > 0.0 {
groups[2].push((name, description, sets_str, vec!["is-light", "is-link"]));
} else {
groups[3].push((name, description, sets_str, vec!["is-light"]));
}
}
groups
.iter()
.filter(|g| !g.is_empty())
.map(|g| view_tags_with_addons(g))
.collect::<Vec<_>>()
}

fn view_tags_with_addons<Ms>(tags: &[(&str, &str, String, Vec<&str>)]) -> Node<Ms>
where
Ms: 'static,
{
div![
C!["table-container"],
table![
C!["table"],
C!["is-flex"],
C!["has-text-centered"],
tbody![
C!["mx-auto"],
stimulus_per_muscle
.iter()
.map(|(name, stimulus)| {
let sets = f64::from(*stimulus) / 100.0;
tr![
td![C!["is-borderless"], C!["py-1"], name],
td![
C!["is-borderless"],
C!["py-1"],
format!("{:.1$}", sets, usize::from(sets.fract() != 0.0))
]
]
})
.collect::<Vec<_>>(),
C!["field"],
C!["is-grouped"],
C!["is-grouped-multiline"],
C!["is-justify-content-center"],
C!["mx-2"],
tags.iter().map(|(name, description, value, attributes)| {
view_element_with_description(
div![
C!["tags"],
C!["has-addons"],
span![C!["tag"], attributes.iter().map(|a| C![a]), name],
span![C!["tag"], attributes.iter().map(|a| C![a]), value]
],
description,
)
})
]
}

pub fn view_element_with_description<Ms>(element: Node<Ms>, description: &str) -> Node<Ms> {
div![
C!["dropdown"],
C!["is-hoverable"],
div![
C!["dropdown-trigger"],
div![C!["control"], C!["is-clickable"], element]
],
IF![
not(description.is_empty()) =>
div![
C!["dropdown-menu"],
C!["has-no-min-width"],
div![
C!["dropdown-content"],
div![C!["dropdown-item"], description]
]
]
]
]
Expand Down
8 changes: 6 additions & 2 deletions frontend/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,10 +279,14 @@ impl Routine {
}

pub fn stimulus_per_muscle(&self, exercises: &BTreeMap<u32, Exercise>) -> BTreeMap<u8, u32> {
let mut result: BTreeMap<u8, u32> = BTreeMap::new();
let mut result: BTreeMap<u8, u32> = domain::Muscle::iter()
.map(|m| (domain::Muscle::id(*m), 0))
.collect();
for section in &self.sections {
for (id, stimulus) in section.stimulus_per_muscle(exercises) {
*result.entry(id).or_insert(0) += stimulus;
if result.contains_key(&id) {
*result.entry(id).or_insert(0) += stimulus;
}
}
}
result
Expand Down
15 changes: 9 additions & 6 deletions frontend/src/page/exercise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,12 +422,15 @@ fn view_muscles(model: &Model) -> Node<Msg> {
C!["mx-2"],
C!["mb-5"],
muscles.iter().map(|(m, stimulus)| {
span![
C!["tag"],
C!["is-link"],
C![IF![*stimulus < 100 => "is-light"]],
domain::Muscle::name(**m)
]
common::view_element_with_description(
span![
C!["tag"],
C!["is-link"],
C![IF![*stimulus < 100 => "is-light"]],
domain::Muscle::name(**m)
],
domain::Muscle::description(**m),
)
})
]
}
Expand Down
10 changes: 2 additions & 8 deletions frontend/src/page/routine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1261,14 +1261,8 @@ fn view_muscles(routine: &data::Routine, data_model: &data::Model) -> Node<Msg>
let stimulus_per_muscle = routine
.stimulus_per_muscle(&data_model.exercises)
.iter()
.map(|(id, stimulus)| {
(
domain::Muscle::from_repr(*id)
.as_ref()
.map(|m| domain::Muscle::name(*m))
.unwrap_or_default(),
*stimulus,
)
.filter_map(|(id, stimulus)| {
domain::Muscle::from_repr(*id).map(|muscle| (muscle, *stimulus))
})
.collect::<Vec<_>>();
if stimulus_per_muscle.is_empty() {
Expand Down
10 changes: 2 additions & 8 deletions frontend/src/page/training_session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1950,14 +1950,8 @@ fn view_muscles(training_session: &data::TrainingSession, data_model: &data::Mod
let stimulus_per_muscle = training_session
.stimulus_per_muscle(&data_model.exercises)
.iter()
.map(|(id, stimulus)| {
(
domain::Muscle::from_repr(*id)
.as_ref()
.map(|m| domain::Muscle::name(*m))
.unwrap_or_default(),
*stimulus,
)
.filter_map(|(id, stimulus)| {
domain::Muscle::from_repr(*id).map(|muscle| (muscle, *stimulus))
})
.collect::<Vec<_>>();
if stimulus_per_muscle.is_empty() {
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/web_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ def test_training_session(driver: webdriver.Chrome) -> None:
page.load()

page.wait_for_title(str(workout.date))
assert page.get_sets() == sets
assert page.get_sets() == [*sets, "Pecs", "2"]

page.edit()

Expand Down

0 comments on commit e44179e

Please sign in to comment.