2023-08-29 21:33:59 +02:00
|
|
|
use maud::{html, Markup, PreEscaped};
|
2023-05-08 00:05:45 +02:00
|
|
|
|
|
|
|
|
use crate::models::*;
|
2023-05-10 00:42:42 +02:00
|
|
|
use crate::ClientState;
|
2023-05-11 16:51:57 +02:00
|
|
|
use uuid::{uuid, Uuid};
|
2023-05-08 00:05:45 +02:00
|
|
|
|
2023-08-29 21:33:59 +02:00
|
|
|
pub struct Inventory;
|
2023-05-08 00:05:45 +02:00
|
|
|
|
|
|
|
|
impl Inventory {
|
2023-08-29 21:34:00 +02:00
|
|
|
pub fn build(state: ClientState, categories: Vec<Category>) -> Result<Markup, Error> {
|
2023-05-08 00:05:45 +02:00
|
|
|
let doc = html!(
|
2023-05-08 22:31:01 +02:00
|
|
|
div id="pkglist-item-manager" {
|
2023-08-29 21:33:59 +02:00
|
|
|
div ."p-8" ."grid" ."grid-cols-4" ."gap-5" {
|
|
|
|
|
div ."col-span-2" ."flex" ."flex-col" ."gap-8" {
|
|
|
|
|
h1 ."text-2xl" ."text-center" { "Categories" }
|
2023-08-29 21:33:59 +02:00
|
|
|
(InventoryCategoryList::build(&state, &categories))
|
2023-08-29 21:33:59 +02:00
|
|
|
(InventoryNewCategoryForm::build())
|
2023-05-08 22:31:01 +02:00
|
|
|
}
|
2023-08-29 21:33:59 +02:00
|
|
|
div ."col-span-2" ."flex" ."flex-col" ."gap-8" {
|
|
|
|
|
h1 ."text-2xl" ."text-center" { "Items" }
|
2023-05-17 17:31:48 +02:00
|
|
|
@if let Some(active_category_id) = state.active_category_id {
|
|
|
|
|
(InventoryItemList::build(&state, categories.iter().find(|category| category.id == active_category_id)
|
2023-08-29 21:34:00 +02:00
|
|
|
.ok_or(Error::NotFound{ description: format!("no category with id {}", active_category_id) })?
|
2023-05-17 17:31:48 +02:00
|
|
|
.items())
|
2023-08-29 21:33:59 +02:00
|
|
|
)
|
2023-05-08 22:31:01 +02:00
|
|
|
}
|
2023-08-29 21:33:59 +02:00
|
|
|
(InventoryNewItemForm::build(&state, &categories))
|
2023-05-08 22:31:01 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-05-08 00:05:45 +02:00
|
|
|
);
|
|
|
|
|
|
2023-08-29 21:33:59 +02:00
|
|
|
Ok(doc)
|
2023-05-08 00:05:45 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-29 21:33:59 +02:00
|
|
|
pub struct InventoryCategoryList;
|
2023-05-08 00:05:45 +02:00
|
|
|
|
|
|
|
|
impl InventoryCategoryList {
|
2023-08-29 21:33:59 +02:00
|
|
|
pub fn build(state: &ClientState, categories: &Vec<Category>) -> Markup {
|
2023-08-29 21:33:59 +02:00
|
|
|
let biggest_category_weight: i64 = categories
|
2023-05-08 00:05:45 +02:00
|
|
|
.iter()
|
2023-05-10 01:02:37 +02:00
|
|
|
.map(Category::total_weight)
|
2023-05-08 00:05:45 +02:00
|
|
|
.max()
|
|
|
|
|
.unwrap_or(1);
|
|
|
|
|
|
2023-08-29 21:33:59 +02:00
|
|
|
html!(
|
2023-08-29 21:33:59 +02:00
|
|
|
table
|
2023-08-29 21:34:00 +02:00
|
|
|
#category-list
|
2023-08-29 21:33:59 +02:00
|
|
|
."table"
|
|
|
|
|
."table-auto"
|
|
|
|
|
."border-collapse"
|
|
|
|
|
."border-spacing-0"
|
|
|
|
|
."border"
|
|
|
|
|
."w-full"
|
|
|
|
|
{
|
2023-05-08 22:31:01 +02:00
|
|
|
|
2023-08-29 21:33:59 +02:00
|
|
|
colgroup {
|
|
|
|
|
col style="width:50%" {}
|
|
|
|
|
col style="width:50%" {}
|
|
|
|
|
}
|
|
|
|
|
thead ."bg-gray-200" {
|
|
|
|
|
tr ."h-10" {
|
|
|
|
|
th ."border" ."p-2" ."w-3/5" { "Name" }
|
|
|
|
|
th ."border" ."p-2" { "Weight" }
|
2023-05-08 22:31:01 +02:00
|
|
|
}
|
2023-08-29 21:33:59 +02:00
|
|
|
}
|
|
|
|
|
tbody {
|
|
|
|
|
@for category in categories {
|
|
|
|
|
@let active = state.active_category_id.map_or(false, |id| category.id == id);
|
|
|
|
|
tr
|
|
|
|
|
."h-10"
|
|
|
|
|
."hover:bg-purple-100"
|
|
|
|
|
."m-3"
|
|
|
|
|
."h-full"
|
|
|
|
|
."outline"[active]
|
|
|
|
|
."outline-2"[active]
|
|
|
|
|
."outline-indigo-300"[active]
|
|
|
|
|
."pointer-events-none"[active]
|
|
|
|
|
{
|
2023-05-08 22:31:01 +02:00
|
|
|
|
2023-08-29 21:33:59 +02:00
|
|
|
td
|
|
|
|
|
class=@if state.active_category_id.map_or(false, |id| category.id == id) {
|
|
|
|
|
"border p-0 m-0 font-bold"
|
|
|
|
|
} @else {
|
|
|
|
|
"border p-0 m-0"
|
|
|
|
|
} {
|
|
|
|
|
a
|
|
|
|
|
id="select-category"
|
|
|
|
|
href=(
|
|
|
|
|
format!(
|
|
|
|
|
"/inventory/category/{id}/",
|
|
|
|
|
id=category.id
|
2023-05-08 22:31:01 +02:00
|
|
|
)
|
2023-08-29 21:33:59 +02:00
|
|
|
)
|
|
|
|
|
// hx-post=(
|
|
|
|
|
// format!(
|
|
|
|
|
// "/inventory/category/{id}/items",
|
|
|
|
|
// id=category.id
|
|
|
|
|
// )
|
|
|
|
|
// )
|
|
|
|
|
// hx-swap="outerHTML"
|
|
|
|
|
// hx-target="#items"
|
|
|
|
|
."inline-block" ."p-2" ."m-0" ."w-full"
|
|
|
|
|
{
|
|
|
|
|
(category.name.clone())
|
2023-05-08 22:31:01 +02:00
|
|
|
}
|
2023-08-29 21:33:59 +02:00
|
|
|
}
|
|
|
|
|
td ."border" ."p-2" ."m-0" style="position:relative;" {
|
|
|
|
|
p {
|
|
|
|
|
(category.total_weight().to_string())
|
2023-05-08 22:31:01 +02:00
|
|
|
}
|
2023-08-29 21:33:59 +02:00
|
|
|
div ."bg-blue-600" ."h-1.5"
|
|
|
|
|
style=(
|
|
|
|
|
format!(
|
|
|
|
|
"width: {width}%;position:absolute;left:0;bottom:0;right:0;",
|
|
|
|
|
width=(
|
|
|
|
|
(category.total_weight() as f64)
|
|
|
|
|
/ (biggest_category_weight as f64)
|
|
|
|
|
* 100.0
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
) {}
|
2023-05-08 22:31:01 +02:00
|
|
|
}
|
|
|
|
|
}
|
2023-08-29 21:33:59 +02:00
|
|
|
}
|
|
|
|
|
tr ."h-10" ."hover:bg-purple-200" ."bg-gray-300" ."font-bold" {
|
|
|
|
|
td ."border" ."p-0" ."m-0" {
|
|
|
|
|
p ."p-2" ."m-2" { "Sum" }
|
|
|
|
|
}
|
|
|
|
|
td ."border" ."p-0" ."m-0" {
|
|
|
|
|
p ."p-2" ."m-2" {
|
|
|
|
|
(categories.iter().map(Category::total_weight).sum::<i64>().to_string())
|
2023-05-08 22:31:01 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-29 21:33:59 +02:00
|
|
|
)
|
2023-05-08 00:05:45 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-29 21:33:59 +02:00
|
|
|
pub struct InventoryItemList;
|
2023-05-08 00:05:45 +02:00
|
|
|
|
|
|
|
|
impl InventoryItemList {
|
2023-08-29 21:33:59 +02:00
|
|
|
pub fn build(state: &ClientState, items: &Vec<Item>) -> Markup {
|
2023-08-29 21:33:59 +02:00
|
|
|
let biggest_item_weight: i64 = items.iter().map(|item| item.weight).max().unwrap_or(1);
|
2023-08-29 21:33:59 +02:00
|
|
|
html!(
|
2023-05-08 22:31:01 +02:00
|
|
|
div #items {
|
|
|
|
|
@if items.is_empty() {
|
|
|
|
|
p ."text-lg" ."text-center" ."py-5" ."text-gray-400" { "[Empty]" }
|
|
|
|
|
} @else {
|
2023-05-17 17:31:48 +02:00
|
|
|
@if let Some(edit_item) = state.edit_item {
|
2023-05-12 00:31:08 +02:00
|
|
|
form
|
|
|
|
|
name="edit-item"
|
|
|
|
|
id="edit-item"
|
|
|
|
|
action=(format!("/inventory/item/{edit_item}/edit"))
|
|
|
|
|
target="_self"
|
|
|
|
|
method="post"
|
|
|
|
|
{}
|
|
|
|
|
}
|
2023-05-08 22:31:01 +02:00
|
|
|
table
|
|
|
|
|
."table"
|
|
|
|
|
."table-auto"
|
2023-05-17 17:31:48 +02:00
|
|
|
.table-fixed
|
2023-05-08 22:31:01 +02:00
|
|
|
."border-collapse"
|
|
|
|
|
."border-spacing-0"
|
|
|
|
|
."border"
|
|
|
|
|
."w-full"
|
|
|
|
|
{
|
|
|
|
|
thead ."bg-gray-200" {
|
|
|
|
|
tr ."h-10" {
|
2023-05-17 17:31:48 +02:00
|
|
|
th ."border" ."p-2" ."w-3/5" { "Name" }
|
2023-05-08 22:31:01 +02:00
|
|
|
th ."border" ."p-2" { "Weight" }
|
2023-05-17 17:31:48 +02:00
|
|
|
th ."border" ."p-2" ."w-10" {}
|
|
|
|
|
th ."border" ."p-2" ."w-10" {}
|
2023-05-08 22:31:01 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
tbody {
|
|
|
|
|
@for item in items {
|
2023-05-17 17:31:48 +02:00
|
|
|
@if state.edit_item.map_or(false, |edit_item| edit_item == item.id) {
|
2023-05-12 00:31:08 +02:00
|
|
|
tr ."h-10" {
|
2023-05-17 17:47:26 +02:00
|
|
|
td ."border" ."bg-blue-300" ."px-2" ."py-0" {
|
2023-08-29 21:33:59 +02:00
|
|
|
div ."h-full" ."w-full" ."flex" {
|
|
|
|
|
input ."m-auto" ."px-1" ."block" ."w-full" ."bg-blue-100" ."hover:bg-white"
|
2023-05-17 17:47:26 +02:00
|
|
|
type="text"
|
|
|
|
|
id="edit-item-name"
|
|
|
|
|
name="edit-item-name"
|
|
|
|
|
form="edit-item"
|
|
|
|
|
value=(item.name)
|
|
|
|
|
{}
|
|
|
|
|
}
|
2023-05-12 00:31:08 +02:00
|
|
|
}
|
2023-05-17 17:31:48 +02:00
|
|
|
td ."border" ."bg-blue-300" ."px-2" ."py-0" {
|
2023-08-29 21:33:59 +02:00
|
|
|
div ."h-full" ."w-full" ."flex" {
|
|
|
|
|
input ."m-auto" ."px-1"."block" ."w-full" ."bg-blue-100" ."hover:bg-white"
|
2023-05-17 17:47:26 +02:00
|
|
|
type="number"
|
|
|
|
|
id="edit-item-weight"
|
|
|
|
|
name="edit-item-weight"
|
|
|
|
|
form="edit-item"
|
|
|
|
|
value=(item.weight)
|
|
|
|
|
{}
|
|
|
|
|
}
|
2023-05-12 00:31:08 +02:00
|
|
|
}
|
2023-08-29 21:33:59 +02:00
|
|
|
td
|
|
|
|
|
."border-none"
|
|
|
|
|
."bg-green-100"
|
|
|
|
|
."hover:bg-green-200"
|
|
|
|
|
."p-0"
|
|
|
|
|
."h-full"
|
|
|
|
|
{
|
|
|
|
|
button
|
|
|
|
|
."aspect-square"
|
|
|
|
|
."flex"
|
|
|
|
|
."w-full"
|
|
|
|
|
."h-full"
|
|
|
|
|
type="submit"
|
|
|
|
|
form="edit-item"
|
|
|
|
|
{
|
|
|
|
|
span
|
|
|
|
|
."m-auto"
|
|
|
|
|
."mdi"
|
|
|
|
|
."mdi-content-save"
|
|
|
|
|
."text-xl";
|
2023-05-12 00:31:08 +02:00
|
|
|
}
|
|
|
|
|
}
|
2023-08-29 21:33:59 +02:00
|
|
|
td
|
|
|
|
|
."border-none"
|
|
|
|
|
."bg-red-100"
|
|
|
|
|
."hover:bg-red-200"
|
|
|
|
|
."p-0"
|
|
|
|
|
."h-full"
|
|
|
|
|
{
|
|
|
|
|
a
|
|
|
|
|
."aspect-square"
|
|
|
|
|
."flex"
|
|
|
|
|
."w-full"
|
|
|
|
|
."h-full"
|
|
|
|
|
."p-0"
|
|
|
|
|
href=(format!("/inventory/item/{id}/cancel", id = item.id))
|
|
|
|
|
{
|
|
|
|
|
span
|
|
|
|
|
."m-auto"
|
|
|
|
|
."mdi"
|
|
|
|
|
."mdi-cancel"
|
|
|
|
|
."text-xl";
|
2023-05-12 00:31:08 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-05-11 16:51:57 +02:00
|
|
|
} @else {
|
|
|
|
|
tr ."h-10" ."even:bg-gray-100" ."hover:bg-purple-100" {
|
|
|
|
|
td ."border" ."p-0" {
|
2023-05-10 00:42:42 +02:00
|
|
|
a
|
2023-05-11 16:51:57 +02:00
|
|
|
."p-2" ."w-full" ."inline-block"
|
|
|
|
|
href=(
|
|
|
|
|
format!("/inventory/item/{id}/", id=item.id)
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
|
|
(item.name.clone())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
td ."border" ."p-2" style="position:relative;" {
|
|
|
|
|
p { (item.weight.to_string()) }
|
|
|
|
|
div ."bg-blue-600" ."h-1.5" style=(format!("
|
|
|
|
|
width: {width}%;
|
|
|
|
|
position:absolute;
|
|
|
|
|
left:0;
|
|
|
|
|
bottom:0;
|
2023-08-29 21:33:59 +02:00
|
|
|
right:0;", width=((item.weight as f64) / (biggest_item_weight as f64) * 100.0))) {}
|
2023-05-11 16:51:57 +02:00
|
|
|
}
|
|
|
|
|
td
|
2023-05-17 17:47:26 +02:00
|
|
|
."border-none"
|
|
|
|
|
."p-0"
|
2023-05-11 16:51:57 +02:00
|
|
|
."bg-blue-200"
|
|
|
|
|
."hover:bg-blue-400"
|
|
|
|
|
."w-8"
|
2023-08-29 21:33:59 +02:00
|
|
|
."h-full"
|
2023-05-11 16:51:57 +02:00
|
|
|
{
|
2023-08-29 21:33:59 +02:00
|
|
|
a
|
|
|
|
|
."aspect-square"
|
|
|
|
|
."flex"
|
|
|
|
|
."w-full"
|
|
|
|
|
href=(format!("?edit_item={id}", id = item.id))
|
|
|
|
|
{
|
|
|
|
|
span ."m-auto" ."mdi" ."mdi-pencil" ."text-xl";
|
2023-05-11 16:51:57 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
td
|
2023-05-17 17:47:26 +02:00
|
|
|
."border-none"
|
|
|
|
|
."p-0"
|
2023-05-11 16:51:57 +02:00
|
|
|
."bg-red-200"
|
|
|
|
|
."hover:bg-red-400"
|
|
|
|
|
."w-8"
|
2023-08-29 21:33:59 +02:00
|
|
|
."h-full"
|
|
|
|
|
{
|
|
|
|
|
a
|
|
|
|
|
."aspect-square"
|
|
|
|
|
."flex"
|
|
|
|
|
."w-full"
|
|
|
|
|
href=(format!("/inventory/item/{id}/delete", id = item.id))
|
2023-05-10 00:42:42 +02:00
|
|
|
{
|
2023-08-29 21:33:59 +02:00
|
|
|
span ."m-auto" ."mdi" ."mdi-delete" ."text-xl";
|
|
|
|
|
}
|
2023-05-11 16:51:57 +02:00
|
|
|
}
|
2023-05-10 00:42:42 +02:00
|
|
|
}
|
2023-05-08 22:31:01 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-29 21:33:59 +02:00
|
|
|
)
|
2023-05-08 22:31:01 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-29 21:33:59 +02:00
|
|
|
pub struct InventoryNewItemFormName;
|
|
|
|
|
|
|
|
|
|
impl InventoryNewItemFormName {
|
|
|
|
|
pub fn build(value: Option<&str>, error: bool) -> Markup {
|
|
|
|
|
html!(
|
|
|
|
|
div
|
|
|
|
|
."grid"
|
|
|
|
|
."grid-cols-[2fr,3fr]"
|
|
|
|
|
."justify-items-center"
|
|
|
|
|
."items-center"
|
|
|
|
|
hx-post="/inventory/item/name/validate"
|
2023-08-29 21:33:59 +02:00
|
|
|
hx-trigger="input delay:1s, loaded from:document"
|
|
|
|
|
|
2023-08-29 21:33:59 +02:00
|
|
|
hx-params="new-item-name"
|
|
|
|
|
hx-swap="outerHTML"
|
2023-08-29 21:33:59 +02:00
|
|
|
#abc
|
2023-08-29 21:33:59 +02:00
|
|
|
{
|
|
|
|
|
label for="name" .font-bold { "Name" }
|
|
|
|
|
input
|
|
|
|
|
type="text"
|
|
|
|
|
id="new-item-name"
|
|
|
|
|
name="new-item-name"
|
|
|
|
|
x-on:input="(e) => {save_active = inventory_new_item_check_input()}"
|
|
|
|
|
."block"
|
|
|
|
|
."w-full"
|
|
|
|
|
."p-2"
|
|
|
|
|
."bg-gray-50"
|
|
|
|
|
."border-2"
|
|
|
|
|
."border-red-500"[error]
|
|
|
|
|
."border-gray-300"[!error]
|
|
|
|
|
."rounded"
|
|
|
|
|
."focus:outline-none"
|
|
|
|
|
."focus:bg-white"
|
|
|
|
|
."focus:border-purple-500"[!error]
|
|
|
|
|
value=[value]
|
|
|
|
|
;
|
|
|
|
|
@if error {
|
|
|
|
|
div
|
|
|
|
|
."col-start-2"
|
|
|
|
|
."text-sm"
|
|
|
|
|
."text-red-500"
|
|
|
|
|
{ "name already exists" }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct InventoryNewItemFormWeight;
|
|
|
|
|
|
|
|
|
|
impl InventoryNewItemFormWeight {
|
|
|
|
|
pub fn build() -> Markup {
|
|
|
|
|
html!(
|
|
|
|
|
div
|
|
|
|
|
."grid"
|
|
|
|
|
."grid-cols-[2fr,3fr]"
|
|
|
|
|
."justify-items-center"
|
|
|
|
|
."items-center"
|
|
|
|
|
{
|
|
|
|
|
label for="weight" .font-bold { "Weight" }
|
|
|
|
|
input
|
|
|
|
|
type="number"
|
|
|
|
|
id="new-item-weight"
|
|
|
|
|
name="new-item-weight"
|
|
|
|
|
min="0"
|
|
|
|
|
x-on:input="(e) => {
|
|
|
|
|
save_active = inventory_new_item_check_input();
|
|
|
|
|
weight_error = !check_weight();
|
|
|
|
|
}"
|
|
|
|
|
x-bind:class="weight_error && 'border-red-500' || 'border-gray-300 focus:border-purple-500'"
|
|
|
|
|
."block"
|
|
|
|
|
."w-full"
|
|
|
|
|
."p-2"
|
|
|
|
|
."bg-gray-50"
|
|
|
|
|
."border-2"
|
|
|
|
|
."rounded"
|
|
|
|
|
."focus:outline-none"
|
|
|
|
|
."focus:bg-white"
|
|
|
|
|
{}
|
|
|
|
|
span
|
|
|
|
|
// x-on produces some errors, this works as well
|
|
|
|
|
x-bind:class="!weight_error && 'hidden'"
|
|
|
|
|
."col-start-2"
|
|
|
|
|
."text-sm"
|
|
|
|
|
."text-red-500"
|
|
|
|
|
{ "invalid input" }
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct InventoryNewItemFormCategory;
|
|
|
|
|
|
|
|
|
|
impl InventoryNewItemFormCategory {
|
|
|
|
|
pub fn build(state: &ClientState, categories: &Vec<Category>) -> Markup {
|
|
|
|
|
html!(
|
|
|
|
|
div
|
|
|
|
|
."grid"
|
|
|
|
|
."grid-cols-[2fr,3fr]"
|
|
|
|
|
."justify-items-center"
|
|
|
|
|
."items-center"
|
|
|
|
|
{
|
|
|
|
|
label for="item-category" .font-bold ."w-1/2" .text-center { "Category" }
|
|
|
|
|
select
|
|
|
|
|
id="new-item-category-id"
|
|
|
|
|
name="new-item-category-id"
|
|
|
|
|
."block"
|
|
|
|
|
."w-full"
|
|
|
|
|
."p-2"
|
|
|
|
|
."bg-gray-50"
|
|
|
|
|
."border-2"
|
|
|
|
|
."border-gray-300"
|
|
|
|
|
."rounded"
|
|
|
|
|
."focus:outline-none"
|
|
|
|
|
."focus:bg-white"
|
|
|
|
|
."focus:border-purple-500"
|
|
|
|
|
autocomplete="off" // https://stackoverflow.com/a/10096033
|
|
|
|
|
{
|
|
|
|
|
@for category in categories {
|
|
|
|
|
option value=(category.id) selected[state.active_category_id.map_or(false, |id| id == category.id)] {
|
|
|
|
|
(category.name)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-29 21:33:59 +02:00
|
|
|
pub struct InventoryNewItemForm;
|
2023-05-08 22:31:01 +02:00
|
|
|
|
|
|
|
|
impl InventoryNewItemForm {
|
2023-08-29 21:33:59 +02:00
|
|
|
pub fn build(state: &ClientState, categories: &Vec<Category>) -> Markup {
|
|
|
|
|
html!(
|
2023-08-29 21:33:59 +02:00
|
|
|
script {
|
|
|
|
|
(PreEscaped("
|
|
|
|
|
function inventory_new_item_check_input() {
|
|
|
|
|
return document.getElementById('new-item-name').value.length != 0
|
|
|
|
|
&& is_positive_integer(document.getElementById('new-item-weight').value)
|
|
|
|
|
}
|
|
|
|
|
function check_weight() {
|
|
|
|
|
return document.getElementById('new-item-weight').validity.valid;
|
|
|
|
|
}
|
|
|
|
|
"))
|
|
|
|
|
}
|
2023-05-08 22:31:01 +02:00
|
|
|
form
|
2023-08-29 21:33:59 +02:00
|
|
|
x-data="{
|
|
|
|
|
save_active: inventory_new_item_check_input(),
|
|
|
|
|
weight_error: !check_weight(),
|
|
|
|
|
}"
|
2023-05-08 22:31:01 +02:00
|
|
|
name="new-item"
|
|
|
|
|
id="new-item"
|
|
|
|
|
action="/inventory/item/"
|
|
|
|
|
target="_self"
|
|
|
|
|
method="post"
|
2023-08-29 21:33:59 +02:00
|
|
|
."p-5" ."border-2" ."border-gray-200" {
|
2023-05-08 22:31:01 +02:00
|
|
|
div ."mb-5" ."flex" ."flex-row" ."items-center" {
|
|
|
|
|
span ."mdi" ."mdi-playlist-plus" ."text-2xl" ."mr-4" {}
|
|
|
|
|
p ."inline" ."text-xl" { "Add new item" }
|
|
|
|
|
}
|
2023-08-29 21:33:59 +02:00
|
|
|
div ."w-11/12" ."mx-auto" ."flex" ."flex-col" ."gap-8" {
|
|
|
|
|
(InventoryNewItemFormName::build(None, false))
|
|
|
|
|
(InventoryNewItemFormWeight::build())
|
2023-08-29 21:34:00 +02:00
|
|
|
(InventoryNewItemFormCategory::build(state, categories))
|
2023-05-08 22:31:01 +02:00
|
|
|
input type="submit" value="Add"
|
2023-08-29 21:33:59 +02:00
|
|
|
x-bind:disabled="!save_active"
|
|
|
|
|
."enabled:cursor-pointer"
|
|
|
|
|
."disabled:opacity-50"
|
2023-05-08 22:31:01 +02:00
|
|
|
."py-2"
|
|
|
|
|
."border-2"
|
|
|
|
|
."rounded"
|
|
|
|
|
."border-gray-300"
|
|
|
|
|
."mx-auto"
|
|
|
|
|
."w-full" {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-29 21:33:59 +02:00
|
|
|
)
|
2023-05-08 00:05:45 +02:00
|
|
|
}
|
|
|
|
|
}
|
2023-08-29 21:33:59 +02:00
|
|
|
|
|
|
|
|
pub struct InventoryNewCategoryForm;
|
|
|
|
|
|
|
|
|
|
impl InventoryNewCategoryForm {
|
|
|
|
|
pub fn build() -> Markup {
|
|
|
|
|
html!(
|
|
|
|
|
form
|
2023-08-29 21:33:59 +02:00
|
|
|
x-data="{ save_active: document.getElementById('new-category-name').value.length != 0 }"
|
2023-08-29 21:33:59 +02:00
|
|
|
name="new-category"
|
|
|
|
|
id="new-category"
|
|
|
|
|
action="/inventory/category/"
|
|
|
|
|
target="_self"
|
|
|
|
|
method="post"
|
2023-08-29 21:33:59 +02:00
|
|
|
."p-5" ."border-2" ."border-gray-200" {
|
2023-08-29 21:33:59 +02:00
|
|
|
div ."mb-5" ."flex" ."flex-row" ."items-center" {
|
|
|
|
|
span ."mdi" ."mdi-playlist-plus" ."text-2xl" ."mr-4" {}
|
|
|
|
|
p ."inline" ."text-xl" { "Add new category" }
|
|
|
|
|
}
|
|
|
|
|
div ."w-11/12" ."mx-auto" {
|
|
|
|
|
div ."pb-8" {
|
|
|
|
|
div ."flex" ."flex-row" ."justify-center" ."items-start"{
|
|
|
|
|
label for="name" .font-bold ."w-1/2" ."p-2" ."text-center" { "Name" }
|
|
|
|
|
span ."w-1/2" {
|
|
|
|
|
input type="text" id="new-category-name" name="new-category-name"
|
2023-08-29 21:33:59 +02:00
|
|
|
x-on:input="(e) => {save_active = e.target.value.length != 0 }"
|
2023-08-29 21:33:59 +02:00
|
|
|
."block"
|
|
|
|
|
."w-full"
|
|
|
|
|
."p-2"
|
|
|
|
|
."bg-gray-50"
|
|
|
|
|
."border-2"
|
2023-08-29 21:33:59 +02:00
|
|
|
."border-gray-300"
|
2023-08-29 21:33:59 +02:00
|
|
|
."rounded"
|
|
|
|
|
."focus:outline-none"
|
|
|
|
|
."focus:bg-white"
|
|
|
|
|
."focus:border-purple-500"
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
input type="submit" value="Add"
|
2023-08-29 21:33:59 +02:00
|
|
|
x-bind:disabled="!save_active"
|
|
|
|
|
."enabled:cursor-pointer"
|
|
|
|
|
."disabled:opacity-50"
|
2023-08-29 21:33:59 +02:00
|
|
|
."py-2"
|
|
|
|
|
."border-2"
|
|
|
|
|
."rounded"
|
|
|
|
|
."border-gray-300"
|
|
|
|
|
."mx-auto"
|
|
|
|
|
."w-full" {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|