diff options
| author | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2026-03-19 07:45:14 +0100 |
|---|---|---|
| committer | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2026-03-19 07:45:14 +0100 |
| commit | f6a3fb9c4d8dd86f78c9f75a23c1ac35bf35d4eb (patch) | |
| tree | 5f28fbca03d83921b568f7cb1708374456d9ec42 /src/pages/create_product.rs | |
| parent | feat(treewide): Add further buttons (diff) | |
| download | web-client-f6a3fb9c4d8dd86f78c9f75a23c1ac35bf35d4eb.zip | |
feat(treewide): Commit MVP
Diffstat (limited to 'src/pages/create_product.rs')
| -rw-r--r-- | src/pages/create_product.rs | 109 |
1 files changed, 79 insertions, 30 deletions
diff --git a/src/pages/create_product.rs b/src/pages/create_product.rs index fcd3b0b..fdf8f28 100644 --- a/src/pages/create_product.rs +++ b/src/pages/create_product.rs @@ -1,4 +1,4 @@ -use std::{convert::Infallible, str::FromStr}; +use std::{convert::Infallible, iter, str::FromStr}; use leptos::{ IntoView, component, @@ -6,16 +6,23 @@ use leptos::{ task::spawn_local, view, }; -use rocie_client::models::{ProductStub, UnitPropertyId}; +use leptos_router::{NavigateOptions, hooks::use_navigate}; +use rocie_client::models::{ProductParentId, 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}, + api::{ + get_config, product_parents_wrapped, register_product_external_wrapped, + unit_properties_wrapped, + }, + components::{ + async_fetch::AsyncResource, banner::Banner, catch_errors::CatchErrors, + login_wall::LoginWall, site_header::SiteHeader, + }, }; -struct OptionalString(Option<String>); +pub(crate) struct OptionalString(pub(crate) Option<String>); impl FromStr for OptionalString { type Err = Infallible; @@ -29,35 +36,54 @@ impl FromStr for OptionalString { } } +struct OptionalParentId(Option<ProductParentId>); + +impl FromStr for OptionalParentId { + type Err = uuid::Error; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + if s.is_empty() { + Ok(Self(None)) + } else { + Ok(Self(Some(ProductParentId { value: s.parse()? }))) + } + } +} + #[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 }, + <CatchErrors> + <LoginWall back=move || "/create-product".to_owned()> + <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, parent| { + let config = get_config!(); + let navigate = use_navigate(); + + spawn_local(async move { + match register_product_external_wrapped(&config, ProductStub { + description: product_description.0.map(|d| d.trim().to_owned()), + name: product_name.trim().to_owned(), + parent: parent.0, + unit_property: UnitPropertyId { value: unit_property_id }, + } + ).await { + Ok(_id) => { + navigate("/create-product", NavigateOptions::default()); + } + Err(err) => error_message_set.set(Some(format!("Failed to create product: {err}"))), } - ).await { - Ok(_id) => {} - Err(err) => error_message_set.set(Some(format!("Failed to create product: {err}"))), - } - }); - }; + }); + }; <Input name=product_name, @@ -74,6 +100,27 @@ pub fn CreateProduct() -> impl IntoView { /> <Select + name=parent, + rust_type=OptionalParentId, + label="Parent", + options=AsyncResource! { + () -> Result<Vec<(String, String)>, leptos::error::Error> { + let parents = product_parents_wrapped().await?; + + Ok( + iter::once(("No parent".to_owned(), String::new())) + .chain( + parents + .into_iter() + .map(|prop| (prop.name, prop.id.to_string())) + ) + .collect() + ) + } + }, + /> + + <Select name=unit_property_id, rust_type=Uuid, label="Unit property", @@ -90,7 +137,9 @@ pub fn CreateProduct() -> impl IntoView { } }, /> - } - } + } + } + </LoginWall> + </CatchErrors> } } |
