From 8a27639aad8b0240599154ea085f999d8381f9e2 Mon Sep 17 00:00:00 2001 From: Matthias Lodner Date: Mon, 26 Jan 2026 22:09:32 +0100 Subject: [PATCH] Added unit to db and structs/types. --- common/src/models/article.rs | 12 ++- common/src/models/mod.rs | 1 + common/src/models/unit.rs | 47 +++++++++ common/src/models/variant.rs | 9 +- frontend/app/components/article/article.vue | 19 ++-- .../app/components/article/articleCreate.vue | 14 ++- .../app/components/variant/variantCreate.vue | 96 +++++++++++-------- .../app/components/variant/variantRow.vue | 15 ++- frontend/app/store/labelEditorStore.ts | 14 ++- frontend/app/types/article.ts | 7 +- frontend/app/types/unit.ts | 22 +++++ frontend/app/types/variant.ts | 6 +- server/migrations/20260126175759_unit.sql | 35 +++++++ server/src/main.rs | 6 ++ 14 files changed, 243 insertions(+), 60 deletions(-) create mode 100644 common/src/models/unit.rs create mode 100644 frontend/app/types/unit.ts create mode 100644 server/migrations/20260126175759_unit.sql diff --git a/common/src/models/article.rs b/common/src/models/article.rs index 5608cf6..4885fd9 100644 --- a/common/src/models/article.rs +++ b/common/src/models/article.rs @@ -5,6 +5,7 @@ use crate::models::variant::{load_article_variants, Variant}; use sqlx::{Arguments, Pool, Row, Postgres, Error}; use sqlx::postgres::{PgArguments, PgQueryResult, PgRow}; use log::{debug, error, info}; +use crate::models::unit::Unit; #[derive(Debug, Deserialize, Serialize, Clone, FromRow)] pub struct Article { @@ -14,6 +15,7 @@ pub struct Article { pub origin: Origin, pub description: Option, pub ingredients: Option, + pub default_unit: Unit, pub variants: Vec, } @@ -25,6 +27,7 @@ fn from_postgres_row_small(row: PgRow) -> Article { origin: row.get(3), description: row.get(4), ingredients: row.get(5), + default_unit: row.get(6), variants: vec![], } } @@ -50,6 +53,7 @@ async fn from_postgres_row(row: PgRow, pool: PgPool) -> Article { origin: row.get(3), description: row.get(4), ingredients: row.get(5), + default_unit: row.get(6), variants: variants, } } @@ -116,9 +120,10 @@ pub async fn insert_article(article: &Article, pool: PgPool) -> Option
args.add(&article.origin); args.add(&article.description); args.add(&article.ingredients); + args.add(&article.default_unit); let statement = format!( - "INSERT INTO {} (name, bio, origin, description, ingredients) VALUES ($1, $2, $3, $4, $5) RETURNING *", + "INSERT INTO {} (name, bio, origin, description, ingredients, default_unit_id) VALUES ($1, $2, $3, $4, $5, $6) RETURNING *", "article", ); @@ -150,9 +155,10 @@ pub async fn update_article(article_id: i64, article: &Article, pool: PgPool) -> args.add(&article.origin); args.add(&article.description); args.add(&article.ingredients); - + args.add(&article.default_unit); + let statement = format!( - "UPDATE {} SET name = $2, bio = $3, origin = $4, description = $5, ingredients = $6 WHERE id = $1 RETURNING *", + "UPDATE {} SET name = $2, bio = $3, origin = $4, description = $5, ingredients = $6, default_unit_id = $7 WHERE id = $1 RETURNING *", "article", ); diff --git a/common/src/models/mod.rs b/common/src/models/mod.rs index 3d475c2..3a7da5f 100644 --- a/common/src/models/mod.rs +++ b/common/src/models/mod.rs @@ -1,3 +1,4 @@ pub mod origin; pub mod article; pub mod variant; +pub mod unit; diff --git a/common/src/models/unit.rs b/common/src/models/unit.rs new file mode 100644 index 0000000..5e1c961 --- /dev/null +++ b/common/src/models/unit.rs @@ -0,0 +1,47 @@ +use std::fmt; +use std::fmt::Formatter; + +use serde::{Deserialize, Serialize}; + +#[repr(i64)] +#[derive(Deserialize, Serialize, Copy, Clone, PartialEq, sqlx::Type)] +pub enum Unit { + Kg, + G, + L, + Ml, + Stk, +} + +impl Unit { + pub const VEC: &'static [Unit] = &[Unit::Kg, Unit::G, Unit::L, Unit::Ml, Unit::Stk]; + + pub fn position(&self) -> usize { + Unit::VEC.iter().position(|r| *r == *self).unwrap() + } + + // TODO: Convert function for units if possible/needed + +} + +fn to_string(unit: Unit, f: &mut Formatter) -> fmt::Result { + match unit { + Unit::Kg => write!(f, "Kilogramm"), + Unit::G => write!(f, "Gramm"), + Unit::L => write!(f, "Liter"), + Unit::Ml => write!(f, "Milliliter"), + Unit::Stk => write!(f, "Stück"), + } +} + +impl fmt::Debug for Unit { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + to_string(*self, f) + } +} + +impl fmt::Display for Unit { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + to_string(*self, f) + } +} diff --git a/common/src/models/variant.rs b/common/src/models/variant.rs index ea971d2..88dce9e 100644 --- a/common/src/models/variant.rs +++ b/common/src/models/variant.rs @@ -2,6 +2,7 @@ use log::{error, info}; use serde::{Deserialize, Serialize}; use sqlx::{Arguments, FromRow, PgPool, Row}; use sqlx::postgres::{PgArguments, PgRow}; +use crate::models::unit::Unit; #[derive(Debug, Deserialize, Serialize, Clone, FromRow)] pub struct Variant { @@ -11,6 +12,7 @@ pub struct Variant { pub name: Option, pub description: Option, pub ingredients: Option, + pub unit: Unit, } fn from_postgres_row_small(row: PgRow) -> Variant { @@ -21,6 +23,7 @@ fn from_postgres_row_small(row: PgRow) -> Variant { name: row.get(4), description: row.get(5), ingredients: row.get(6), + unit: row.get(7), } } @@ -64,9 +67,10 @@ pub async fn insert_variant(article_id: i64, variant: &Variant, pool: PgPool) -> args.add(&variant.name); args.add(&variant.description); args.add(&variant.ingredients); + args.add(&variant.unit); let statement = format!( - "INSERT INTO {} (article_id, weight, ean, name, description, ingredients) VALUES ($1, $2, $3, $4, $5, $6) RETURNING *", + "INSERT INTO {} (article_id, weight, ean, name, description, ingredients, unit_id) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING *", "variant", ); @@ -97,11 +101,12 @@ pub async fn update_variant(variant_id: i64, variant: &Variant, pool: PgPool) -> args.add(&variant.name); args.add(&variant.description); args.add(&variant.ingredients); + args.add(&variant.unit); info!("Variant: {:#?}", variant); let statement = format!( - "UPDATE {} SET weight = $2, ean = $3, name = $4, description = $5, ingredients = $6 WHERE id = $1 RETURNING *", + "UPDATE {} SET weight = $2, ean = $3, name = $4, description = $5, ingredients = $6, unit_id = $7 WHERE id = $1 RETURNING *", "variant", ); diff --git a/frontend/app/components/article/article.vue b/frontend/app/components/article/article.vue index a0b9ef1..a6fc4e6 100644 --- a/frontend/app/components/article/article.vue +++ b/frontend/app/components/article/article.vue @@ -115,7 +115,7 @@ - + - - Herkunft: - + Herkunft: - - {{ originToString(store.article.origin) }} - + {{ originToString(store.article.origin) }} + + + + diff --git a/frontend/app/components/article/articleCreate.vue b/frontend/app/components/article/articleCreate.vue index 4dd9c6f..20d2334 100644 --- a/frontend/app/components/article/articleCreate.vue +++ b/frontend/app/components/article/articleCreate.vue @@ -3,6 +3,7 @@ import {useLabelEditorStore} from "~/store/labelEditorStore"; import {Article} from "~/types/article"; import {Origin} from "~/types/origin"; + import type {Unit} from "~/types/unit"; let store = useLabelEditorStore(); @@ -12,16 +13,18 @@ let name: Ref = ref(null); let bio: Ref = ref(false); let origin: Ref = ref(null); + let default_unit: Ref = ref(null); let description: Ref = ref(null); let ingredients: Ref = ref(null); async function create() { if (name.value != null && name.value.trim().length > 0 && - origin.value != null && origin.value.trim().length > 0 + origin.value != null && origin.value.trim().length > 0 && + default_unit.value != null && default_unit.value.trim().length > 0 ) { loading.value = true; - const article: Article = new Article(0, name.value, bio.value, origin.value, description.value, ingredients.value, []); + const article: Article = new Article(0, name.value, bio.value, origin.value, description.value, ingredients.value, default_unit.value, []); await store.createArticle(article); @@ -102,6 +105,13 @@ label="Herkunft" > + + + -import type {Ref} from "vue"; -import {useLabelEditorStore} from "~/store/labelEditorStore"; -import { Variant } from "~/types/variant"; + import type {Ref} from "vue"; + import {useLabelEditorStore} from "~/store/labelEditorStore"; + import { Variant } from "~/types/variant"; + import type {Unit} from "~/types/unit"; -let store = useLabelEditorStore(); + let store = useLabelEditorStore(); -let dialog: Ref = ref(false); -let loading: Ref = ref(false); + let dialog: Ref = ref(false); + let loading: Ref = ref(false); -let weight: Ref = ref(null); -let ean: Ref = ref(null); -let name: Ref = ref(null); -let description: Ref = ref(null); -let ingredients: Ref = ref(null); + let weight: Ref = ref(null); + let ean: Ref = ref(null); + let name: Ref = ref(null); + let unit: Ref = ref(null); + let description: Ref = ref(null); + let ingredients: Ref = ref(null); -async function create() { - if (store.article != null && - weight.value != null && weight.value.trim().length > 0 - ) { - loading.value = true; - - const variant: Variant = new Variant(0, weight.value, ean.value, name.value, description.value, ingredients.value); - - await store.addVariant(variant); - - closeDialog(); + if (store.article != null) { + unit.value = store.article.default_unit; } -} -function closeDialog() { - dialog.value = false; - clearVariables(); -} + async function create() { + if (store.article != null && + weight.value != null && weight.value.trim().length > 0 && + unit.value != null && unit.value.trim().length > 0 + ) { + loading.value = true; -function clearVariables() { - weight.value = null; - ean.value = null; - name.value = null; - description.value = null; - ingredients.value = null; + const variant: Variant = new Variant(0, weight.value, ean.value, name.value, description.value, ingredients.value, unit.value); - loading.value = false; -} + await store.addVariant(variant); + + closeDialog(); + } + } + + function closeDialog() { + dialog.value = false; + clearVariables(); + } + + function clearVariables() { + weight.value = null; + ean.value = null; + name.value = null; + description.value = null; + ingredients.value = null; + + loading.value = false; + }