migration, adding categories, small fixes
This commit is contained in:
@@ -13,6 +13,7 @@ impl Inventory {
|
||||
div ."p-8" ."grid" ."grid-cols-4" ."gap-3" {
|
||||
div ."col-span-2" {
|
||||
(InventoryCategoryList::build(&state, &categories))
|
||||
(InventoryNewCategoryForm::build())
|
||||
}
|
||||
div ."col-span-2" {
|
||||
h1 ."text-2xl" ."mb-5" ."text-center" { "Items" }
|
||||
@@ -409,3 +410,53 @@ impl InventoryNewItemForm {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct InventoryNewCategoryForm;
|
||||
|
||||
impl InventoryNewCategoryForm {
|
||||
pub fn build() -> Markup {
|
||||
html!(
|
||||
form
|
||||
name="new-category"
|
||||
id="new-category"
|
||||
action="/inventory/category/"
|
||||
target="_self"
|
||||
method="post"
|
||||
."mt-8" ."p-5" ."border-2" ."border-gray-200" {
|
||||
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"
|
||||
."block"
|
||||
."w-full"
|
||||
."p-2"
|
||||
."bg-gray-50"
|
||||
."border-2"
|
||||
."rounded"
|
||||
."focus:outline-none"
|
||||
."focus:bg-white"
|
||||
."focus:border-purple-500"
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input type="submit" value="Add"
|
||||
."py-2"
|
||||
."border-2"
|
||||
."rounded"
|
||||
."border-gray-300"
|
||||
."mx-auto"
|
||||
."w-full" {
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -411,61 +411,73 @@ impl TripInfo {
|
||||
."flex-wrap"
|
||||
."gap-2"
|
||||
."justify-between"
|
||||
// as we have a gap between the elements, we have
|
||||
// to completely skip an element when there are no
|
||||
// active or inactive items, otherwise we get the gap
|
||||
// between the empty (invisible) item, throwing off
|
||||
// the margins
|
||||
{
|
||||
@let types = trip.types();
|
||||
div
|
||||
."flex"
|
||||
."flex-row"
|
||||
."flex-wrap"
|
||||
."gap-2"
|
||||
."justify-start"
|
||||
{
|
||||
@for triptype in types.iter().filter(|t| t.active) {
|
||||
a href=(format!("type/{}/remove", triptype.id)) {
|
||||
li
|
||||
."border"
|
||||
."rounded-2xl"
|
||||
."py-0.5"
|
||||
."px-2"
|
||||
."bg-green-100"
|
||||
."cursor-pointer"
|
||||
."flex"
|
||||
."flex-column"
|
||||
."items-center"
|
||||
."hover:bg-red-200"
|
||||
."gap-1"
|
||||
{
|
||||
span { (triptype.name) }
|
||||
span ."mdi" ."mdi-delete" ."text-sm" {}
|
||||
@let active_triptypes = types.iter().filter(|t| t.active).collect::<Vec<&TripType>>();
|
||||
@let inactive_triptypes = types.iter().filter(|t| !t.active).collect::<Vec<&TripType>>();
|
||||
|
||||
@if !active_triptypes.is_empty() {
|
||||
div
|
||||
."flex"
|
||||
."flex-row"
|
||||
."flex-wrap"
|
||||
."gap-2"
|
||||
."justify-start"
|
||||
{
|
||||
@for triptype in active_triptypes {
|
||||
a href=(format!("type/{}/remove", triptype.id)) {
|
||||
li
|
||||
."border"
|
||||
."rounded-2xl"
|
||||
."py-0.5"
|
||||
."px-2"
|
||||
."bg-green-100"
|
||||
."cursor-pointer"
|
||||
."flex"
|
||||
."flex-column"
|
||||
."items-center"
|
||||
."hover:bg-red-200"
|
||||
."gap-1"
|
||||
{
|
||||
span { (triptype.name) }
|
||||
span ."mdi" ."mdi-delete" ."text-sm" {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
div
|
||||
."flex"
|
||||
."flex-row"
|
||||
."flex-wrap"
|
||||
."gap-2"
|
||||
."justify-start"
|
||||
{
|
||||
@for triptype in types.iter().filter(|t| !t.active) {
|
||||
a href=(format!("type/{}/add", triptype.id)) {
|
||||
li
|
||||
."border"
|
||||
."rounded-2xl"
|
||||
."py-0.5"
|
||||
."px-2"
|
||||
."bg-gray-100"
|
||||
."cursor-pointer"
|
||||
."flex"
|
||||
."flex-column"
|
||||
."items-center"
|
||||
."hover:bg-green-200"
|
||||
."gap-1"
|
||||
."opacity-60"
|
||||
{
|
||||
span { (triptype.name) }
|
||||
span ."mdi" ."mdi-plus" ."text-sm" {}
|
||||
@if !inactive_triptypes.is_empty() {
|
||||
div
|
||||
."flex"
|
||||
."flex-row"
|
||||
."flex-wrap"
|
||||
."gap-2"
|
||||
."justify-start"
|
||||
{
|
||||
@for triptype in inactive_triptypes {
|
||||
a href=(format!("type/{}/add", triptype.id)) {
|
||||
li
|
||||
."border"
|
||||
."rounded-2xl"
|
||||
."py-0.5"
|
||||
."px-2"
|
||||
."bg-gray-100"
|
||||
."cursor-pointer"
|
||||
."flex"
|
||||
."flex-column"
|
||||
."items-center"
|
||||
."hover:bg-green-200"
|
||||
."gap-1"
|
||||
."opacity-60"
|
||||
{
|
||||
span { (triptype.name) }
|
||||
span ."mdi" ."mdi-plus" ."text-sm" {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
113
rust/src/main.rs
113
rust/src/main.rs
@@ -9,6 +9,8 @@ use axum::{
|
||||
Form, Router,
|
||||
};
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use serde_variant::to_variant_name;
|
||||
|
||||
use sqlx::{
|
||||
@@ -72,13 +74,16 @@ async fn main() -> Result<(), sqlx::Error> {
|
||||
let database_pool = SqlitePoolOptions::new()
|
||||
.max_connections(5)
|
||||
.connect_with(
|
||||
SqliteConnectOptions::new()
|
||||
.filename(std::env::var("SQLITE_DATABASE").expect("env SQLITE_DATABASE not found"))
|
||||
.pragma("foreign_keys", "1"),
|
||||
SqliteConnectOptions::from_str(
|
||||
&std::env::var("DATABASE_URL").expect("env DATABASE_URL not found"),
|
||||
)?
|
||||
.pragma("foreign_keys", "1"),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
sqlx::migrate!().run(&database_pool).await?;
|
||||
|
||||
let state = AppState {
|
||||
database_pool,
|
||||
client_state: ClientState::new(),
|
||||
@@ -102,6 +107,7 @@ async fn main() -> Result<(), sqlx::Error> {
|
||||
.route("/trip/:id/items/:id/pack", get(trip_item_set_pack))
|
||||
.route("/trip/:id/items/:id/unpack", get(trip_item_set_unpack))
|
||||
.route("/inventory/", get(inventory_inactive))
|
||||
.route("/inventory/category/", post(inventory_category_create))
|
||||
.route("/inventory/item/", post(inventory_item_create))
|
||||
.route("/inventory/category/:id/", get(inventory_active))
|
||||
.route("/inventory/item/:id/delete", get(inventory_item_delete))
|
||||
@@ -142,8 +148,8 @@ impl Default for InventoryQuery {
|
||||
}
|
||||
|
||||
async fn inventory_active(
|
||||
Path(id): Path<Uuid>,
|
||||
State(mut state): State<AppState>,
|
||||
Path(id): Path<Uuid>,
|
||||
Query(inventory_query): Query<InventoryQuery>,
|
||||
) -> Result<(StatusCode, Markup), (StatusCode, Markup)> {
|
||||
state.client_state.edit_item = inventory_query.edit_item;
|
||||
@@ -164,7 +170,7 @@ async fn inventory(
|
||||
) -> Result<(StatusCode, Markup), (StatusCode, Markup)> {
|
||||
state.client_state.active_category_id = active_id;
|
||||
|
||||
let mut categories = query("SELECT id,name,description FROM inventoryitemcategories")
|
||||
let mut categories = query("SELECT id,name,description FROM inventory_items_categories")
|
||||
.fetch(&state.database_pool)
|
||||
.map_ok(std::convert::TryInto::try_into)
|
||||
.try_collect::<Vec<Result<Category, models::Error>>>()
|
||||
@@ -236,7 +242,7 @@ async fn inventory_item_create(
|
||||
Form(new_item): Form<NewItem>,
|
||||
) -> Result<Redirect, (StatusCode, String)> {
|
||||
query(
|
||||
"INSERT INTO inventoryitems
|
||||
"INSERT INTO inventory_items
|
||||
(id, name, description, weight, category_id)
|
||||
VALUES
|
||||
(?, ?, ?, ?, ?)",
|
||||
@@ -301,7 +307,7 @@ async fn inventory_item_delete(
|
||||
Path(id): Path<Uuid>,
|
||||
) -> Result<Redirect, (StatusCode, String)> {
|
||||
let results = query(
|
||||
"DELETE FROM inventoryitems
|
||||
"DELETE FROM inventory_items
|
||||
WHERE id = ?",
|
||||
)
|
||||
.bind(id.to_string())
|
||||
@@ -346,7 +352,7 @@ async fn inventory_item_delete(
|
||||
// //TODO bind this stuff!!!!!!! no sql injection pls
|
||||
// "SELECT
|
||||
// i.id, i.name, i.description, i.weight, i.category_id
|
||||
// FROM inventoryitemcategories AS c
|
||||
// FROM inventory_items_categories AS c
|
||||
// INNER JOIN inventoryitems AS i
|
||||
// ON i.category_id = c.id WHERE c.id = '{id}';",
|
||||
// id = id,
|
||||
@@ -476,7 +482,7 @@ async fn trip_create(
|
||||
),
|
||||
})?;
|
||||
|
||||
Ok(Redirect::to(&format!("/trips/{id}/", id = id.to_string())))
|
||||
Ok(Redirect::to(&format!("/trip/{id}/", id = id.to_string())))
|
||||
}
|
||||
|
||||
async fn trips(
|
||||
@@ -519,8 +525,8 @@ struct TripQuery {
|
||||
}
|
||||
|
||||
async fn trip(
|
||||
Path(id): Path<Uuid>,
|
||||
State(mut state): State<AppState>,
|
||||
Path(id): Path<Uuid>,
|
||||
Query(trip_query): Query<TripQuery>,
|
||||
) -> Result<(StatusCode, Markup), (StatusCode, Markup)> {
|
||||
state.client_state.trip_edit_attribute = trip_query.edit;
|
||||
@@ -541,7 +547,7 @@ async fn trip(
|
||||
})?
|
||||
.map_err(|e: Error| (StatusCode::INTERNAL_SERVER_ERROR, ErrorPage::build(&e.to_string())))?;
|
||||
|
||||
trip.load_triptypes(&state.database_pool)
|
||||
trip.load_trips_types(&state.database_pool)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
(
|
||||
@@ -577,11 +583,11 @@ async fn trip(
|
||||
}
|
||||
|
||||
async fn trip_type_remove(
|
||||
Path((trip_id, type_id)): Path<(Uuid, Uuid)>,
|
||||
State(state): State<AppState>,
|
||||
Path((trip_id, type_id)): Path<(Uuid, Uuid)>,
|
||||
) -> Result<Redirect, (StatusCode, Markup)> {
|
||||
let results = query(
|
||||
"DELETE FROM trips_to_triptypes AS ttt
|
||||
"DELETE FROM trips_to_trips_types AS ttt
|
||||
WHERE ttt.trip_id = ?
|
||||
AND ttt.trip_type_id = ?
|
||||
",
|
||||
@@ -603,11 +609,11 @@ async fn trip_type_remove(
|
||||
}
|
||||
|
||||
async fn trip_type_add(
|
||||
Path((trip_id, type_id)): Path<(Uuid, Uuid)>,
|
||||
State(state): State<AppState>,
|
||||
Path((trip_id, type_id)): Path<(Uuid, Uuid)>,
|
||||
) -> Result<Redirect, (StatusCode, Markup)> {
|
||||
query(
|
||||
"INSERT INTO trips_to_triptypes
|
||||
"INSERT INTO trips_to_trips_types
|
||||
(trip_id, trip_type_id) VALUES (?, ?)",
|
||||
)
|
||||
.bind(trip_id.to_string())
|
||||
@@ -672,8 +678,8 @@ struct CommentUpdate {
|
||||
}
|
||||
|
||||
async fn trip_comment_set(
|
||||
Path(trip_id): Path<Uuid>,
|
||||
State(state): State<AppState>,
|
||||
Path(trip_id): Path<Uuid>,
|
||||
Form(comment_update): Form<CommentUpdate>,
|
||||
) -> Result<Redirect, (StatusCode, Markup)> {
|
||||
let result = query(
|
||||
@@ -704,8 +710,8 @@ struct TripUpdate {
|
||||
}
|
||||
|
||||
async fn trip_edit_attribute(
|
||||
Path((trip_id, attribute)): Path<(Uuid, TripAttribute)>,
|
||||
State(state): State<AppState>,
|
||||
Path((trip_id, attribute)): Path<(Uuid, TripAttribute)>,
|
||||
Form(trip_update): Form<TripUpdate>,
|
||||
) -> Result<Redirect, (StatusCode, Markup)> {
|
||||
let result = query(&format!(
|
||||
@@ -738,7 +744,7 @@ async fn trip_item_set_state(
|
||||
value: bool,
|
||||
) -> Result<(), (StatusCode, Markup)> {
|
||||
let result = query(&format!(
|
||||
"UPDATE tripitems
|
||||
"UPDATE trips_items
|
||||
SET {key} = ?
|
||||
WHERE trip_id = ?
|
||||
AND item_id = ?",
|
||||
@@ -764,9 +770,9 @@ async fn trip_item_set_state(
|
||||
}
|
||||
|
||||
async fn trip_item_set_pick(
|
||||
State(state): State<AppState>,
|
||||
Path((trip_id, item_id)): Path<(Uuid, Uuid)>,
|
||||
headers: HeaderMap,
|
||||
State(state): State<AppState>,
|
||||
) -> Result<Redirect, (StatusCode, Markup)> {
|
||||
Ok(trip_item_set_state(&state, trip_id, item_id, TripItemStateKey::Pick, true).await?).map(
|
||||
|_| -> Result<Redirect, (StatusCode, Markup)> {
|
||||
@@ -790,9 +796,9 @@ async fn trip_item_set_pick(
|
||||
}
|
||||
|
||||
async fn trip_item_set_unpick(
|
||||
State(state): State<AppState>,
|
||||
Path((trip_id, item_id)): Path<(Uuid, Uuid)>,
|
||||
headers: HeaderMap,
|
||||
State(state): State<AppState>,
|
||||
) -> Result<Redirect, (StatusCode, Markup)> {
|
||||
Ok(trip_item_set_state(&state, trip_id, item_id, TripItemStateKey::Pick, false).await?).map(
|
||||
|_| -> Result<Redirect, (StatusCode, Markup)> {
|
||||
@@ -816,9 +822,9 @@ async fn trip_item_set_unpick(
|
||||
}
|
||||
|
||||
async fn trip_item_set_pack(
|
||||
State(state): State<AppState>,
|
||||
Path((trip_id, item_id)): Path<(Uuid, Uuid)>,
|
||||
headers: HeaderMap,
|
||||
State(state): State<AppState>,
|
||||
) -> Result<Redirect, (StatusCode, Markup)> {
|
||||
Ok(trip_item_set_state(&state, trip_id, item_id, TripItemStateKey::Pack, true).await?).map(
|
||||
|_| -> Result<Redirect, (StatusCode, Markup)> {
|
||||
@@ -842,9 +848,9 @@ async fn trip_item_set_pack(
|
||||
}
|
||||
|
||||
async fn trip_item_set_unpack(
|
||||
State(state): State<AppState>,
|
||||
Path((trip_id, item_id)): Path<(Uuid, Uuid)>,
|
||||
headers: HeaderMap,
|
||||
State(state): State<AppState>,
|
||||
) -> Result<Redirect, (StatusCode, Markup)> {
|
||||
Ok(trip_item_set_state(&state, trip_id, item_id, TripItemStateKey::Pack, false).await?).map(
|
||||
|_| -> Result<Redirect, (StatusCode, Markup)> {
|
||||
@@ -866,3 +872,66 @@ async fn trip_item_set_unpack(
|
||||
},
|
||||
)?
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct NewCategory {
|
||||
#[serde(rename = "new-category-name")]
|
||||
name: String,
|
||||
}
|
||||
|
||||
async fn inventory_category_create(
|
||||
State(state): State<AppState>,
|
||||
Form(new_category): Form<NewCategory>,
|
||||
) -> Result<Redirect, (StatusCode, Markup)> {
|
||||
let id = Uuid::new_v4();
|
||||
query(
|
||||
"INSERT INTO inventory_items_categories
|
||||
(id, name)
|
||||
VALUES
|
||||
(?, ?)",
|
||||
)
|
||||
.bind(id.to_string())
|
||||
.bind(&new_category.name)
|
||||
.execute(&state.database_pool)
|
||||
.map_err(|e| match e {
|
||||
sqlx::Error::Database(ref error) => {
|
||||
let sqlite_error = error.downcast_ref::<SqliteError>();
|
||||
if let Some(code) = sqlite_error.code() {
|
||||
match &*code {
|
||||
"2067" => {
|
||||
// SQLITE_CONSTRAINT_UNIQUE
|
||||
(
|
||||
StatusCode::BAD_REQUEST,
|
||||
ErrorPage::build(&format!(
|
||||
"category with name \"{name}\" already exists",
|
||||
name = new_category.name
|
||||
)),
|
||||
)
|
||||
}
|
||||
_ => (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
ErrorPage::build(&format!(
|
||||
"got error with unknown code: {}",
|
||||
sqlite_error.to_string()
|
||||
)),
|
||||
),
|
||||
}
|
||||
} else {
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
ErrorPage::build(&format!(
|
||||
"got error without code: {}",
|
||||
sqlite_error.to_string()
|
||||
)),
|
||||
)
|
||||
}
|
||||
}
|
||||
_ => (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
ErrorPage::build(&format!("got unknown error: {}", e.to_string())),
|
||||
),
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(Redirect::to("/inventory/"))
|
||||
}
|
||||
|
||||
@@ -229,18 +229,18 @@ impl<'a> Trip {
|
||||
pub fn types(&'a self) -> &Vec<TripType> {
|
||||
self.types
|
||||
.as_ref()
|
||||
.expect("you need to call load_triptypes()")
|
||||
.expect("you need to call load_trips_types()")
|
||||
}
|
||||
|
||||
pub fn categories(&'a self) -> &Vec<TripCategory> {
|
||||
self.categories
|
||||
.as_ref()
|
||||
.expect("you need to call load_triptypes()")
|
||||
.expect("you need to call load_trips_types()")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Trip {
|
||||
pub async fn load_triptypes(
|
||||
pub async fn load_trips_types(
|
||||
&'a mut self,
|
||||
pool: &sqlx::Pool<sqlx::Sqlite>,
|
||||
) -> Result<(), Error> {
|
||||
@@ -250,13 +250,13 @@ impl<'a> Trip {
|
||||
type.id as id,
|
||||
type.name as name,
|
||||
CASE WHEN inner.id IS NOT NULL THEN true ELSE false END AS active
|
||||
FROM triptypes AS type
|
||||
FROM trips_types AS type
|
||||
LEFT JOIN (
|
||||
SELECT type.id as id, type.name as name
|
||||
FROM trips as trip
|
||||
INNER JOIN trips_to_triptypes as ttt
|
||||
INNER JOIN trips_to_trips_types as ttt
|
||||
ON ttt.trip_id = trip.id
|
||||
INNER JOIN triptypes AS type
|
||||
INNER JOIN trips_types AS type
|
||||
ON type.id == ttt.trip_type_id
|
||||
WHERE trip.id = ?
|
||||
) AS inner
|
||||
@@ -287,19 +287,36 @@ impl<'a> Trip {
|
||||
SELECT
|
||||
category.id as category_id,
|
||||
category.name as category_name,
|
||||
category.description as category_description,
|
||||
item.id as item_id,
|
||||
item.name as item_name,
|
||||
item.description as item_description,
|
||||
item.weight as item_weight,
|
||||
trip.pick as item_is_picked,
|
||||
trip.pack as item_is_packed
|
||||
FROM tripitems as trip
|
||||
INNER JOIN inventoryitems as item
|
||||
ON item.id = trip.item_id
|
||||
INNER JOIN inventoryitemcategories as category
|
||||
ON category.id = item.category_id
|
||||
WHERE trip.trip_id = ?;
|
||||
category.description AS category_description,
|
||||
inner.trip_id AS trip_id,
|
||||
inner.category_description AS category_description,
|
||||
inner.item_id AS item_id,
|
||||
inner.item_name AS item_name,
|
||||
inner.item_description AS item_description,
|
||||
inner.item_weight AS item_weight,
|
||||
inner.item_is_picked AS item_is_picked,
|
||||
inner.item_is_packed AS item_is_packed
|
||||
FROM inventory_items_categories AS category
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
trip.trip_id AS trip_id,
|
||||
category.id as category_id,
|
||||
category.name as category_name,
|
||||
category.description as category_description,
|
||||
item.id as item_id,
|
||||
item.name as item_name,
|
||||
item.description as item_description,
|
||||
item.weight as item_weight,
|
||||
trip.pick as item_is_picked,
|
||||
trip.pack as item_is_packed
|
||||
FROM trips_items as trip
|
||||
INNER JOIN inventory_items as item
|
||||
ON item.id = trip.item_id
|
||||
INNER JOIN inventory_items_categories as category
|
||||
ON category.id = item.category_id
|
||||
WHERE trip.trip_id = 'a8b181d6-3b16-4a41-99fa-0713b94a34d9'
|
||||
) AS inner
|
||||
ON inner.category_id = category.id
|
||||
",
|
||||
)
|
||||
.bind(self.id.to_string())
|
||||
@@ -315,28 +332,38 @@ impl<'a> Trip {
|
||||
items: None,
|
||||
};
|
||||
|
||||
let item = TripItem {
|
||||
item: Item {
|
||||
id: Uuid::try_parse(row.try_get("item_id")?)?,
|
||||
name: row.try_get("item_name")?,
|
||||
description: row.try_get("item_description")?,
|
||||
weight: row.try_get("item_weight")?,
|
||||
category_id: category.category.id,
|
||||
},
|
||||
picked: row.try_get("item_is_picked")?,
|
||||
packed: row.try_get("item_is_packed")?,
|
||||
};
|
||||
match row.try_get("item_id")? {
|
||||
None => {
|
||||
// we have an empty (unused) category which has NULL values
|
||||
// for the item_id column
|
||||
category.items = Some(vec![]);
|
||||
categories.push(category);
|
||||
}
|
||||
Some(item_id) => {
|
||||
let item = TripItem {
|
||||
item: Item {
|
||||
id: Uuid::try_parse(item_id)?,
|
||||
name: row.try_get("item_name")?,
|
||||
description: row.try_get("item_description")?,
|
||||
weight: row.try_get("item_weight")?,
|
||||
category_id: category.category.id,
|
||||
},
|
||||
picked: row.try_get("item_is_picked")?,
|
||||
packed: row.try_get("item_is_packed")?,
|
||||
};
|
||||
|
||||
if let Some(&mut ref mut c) = categories
|
||||
.iter_mut()
|
||||
.find(|c| c.category.id == category.category.id)
|
||||
{
|
||||
// we always populate c.items when we add a new category, so
|
||||
// it's safe to unwrap here
|
||||
c.items.as_mut().unwrap().push(item);
|
||||
} else {
|
||||
category.items = Some(vec![item]);
|
||||
categories.push(category);
|
||||
if let Some(&mut ref mut c) = categories
|
||||
.iter_mut()
|
||||
.find(|c| c.category.id == category.category.id)
|
||||
{
|
||||
// we always populate c.items when we add a new category, so
|
||||
// it's safe to unwrap here
|
||||
c.items.as_mut().unwrap().push(item);
|
||||
} else {
|
||||
category.items = Some(vec![item]);
|
||||
categories.push(category);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -413,7 +440,7 @@ impl<'a> Category {
|
||||
let items = sqlx::query(&format!(
|
||||
"SELECT
|
||||
id,name,weight,description,category_id
|
||||
FROM inventoryitems
|
||||
FROM inventory_items
|
||||
WHERE category_id = '{id}'",
|
||||
id = self.id
|
||||
))
|
||||
@@ -461,7 +488,7 @@ impl TryFrom<SqliteRow> for Item {
|
||||
impl Item {
|
||||
pub async fn find(pool: &sqlx::Pool<sqlx::Sqlite>, id: Uuid) -> Result<Option<Item>, Error> {
|
||||
let item: Result<Result<Item, Error>, sqlx::Error> = sqlx::query(
|
||||
"SELECT * FROM inventoryitems AS item
|
||||
"SELECT * FROM inventory_items AS item
|
||||
WHERE item.id = ?",
|
||||
)
|
||||
.bind(id.to_string())
|
||||
@@ -485,12 +512,12 @@ impl Item {
|
||||
weight: u32,
|
||||
) -> Result<Option<Uuid>, Error> {
|
||||
let id: Result<Result<Uuid, Error>, sqlx::Error> = sqlx::query(
|
||||
"UPDATE inventoryitems AS item
|
||||
"UPDATE inventory_items AS item
|
||||
SET
|
||||
name = ?,
|
||||
weight = ?
|
||||
WHERE item.id = ?
|
||||
RETURNING inventoryitems.category_id AS id
|
||||
RETURNING inventory_items.category_id AS id
|
||||
",
|
||||
)
|
||||
.bind(name)
|
||||
|
||||
Reference in New Issue
Block a user