mirror of
https://github.com/zaphar/kitchen.git
synced 2025-07-21 19:29:49 -04:00
feat: Allow restoring deleted inventory items
This commit is contained in:
parent
c77fa24515
commit
4ed0b6f8fb
@ -86,6 +86,7 @@ pub enum Message {
|
||||
UpdateCategory(String, String, Option<Box<dyn FnOnce()>>),
|
||||
ResetInventory,
|
||||
AddFilteredIngredient(IngredientKey),
|
||||
RemoveFilteredIngredient(IngredientKey),
|
||||
UpdateAmt(IngredientKey, String),
|
||||
SetUserData(UserData),
|
||||
SaveState(Option<Box<dyn FnOnce()>>),
|
||||
@ -124,6 +125,9 @@ impl Debug for Message {
|
||||
Self::AddFilteredIngredient(arg0) => {
|
||||
f.debug_tuple("AddFilteredIngredient").field(arg0).finish()
|
||||
}
|
||||
Self::RemoveFilteredIngredient(arg0) => {
|
||||
f.debug_tuple("RemoveFilteredIngredient").field(arg0).finish()
|
||||
}
|
||||
Self::UpdateAmt(arg0, arg1) => {
|
||||
f.debug_tuple("UpdateAmt").field(arg0).field(arg1).finish()
|
||||
}
|
||||
@ -393,6 +397,9 @@ impl MessageMapper<Message, AppState> for StateMachine {
|
||||
Message::AddFilteredIngredient(key) => {
|
||||
original_copy.filtered_ingredients.insert(key);
|
||||
}
|
||||
Message::RemoveFilteredIngredient(key) => {
|
||||
original_copy.filtered_ingredients.remove(&key);
|
||||
}
|
||||
Message::UpdateAmt(key, amt) => {
|
||||
original_copy.modified_amts.insert(key, amt);
|
||||
}
|
||||
|
@ -19,6 +19,115 @@ use tracing::{debug, info, instrument};
|
||||
|
||||
use crate::app_state::{Message, StateHandler};
|
||||
|
||||
#[instrument(skip_all)]
|
||||
fn make_deleted_ingredients_rows<'ctx, G: Html>(
|
||||
cx: Scope<'ctx>,
|
||||
sh: StateHandler<'ctx>,
|
||||
show_staples: &'ctx ReadSignal<bool>,
|
||||
) -> View<G> {
|
||||
debug!("Making ingredients rows");
|
||||
let ingredients = sh.get_selector(cx, move |state| {
|
||||
let state = state.get();
|
||||
let category_map = &state.category_map;
|
||||
debug!("building ingredient list from state");
|
||||
let mut acc = IngredientAccumulator::new();
|
||||
for (id, count) in state.recipe_counts.iter() {
|
||||
for _ in 0..(*count) {
|
||||
acc.accumulate_from(
|
||||
state
|
||||
.recipes
|
||||
.get(id)
|
||||
.expect(&format!("No such recipe id exists: {}", id)),
|
||||
);
|
||||
}
|
||||
}
|
||||
if *show_staples.get() {
|
||||
if let Some(staples) = &state.staples {
|
||||
acc.accumulate_ingredients_for("Staples", staples.iter());
|
||||
}
|
||||
}
|
||||
let mut ingredients = acc
|
||||
.ingredients()
|
||||
.into_iter()
|
||||
// First we filter out any filtered ingredients
|
||||
.filter(|(i, _)| state.filtered_ingredients.contains(i))
|
||||
// Then we take into account our modified amts
|
||||
.map(|(k, (i, rs))| {
|
||||
let category = category_map
|
||||
.get(&i.name)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| String::new());
|
||||
if state.modified_amts.contains_key(&k) {
|
||||
(
|
||||
k.clone(),
|
||||
(
|
||||
i.name,
|
||||
i.form,
|
||||
category,
|
||||
state.modified_amts.get(&k).unwrap().clone(),
|
||||
rs,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
k.clone(),
|
||||
(
|
||||
i.name,
|
||||
i.form,
|
||||
category,
|
||||
format!("{}", i.amt.normalize()),
|
||||
rs,
|
||||
),
|
||||
)
|
||||
}
|
||||
})
|
||||
.collect::<Vec<(
|
||||
IngredientKey,
|
||||
(String, Option<String>, String, String, BTreeSet<String>),
|
||||
)>>();
|
||||
ingredients.sort_by(|tpl1, tpl2| (&tpl1.1 .2, &tpl1.1 .0).cmp(&(&tpl2.1 .2, &tpl2.1 .0)));
|
||||
ingredients
|
||||
});
|
||||
view!(
|
||||
cx,
|
||||
Indexed(
|
||||
iterable = ingredients,
|
||||
view = move |cx, (k, (name, form, category, amt, rs))| {
|
||||
let category = if category == "" {
|
||||
"other".to_owned()
|
||||
} else {
|
||||
category
|
||||
};
|
||||
let amt_signal = create_signal(cx, amt);
|
||||
let k_clone = k.clone();
|
||||
let form = form.map(|form| format!("({})", form)).unwrap_or_default();
|
||||
let recipes = rs
|
||||
.iter()
|
||||
.fold(String::new(), |acc, s| format!("{}{},", acc, s))
|
||||
.trim_end_matches(",")
|
||||
.to_owned();
|
||||
view! {cx,
|
||||
tr {
|
||||
td {
|
||||
input(bind:value=amt_signal, class="width-5", type="text", on:change=move |_| {
|
||||
sh.dispatch(cx, Message::UpdateAmt(k_clone.clone(), amt_signal.get_untracked().as_ref().clone()));
|
||||
})
|
||||
}
|
||||
td {
|
||||
input(type="button", class="fit-content no-print", value="Undo", on:click={
|
||||
move |_| {
|
||||
sh.dispatch(cx, Message::RemoveFilteredIngredient(k.clone()));
|
||||
}})
|
||||
}
|
||||
td { (name) " " (form) "" br {} "" (category) "" }
|
||||
td { (recipes) }
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
fn make_ingredients_rows<'ctx, G: Html>(
|
||||
cx: Scope<'ctx>,
|
||||
@ -188,6 +297,18 @@ fn make_shopping_table<'ctx, G: Html>(
|
||||
(make_extras_rows(cx, sh))
|
||||
}
|
||||
}
|
||||
("Deleted Items")
|
||||
table(class="pad-top shopping-list page-breaker container-fluid", role="grid") {
|
||||
tr {
|
||||
th { " Quantity " }
|
||||
th { " Delete " }
|
||||
th { " Ingredient " }
|
||||
th { " Recipes " }
|
||||
}
|
||||
tbody {
|
||||
(make_deleted_ingredients_rows(cx, sh, show_staples))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user