From d0263ce46160cd4152c67381fab2ee557f3aa483 Mon Sep 17 00:00:00 2001
From: Benedikt Peetz
Date: Tue, 30 Sep 2025 09:15:56 +0200
Subject: feat(treewide): Switch to tailwindcss and add more components
---
src/components/async_fetch.rs | 50 +++++++++++++++++++++++++++
src/components/container.rs | 47 +++++++++++++------------
src/components/icon_p.rs | 18 ++++++++++
src/components/inventory.rs | 55 +++++++++++++++++++++++++++++
src/components/mod.rs | 6 +++-
src/components/product_overview.rs | 71 +++++++++++++++++---------------------
src/components/recipies.rs | 12 +++++++
src/components/side_header.rs | 22 ------------
src/components/site_header.rs | 29 ++++++++++++++++
9 files changed, 225 insertions(+), 85 deletions(-)
create mode 100644 src/components/async_fetch.rs
create mode 100644 src/components/icon_p.rs
create mode 100644 src/components/inventory.rs
create mode 100644 src/components/recipies.rs
delete mode 100644 src/components/side_header.rs
create mode 100644 src/components/site_header.rs
(limited to 'src/components')
diff --git a/src/components/async_fetch.rs b/src/components/async_fetch.rs
new file mode 100644
index 0000000..7105c6f
--- /dev/null
+++ b/src/components/async_fetch.rs
@@ -0,0 +1,50 @@
+macro_rules! AsyncFetch {
+ (fetcher = $fetcher:block producer = |$bound_variable:pat_param| $producer:block) => {{
+ use leptos::{
+ prelude::{ElementChild, LocalResource, Suspend, Transition},
+ view,
+ };
+
+ view! {
+ "Loading..."
}
+ }>
+ {move || Suspend::new(async move {
+ let resource = { LocalResource::new(move || $fetcher) };
+ resource
+ .await
+ .map(|$bound_variable| $producer)
+ })}
+
+ }
+ }};
+}
+pub(crate) use AsyncFetch;
+
+// #[component]
+// pub fn AsyncFetch(
+// fetcher: impl Fn() -> Fut + 'static + Send + Sync,
+// producer: P,
+// ) -> impl IntoView
+// where
+// V: IntoView + 'static,
+// P: Fn(T) -> V + 'static + Send + Sync,
+// Fut: Future
}
+// }>
+// { || Suspend::new(async {
+// let value_resource = LocalResource::new( || fetcher());
+// value_resource
+// .await
+// .map(|value| {
+// producer(value)
+// })
+// })}
+//
+// }
+// }
diff --git a/src/components/container.rs b/src/components/container.rs
index cf7aa5a..7a4a64f 100644
--- a/src/components/container.rs
+++ b/src/components/container.rs
@@ -1,34 +1,35 @@
use leptos::{
IntoView, component,
- prelude::{Children, ClassAttribute, ElementChild},
+ prelude::{Children, ClassAttribute, ElementChild, OnAttribute},
view,
};
-use leptos_meta::Style;
+use leptos_router::{NavigateOptions, hooks::use_navigate};
#[component]
-pub fn Container(header: impl IntoView, children: Children) -> impl IntoView {
+pub fn Container(
+ header: impl IntoView,
+ buttons: Vec<(impl IntoView, &'static str)>,
+ children: Children,
+) -> impl IntoView {
view! {
-
-
-
-
+
+
{header}
{children()}
+
+
+ {buttons
+ .into_iter()
+ .map(|(name, path)| {
+ view! {
+ -
+
+
+ }
+ })
+ .collect::>()}
+
}
}
diff --git a/src/components/icon_p.rs b/src/components/icon_p.rs
new file mode 100644
index 0000000..372e280
--- /dev/null
+++ b/src/components/icon_p.rs
@@ -0,0 +1,18 @@
+use leptos::{
+ IntoView, component,
+ prelude::{ClassAttribute, ElementChild, Signal},
+ view,
+};
+use leptos_icons::Icon;
+
+#[component]
+pub fn IconP(#[prop(into)] icon: Signal
, text: &'static str) -> impl IntoView {
+ view! {
+
+ }
+}
diff --git a/src/components/inventory.rs b/src/components/inventory.rs
new file mode 100644
index 0000000..5855b33
--- /dev/null
+++ b/src/components/inventory.rs
@@ -0,0 +1,55 @@
+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! {
+
+
+
+ {
+ 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! {
+
+ - {product.name}
+ -
+
+ {
+ format!(
+ "{} {}",
+ amount.amount.value,
+ unit.short_name
+ )
+ }
+
+
+
+ }
+ }
+ }}
+ }
+ })
+ .collect::>()
+ }
+ }
+ }
+
+ }
+}
diff --git a/src/components/mod.rs b/src/components/mod.rs
index 85f9671..7174ad8 100644
--- a/src/components/mod.rs
+++ b/src/components/mod.rs
@@ -1,6 +1,10 @@
// Generic
+pub mod async_fetch;
pub mod container;
+pub mod icon_p;
// Specific
+pub mod inventory;
pub mod product_overview;
-pub mod side_header;
+pub mod recipies;
+pub mod site_header;
diff --git a/src/components/product_overview.rs b/src/components/product_overview.rs
index 4e95335..ae2eaf2 100644
--- a/src/components/product_overview.rs
+++ b/src/components/product_overview.rs
@@ -1,47 +1,40 @@
-use std::sync::Arc;
+use leptos::{IntoView, component, view};
-use leptos::{
- IntoView, component,
- prelude::{ElementChild, Set, signal},
- task::spawn_local,
- view,
+use crate::{
+ api::get_products,
+ components::{async_fetch::AsyncFetch, container::Container, icon_p::IconP},
};
-use rocie_client::apis::{api_get_product_api::products, configuration::Configuration};
-
-use crate::components::container::Container;
#[component]
-pub fn ProductOverview(config: Arc) -> impl IntoView {
- let (read_status, write_status) = signal("Loading..".to_owned());
-
- {
- let local_config = Arc::clone(&config);
-
- spawn_local(async move {
- let products = products(&local_config).await;
-
- write_status.set(
- products
- .as_ref()
- .map(move |products| {
- let products_num = products.len();
- let plural_s = if products_num == 1 { "" } else { "s" };
- let products_value = 2;
- let products_currency = "EUR";
- format!(
- "You have {products_num} product{plural_s} \
- in stock with a value \
- of {products_value} {products_currency}.",
- )
- })
- .unwrap(),
- );
- });
- }
-
+pub fn ProductOverview() -> impl IntoView {
view! {
-
- {read_status}
+ }, "inventory"),
+ (view! { }, "consume"),
+ (view! { }, "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";
+
+ view! {
+
+ {format!(
+ "You have {products_num} product{plural_s} \
+ in stock with a value \
+ of {products_value} {products_currency}.",
+ )}
+
+ }
+ }
+ )}
}
}
diff --git a/src/components/recipies.rs b/src/components/recipies.rs
new file mode 100644
index 0000000..1bd3a0d
--- /dev/null
+++ b/src/components/recipies.rs
@@ -0,0 +1,12 @@
+use leptos::{IntoView, component, prelude::ElementChild, view};
+
+use crate::components::container::Container;
+
+#[component]
+pub fn Recipies() -> impl IntoView {
+ view! {
+
+ "You have 0 recipies."
+
+ }
+}
diff --git a/src/components/side_header.rs b/src/components/side_header.rs
deleted file mode 100644
index 9cd6777..0000000
--- a/src/components/side_header.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-use leptos::prelude::{AddAnyAttr, ElementChild, IntoView, StyleAttribute, component, view};
-use leptos_router::{NavigateOptions, hooks::use_navigate};
-use thaw::{Flex, FlexJustify, LayoutHeader};
-
-#[component]
-pub fn SiteHeader() -> impl IntoView {
- let navigate = use_navigate();
-
- view! {
-
-
-
- "Rocie"
-
-
- }
-}
diff --git a/src/components/site_header.rs b/src/components/site_header.rs
new file mode 100644
index 0000000..65f7137
--- /dev/null
+++ b/src/components/site_header.rs
@@ -0,0 +1,29 @@
+use icondata_core::Icon as DataIcon;
+use leptos::prelude::{ClassAttribute, ElementChild, IntoView, OnAttribute, component, view};
+use leptos_icons::Icon;
+use leptos_router::{NavigateOptions, hooks::use_navigate};
+
+#[component]
+pub fn SiteHeader(
+ logo: DataIcon,
+ back_location: &'static str,
+ name: &'static str,
+ #[prop(default = None)] menu: Option,
+) -> impl IntoView {
+ let navigate = use_navigate();
+
+ view! {
+
+
+
+
+
{name}
+
{menu}
+
+ }
+}
--
cgit 1.4.1