// rocie - An enterprise grocery management system - Web app // // Copyright (C) 2026 Benedikt Peetz // SPDX-License-Identifier: GPL-3.0-or-later // // This file is part of Rocie. // // You should have received a copy of the License along with this program. // If not, see . use std::{convert::Infallible, iter, str::FromStr}; use leptos::{ IntoView, component, prelude::{Get, Show, signal}, task::spawn_local, view, }; 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, 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, }, }; pub(crate) struct OptionalString(pub(crate) Option); impl FromStr for OptionalString { type Err = Infallible; fn from_str(s: &str) -> Result { if s.is_empty() { Ok(Self(None)) } else { Ok(Self(Some(s.to_owned()))) } } } struct OptionalParentId(Option); impl FromStr for OptionalParentId { type Err = uuid::Error; fn from_str(s: &str) -> Result { 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! { { 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}"))), } }); }; Result, leptos::error::Error> { let unit_properties = unit_properties_wrapped().await?; Ok( unit_properties .into_iter() .map(|prop| (prop.name, prop.id.to_string())) .collect() ) } }, /> } } } }