diff --git a/web/src/components/shopping_list.rs b/web/src/components/shopping_list.rs index 0a7e211..ae7c8c3 100644 --- a/web/src/components/shopping_list.rs +++ b/web/src/components/shopping_list.rs @@ -15,6 +15,7 @@ use crate::service::AppService; use std::collections::HashMap; use std::collections::{BTreeMap, HashSet}; +use crate::console_debug; use sycamore::{context::use_context, prelude::*}; #[component(ShoppingList)] @@ -22,10 +23,12 @@ pub fn shopping_list() -> View { let app_service = use_context::(); let filtered_keys = Signal::new(HashSet::new()); let ingredients_map = Signal::new(BTreeMap::new()); + let extras = Signal::new(Vec::<(usize, (Signal, Signal))>::new()); let modified_amts = Signal::new(HashMap::new()); create_effect(cloned!((app_service, ingredients_map) => move || { ingredients_map.set(app_service.get_shopping_list()); })); + console_debug!("Ingredients map: {:?}", ingredients_map.get_untracked()); let ingredients = create_memo(cloned!((ingredients_map, filtered_keys) => move || { let mut ingredients = Vec::new(); // This has the effect of sorting the ingredients by category @@ -38,10 +41,11 @@ pub fn shopping_list() -> View { } ingredients })); + console_debug!("Ingredients: {:?}", ingredients.get_untracked()); let table_view = Signal::new(View::empty()); create_effect( - cloned!((table_view, ingredients, filtered_keys, modified_amts) => move || { - if ingredients.get().len() > 0 { + cloned!((table_view, ingredients, filtered_keys, modified_amts, extras) => move || { + if (ingredients.get().len() > 0) || (extras.get().len() > 0) { let t = view ! { table(class="pad-top shopping-list page-breaker container-fluid", role="grid") { tr { @@ -50,7 +54,8 @@ pub fn shopping_list() -> View { th { " Ingredient " } th { " Recipes " } } - tbody {Indexed(IndexedProps{ + tbody { + Indexed(IndexedProps{ iterable: ingredients.clone(), template: cloned!((filtered_keys, modified_amts) => move |(k, (i, rs))| { let mut modified_amt_set = (*modified_amts.get()).clone(); @@ -77,7 +82,33 @@ pub fn shopping_list() -> View { } } }), - })} + }) + Indexed(IndexedProps{ + iterable: extras.handle(), + template: cloned!((extras) => move |(idx, (amt, name))| { + view! { + tr { + td { + input(bind:value=amt.clone(), type="text") + } + td { + input(type="button", class="no-print destructive", value="X", on:click=cloned!((extras) => move |_| { + extras.set(extras.get().iter() + .filter(|(i, _)| *i != idx) + .map(|(_, v)| v.clone()) + .enumerate() + .collect()) + })) + } + td { + input(bind:value=name.clone(), type="text") + } + td { "Misc" } + } + } + }) + }) + } } }; table_view.set(t); @@ -89,11 +120,18 @@ pub fn shopping_list() -> View { view! { h1 { "Shopping List " } (table_view.get().as_ref().clone()) - input(type="button", value="Reset", class="no-print", on:click=cloned!((ingredients_map, filtered_keys, app_service, modified_amts) => move |_| { + input(type="button", value="Add Item", class="no-print", on:click=cloned!((extras) => move |_| { + let mut cloned_extras: Vec<(Signal, Signal)> = (*extras.get()).iter().map(|(_, v)| v.clone()).collect(); + cloned_extras.push((Signal::new("".to_owned()), Signal::new("".to_owned()))); + extras.set(cloned_extras.drain(0..).enumerate().collect()); + })) + input(type="button", value="Reset", class="no-print", on:click=cloned!((ingredients_map, filtered_keys, app_service, modified_amts, extras) => move |_| { + // TODO(jwall): We should actually pop up a modal here or use a different set of items. ingredients_map.set(app_service.get_shopping_list()); // clear the filter_signal filtered_keys.set(HashSet::new()); modified_amts.set(HashMap::new()); + extras.set(Vec::new()); })) } } diff --git a/web/src/service.rs b/web/src/service.rs index dc5cf8b..072ced5 100644 --- a/web/src/service.rs +++ b/web/src/service.rs @@ -31,6 +31,7 @@ pub struct AppService { impl AppService { pub fn new() -> Self { + let mut category_map = BTreeMap::new(); Self { recipes: Signal::new(Vec::new()), staples: Signal::new(None), @@ -206,7 +207,7 @@ impl AppService { .push((i.clone(), recipes.clone())); } }); - console_debug!("{:?}", self.category_map); + console_debug!("Category map {:?}", self.category_map); // FIXM(jwall): Sort by categories and names. groups }