// 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::{iter, str::FromStr}; use leptos::{ IntoView, component, prelude::{Get, Show, signal}, task::spawn_local, view, }; use leptos_router::{NavigateOptions, hooks::use_navigate}; use log::info; use rocie_client::models::{RecipeParentId, RecipeStub}; use rocie_macros::Form; use crate::{ api::{add_recipe_external_wrapped, get_config, recipe_parents_wrapped}, components::{ async_fetch::AsyncResource, banner::Banner, catch_errors::CatchErrors, login_wall::LoginWall, site_header::SiteHeader, }, pages::create_product::OptionalString, }; 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(RecipeParentId { value: s.parse()? }))) } } } #[component] pub fn CreateRecipe() -> impl IntoView { let (error_message, error_message_set) = signal(None); view! { { Form! { on_submit = |content, name, parent| { let config = get_config!(); let navigate = use_navigate(); spawn_local(async move { match add_recipe_external_wrapped(&config, RecipeStub { content: content.trim().to_owned(), name: name.trim().to_owned(), parent: parent.0, }).await { Ok(_id) => { info!("Navigating"); navigate("/create-recipe", NavigateOptions::default()); } Err(err) => error_message_set.set(Some(format!("Failed to create recipe: {err}"))), } }); };