diff options
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/buy.rs | 23 | ||||
| -rw-r--r-- | src/components/form.rs | 120 | ||||
| -rw-r--r-- | src/components/input_placeholder.rs | 7 | ||||
| -rw-r--r-- | src/components/mod.rs | 11 | ||||
| -rw-r--r-- | src/components/select_placeholder.rs | 93 |
5 files changed, 120 insertions, 134 deletions
diff --git a/src/components/buy.rs b/src/components/buy.rs index 0c294ee..6d9402e 100644 --- a/src/components/buy.rs +++ b/src/components/buy.rs @@ -1,7 +1,9 @@ use leptos::{IntoView, component, view}; use log::info; +use rocie_client::models::UnitId; +use uuid::Uuid; -use crate::components::{form::Form, input_placeholder::InputPlaceholder, site_header::SiteHeader}; +use crate::components::{form::Form, site_header::SiteHeader}; #[component] pub fn Buy() -> impl IntoView { @@ -9,22 +11,27 @@ pub fn Buy() -> impl IntoView { <SiteHeader logo=icondata_io::IoPricetag back_location="/" name="Buy" /> {Form! { - on_submit = |Inputs {product_barcode, amount}| { - info!("Got product barcode: {product_barcode} with amount: {amount}"); - } + on_submit = |product_barcode, amount, unit_id| { + info!("Got product barcode: {product_barcode} with amount: {amount}, {unit_id}"); + }; <Input name=product_barcode, - signal_name_get=product_barcode_get, - signal_name_set=product_barcode_set, rust_type=u32, html_type="number", label="Product Barcode" /> + <Select + name=unit_id, + rust_type=Uuid, + label="Unit", + options=[ + ("Kilogram", Uuid::new_v4()), + ("Gram", Uuid::new_v4()) + ] + /> <Input name=amount, - signal_name_get=amount_get, - signal_name_set=amount_set, rust_type=u16, html_type="number", label="Amount" diff --git a/src/components/form.rs b/src/components/form.rs index fd55897..9c371ad 100644 --- a/src/components/form.rs +++ b/src/components/form.rs @@ -1,119 +1 @@ -macro_rules! Form { - ( - on_submit = |$bound:pat_param| $on_submit:block - $( - <Input - name=$name:ident, - signal_name_get=$signal_name_get:ident, - signal_name_set=$signal_name_set:ident, - rust_type=$rust_type:ty, - html_type=$input_type:literal, - label=$label:literal $(,)* - /> - )* - ) => {{ - use leptos::{ - view, - prelude::{ - Get, - NodeRef, - ElementChild, - ClassAttribute, - OnAttribute, - signal, - Set, - Show, - }, - html::Input, - web_sys::SubmitEvent - }; - - use log::info; - - - $( - let ($signal_name_get, $signal_name_set) = signal(None); - let $name: NodeRef<Input> = NodeRef::new(); - )* - - let on_submit = move |ev: SubmitEvent| { - struct Inputs { - $( - $name: $rust_type - ),* - } - - // stop the page from reloading! - ev.prevent_default(); - - $( - let value = { - let output = $name - .get() - // event handlers can only fire after the view - // is mounted to the DOM, so the `NodeRef` will be `Some` - .expect("<input> to exist") - .value(); - - let fin: Result<$rust_type, leptos::error::Error> = output - .parse() - .map_err(Into::<leptos::error::Error>::into); - fin - }; - - let $name = match value { - Ok(ok) => { - // Reset the signal - $signal_name_set.set(None); - - ok - } , - Err(err) => { - $signal_name_set.set(Some(err)); - - // Skip running the real `on_submit` - return - } - }; - )* - - let real_on_submit = |$bound| $on_submit; - real_on_submit(Inputs { - $( - $name - ),* - }) - }; - - - view! { - <form class="flex flex-col contents-start m-2 g-2" on:submit=on_submit> - $( - <InputPlaceholder input_type=$input_type label=$label node_ref=$name /> - <Show - when=move || $signal_name_get.get().is_some() - fallback=|| () - > - <p class="ps-2 text-red-300">{move || - format!( - "Input is invalid for type {}: {}", - stringify!($rust_type), - $signal_name_get.get().expect("Was `is_some`") - ) - }</p> - </Show> - )* - - <div class="static"> - <input - type="submit" - value="Submit" - class="absolute bottom-0 right-0 h-20 w-20 rounded-lg bg-green-300 m-2" - /> - </div> - </form> - } - }}; -} - -pub(crate) use Form; +pub(crate) use rocie_macros::Form; diff --git a/src/components/input_placeholder.rs b/src/components/input_placeholder.rs index 05b9509..aeef838 100644 --- a/src/components/input_placeholder.rs +++ b/src/components/input_placeholder.rs @@ -1,5 +1,3 @@ -use std::sync::atomic::{AtomicU32, Ordering}; - use leptos::{ IntoView, component, html::Input, @@ -7,11 +5,8 @@ use leptos::{ view, }; -fn get_id() -> u32 { - static ID: AtomicU32 = AtomicU32::new(0); +use crate::components::get_id; - ID.fetch_add(1, Ordering::Relaxed) -} #[component] pub fn InputPlaceholder( diff --git a/src/components/mod.rs b/src/components/mod.rs index f7b8dba..1ee37d5 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -1,9 +1,12 @@ +use std::sync::atomic::{AtomicU32, Ordering}; + // Generic pub mod async_fetch; pub mod container; +pub mod form; pub mod icon_p; pub mod input_placeholder; -pub mod form; +pub mod select_placeholder; // Specific pub mod buy; @@ -11,3 +14,9 @@ pub mod inventory; pub mod product_overview; pub mod recipies; pub mod site_header; + +fn get_id() -> u32 { + static ID: AtomicU32 = AtomicU32::new(0); + + ID.fetch_add(1, Ordering::Relaxed) +} diff --git a/src/components/select_placeholder.rs b/src/components/select_placeholder.rs new file mode 100644 index 0000000..947931c --- /dev/null +++ b/src/components/select_placeholder.rs @@ -0,0 +1,93 @@ +use leptos::{ + IntoView, + attr::{AttributeValue, IntoAttributeValue}, + component, + html::Select, + prelude::{ + ClassAttribute, CollectView, ElementChild, GlobalAttributes, NodeRef, NodeRefAttribute, + }, + view, +}; + +use crate::components::get_id; + +#[component] +pub fn SelectPlaceholder<T>( + label: &'static str, + node_ref: NodeRef<Select>, + options: Vec<(&'static str, T)>, +) -> impl IntoView +where + T: IntoAttributeValue, + <T as IntoAttributeValue>::Output: Send + AttributeValue, +{ + let id = get_id(); + + let options = options + .into_iter() + .map(|(label, value)| { + view! { + <option value=value>{label}</option> + } + }) + .collect_view(); + + view! { + <div class="relative h-14"> + <select + id=id.to_string() + class="\ + absolute \ + bottom-0 \ + bg-gray-200 \ + border-8 \ + border-b-2 \ + border-b-trasparent \ + border-gray-200 \ + focus:outline-none \ + h-10 \ + peer \ + placeholder-transparent \ + rounded-t-lg \ + text-gray-900 \ + w-full \ + " + node_ref=node_ref + > + {options} + </select> + + // TODO: Reference `var(--tw-border-2)` instead of the `2 px` <2025-10-01> + <div class=" + absolute \ + bottom-0 \ + h-[2px] \ + w-full \ + bg-gray-300 \ + peer-focus:bg-indigo-600 \ + " /> + + <label + for=id.to_string() + class="\ + bottom-10 \ + absolute \ + left-0 \ + text-gray-700 \ + text-sm \ + transition-all \ + peer-focus:bottom-10 \ + peer-focus:left-0 \ + peer-focus:text-gray-700 \ + peer-focus:text-sm \ + peer-placeholder-shown:text-base \ + peer-placeholder-shown:text-gray-400 \ + peer-placeholder-shown:bottom-2 \ + peer-placeholder-shown:left-2 \ + " + > + {label} + </label> + </div> + } +} |
