summary refs log tree commit diff stats
path: root/src/pages/create_product.rs
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-10-25 02:15:31 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-10-25 02:15:31 +0200
commit3a0e91bda1e93afa33dd182c2e820c94b3e94593 (patch)
tree436fb1b1e1b0bbe450436ccb5e105b8bea8db17f /src/pages/create_product.rs
parentfeat(treewide): Make usage more intuitive (diff)
downloadweb-client-3a0e91bda1e93afa33dd182c2e820c94b3e94593.zip
feat(treewide): Add further buttons
The register product > associate barcode > buy barcode workflow is now
usable.

The only missing features for an MVP are unit and unit property
creation.
Diffstat (limited to 'src/pages/create_product.rs')
-rw-r--r--src/pages/create_product.rs96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/pages/create_product.rs b/src/pages/create_product.rs
new file mode 100644
index 0000000..fcd3b0b
--- /dev/null
+++ b/src/pages/create_product.rs
@@ -0,0 +1,96 @@
+use std::{convert::Infallible, str::FromStr};
+
+use leptos::{
+    IntoView, component,
+    prelude::{Get, Show, signal},
+    task::spawn_local,
+    view,
+};
+use rocie_client::models::{ProductStub, UnitPropertyId};
+use rocie_macros::Form;
+use uuid::Uuid;
+
+use crate::{
+    api::{get_config, register_product_external_wrapped, unit_properties_wrapped},
+    components::{async_fetch::AsyncResource, banner::Banner, site_header::SiteHeader},
+};
+
+struct OptionalString(Option<String>);
+
+impl FromStr for OptionalString {
+    type Err = Infallible;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        if s.is_empty() {
+            Ok(Self(None))
+        } else {
+            Ok(Self(Some(s.to_owned())))
+        }
+    }
+}
+
+#[component]
+pub fn CreateProduct() -> impl IntoView {
+    let (error_message, error_message_set) = signal(None);
+
+    view! {
+        <SiteHeader logo=icondata_io::IoArrowBack back_location="/" name="Create Product" />
+
+        <Show when=move || error_message.get().is_some()>
+            <Banner text=move || error_message.get().expect("Is some") />
+        </Show>
+
+        {
+            Form! {
+                on_submit = |product_name, product_description, unit_property_id| {
+                    let config = get_config!();
+
+                    spawn_local(async move {
+                        match register_product_external_wrapped(&config, ProductStub {
+                                description: Some(product_description.0),
+                                name: product_name,
+                                parent: None, // TODO: Add this <2025-10-25>
+                                unit_property: UnitPropertyId { value: unit_property_id },
+                            }
+                        ).await {
+                            Ok(_id) => {}
+                            Err(err) => error_message_set.set(Some(format!("Failed to create product: {err}"))),
+                        }
+                    });
+                };
+
+                <Input
+                    name=product_name,
+                    rust_type=String,
+                    html_type="text",
+                    label="Product Name",
+                />
+
+                <Input
+                    name=product_description,
+                    rust_type=OptionalString,
+                    html_type="text",
+                    label="Product Description"
+                />
+
+                <Select
+                    name=unit_property_id,
+                    rust_type=Uuid,
+                    label="Unit property",
+                    options=AsyncResource! {
+                        () -> Result<Vec<(String, String)>, leptos::error::Error> {
+                            let unit_properties = unit_properties_wrapped().await?;
+
+                            Ok(
+                                unit_properties
+                                    .into_iter()
+                                    .map(|prop| (prop.name, prop.id.to_string()))
+                                    .collect()
+                            )
+                        }
+                    },
+                />
+            }
+        }
+    }
+}