From f6a3fb9c4d8dd86f78c9f75a23c1ac35bf35d4eb Mon Sep 17 00:00:00 2001 From: Benedikt Peetz Date: Thu, 19 Mar 2026 07:45:14 +0100 Subject: feat(treewide): Commit MVP --- src/components/async_fetch.rs | 12 ++++--- src/components/buy.rs | 1 + src/components/catch_errors.rs | 40 +++++++++++++++++++++ src/components/checkbox_placeholder.rs | 54 ++++++++++++++++++++++++++++ src/components/container.rs | 52 ++++++++++++--------------- src/components/inventory.rs | 4 +-- src/components/login_wall.rs | 42 ++++++++++++++++++++++ src/components/mod.rs | 7 ++++ src/components/product_overview.rs | 19 +++++++--- src/components/product_parent_overview.rs | 37 +++++++++++++++++++ src/components/recipies.rs | 20 +++++++++-- src/components/textarea_placeholder.rs | 60 +++++++++++++++++++++++++++++++ src/components/unit_overview.rs | 37 ++++++++++++++++--- 13 files changed, 336 insertions(+), 49 deletions(-) create mode 100644 src/components/catch_errors.rs create mode 100644 src/components/checkbox_placeholder.rs create mode 100644 src/components/login_wall.rs create mode 100644 src/components/product_parent_overview.rs create mode 100644 src/components/textarea_placeholder.rs (limited to 'src/components') diff --git a/src/components/async_fetch.rs b/src/components/async_fetch.rs index 7bf44a0..43469a7 100644 --- a/src/components/async_fetch.rs +++ b/src/components/async_fetch.rs @@ -37,11 +37,13 @@ macro_rules! AsyncFetch { "Loading..."

} }> - {move || Suspend::new(async move { - $resource - .await - .map($producer) - })} + { + Suspend::new(async move { + $resource + .await + .map($producer) + }) + }
} }}; diff --git a/src/components/buy.rs b/src/components/buy.rs index e69de29..8b13789 100644 --- a/src/components/buy.rs +++ b/src/components/buy.rs @@ -0,0 +1 @@ + diff --git a/src/components/catch_errors.rs b/src/components/catch_errors.rs new file mode 100644 index 0000000..d5a452d --- /dev/null +++ b/src/components/catch_errors.rs @@ -0,0 +1,40 @@ +use leptos::{ + IntoView, component, + error::ErrorBoundary, + prelude::{Children, ClassAttribute, CollectView, ElementChild, Get}, + view, +}; + +use crate::components::site_header::SiteHeader; + +#[component] +pub(crate) fn CatchErrors(children: Children) -> impl IntoView { + view! { + + +

"Uh oh! Something went wrong!"

+ +

"Errors: "

+ + } + }>{children()}
+ } +} diff --git a/src/components/checkbox_placeholder.rs b/src/components/checkbox_placeholder.rs new file mode 100644 index 0000000..a1aaa0c --- /dev/null +++ b/src/components/checkbox_placeholder.rs @@ -0,0 +1,54 @@ +use leptos::{ + IntoView, component, + html::Input, + prelude::{ClassAttribute, ElementChild, GlobalAttributes, NodeRef, NodeRefAttribute}, + view, +}; + +use crate::components::get_id; + +#[component] +pub fn CheckboxPlaceholder( + label: &'static str, + node_ref: NodeRef, +) -> impl IntoView { + let id = get_id(); + + view! { +
+ + + +
+ } +} diff --git a/src/components/container.rs b/src/components/container.rs index d6d2f03..3b56713 100644 --- a/src/components/container.rs +++ b/src/components/container.rs @@ -1,46 +1,38 @@ use leptos::{ IntoView, component, - prelude::{Children, ClassAttribute, ElementChild, OnAttribute}, + prelude::{Children, ClassAttribute, ElementChild}, view, }; -use leptos_router::{NavigateOptions, hooks::use_navigate}; +use leptos_router::components::A; #[component] pub fn Container( - header: impl IntoView, - buttons: Vec<(impl IntoView, &'static str)>, + header: impl IntoView + 'static, + buttons: Vec<(impl IntoView + 'static, &'static str)>, children: Children, ) -> impl IntoView { assert!(!buttons.is_empty()); - let first_button_path = buttons.first().expect("Should have at least on button").1; + // TODO: Add the direct link to the first button back. <2026-02-15> + // let first_button_path = buttons.first().expect("Should have at least on button").1; view! { - - - } - }) - .collect::>()} - - - + + } } diff --git a/src/components/inventory.rs b/src/components/inventory.rs index 275dd0b..31b1c12 100644 --- a/src/components/inventory.rs +++ b/src/components/inventory.rs @@ -23,8 +23,8 @@ pub fn Inventory() -> impl IntoView { producer = |products| { let products_num = products.len(); let plural_s = if products_num == 1 { "" } else { "s" }; - let products_value = 2; - let products_currency = "EUR"; + let products_value = -1; + let products_currency = "TODO"; view! {

diff --git a/src/components/login_wall.rs b/src/components/login_wall.rs new file mode 100644 index 0000000..fd5c64f --- /dev/null +++ b/src/components/login_wall.rs @@ -0,0 +1,42 @@ +use leptos::{ + IntoView, component, + error::Error, + prelude::{Children, IntoAny}, + view, +}; +use leptos_router::{NavigateOptions, hooks::use_navigate}; + +use crate::{ + api::{can_be_provisioned_wrapped, is_logged_in_wrapped}, + components::async_fetch::{AsyncFetch, AsyncResource}, +}; + +#[component] +pub fn LoginWall( + back: impl Fn() -> String + Send + Sync + 'static, + children: Children, +) -> impl IntoView { + view! { + { + AsyncFetch! { + @map_error_in_producer + from_resource = AsyncResource!( + () -> Result<(bool, bool), Error> { + Ok((can_be_provisioned_wrapped().await?, is_logged_in_wrapped().await?)) + } + ), + producer = |(can_be_provisioned, is_logged_in)| { + if is_logged_in { + children() + } else if can_be_provisioned { + use_navigate()(format!("/provision/?back={}", back()).as_str(), NavigateOptions::default()); + ().into_any() + } else { + use_navigate()(format!("/login/?back={}", back()).as_str(), NavigateOptions::default()); + ().into_any() + } + } + } + } + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs index 2c3d79a..2a3a0b1 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -3,15 +3,22 @@ use std::sync::atomic::{AtomicU32, Ordering}; // Generic pub mod async_fetch; pub mod banner; +pub mod catch_errors; pub mod container; pub mod form; pub mod icon_p; +pub mod login_wall; + +// placeholders +pub mod checkbox_placeholder; pub mod input_placeholder; pub mod select_placeholder; +pub mod textarea_placeholder; // Specific pub mod inventory; pub mod product_overview; +pub mod product_parent_overview; pub mod recipies; pub mod site_header; pub mod unit_overview; diff --git a/src/components/product_overview.rs b/src/components/product_overview.rs index bf81624..233b8a7 100644 --- a/src/components/product_overview.rs +++ b/src/components/product_overview.rs @@ -11,9 +11,20 @@ pub fn ProductOverview() -> impl IntoView { }, "products"), - (view! { }, "create-product"), - (view! { }, "associate-barcode-product"), + (view! { }, "products"), + ( + view! { }, + "create-product", + ), + ( + view! { + + }, + "associate-barcode-product", + ), ] > { @@ -22,7 +33,7 @@ pub fn ProductOverview() -> impl IntoView { fetcher = products_registered_wrapped(), producer = |products| { view! { -

{format!("You have {} products", products.len())}

+

{format!("You have {} products.", products.len())}

} } } diff --git a/src/components/product_parent_overview.rs b/src/components/product_parent_overview.rs new file mode 100644 index 0000000..4aa2a0f --- /dev/null +++ b/src/components/product_parent_overview.rs @@ -0,0 +1,37 @@ +use leptos::{IntoView, component, view}; + +use crate::{ + api::product_parents_wrapped, + components::{async_fetch::AsyncFetch, container::Container, icon_p::IconP}, +}; + +#[component] +pub fn ProductParentOverview() -> impl IntoView { + view! { + }, + "products", + ), + ( + view! { }, + "create-product-parent", + ), + ] + > + { + AsyncFetch! { + @map_error_in_producer + fetcher = product_parents_wrapped(), + producer = |product_parents| { + view! { +

{format!("You have {} product parents.", product_parents.len())}

+ } + } + } + } +
+ } +} diff --git a/src/components/recipies.rs b/src/components/recipies.rs index f7903e4..755954e 100644 --- a/src/components/recipies.rs +++ b/src/components/recipies.rs @@ -1,6 +1,9 @@ -use leptos::{IntoView, component, prelude::ElementChild, view}; +use leptos::{IntoView, component, view}; -use crate::components::{container::Container, icon_p::IconP}; +use crate::{ + api::recipes_wrapped, + components::{async_fetch::AsyncFetch, container::Container, icon_p::IconP}, +}; #[component] pub fn Recipies() -> impl IntoView { @@ -9,10 +12,21 @@ pub fn Recipies() -> impl IntoView { header="Recipies" buttons=vec![ (view! { }, "recipies"), + (view! { }, "create-recipe"), (view! { }, "mealplan"), ] > -

"You have 0 recipies."

+ { + AsyncFetch! { + @map_error_in_producer + fetcher = recipes_wrapped(), + producer = |recipes| { + view! { +

{format!("You have {} recipies.", recipes.len())}

+ } + } + } + } } } diff --git a/src/components/textarea_placeholder.rs b/src/components/textarea_placeholder.rs new file mode 100644 index 0000000..a0bae6d --- /dev/null +++ b/src/components/textarea_placeholder.rs @@ -0,0 +1,60 @@ +use leptos::{ + IntoView, component, + html::Textarea, + prelude::{ClassAttribute, ElementChild, GlobalAttributes, NodeRef, NodeRefAttribute}, + view, +}; + +use crate::components::get_id; + +#[component] +pub fn TextareaPlaceholder( + label: &'static str, + node_ref: NodeRef + + + + } +} diff --git a/src/components/unit_overview.rs b/src/components/unit_overview.rs index 25e5675..0ea3825 100644 --- a/src/components/unit_overview.rs +++ b/src/components/unit_overview.rs @@ -1,6 +1,10 @@ use leptos::{IntoView, component, view}; +use rocie_client::models::{Unit, UnitProperty}; -use crate::components::{container::Container, icon_p::IconP}; +use crate::{ + api::{unit_properties_wrapped, units_wrapped}, + components::{async_fetch::AsyncFetch, container::Container, icon_p::IconP}, +}; #[component] pub fn UnitOverview() -> impl IntoView { @@ -8,14 +12,37 @@ pub fn UnitOverview() -> impl IntoView { }, "units"), - (view! { }, "create-unit"), - (view! { }, "create-unit-property"), + (view! { }, "units"), + ( + view! { }, + "create-unit", + ), + ( + view! { }, + "create-unit-property", + ), ] > { - "You have units" + AsyncFetch! { + @map_error_in_producer + fetcher = get_units_and_unit_properties(), + producer = |(units, unit_properties)| { + view! { +

{move || format!( + "You have {} units and {} unit properties.", + units.len(), + unit_properties.len() + )}

+ } + }, + } }
} } + +async fn get_units_and_unit_properties() +-> Result<(Vec, Vec), leptos::error::Error> { + Ok((units_wrapped().await?, unit_properties_wrapped().await?)) +} -- cgit 1.4.1