use std::str::FromStr; use dioxus::prelude::*; use serde::{Deserialize, Serialize}; use crate::{api, page::consume::PredefinedSelector, Route}; #[component] pub fn SupplyPage(item: String, param: SupplyPageParam) -> Element { let item_spec = crate::API .read() .as_ref() .unwrap() .get_item(item.clone()) .unwrap(); // TODO : filter with onlyVariants let variants = use_signal(|| { item_spec .variants .into_iter() .map(|x| x.1) .collect::>() }); let variant = use_signal(|| variants.first().unwrap().clone()); let (item, variant) = (use_signal(|| item.clone()), use_signal(|| variant.clone())); let origins = use_resource(move || async move { api::API::get_unique_field( item(), variant().read().variant.clone(), "origin".to_string(), ) .await }); let variants_str = use_resource( move || async move { variants.iter().map(|x| x.name.clone()).collect::>() }, ); let variant_id = use_signal(|| String::new()); let origin = use_signal(|| String::new()); let mut price = use_signal(|| 0.0); let location = use_signal(|| String::new()); let mut note = use_signal(|| String::new()); let mut state = use_signal(|| String::new()); rsx! { h1 { "Add new Item" }, p { {state} }, // Variant Selection PredefinedSelector { name: "Variant", value: variant_id, predefined: variants_str } // Origin Field with Dropdown and Text Input PredefinedSelector { name: "Origin", value: origin, predefined: origins } // Price Field label { "Price: ", input { r#type: "number", value: "{price}", oninput: move |e| price.set(e.value().parse().unwrap()) } }, // Location Dropdown // Note label { "Note: ", input { r#type: "text", value: "{note}", oninput: move |e| note.set(e.value()) } }, // Submit Button button { onclick: move |_| { spawn(async move { let variant = variants.iter().find(|x| x.name == variant_id()).unwrap().variant.clone(); let s = format!("{} {} {} {} {} {}", item(), variant, price(), origin(), location(), note()); state.set(s); let tid = crate::api::API::supply_item(item(), variant, price(), Some(origin()), Some(location()), Some(note())).await; navigator().replace(Route::TransactionPage { id: tid }); }); }, "Create" } } } #[derive(Clone, PartialEq, Debug, Default, Deserialize, Serialize)] pub struct SupplyPageParam { pub onlyVariants: Option>, pub forcePrice: Option, pub forceOrigin: Option, } impl std::fmt::Display for SupplyPageParam { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(&serde_json::to_string(self).unwrap()) } } impl FromStr for SupplyPageParam { type Err = serde_json::Error; fn from_str(s: &str) -> Result { serde_json::from_str(s) } }