use dioxus::prelude::*; use crate::{ api, page::{BasicButton, LabeledInput, TransientHeader}, }; #[component] pub fn ConsumePage(id: String, item: String, variant: String) -> Element { println!("{item} {variant}"); let (item, variant) = (use_signal(|| item.clone()), use_signal(|| variant.clone())); let destinations = use_resource(move || async move { api::API::get_unique_field(item(), variant(), "destination".to_string()).await }); let dest = use_signal(|| String::new()); let mut price = use_signal(|| 0.00); rsx! { div { class: "w-full py-4 flex flex-col gap-6", TransientHeader { title: format!("Consume {item} - {variant}") } LabeledInput { label: "Destination", PredefinedSelector { name: "Destination", value: dest, custom: true, predefined: destinations } } // Price Field LabeledInput { label: "Price", input { class: "rounded-md border border-neutral-300 dark:border-neutral-700 bg-white dark:bg-neutral-800 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400", r#type: "number", value: "{price}", oninput: move |e| { price.set(e.value().parse().unwrap()) } } } BasicButton { title: "Consume", onclick: move |_| { let id2 = id.clone(); spawn(async move { api::API::consume_item(id2, dest(), price()).await; navigator().go_back(); }); }, } } } } #[component] pub fn PredefinedSelector( name: String, value: Signal, custom: bool, predefined: Resource>, ) -> Element { let mut screen_visible = use_signal(|| false); let mut input_value = use_signal(|| value.read().clone()); rsx! { div { class: "p-2", button { class: "\ cursor-pointer rounded-lg border border-neutral-300 dark:border-neutral-700 \ px-3 py-1 text-md font-medium text-neutral-700 dark:text-neutral-300 \ hover:bg-neutral-100 dark:hover:bg-neutral-800 transition-colors duration-200", onclick: move |_| screen_visible.set(true), "{name}: {value}" } } if *screen_visible.read() { div { class: "\ fixed inset-0 z-40 flex flex-col bg-black bg-opacity-80 p-6 space-y-6 text-white \ backdrop-blur-sm", h2 { class: "text-2xl font-semibold", "Select a value for {name}" } if custom { input { class: "\ rounded-md border border-neutral-600 bg-neutral-900 px-4 py-2 text-lg \ text-white focus:outline-none focus:ring-2 focus:ring-blue-500 transition", r#type: "text", value: "{input_value}", oninput: move |evt| input_value.set(evt.value().clone()), } } div { class: "flex flex-wrap gap-3", match &*predefined.read() { Some(list) => rsx! { {list.iter().map(|item| rsx! { button { class: "\ rounded-md bg-neutral-700 px-4 py-2 text-sm hover:bg-neutral-600 \ transition-colors cursor-pointer select-none", onclick: { let item = item.clone(); move |_| { value.set(item.clone()); input_value.set(item.clone()); screen_visible.set(false); } }, "{item}" } })} }, None => rsx!(p { "Loading..." }), } } div { class: "mt-auto flex gap-4", button { class: "\ flex-1 bg-blue-600 hover:bg-blue-700 rounded-md px-5 py-2 text-white font-semibold \ transition-colors cursor-pointer", onclick: move |_| { value.set(input_value.read().clone()); screen_visible.set(false); }, "Confirm" } button { class: "\ flex-1 text-center underline text-neutral-400 hover:text-neutral-200 \ transition-colors cursor-pointer", onclick: move |_| screen_visible.set(false), "Cancel" } } } } } }