diff --git a/rust/src/components/inventory.rs b/rust/src/components/inventory.rs index 5e9e529..f1e5cb7 100644 --- a/rust/src/components/inventory.rs +++ b/rust/src/components/inventory.rs @@ -2,7 +2,7 @@ use maud::{html, Markup}; use crate::models::*; use crate::ClientState; -use uuid::uuid; +use uuid::{uuid, Uuid}; pub struct Inventory { doc: Markup, @@ -19,7 +19,7 @@ impl Inventory { div ."col-span-2" { h1 ."text-2xl" ."mb-5" ."text-center" { "Items" } @if state.active_category_id.is_some() { - ({>::into(InventoryItemList::build(categories.iter().find(|category| category.active).unwrap().items()))}) + ({>::into(InventoryItemList::build(categories.iter().find(|category| category.active).unwrap().items(), state.edit_item))}) } ({>::into(InventoryNewItemForm::build(&state, &categories))}) @@ -155,7 +155,7 @@ pub struct InventoryItemList { } impl InventoryItemList { - pub fn build(items: &Vec) -> Self { + pub fn build(items: &Vec, edit_item: Option) -> Self { let biggest_item_weight: u32 = items.iter().map(|item| item.weight).max().unwrap_or(1); let doc = html!( div #items { @@ -178,41 +178,59 @@ impl InventoryItemList { } tbody { @for item in items { - tr ."h-10" ."even:bg-gray-100" ."hover:bg-purple-100" { - td ."border" ."p-0" { - a - ."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; - right:0;", width=(f64::from(item.weight) / f64::from(biggest_item_weight) * 100.0))) {} - } - td - ."border" - ."bg-red-200" - ."hover:bg-red-400" - ."cursor-pointer" - ."w-8" - ."text-center" - { + @if edit_item.map_or(false, |edit_item| edit_item == item.id) { + tr { td { (item.name.clone()) " is being edited" }} + } @else { + tr ."h-10" ."even:bg-gray-100" ."hover:bg-purple-100" { + td ."border" ."p-0" { a - href = (format!("/inventory/item/{id}/delete", id = item.id)) - { - button { - span ."mdi" ."mdi-delete" ."text-xl" {} + ."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; + right:0;", width=(f64::from(item.weight) / f64::from(biggest_item_weight) * 100.0))) {} + } + td + ."border" + ."bg-blue-200" + ."hover:bg-blue-400" + ."cursor-pointer" + ."w-8" + ."text-center" + { + a href = (format!("?edit_item={id}", id = item.id)) + { + button { + span ."mdi" ."mdi-pencil" ."text-xl" {} + } + } + } + td + ."border" + ."bg-red-200" + ."hover:bg-red-400" + ."cursor-pointer" + ."w-8" + ."text-center" + { + a href = (format!("/inventory/item/{id}/delete", id = item.id)) + { + button { + span ."mdi" ."mdi-delete" ."text-xl" {} + } + } + } } } } diff --git a/rust/src/main.rs b/rust/src/main.rs index 127d448..6d8239c 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -1,7 +1,6 @@ #![allow(unused_imports)] use axum::{ - extract::Path, - extract::State, + extract::{Path, Query, State}, headers, headers::Header, http::{header::HeaderMap, StatusCode}, @@ -39,12 +38,14 @@ pub struct AppState { #[derive(Clone)] pub struct ClientState { pub active_category_id: Option, + pub edit_item: Option, } impl ClientState { pub fn new() -> Self { ClientState { active_category_id: None, + edit_item: None, } } } @@ -65,7 +66,7 @@ async fn main() -> Result<(), sqlx::Error> { .max_connections(5) .connect_with( SqliteConnectOptions::new() - .filename("/home/hannes-private/sync/items/items.sqlite") + .filename(std::env::var("SQLITE_DATABASE").expect("env SQLITE_DATABASE not found")) .pragma("foreign_keys", "1"), ) .await @@ -107,16 +108,31 @@ async fn root() -> (StatusCode, Html) { ) } +#[derive(Deserialize)] +struct InventoryQuery { + edit_item: Option, +} + +impl Default for InventoryQuery { + fn default() -> Self { + Self { edit_item: None } + } +} + async fn inventory_active( Path(id): Path, - State(state): State, + State(mut state): State, + Query(inventory_query): Query, ) -> Result<(StatusCode, Html), (StatusCode, Html)> { + state.client_state.edit_item = inventory_query.edit_item; inventory(state, Some(id)).await } async fn inventory_inactive( - State(state): State, + State(mut state): State, + Query(inventory_query): Query, ) -> Result<(StatusCode, Html), (StatusCode, Html)> { + state.client_state.edit_item = inventory_query.edit_item; inventory(state, None).await } @@ -147,7 +163,7 @@ async fn inventory( for category in &mut categories { category - .populate_items() + .populate_items(&state.database_pool) .await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, Html::from(e.to_string())))?; diff --git a/rust/src/models.rs b/rust/src/models.rs index 7a94434..40e6d09 100644 --- a/rust/src/models.rs +++ b/rust/src/models.rs @@ -114,13 +114,10 @@ impl<'a> Category { self.items().iter().map(|item| item.weight).sum() } - pub async fn populate_items(&'a mut self) -> Result<(), Error> { - let pool = SqlitePoolOptions::new() - .max_connections(5) - .connect("sqlite:///home/hannes-private/sync/items/items.sqlite") - .await - .unwrap(); - + pub async fn populate_items( + &'a mut self, + pool: &sqlx::Pool, + ) -> Result<(), Error> { let items = sqlx::query(&format!( "SELECT id,name,weight,description,category_id @@ -128,7 +125,7 @@ impl<'a> Category { WHERE category_id = '{id}'", id = self.id )) - .fetch(&pool) + .fetch(pool) .map_ok(std::convert::TryInto::try_into) .try_collect::>>() .await?