Feature: Tagebuch Ort/POI, Foto/Video-Edit, Modal-UX, iOS-Fixes

Tagebuch — Ort/POI (DayOne-ähnlich):
- diary.location_name Spalte, DiaryCreate/Update mit gps_lat/lon/location_name
- GET /api/dogs/{id}/diary/nearby: Overpass + Nominatim (vor {entry_id}-Route)
- Mini-Karte im Edit-Formular: Leaflet lazy, Edit-Modus, SVG-Pin
- Meilenstein-Toggle: Button statt Checkbox, Filter in Toolbar
- Datenmigration: 97 Ort-Einträge aus text → location_name

Tagebuch — Foto/Video:
- Foto/Video im Edit: Ersetzen + Löschen, DELETE media endpoint
- Media-Picker: Kamera/Mediathek/Datei Buttons
- Video-Wiedergabe (<video controls> in Detail + Edit)

Modal-UX (alle Edit-Karten vereinheitlicht):
- Footer-Pattern: [Speichern vollbreit] / [Löschen][Abbrechen]
- diary, dog-profile, events, health, places, walks, settings, sitting
- Löschen aus Detail-Modal → Edit-Form verschoben

iOS Mobile-Fixes:
- Auto-Zoom: input/select/textarea font-size 16px !important
- Scroll-Through: html.modal-open + touch-action:none auf Overlay
- Kein position:fixed mehr auf body (kein Scroll-Sprung)

PWA & Icons:
- icon-512-any.png + icon-192-any.png (quadratisch, maskable)
- manifest.json: purpose any/maskable getrennt
- Gesundheits-Icon: syringe → first-aid

Import-Fix:
- _HTMLStripper überspringt video/audio/script → kein "Video nicht gefunden" mehr
This commit is contained in:
rene 2026-04-18 11:56:54 +02:00
parent 88912e2746
commit f8d354749d
19 changed files with 963 additions and 198 deletions

View file

@ -53,6 +53,41 @@
border-color: var(--c-surface-3);
}
.btn-active {
background: color-mix(in srgb, var(--c-primary) 15%, var(--c-surface)) !important;
border-color: var(--c-primary) !important;
color: var(--c-primary-dark) !important;
}
/* Meilenstein-Toggle im Formular */
.diary-milestone-toggle {
display: flex;
align-items: center;
gap: var(--space-2);
width: 100%;
padding: var(--space-3) var(--space-4);
border: 1.5px dashed var(--c-border);
border-radius: var(--radius-md);
background: transparent;
color: var(--c-text-secondary);
font-size: var(--text-sm);
font-weight: var(--weight-medium);
cursor: pointer;
transition: all var(--transition-fast);
}
.diary-milestone-toggle:hover {
border-color: #d4a017;
color: #8a6400;
}
.diary-milestone-toggle--active {
border-style: solid;
border-color: #d4a017;
background: color-mix(in srgb, #d4a017 10%, transparent);
color: #8a6400;
font-weight: var(--weight-semibold);
}
.diary-milestone-toggle .ph-icon { font-size: 1.2rem; }
.btn-ghost {
background: transparent;
color: var(--c-text-secondary);
@ -402,6 +437,11 @@
color: var(--c-text-secondary);
}
/* iOS Safari: font-size < 16px triggert Auto-Zoom beim Fokus — muss alle Klassen überschreiben */
input, select, textarea {
font-size: var(--text-base) !important;
}
.form-control {
width: 100%;
padding: var(--space-3) var(--space-4);
@ -624,6 +664,12 @@ textarea.form-control {
/* ------------------------------------------------------------
8. MODAL
------------------------------------------------------------ */
/* Verhindert Body-Scroll wenn Modal offen — kein Layout-Sprung */
html.modal-open {
overflow: hidden;
overscroll-behavior: none;
}
.modal-overlay {
position: fixed;
inset: 0;
@ -635,7 +681,8 @@ textarea.form-control {
padding: var(--space-4);
backdrop-filter: blur(2px);
animation: overlay-in var(--transition-normal) ease;
touch-action: manipulation;
touch-action: none;
overscroll-behavior: none;
}
@media (min-width: 768px) {
.modal-overlay { align-items: center; }
@ -702,9 +749,11 @@ textarea.form-control {
font-weight: var(--weight-semibold);
}
.modal-body {
padding: var(--space-6);
overflow-y: auto;
flex: 1; /* füllt den Raum zwischen Header und Footer */
padding: var(--space-6);
overflow-y: auto;
flex: 1;
overscroll-behavior: contain;
-webkit-overflow-scrolling: touch;
scrollbar-width: thin;
scrollbar-color: var(--c-primary) var(--c-surface);
}
@ -977,7 +1026,7 @@ textarea.form-control {
letter-spacing: 0.03em;
}
/* Foto oben */
/* Foto / Video oben */
.diary-card-photo {
width: 100%;
height: 180px;
@ -989,6 +1038,43 @@ textarea.form-control {
object-fit: cover;
display: block;
}
.diary-media-picker {
display: flex;
gap: var(--space-2);
margin-top: var(--space-1);
}
.diary-media-pick-btn {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: var(--space-1);
padding: var(--space-3) var(--space-2);
border: 1.5px solid var(--c-border);
border-radius: var(--radius-md);
background: var(--c-surface);
color: var(--c-text-secondary);
font-size: var(--text-sm);
cursor: pointer;
transition: border-color var(--transition-fast), color var(--transition-fast);
}
.diary-media-pick-btn:hover,
.diary-media-pick-btn:active {
border-color: var(--c-primary);
color: var(--c-primary);
}
.diary-media-pick-btn .ph-icon { font-size: 1.5rem; }
.diary-card-video-thumb {
width: 100%;
height: 100%;
background: var(--c-surface-2);
display: flex;
align-items: center;
justify-content: center;
color: var(--c-primary);
font-size: 3rem;
}
/* Card Body */
.diary-card-body {
@ -1022,6 +1108,79 @@ textarea.form-control {
margin-bottom: var(--space-1);
}
/* Ort-Zeile in Karte */
.diary-card-location {
display: flex;
align-items: center;
gap: var(--space-1);
font-size: var(--text-sm);
color: var(--c-primary);
margin: 0 0 var(--space-1);
}
.diary-card-location .ph-icon { flex-shrink: 0; }
/* Ort in Detail-Ansicht */
.diary-detail-location {
display: flex;
align-items: center;
gap: var(--space-2);
font-size: var(--text-sm);
color: var(--c-primary);
margin-bottom: var(--space-3);
}
/* Koordinaten-Zeile im Formular */
.diary-coords-row {
display: flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-3);
background: var(--c-surface-2);
border-radius: var(--radius-md);
font-size: var(--text-sm);
color: var(--c-text-secondary);
font-variant-numeric: tabular-nums;
}
.diary-coords-row .ph-icon { flex-shrink: 0; }
/* Location-Chip im Formular */
.diary-location-chip {
display: flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-3);
background: color-mix(in srgb, var(--c-primary) 10%, transparent);
border: 1.5px solid var(--c-primary);
border-radius: var(--radius-full);
font-size: var(--text-sm);
color: var(--c-primary-dark);
}
.diary-location-chip span { flex: 1; }
.diary-location-chip button {
background: none; border: none; padding: 0; cursor: pointer;
color: var(--c-primary); display: flex;
}
/* Vorschlagsliste */
.diary-location-suggestion {
display: flex;
align-items: center;
gap: var(--space-2);
width: 100%;
padding: var(--space-2) var(--space-3);
background: var(--c-surface);
border: 1px solid var(--c-border-light);
border-radius: var(--radius-md);
margin-bottom: var(--space-1);
cursor: pointer;
text-align: left;
font-size: var(--text-sm);
color: var(--c-text);
}
.diary-location-suggestion span { flex: 1; }
.diary-location-suggestion small { color: var(--c-text-muted); flex-shrink: 0; }
.diary-location-suggestion:hover { border-color: var(--c-primary); color: var(--c-primary); }
/* Text-Vorschau */
.diary-card-text {
font-size: var(--text-sm);