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

@ -1065,6 +1065,79 @@ html.modal-open {
}
.diary-media-pick-btn .ph-icon { font-size: 1.5rem; }
/* Multi-Medien: Formular-Grid (Thumbnails beim Erstellen/Bearbeiten) */
.diary-media-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
gap: var(--space-2);
margin-bottom: var(--space-2);
}
.diary-media-thumb-wrap {
position: relative;
aspect-ratio: 1;
border-radius: var(--radius-md);
overflow: hidden;
background: var(--c-surface-2);
}
.diary-media-thumb {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.diary-media-thumb-del {
position: absolute;
top: var(--space-1);
right: var(--space-1);
width: 24px;
height: 24px;
border-radius: 50%;
border: none;
background: rgba(0,0,0,.55);
color: #fff;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
line-height: 1;
}
.diary-media-thumb-del .ph-icon { font-size: .9rem; }
/* Medien-Zähler-Badge auf der Karte */
.diary-card-photo { position: relative; }
.diary-card-media-count {
position: absolute;
bottom: var(--space-1);
right: var(--space-1);
background: rgba(0,0,0,.55);
color: #fff;
font-size: var(--text-xs);
font-weight: var(--weight-semibold);
padding: 2px 6px;
border-radius: 12px;
pointer-events: none;
}
/* Detail-Ansicht: horizontale Scroll-Galerie */
.diary-gallery {
display: flex;
gap: var(--space-2);
overflow-x: auto;
-webkit-overflow-scrolling: touch;
scroll-snap-type: x mandatory;
border-radius: var(--radius-md);
}
.diary-gallery-item {
flex: 0 0 auto;
width: min(80vw, 320px);
max-height: 260px;
object-fit: cover;
border-radius: var(--radius-md);
scroll-snap-align: start;
display: block;
}
.diary-card-video-thumb {
width: 100%;
height: 100%;