Redesign shopping list app, 2-portal home, real-time WebSocket sync, and edit modals
This commit is contained in:
+60
-6
@@ -335,6 +335,16 @@ def init_db():
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
cursor.execute("""
|
||||
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = %s AND TABLE_NAME = 'shopping_list' AND COLUMN_NAME = 'note'
|
||||
""", (MARIADB_NAME,))
|
||||
if not cursor.fetchone():
|
||||
cursor.execute("ALTER TABLE shopping_list ADD COLUMN note VARCHAR(255) DEFAULT '' AFTER category")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
cursor.execute("DELETE FROM dishes")
|
||||
else:
|
||||
cursor = conn.cursor()
|
||||
@@ -421,6 +431,8 @@ def init_db():
|
||||
existing_shop_cols = [c[1] for c in cursor.fetchall()]
|
||||
if "category" not in existing_shop_cols:
|
||||
cursor.execute("ALTER TABLE shopping_list ADD COLUMN category TEXT DEFAULT 'Drogerie & Sonstiges'")
|
||||
if "note" not in existing_shop_cols:
|
||||
cursor.execute("ALTER TABLE shopping_list ADD COLUMN note TEXT DEFAULT ''")
|
||||
|
||||
cursor.execute("DELETE FROM dishes")
|
||||
conn.commit()
|
||||
@@ -1039,6 +1051,36 @@ def reset_default_shopping_categories() -> List[Dict[str, Any]]:
|
||||
return get_shopping_categories()
|
||||
|
||||
|
||||
def update_shopping_item(
|
||||
item_id: int,
|
||||
item_name: str,
|
||||
amount: str = "",
|
||||
unit: str = "",
|
||||
category: Optional[str] = None,
|
||||
note: str = ""
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Aktualisiert alle Eigenschaften eines Eintrags in der Einkaufsliste."""
|
||||
cat = (category or "").strip()
|
||||
if not cat:
|
||||
cat = guess_category_for_ingredient(item_name)
|
||||
query = """
|
||||
UPDATE shopping_list
|
||||
SET item_name = ?, amount = ?, unit = ?, category = ?, note = ?
|
||||
WHERE id = ?
|
||||
"""
|
||||
execute_query(query, (item_name.strip(), amount.strip(), unit.strip(), cat, (note or "").strip(), item_id), fetch="none", commit=True)
|
||||
row = execute_query("SELECT * FROM shopping_list WHERE id = ?", (item_id,), fetch="one")
|
||||
if row:
|
||||
row["checked"] = bool(row.get("checked"))
|
||||
row["display_source"] = clean_source_label(row.get("source", ""))
|
||||
row["note"] = str(row.get("note") or "").strip()
|
||||
if isinstance(row.get("created_at"), (datetime, date)):
|
||||
row["created_at"] = row["created_at"].isoformat()
|
||||
if isinstance(row.get("updated_at"), (datetime, date)):
|
||||
row["updated_at"] = row["updated_at"].isoformat()
|
||||
return row
|
||||
|
||||
|
||||
def update_shopping_item_category(item_id: int, category: str) -> Optional[Dict[str, Any]]:
|
||||
"""Ändert die Kategorie/den Bereich eines einzelnen Listeneintrags."""
|
||||
clean_cat = category.strip()
|
||||
@@ -1048,6 +1090,7 @@ def update_shopping_item_category(item_id: int, category: str) -> Optional[Dict[
|
||||
if row:
|
||||
row["checked"] = bool(row.get("checked"))
|
||||
row["display_source"] = clean_source_label(row.get("source", ""))
|
||||
row["note"] = str(row.get("note") or "").strip()
|
||||
if isinstance(row.get("created_at"), (datetime, date)):
|
||||
row["created_at"] = row["created_at"].isoformat()
|
||||
if isinstance(row.get("updated_at"), (datetime, date)):
|
||||
@@ -1058,7 +1101,7 @@ def update_shopping_item_category(item_id: int, category: str) -> Optional[Dict[
|
||||
def get_shopping_list() -> List[Dict[str, Any]]:
|
||||
"""Gibt alle Einträge der Einkaufsliste zurück, sortiert nach unvollständig/erledigt."""
|
||||
query = """
|
||||
SELECT id, item_name, amount, unit, checked, source, category, created_at, updated_at
|
||||
SELECT id, item_name, amount, unit, checked, source, category, note, created_at, updated_at
|
||||
FROM shopping_list
|
||||
ORDER BY checked ASC, id DESC
|
||||
"""
|
||||
@@ -1068,6 +1111,7 @@ def get_shopping_list() -> List[Dict[str, Any]]:
|
||||
if not r.get("category"):
|
||||
r["category"] = guess_category_for_ingredient(r.get("item_name", ""))
|
||||
r["display_source"] = clean_source_label(r.get("source", ""))
|
||||
r["note"] = str(r.get("note") or "").strip()
|
||||
if isinstance(r.get("created_at"), (datetime, date)):
|
||||
r["created_at"] = r["created_at"].isoformat()
|
||||
if isinstance(r.get("updated_at"), (datetime, date)):
|
||||
@@ -1075,19 +1119,28 @@ def get_shopping_list() -> List[Dict[str, Any]]:
|
||||
return rows
|
||||
|
||||
|
||||
def add_shopping_item(item_name: str, amount: str = "", unit: str = "", source: str = "", category: Optional[str] = None) -> Dict[str, Any]:
|
||||
def add_shopping_item(
|
||||
item_name: str,
|
||||
amount: str = "",
|
||||
unit: str = "",
|
||||
source: str = "",
|
||||
category: Optional[str] = None,
|
||||
note: str = ""
|
||||
) -> Dict[str, Any]:
|
||||
"""Fügt einen einzelnen Eintrag zur Einkaufsliste hinzu."""
|
||||
cat = (category or "").strip()
|
||||
if not cat:
|
||||
cat = guess_category_for_ingredient(item_name)
|
||||
clean_src = clean_source_label(source)
|
||||
query = "INSERT INTO shopping_list (item_name, amount, unit, source, category, checked) VALUES (?, ?, ?, ?, ?, 0)"
|
||||
res = execute_query(query, (item_name.strip(), amount.strip(), unit.strip(), clean_src, cat), fetch="none", commit=True)
|
||||
clean_note = (note or "").strip()
|
||||
query = "INSERT INTO shopping_list (item_name, amount, unit, source, category, note, checked) VALUES (?, ?, ?, ?, ?, ?, 0)"
|
||||
res = execute_query(query, (item_name.strip(), amount.strip(), unit.strip(), clean_src, cat, clean_note), fetch="none", commit=True)
|
||||
item_id = res.get("lastrowid")
|
||||
row = execute_query("SELECT * FROM shopping_list WHERE id = ?", (item_id,), fetch="one")
|
||||
if row:
|
||||
row["checked"] = bool(row.get("checked"))
|
||||
row["display_source"] = clean_source_label(row.get("source", ""))
|
||||
row["note"] = str(row.get("note") or "").strip()
|
||||
if isinstance(row.get("created_at"), (datetime, date)):
|
||||
row["created_at"] = row["created_at"].isoformat()
|
||||
if isinstance(row.get("updated_at"), (datetime, date)):
|
||||
@@ -1111,8 +1164,9 @@ def add_shopping_items_bulk(items: List[Dict[str, Any]]) -> int:
|
||||
cat = str(it.get("category") or "").strip()
|
||||
if not cat:
|
||||
cat = guess_category_for_ingredient(name)
|
||||
query = "INSERT INTO shopping_list (item_name, amount, unit, source, category, checked) VALUES (?, ?, ?, ?, ?, 0)"
|
||||
execute_query(query, (name, amt, unit, src, cat), fetch="none", commit=True)
|
||||
note = str(it.get("note") or "").strip()
|
||||
query = "INSERT INTO shopping_list (item_name, amount, unit, source, category, note, checked) VALUES (?, ?, ?, ?, ?, ?, 0)"
|
||||
execute_query(query, (name, amt, unit, src, cat, note), fetch="none", commit=True)
|
||||
count += 1
|
||||
return count
|
||||
|
||||
|
||||
Reference in New Issue
Block a user