Added variant update functionality.

This commit is contained in:
2026-01-23 23:12:47 +01:00
parent 897f154fae
commit ea482fab07
5 changed files with 144 additions and 19 deletions
+35
View File
@@ -88,3 +88,38 @@ pub async fn insert_variant(article_id: i64, variant: &Variant, pool: PgPool) ->
}
}
}
pub async fn update_variant(variant_id: i64, variant: &Variant, pool: PgPool) -> Option<Variant> {
let mut args = PgArguments::default();
args.add(&variant.id);
args.add(&variant.weight);
args.add(&variant.ean);
args.add(&variant.name);
args.add(&variant.description);
args.add(&variant.ingredients);
info!("Variant: {:#?}", variant);
let statement = format!(
"UPDATE {} SET weight = $2, ean = $3, name = $4, description = $5, ingredients = $6 WHERE id = $1 RETURNING *",
"variant",
);
let res = sqlx::query_with(
statement.as_str(),
args)
.fetch_one(&pool).await;
info!("{:#?}", res);
match res {
Ok(record) => {
let variant = from_postgres_row_small(record);
Some(variant)
}
Err(err) => {
error!("Error while updating variant: {}", variant_id);
None
}
}
}
@@ -22,7 +22,7 @@ async function create() {
const variant: Variant = new Variant(0, weight.value, ean.value, name.value, description.value, ingredients.value);
await store.addVariant(store.article.id, variant);
await store.addVariant(variant);
closeDialog();
}
@@ -73,7 +73,7 @@ function clearVariables() {
mdi-plus-thick
</v-icon>
Artikel erstellen
Variante erstellen
<v-progress-circular v-if="loading" indeterminate :size="15" :width="2"></v-progress-circular>
</v-card-title>
+54 -14
View File
@@ -1,7 +1,7 @@
<script setup lang="ts">
import type {Variant} from "~/types/variant";
import {useLabelEditorStore} from "~/store/labelEditorStore";
import type {Ref} from "vue";
import {Variant} from "~/types/variant";
let store = useLabelEditorStore();
@@ -11,13 +11,51 @@
let edit: Ref<boolean> = ref<boolean>(false);
JSON.parse(JSON.stringify(props.variant.weight))
let weight: Ref<string | null> = ref<string | null>(JSON.parse(JSON.stringify(props.variant.weight)));
let ean: Ref<string | null> = ref<string | null>(JSON.parse(JSON.stringify(props.variant.ean)));
let name: Ref<string | null> = ref<string | null>(JSON.parse(JSON.stringify(props.variant.name)));
let description: Ref<string | null> = ref<string | null>(JSON.parse(JSON.stringify(props.variant.description)));
let ingredients: Ref<string | null> = ref<string | null>(JSON.parse(JSON.stringify(props.variant.ingredients)));
function toggleEdit() {
if (edit.value) {
disableEdit();
} else {
enableEdit();
}
}
function enableEdit() {
edit.value = true;
}
function disableEdit() {
edit.value = false;
weight.value = JSON.parse(JSON.stringify(props.variant.weight));
ean.value = JSON.parse(JSON.stringify(props.variant.ean));
name.value = JSON.parse(JSON.stringify(props.variant.name));
description.value = JSON.parse(JSON.stringify(props.variant.description));
ingredients.value = JSON.parse(JSON.stringify(props.variant.ingredients));
}
async function updateVariant() {
if (weight.value != null) {
let updateVariant: Variant = new Variant(props.variant.id, weight.value, ean.value, name.value, description.value, ingredients.value);
await store.updateVariant(updateVariant);
disableEdit();
}
}
</script>
<template>
<v-card>
<v-card-title>
<v-row>
{{ variant.name }}
{{ name }}
<v-spacer />
@@ -25,8 +63,8 @@
<v-btn
:flat="true"
size="small"
:disabled="!edit"
:hidden="edit"
>
<v-icon>mdi-delete-empty</v-icon>
<v-tooltip
@@ -41,8 +79,9 @@
<v-btn
:flat="true"
size="small"
:disabled="!edit"
:hidden="edit"
@click="disableEdit()"
>
<v-icon>mdi-cancel</v-icon>
<v-tooltip
@@ -55,8 +94,9 @@
<v-btn
:flat="true"
size="small"
:disabled="!edit"
:hidden="edit"
@click="updateVariant()"
>
<v-icon>mdi-content-save</v-icon>
<v-tooltip
@@ -71,7 +111,7 @@
<v-btn
:flat="true"
size="small"
@click="toggleEdit();"
>
<v-icon>mdi-pencil</v-icon>
<v-tooltip
@@ -93,30 +133,30 @@
<v-col cols="2">
<v-row>
<v-text-field
v-model.trim="variant.weight"
v-model.trim="weight"
label="Gewicht"
:readonly="true"
:readonly="!edit"
/>
</v-row>
<v-row>
<v-text-field
v-model.trim="variant.ean"
v-model.trim="ean"
label="EAN"
:readonly="true"
:readonly="!edit"
/>
</v-row>
</v-col>
<v-col cols="5">
<v-textarea
:model-value="variant.description"
v-model.trim="description"
:tile=true
label="Beschreibung"
counter
:persistentCounter=true
rows="6"
no-resize
:readonly="true"
:readonly="!edit"
>
<template v-slot:counter="{ counter }">
<span>{{ counter }} von {{ store.ingredientsMaxChars }} Zeichen.</span>
@@ -126,14 +166,14 @@
<v-col cols="5">
<v-textarea
:model-value="variant.ingredients"
v-model.trim="ingredients"
:tile=true
label="Zutaten"
counter
:persistentCounter=true
rows="6"
no-resize
:readonly="true"
:readonly="!edit"
>
<template v-slot:counter="{ counter }">
<span>{{ counter }} von {{ store.ingredientsMaxChars }} Zeichen.</span>
+23 -2
View File
@@ -168,10 +168,10 @@ export const useLabelEditorStore = defineStore('label_editor_store', {
},
// Variant
async addVariant(articleID: number, variant: Variant) {
async addVariant(variant: Variant) {
if(this.article != null) {
try {
let createdVariant = await $fetch<Variant>(this.config.public.url + '/article/' + articleID + '/variant', {
let createdVariant = await $fetch<Variant>(this.config.public.url + '/article/' + this.article.id + '/variant', {
method: 'POST',
body: JSON.stringify(variant),
});
@@ -186,5 +186,26 @@ export const useLabelEditorStore = defineStore('label_editor_store', {
this.addNotification(true, 'Kann Variante nicht erstellen. Es ist kein Artikel ausgewählt.');
}
},
async updateVariant(variant: Variant) {
if(this.article != null) {
let variantIndex = this.article.variants.findIndex(i => i.id === variant.id);
try {
let updatedVariant = await $fetch<Variant>(this.config.public.url + '/variant/' + variant.id, {
method: 'POST',
body: JSON.stringify(variant),
});
this.article.variants[variantIndex] = updatedVariant;
this.addNotification(false, 'Variante aktualisiert.');
} catch {
this.addNotification(true, 'Fehler beim aktualisieren der Variante.');
}
} else {
this.addNotification(true, 'Kann Variante nicht aktualisiert werden. Es ist kein Artikel ausgewählt.');
}
},
},
});
+30 -1
View File
@@ -15,7 +15,7 @@ use tower_http::cors::{AllowOrigin, Any, CorsLayer};
use tracing::info;
use http::header::{AUTHORIZATION, ACCEPT, ACCESS_CONTROL_ALLOW_ORIGIN, CONTENT_TYPE, ACCESS_CONTROL_ALLOW_CREDENTIALS};
use common::models::article;
use common::models::variant::{insert_variant, Variant};
use common::models::variant::{insert_variant, update_variant, Variant};
#[tokio::main]
async fn main() {
@@ -49,6 +49,7 @@ async fn main() {
.route("/article", post(create_article))
.route("/article/{id}", get(get_article))
.route("/article/{id}/variant", post(add_variant))
.route("/variant/{id}", post(update_variant_route))
.with_state(pool)
.layer(cors);
@@ -153,4 +154,32 @@ async fn add_variant(
(StatusCode::INTERNAL_SERVER_ERROR, Json(variant))
}
}
}
async fn update_variant_route(
State(pool): State<PgPool>,
Path(variant_id): Path<i64>,
Json(payload): Json<Variant>,
) -> (StatusCode, Json<Variant>) {
info!("Update variant");
let update_variant = update_variant(variant_id, &payload, pool).await;
match update_variant {
Some(variant) => {
(StatusCode::OK, Json(variant))
}
None => {
let variant = Variant {
id: 0,
weight: "".to_string(),
ean: None,
name: None,
description: None,
ingredients: None,
};
(StatusCode::INTERNAL_SERVER_ERROR, Json(variant))
}
}
}