Feature: Tagebuch Multi-Medien (beliebig viele Fotos/Videos pro Eintrag)

- Backend: neue Tabelle diary_media (Migration), upload_media schreibt
  jetzt in diary_media statt media_url; neuer DELETE-Endpoint
  /diary/{id}/media/{media_id}; alle GET-Endpoints liefern media_items[].
- Frontend: Multi-Upload-Grid im Formular mit Vorschau und X-Button
  zum Entfernen vor dem Speichern; bestehende Medien im Edit-Modus
  einzeln löschbar; Detail-Ansicht zeigt horizontale Scroll-Galerie
  bei mehreren Medien; Karten-Badge zeigt Anzahl bei > 1 Medium.
- Rückwärtskompatibilität: Einträge mit media_url werden weiterhin
  korrekt angezeigt.
- SW by-v211, APP_VER 181
This commit is contained in:
rene 2026-04-18 18:45:48 +02:00
parent 6581a9a88c
commit 63ab092f5e
7 changed files with 367 additions and 165 deletions

View file

@ -466,6 +466,11 @@ def _migrate(conn_factory):
("dogs", "foto_offset_y", "REAL NOT NULL DEFAULT 0.0"),
# Tagebuch: Ortsname (POI/Adresse)
("diary", "location_name", "TEXT"),
# Bewertungen: walks + sitters brauchen bewertung + anz_bewertungen
("walks", "bewertung", "REAL DEFAULT 0"),
("walks", "anz_bewertungen", "INTEGER DEFAULT 0"),
("sitters", "bewertung", "REAL DEFAULT 0"),
("sitters", "anz_bewertungen", "INTEGER DEFAULT 0"),
]
with conn_factory() as conn:
for table, column, col_type in migrations:
@ -739,6 +744,36 @@ def _migrate(conn_factory):
CREATE INDEX IF NOT EXISTS idx_service_offers_user ON service_offers(user_id, type);
""")
# Ratings — einheitliches Bewertungssystem
conn.executescript("""
CREATE TABLE IF NOT EXISTS ratings (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
target_type TEXT NOT NULL,
target_id INTEGER NOT NULL,
stars INTEGER NOT NULL,
kommentar TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE(user_id, target_type, target_id)
);
CREATE INDEX IF NOT EXISTS idx_ratings_target ON ratings(target_type, target_id);
""")
logger.info("Migration: ratings Tabelle bereit.")
# Tagebuch: mehrere Mediendateien pro Eintrag
conn.executescript("""
CREATE TABLE IF NOT EXISTS diary_media (
id INTEGER PRIMARY KEY AUTOINCREMENT,
diary_id INTEGER NOT NULL REFERENCES diary(id) ON DELETE CASCADE,
url TEXT NOT NULL,
media_type TEXT NOT NULL DEFAULT 'image',
sort_order INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_diary_media_entry ON diary_media(diary_id, sort_order);
""")
logger.info("Migration: diary_media Tabelle bereit.")
# Walk-Einladungen (RSVP)
conn.executescript("""
CREATE TABLE IF NOT EXISTS walk_invitations (