159 lines
5.4 KiB
Rust
159 lines
5.4 KiB
Rust
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<String>,
|
|
custom: bool,
|
|
predefined: Resource<Vec<String>>,
|
|
) -> 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"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|