Render and be able to edit bike rides (and sorta other time distance workouts) #169

Merged
savanni merged 13 commits from fitnesstrax/time-distance-workout into main 2024-02-09 00:05:26 +00:00
2 changed files with 90 additions and 50 deletions
Showing only changes of commit 74df2880bb - Show all commits

View File

@ -238,52 +238,8 @@ impl DayEdit {
*s.imp().on_finished.borrow_mut() = Box::new(on_finished);
*s.imp().view_model.borrow_mut() = Some(view_model.clone());
s.append(
&ActionGroup::builder()
.primary_action("Save", {
let s = s.clone();
let view_model = view_model.clone();
move || {
view_model.save();
s.finish();
}
})
.secondary_action("Cancel", {
let s = s.clone();
let view_model = view_model.clone();
move || {
view_model.revert();
s.finish();
}
})
.build(),
);
let top_row = gtk::Box::builder()
.orientation(gtk::Orientation::Horizontal)
.build();
top_row.append(
&weight_field(view_model.weight().map(WeightFormatter::from), {
let view_model = view_model.clone();
move |w| match w {
Some(w) => view_model.set_weight(*w),
None => eprintln!("have not implemented record delete"),
}
})
.widget(),
);
top_row.append(
&steps_editor(view_model.steps(), {
let view_model = view_model.clone();
move |s| match s {
Some(s) => view_model.set_steps(s),
None => eprintln!("have not implemented record delete"),
}
})
.widget(),
);
s.append(&top_row);
s.append(&control_buttons(&s, &view_model));
s.append(&weight_and_steps_row(&view_model));
s
}
@ -292,3 +248,57 @@ impl DayEdit {
(self.imp().on_finished.borrow())()
}
}
fn control_buttons(s: &DayEdit, view_model: &DayDetailViewModel) -> ActionGroup {
ActionGroup::builder()
.primary_action("Save", {
let s = s.clone();
let view_model = view_model.clone();
move || {
view_model.save();
s.finish();
}
})
.secondary_action("Cancel", {
let s = s.clone();
let view_model = view_model.clone();
move || {
let s = s.clone();
let view_model = view_model.clone();
glib::spawn_future_local(async move {
view_model.revert().await;
s.finish();
});
}
})
.build()
}
fn weight_and_steps_row(view_model: &DayDetailViewModel) -> gtk::Box {
let row = gtk::Box::builder()
.orientation(gtk::Orientation::Horizontal)
.build();
row.append(
&weight_field(view_model.weight().map(WeightFormatter::from), {
let view_model = view_model.clone();
move |w| match w {
Some(w) => view_model.set_weight(*w),
None => eprintln!("have not implemented record delete"),
}
})
.widget(),
);
row.append(
&steps_editor(view_model.steps(), {
let view_model = view_model.clone();
move |s| match s {
Some(s) => view_model.set_steps(s),
None => eprintln!("have not implemented record delete"),
}
})
.widget(),
);
row
}

View File

@ -374,8 +374,38 @@ impl DayDetailViewModel {
}
}
pub fn revert(&self) {
unimplemented!();
pub async fn revert(&self) {
self.populate_records().await;
}
async fn populate_records(&self) {
let records = self.provider.records(self.date, self.date).await.unwrap();
let (weight_records, records): (Vec<Record<TraxRecord>>, Vec<Record<TraxRecord>>) =
records.into_iter().partition(|r| r.data.is_weight());
let (step_records, records): (Vec<Record<TraxRecord>>, Vec<Record<TraxRecord>>) =
records.into_iter().partition(|r| r.data.is_steps());
*self.weight.write().unwrap() = weight_records
.first()
.and_then(|r| match r.data {
TraxRecord::Weight(ref w) => Some((r.id.clone(), w.clone())),
_ => None,
})
.map(|(id, w)| RecordState::Original(Record { id, data: w }));
*self.steps.write().unwrap() = step_records
.first()
.and_then(|r| match r.data {
TraxRecord::Steps(ref w) => Some((r.id.clone(), w.clone())),
_ => None,
})
.map(|(id, w)| RecordState::Original(Record { id, data: w }));
*self.records.write().unwrap() = records
.into_iter()
.map(|r| (r.id.clone(), RecordState::Original(r)))
.collect::<HashMap<RecordId, RecordState<TraxRecord>>>();
}
}
@ -383,7 +413,7 @@ impl DayDetailViewModel {
mod test {
use super::*;
use async_trait::async_trait;
use chrono::{DateTime, FixedOffset, TimeZone};
use chrono::{DateTime, FixedOffset};
use dimensioned::si;
use emseries::Record;
@ -640,7 +670,7 @@ mod test {
#[tokio::test]
async fn it_can_delete_an_existing_record() {
let (view_model, provider) = create_view_model().await;
let mut workout = view_model.time_distance_records().first().cloned().unwrap();
let workout = view_model.time_distance_records().first().cloned().unwrap();
view_model.remove_record(workout.id);
assert_eq!(