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()>>),
|
UpdateCategory(String, String, Option<Box<dyn FnOnce()>>),
|
||||||
ResetInventory,
|
ResetInventory,
|
||||||
AddFilteredIngredient(IngredientKey),
|
AddFilteredIngredient(IngredientKey),
|
||||||
|
RemoveFilteredIngredient(IngredientKey),
|
||||||
UpdateAmt(IngredientKey, String),
|
UpdateAmt(IngredientKey, String),
|
||||||
SetUserData(UserData),
|
SetUserData(UserData),
|
||||||
SaveState(Option<Box<dyn FnOnce()>>),
|
SaveState(Option<Box<dyn FnOnce()>>),
|
||||||
@ -124,6 +125,9 @@ impl Debug for Message {
|
|||||||
Self::AddFilteredIngredient(arg0) => {
|
Self::AddFilteredIngredient(arg0) => {
|
||||||
f.debug_tuple("AddFilteredIngredient").field(arg0).finish()
|
f.debug_tuple("AddFilteredIngredient").field(arg0).finish()
|
||||||
}
|
}
|
||||||
|
Self::RemoveFilteredIngredient(arg0) => {
|
||||||
|
f.debug_tuple("RemoveFilteredIngredient").field(arg0).finish()
|
||||||
|
}
|
||||||
Self::UpdateAmt(arg0, arg1) => {
|
Self::UpdateAmt(arg0, arg1) => {
|
||||||
f.debug_tuple("UpdateAmt").field(arg0).field(arg1).finish()
|
f.debug_tuple("UpdateAmt").field(arg0).field(arg1).finish()
|
||||||
}
|
}
|
||||||
@ -393,6 +397,9 @@ impl MessageMapper<Message, AppState> for StateMachine {
|
|||||||
Message::AddFilteredIngredient(key) => {
|
Message::AddFilteredIngredient(key) => {
|
||||||
original_copy.filtered_ingredients.insert(key);
|
original_copy.filtered_ingredients.insert(key);
|
||||||
}
|
}
|
||||||
|
Message::RemoveFilteredIngredient(key) => {
|
||||||
|
original_copy.filtered_ingredients.remove(&key);
|
||||||
|
}
|
||||||
Message::UpdateAmt(key, amt) => {
|
Message::UpdateAmt(key, amt) => {
|
||||||
original_copy.modified_amts.insert(key, amt);
|
original_copy.modified_amts.insert(key, amt);
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,115 @@ use tracing::{debug, info, instrument};
|
|||||||
|
|
||||||
use crate::app_state::{Message, StateHandler};
|
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)]
|
#[instrument(skip_all)]
|
||||||
fn make_ingredients_rows<'ctx, G: Html>(
|
fn make_ingredients_rows<'ctx, G: Html>(
|
||||||
cx: Scope<'ctx>,
|
cx: Scope<'ctx>,
|
||||||
@ -188,6 +297,18 @@ fn make_shopping_table<'ctx, G: Html>(
|
|||||||
(make_extras_rows(cx, sh))
|
(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