From 3dcbfecbe4c5826350ba5c09546b5d1d6c7a5a47 Mon Sep 17 00:00:00 2001 From: Bjoern Welker Date: Wed, 11 Feb 2026 15:12:12 +0100 Subject: [PATCH] feat: add info field to articles for shop display Added optional info text field to articles that can be managed in the backend and is displayed in the shop only when filled. The info appears in both card view and detail modal with an informative style. - Added info column to items table with migration - Updated backend edit form with textarea for info text - Modified API to include info field in bestand response - Enhanced shop frontend to display info badge when available Co-Authored-By: Claude Sonnet 4.5 --- index.html | 8 +++++++- wawi/app.py | 34 +++++++++++++++++++++++++--------- wawi/templates/edit.html | 4 ++++ 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/index.html b/index.html index 3432755..702da7b 100755 --- a/index.html +++ b/index.html @@ -605,6 +605,9 @@ function render(items) { // Sale-Badge anzeigen const saleBadge = item.sale ? '
SALE 🔥
' : ''; + // Info-Text (nur wenn vorhanden) + const infoText = item.info ? `
ℹ️ ${item.info}
` : ''; + return `
${saleBadge} @@ -615,6 +618,7 @@ function render(items) {
${item.artikel}
${priceText}
${item.rows.length} Größen
+ ${infoText} ${stockBadge}
@@ -692,7 +696,9 @@ document.addEventListener("click", (e) => { media.innerHTML = img ? `${artikel}` : ""; document.getElementById("detailTitle").textContent = artikel; document.getElementById("detailPrice").textContent = detailBtn.dataset.preis || "Preis auf Anfrage"; - document.getElementById("detailSizes").textContent = `${item.rows.length} Größen`; + const sizesText = `${item.rows.length} Größen`; + const infoText = item.info ? ` · ℹ️ ${item.info}` : ''; + document.getElementById("detailSizes").textContent = sizesText + infoText; const list = item.rows.map(r => { const stock = Number(r.gezaehlt) || 0; let stockInfo = ''; diff --git a/wawi/app.py b/wawi/app.py index 40184c1..b74219e 100755 --- a/wawi/app.py +++ b/wawi/app.py @@ -167,6 +167,7 @@ def init_db() -> None: ensure_price_column(db) ensure_image_column(db) ensure_sale_column(db) + ensure_info_column(db) ensure_orders_columns(db) ensure_payment_columns(db) ensure_indexes(db) @@ -201,6 +202,16 @@ def ensure_sale_column(db: sqlite3.Connection) -> None: logger.info("Sale-Spalte für items erstellt") +def ensure_info_column(db: sqlite3.Connection) -> None: + """Fügt info-Spalte für zusätzliche Artikelinformationen hinzu.""" + cols = db.execute("PRAGMA table_info(items)").fetchall() + if any(c["name"] == "info" for c in cols): + return + db.execute("ALTER TABLE items ADD COLUMN info TEXT") + db.commit() + logger.info("Info-Spalte für items erstellt") + + def ensure_orders_columns(db: sqlite3.Connection) -> None: """Sorgt für alle nachträglich eingeführten Orders‑Spalten.""" cols = db.execute("PRAGMA table_info(orders)").fetchall() @@ -475,6 +486,7 @@ def new_item(): if uploaded: bild_url = uploaded sale = 1 if request.form.get("sale") else 0 + info = (request.form.get("info") or "").strip() or None soll = int(request.form.get("soll") or 0) gezaehlt = int(request.form.get("gezaehlt") or 0) verkaeufe = int(request.form.get("verkaeufe") or 0) @@ -483,12 +495,12 @@ def new_item(): db = get_db() db.execute( """ - INSERT INTO items (artikel, groesse, preis, bild_url, sale, soll, gezaehlt, verkaeufe, created_at, updated_at) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + INSERT INTO items (artikel, groesse, preis, bild_url, sale, info, soll, gezaehlt, verkaeufe, created_at, updated_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, - (artikel, groesse, preis, bild_url, sale, soll, gezaehlt, verkaeufe, now_iso(), now_iso()), + (artikel, groesse, preis, bild_url, sale, info, soll, gezaehlt, verkaeufe, now_iso(), now_iso()), ) - db.execute("UPDATE items SET preis = ?, bild_url = ?, sale = ? WHERE artikel = ?", (preis, bild_url, sale, artikel)) + db.execute("UPDATE items SET preis = ?, bild_url = ?, sale = ?, info = ? WHERE artikel = ?", (preis, bild_url, sale, info, artikel)) db.commit() return redirect(url_for("bp.index")) @@ -513,6 +525,7 @@ def edit_item(item_id: int): if uploaded: bild_url = uploaded sale = 1 if request.form.get("sale") else 0 + info = (request.form.get("info") or "").strip() or None soll = int(request.form.get("soll") or 0) gezaehlt = int(request.form.get("gezaehlt") or 0) verkaeufe = int(request.form.get("verkaeufe") or 0) @@ -520,12 +533,12 @@ def edit_item(item_id: int): db.execute( """ UPDATE items - SET artikel = ?, groesse = ?, preis = ?, bild_url = ?, sale = ?, soll = ?, gezaehlt = ?, verkaeufe = ?, updated_at = ? + SET artikel = ?, groesse = ?, preis = ?, bild_url = ?, sale = ?, info = ?, soll = ?, gezaehlt = ?, verkaeufe = ?, updated_at = ? WHERE id = ? """, - (artikel, groesse, preis, bild_url, sale, soll, gezaehlt, verkaeufe, now_iso(), item_id), + (artikel, groesse, preis, bild_url, sale, info, soll, gezaehlt, verkaeufe, now_iso(), item_id), ) - db.execute("UPDATE items SET preis = ?, bild_url = ?, sale = ? WHERE artikel = ?", (preis, bild_url, sale, artikel)) + db.execute("UPDATE items SET preis = ?, bild_url = ?, sale = ?, info = ? WHERE artikel = ?", (preis, bild_url, sale, info, artikel)) db.commit() return redirect(url_for("bp.index")) @@ -719,7 +732,7 @@ def build_bestand() -> list[dict]: """Aggregiert DB‑Zeilen in die Struktur der Live‑Bestand Ansicht.""" rows = get_db().execute( """ - SELECT artikel, groesse, preis, bild_url, sale, soll, gezaehlt, verkaeufe + SELECT artikel, groesse, preis, bild_url, sale, info, soll, gezaehlt, verkaeufe FROM items ORDER BY artikel, groesse """ @@ -732,7 +745,7 @@ def build_bestand() -> list[dict]: continue item = data.setdefault( artikel, - {"artikel": artikel, "preis": 0, "bild_url": "", "sale": 0, "rows": [], "totals": {"soll": 0, "gezaehlt": 0, "abweichung": 0, "fehlbestand": 0, "verkaeufe": 0}}, + {"artikel": artikel, "preis": 0, "bild_url": "", "sale": 0, "info": None, "rows": [], "totals": {"soll": 0, "gezaehlt": 0, "abweichung": 0, "fehlbestand": 0, "verkaeufe": 0}}, ) if not item["preis"]: item["preis"] = float(r["preis"] or 0) @@ -741,6 +754,9 @@ def build_bestand() -> list[dict]: # Sale-Status (1 wenn mindestens eine Größe sale=1 hat) if r["sale"]: item["sale"] = 1 + # Info-Text (nur wenn vorhanden) + if r["info"] and not item["info"]: + item["info"] = (r["info"] or "").strip() soll = int(r["soll"] or 0) gezaehlt = int(r["gezaehlt"] or 0) verkaeufe = int(r["verkaeufe"] or 0) diff --git a/wawi/templates/edit.html b/wawi/templates/edit.html index 657964d..6d1c1a5 100755 --- a/wawi/templates/edit.html +++ b/wawi/templates/edit.html @@ -29,6 +29,10 @@ Sale / Abverkauf 🔥 +