summary refs log tree commit diff stats
path: root/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/components')
-rw-r--r--src/components/async_fetch.rs32
-rw-r--r--src/components/banner.rs6
-rw-r--r--src/components/buy.rs193
-rw-r--r--src/components/container.rs47
-rw-r--r--src/components/input_placeholder.rs15
-rw-r--r--src/components/inventory.rs55
-rw-r--r--src/components/mod.rs4
-rw-r--r--src/components/product_overview.rs38
-rw-r--r--src/components/recipies.rs10
-rw-r--r--src/components/select_placeholder.rs22
10 files changed, 85 insertions, 337 deletions
diff --git a/src/components/async_fetch.rs b/src/components/async_fetch.rs
index f24e3a5..7bf44a0 100644
--- a/src/components/async_fetch.rs
+++ b/src/components/async_fetch.rs
@@ -15,31 +15,21 @@ pub(crate) use AsyncResource;
 
 macro_rules! AsyncFetch {
     (
-        fetcher = $fetcher:block
-        producer = |$bound_variable:pat_param| $producer:block
+        @map_error_in_producer
+        fetcher = $fetcher:expr,
+        producer = $producer:expr $(,)?
     ) => {{
-        use leptos::{
-            prelude::{ElementChild, LocalResource, Suspend, Transition},
-            view,
-        };
-
-        view! {
-            <Transition fallback=|| {
-                view! { <p>"Loading..."</p> }
-            }>
-                {move || Suspend::new(async move {
-                    let resource = { LocalResource::new(move || $fetcher) };
-                    resource
-                        .await
-                        .map(|$bound_variable| $producer)
-                })}
-            </Transition>
+        AsyncFetch! {
+            @map_error_in_producer
+            from_resource = leptos::prelude::LocalResource::new(move || $fetcher),
+            producer = $producer
         }
     }};
+
     (
         @map_error_in_producer
-        from_resource = $resource:ident
-        producer = |$bound_variable:pat_param| $producer:block
+        from_resource = $resource:expr,
+        producer = $producer:expr $(,)?
     ) => {{
         use leptos::prelude::{ElementChild, Suspend, Transition};
 
@@ -50,7 +40,7 @@ macro_rules! AsyncFetch {
                 {move || Suspend::new(async move {
                     $resource
                         .await
-                        .map(|$bound_variable| $producer)
+                        .map($producer)
                 })}
             </Transition>
         }
diff --git a/src/components/banner.rs b/src/components/banner.rs
index acaaf62..3244a07 100644
--- a/src/components/banner.rs
+++ b/src/components/banner.rs
@@ -9,9 +9,5 @@ pub fn Banner<T>(mut text: T) -> impl IntoView
 where
     T: FnMut() -> String + Send + 'static,
 {
-    view! {
-        <p class="text-white rounded-lg m-2 p-2 bg-red-600">
-            {move || text()}
-        </p>
-    }
+    view! { <p class="text-white rounded-lg m-2 p-2 bg-red-600">{move || text()}</p> }
 }
diff --git a/src/components/buy.rs b/src/components/buy.rs
deleted file mode 100644
index cb4cff4..0000000
--- a/src/components/buy.rs
+++ /dev/null
@@ -1,193 +0,0 @@
-use leptos::{
-    IntoView, component,
-    prelude::{Get, Read, Show, WriteSignal, expect_context, signal},
-    task::spawn_local,
-    view,
-};
-use leptos_router::{NavigateOptions, hooks::use_navigate};
-use log::info;
-use reactive_stores::Store;
-use rocie_client::{
-    apis::Error,
-    models::{Product, Unit},
-};
-use uuid::Uuid;
-
-use crate::{
-    ConfigState, ConfigStateStoreFields,
-    api::{
-        buy_barcode_wrapper, get_product_by_name, get_product_unit_by_id,
-        get_products_by_part_name, get_unit_by_id,
-    },
-    components::{async_fetch::AsyncResource, banner::Banner, form::Form, site_header::SiteHeader},
-};
-
-#[component]
-pub fn Buy() -> impl IntoView {
-    let (on_submit_errored, on_submit_errored_set) = signal(None);
-
-    view! {
-        <SiteHeader logo=icondata_io::IoPricetag back_location="/" name="Buy" />
-
-        <Show when=move || on_submit_errored.get().is_some()>
-            <Banner text=move || on_submit_errored.get().expect("Should be some") />
-        </Show>
-
-        {
-            Form! {
-                on_submit = |barcode_number, amount| {
-                    let config = expect_context::<Store<ConfigState>>();
-                    let config = config.config().read();
-
-                    spawn_local(async move {
-                        if let Err(err) = buy_barcode_wrapper(&config, barcode_number).await {
-                            let error = format!("Error in form on-submit for barcode `{barcode_number}`: {err}");
-                            on_submit_errored_set.set(Some(error));
-                        } else {
-                            on_submit_errored_set.set(None);
-
-                            info!("Bought barcode {barcode_number} {amount} times");
-                        }
-
-                    });
-                };
-
-                <Input
-                    name=barcode_number,
-                    rust_type=u32,
-                    html_type="number",
-                    label="Barcode Number",
-                />
-
-                <Input
-                    name=amount,
-                    rust_type=u16,
-                    html_type="number",
-                    label="Amount"
-                />
-            }
-        }
-    }
-}
-
-#[component]
-pub fn AssociateBarcode() -> impl IntoView {
-    let product_name_signal;
-
-    let (show_units, show_units_set) = signal(false);
-
-    view! {
-        <SiteHeader logo=icondata_io::IoPricetag back_location="/" name="Buy" />
-
-        {
-            Form! {
-                on_submit = |product_name, amount, unit_id| {
-                    spawn_local(async move {
-                        let navigate = use_navigate();
-
-                        info!("Got product barcode: {product_name} with amount: {amount}, and {unit_id}");
-
-                        navigate("/", NavigateOptions::default());
-                    });
-                };
-
-                <Input
-                    name=product_name,
-                    rust_type=String,
-                    html_type="text",
-                    label="Product Name",
-                    reactive=product_name_signal
-                    auto_complete=generate_suggest_products
-                />
-
-                <Show
-                    when=move || show_units.get(),
-                >
-                    <Select
-                        name=unit_id,
-                        rust_type=Uuid,
-                        label="Unit",
-                        options=AsyncResource! {
-                            (
-                                product_name: Option<String> = product_name_signal(),
-                                show_units_set: WriteSignal<bool> = show_units_set
-                            ) -> Result<Vec<(String, String)>, leptos::error::Error> {
-                                let units = product_unit_fetcher(product_name).await?;
-
-                                show_units_set.set(units.is_some());
-                                if let Some(units) = units {
-                                    Ok(
-                                        units
-                                            .into_iter()
-                                            .map(|unit| (unit.full_name_singular, unit.id.to_string()))
-                                            .collect()
-                                    )
-                                } else {
-                                    Ok(vec![])
-                                }
-                            }
-                        },
-                    />
-                </Show>
-
-                <Input
-                    name=amount,
-                    rust_type=u16,
-                    html_type="number",
-                    label="Amount"
-                />
-            }
-        }
-    }
-}
-
-async fn generate_suggest_products(
-    optional_product_name: Option<String>,
-) -> Result<Option<Vec<String>>, leptos::error::Error> {
-    if let Some(product_name) = optional_product_name
-        && !product_name.is_empty()
-    {
-        let products = get_products_by_part_name(product_name).await?;
-        Ok(Some(products.into_iter().map(|prod| prod.name).collect()))
-    } else {
-        Ok(None)
-    }
-}
-
-async fn product_unit_fetcher(
-    optinal_product_name: Option<String>,
-) -> Result<Option<Vec<Unit>>, leptos::error::Error> {
-    if let Some(product_name) = optinal_product_name
-        && !product_name.is_empty()
-    {
-        let value: Option<Product> = {
-            match get_product_by_name(product_name).await {
-                Ok(ok) => Ok::<_, leptos::error::Error>(Some(ok)),
-                Err(err) => match err {
-                    Error::ResponseError(ref response_content) => {
-                        match response_content.status.as_u16() {
-                            404 => Ok(None),
-                            _ => Err(err.into()),
-                        }
-                    }
-                    err => Err(err.into()),
-                },
-            }?
-        };
-
-        if let Some(value) = value {
-            let (_, unit_property) = get_product_unit_by_id(value.id).await?;
-
-            let mut units = Vec::with_capacity(unit_property.units.len());
-            for unit_id in unit_property.units {
-                units.push(get_unit_by_id(unit_id).await?);
-            }
-
-            Ok(Some(units))
-        } else {
-            Ok(None)
-        }
-    } else {
-        Ok(None)
-    }
-}
diff --git a/src/components/container.rs b/src/components/container.rs
index 7a4a64f..83b9584 100644
--- a/src/components/container.rs
+++ b/src/components/container.rs
@@ -11,25 +11,36 @@ pub fn Container(
     buttons: Vec<(impl IntoView, &'static str)>,
     children: Children,
 ) -> impl IntoView {
+    assert!(!buttons.is_empty());
+
+    let first_button_path = buttons.first().expect("Should have at least on button").1;
+
     view! {
-        <div class="p-4 mt-4 mr-4 ml-4 md-2 rounded-lg border-gray-600 border">
-            <p class="text-lg text-bold">{header}</p>
-            {children()}
+        <button
+            type="button"
+            on:click=|_| {
+                use_navigate()(first_button_path, NavigateOptions::default());
+            }
+        >
+            <div class="p-4 mt-4 mr-4 ml-4 md-2 text-justify rounded-lg border-gray-600 border">
+                <p class="text-lg text-bold">{header}</p>
+                {children()}
 
-            <ul class="flex flex-row gap-1 pt-2 overflow-x-auto">
-                {buttons
-                    .into_iter()
-                    .map(|(name, path)| {
-                        view! {
-                            <li class="bg-green-400/40 p-2 first:rounded-l-full last:rounded-r-full">
-                                <button on:click=move |_| {
-                                    use_navigate()(path, NavigateOptions::default());
-                                }>{name}</button>
-                            </li>
-                        }
-                    })
-                    .collect::<Vec<_>>()}
-            </ul>
-        </div>
+                <ul class="flex flex-row gap-1 pt-2 overflow-x-auto">
+                    {buttons
+                        .into_iter()
+                        .map(|(name, path)| {
+                            view! {
+                                <li class="bg-green-400/40 p-2 first:rounded-l-full last:rounded-r-full">
+                                    <button on:click=move |_| {
+                                        use_navigate()(path, NavigateOptions::default());
+                                    }>{name}</button>
+                                </li>
+                            }
+                        })
+                        .collect::<Vec<_>>()}
+                </ul>
+            </div>
+        </button>
     }
 }
diff --git a/src/components/input_placeholder.rs b/src/components/input_placeholder.rs
index 99b3196..0589363 100644
--- a/src/components/input_placeholder.rs
+++ b/src/components/input_placeholder.rs
@@ -96,12 +96,7 @@ pub fn InputPlaceholder(
                 {label}
             </label>
 
-            <Show
-                when=move || {
-                    !autocomplete_signal.get().is_empty()
-                }
-                fallback=move || ()
-            >
+            <Show when=move || { !autocomplete_signal.get().is_empty() } fallback=move || ()>
                 <div class="\
                 absolute \
                 top-0 \
@@ -139,7 +134,7 @@ pub fn InputPlaceholder(
                                             provide_auto_completion(
                                                 auto_complete,
                                                 autocomplete_set,
-                                                reactive
+                                                reactive,
                                             )
                                         })
                                 }}
@@ -178,10 +173,10 @@ fn provide_auto_completion(
                                                 autocomplete_set.set(item2.clone());
                                                 reactive
                                                     .expect(
-                                                    "Should be set, \
-                                                    when autocomplete is used")
+                                                        "Should be set, \
+                                                    when autocomplete is used",
+                                                    )
                                                     .set(Some(item2.clone()));
-
                                                 info!("Set autocomplete to {item2}.");
                                             }
                                         >
diff --git a/src/components/inventory.rs b/src/components/inventory.rs
deleted file mode 100644
index 5855b33..0000000
--- a/src/components/inventory.rs
+++ /dev/null
@@ -1,55 +0,0 @@
-use leptos::{
-    IntoView, component,
-    prelude::{ClassAttribute, ElementChild},
-    view,
-};
-
-use crate::{
-    api::{get_full_product_by_id, get_products},
-    components::{async_fetch::AsyncFetch, site_header::SiteHeader},
-};
-
-#[component]
-pub fn Inventory() -> impl IntoView {
-    view! {
-        <SiteHeader logo=icondata_io::IoArrowBack back_location="/" name="Inventory" />
-
-        <ul class="flex flex-col p-2 m-2">
-            {
-                AsyncFetch! {
-                    fetcher = {get_products()}
-                    producer = |products| {
-                        products
-                         .into_iter()
-                         .map(|product| {
-                            view! {
-                                {AsyncFetch! {
-                                    fetcher = {get_full_product_by_id(product.id)}
-                                    producer = |(product, amount, unit)| {
-                                      view! {
-                                          <ul class="my-3">
-                                              <li class="m-2">{product.name}</li>
-                                              <li class="m-2">
-                                                  <span class="bg-gray-200 p-1 px-2 rounded-lg">
-                                                      {
-                                                        format!(
-                                                            "{} {}",
-                                                            amount.amount.value,
-                                                            unit.short_name
-                                                            )
-                                                        }
-                                                  </span>
-                                              </li>
-                                          </ul>
-                                      }
-                                    }
-                                }}
-                            }
-                        })
-                        .collect::<Vec<_>>()
-                    }
-                }
-            }
-        </ul>
-    }
-}
diff --git a/src/components/mod.rs b/src/components/mod.rs
index ca2ac10..efc4842 100644
--- a/src/components/mod.rs
+++ b/src/components/mod.rs
@@ -2,16 +2,14 @@ use std::sync::atomic::{AtomicU32, Ordering};
 
 // Generic
 pub mod async_fetch;
+pub mod banner;
 pub mod container;
 pub mod form;
 pub mod icon_p;
 pub mod input_placeholder;
 pub mod select_placeholder;
-pub mod banner;
 
 // Specific
-pub mod buy;
-pub mod inventory;
 pub mod product_overview;
 pub mod recipies;
 pub mod site_header;
diff --git a/src/components/product_overview.rs b/src/components/product_overview.rs
index 777baef..5413dc1 100644
--- a/src/components/product_overview.rs
+++ b/src/components/product_overview.rs
@@ -11,33 +11,31 @@ pub fn ProductOverview() -> impl IntoView {
         <Container
             header="Inventory"
             buttons=vec![
-                (
-                    view! { <IconP icon=icondata_io::IoClipboardOutline text="Inventory" /> },
-                    "inventory",
-                ),
+                (view! { <IconP icon=icondata_io::IoClipboard text="Inventory" /> }, "inventory"),
                 (view! { <IconP icon=icondata_io::IoPricetags text="Consume" /> }, "consume"),
                 (view! { <IconP icon=icondata_io::IoStorefront text="Buy" /> }, "buy"),
             ]
         >
             {
                 AsyncFetch! {
-                    fetcher = {get_products()}
-                producer = |products| {
-                  let products_num = products.len();
-                  let plural_s = if products_num == 1 { "" } else { "s" };
-                  let products_value = 2;
-                  let products_currency = "EUR";
+                    @map_error_in_producer
+                    fetcher = get_products(),
+                    producer = |products| {
+                        let products_num = products.len();
+                        let plural_s = if products_num == 1 { "" } else { "s" };
+                        let products_value = 2;
+                        let products_currency = "EUR";
 
-                  view! {
-                      <p>
-                          {format!(
-                              "You have {products_num} product{plural_s} \
-                                   in stock with a value \
-                                   of {products_value} {products_currency}.",
-                          )}
-                      </p>
-                  }
-            }
+                        view! {
+                            <p>
+                                {format!(
+                                    "You have {products_num} product{plural_s} \
+                                         in stock with a value \
+                                         of {products_value} {products_currency}.",
+                                )}
+                            </p>
+                        }
+                    }
                 }
             }
         </Container>
diff --git a/src/components/recipies.rs b/src/components/recipies.rs
index 1bd3a0d..f7903e4 100644
--- a/src/components/recipies.rs
+++ b/src/components/recipies.rs
@@ -1,11 +1,17 @@
 use leptos::{IntoView, component, prelude::ElementChild, view};
 
-use crate::components::container::Container;
+use crate::components::{container::Container, icon_p::IconP};
 
 #[component]
 pub fn Recipies() -> impl IntoView {
     view! {
-        <Container header="Recipies" buttons=vec![("Mealplan", "mealplan")]>
+        <Container
+            header="Recipies"
+            buttons=vec![
+                (view! { <IconP icon=icondata_io::IoFastFood text="Recipies" /> }, "recipies"),
+                (view! { <IconP icon=icondata_io::IoCalendarSharp text="Mealplan" /> }, "mealplan"),
+            ]
+        >
             <p>"You have 0 recipies."</p>
         </Container>
     }
diff --git a/src/components/select_placeholder.rs b/src/components/select_placeholder.rs
index 2e0f783..7289793 100644
--- a/src/components/select_placeholder.rs
+++ b/src/components/select_placeholder.rs
@@ -41,16 +41,18 @@ pub fn SelectPlaceholder(
                 "
                 node_ref=node_ref
             >
-                {move || AsyncFetch! {
-                    @map_error_in_producer
-                    from_resource = options
-                    producer = |options| {
-                        options
-                            .into_iter()
-                            .map(|(label, value)| {
-                                view! { <option value=value>{label}</option> }
-                            })
-                            .collect_view()
+                {move || {
+                    AsyncFetch! {
+                        @map_error_in_producer
+                        from_resource = options,
+                        producer = |options| {
+                            options
+                                .into_iter()
+                                .map(|(label, value)| {
+                                    view! { <option value=value>{label}</option> }
+                                })
+                                .collect_view()
+                        }
                     }
                 }}
             </select>