Sprint 12: UI-Vereinheitlichung + Läufigkeits-Tracker

- by-tabs/by-tab: einheitliche Tab/Pill-Navigation in allen Seiten
- by-section-label, by-toolbar: einheitliche Section-Labels und Toolbars
- Design-Tokens: fehlende --c-amber, --c-primary-soft ergänzt, Fallback-Werte entfernt
- sitting.js: sitting-layout für konsistentes flush-Layout (wie walks)
- Läufigkeits-Tracker: neuer Health-Tab für Hündinnen mit Zyklusvorhersage,
  Timeline vergangener Läufigkeiten, Erinnerungen und auto-berechnetem Nächst-Datum
- emptyState-Bug: icon-Parameter muss SVG sein, nicht Icon-Name (dog/bell/warning gefixt)
- SW-Cache: by-v103, APP_VER: 79
This commit is contained in:
rene 2026-04-16 22:31:33 +02:00
parent 32d630d5a1
commit b58789373c
30 changed files with 4344 additions and 523 deletions

View file

@ -63,7 +63,7 @@ window.Page_walks = (() => {
<div class="walks-layout">
<!-- Toolbar -->
<div class="walks-toolbar">
<div class="by-toolbar">
<div class="walks-view-toggle" id="walks-view-toggle">
<button class="walks-view-btn active" data-view="liste">${UI.icon('list')} Liste</button>
<button class="walks-view-btn" data-view="karte">${UI.icon('map-trifold')} Karte</button>
@ -113,6 +113,7 @@ window.Page_walks = (() => {
_loadLeaflet().then(() => {
_initMap();
setTimeout(() => _map?.invalidateSize(), 50);
setTimeout(() => _map?.invalidateSize(), 300);
});
}
}
@ -160,12 +161,12 @@ window.Page_walks = (() => {
let html = '';
if (heute.length) {
html += `<div class="walks-section-label">${UI.icon('star')} Heute</div>`;
html += `<div class="by-section-label">${UI.icon('star')} Heute</div>`;
html += heute.map(w => _walkCardHTML(w)).join('');
}
if (upcoming.length) {
html += `<div class="walks-section-label">${UI.icon('calendar-dots')} Demnächst</div>`;
html += `<div class="by-section-label">${UI.icon('calendar-dots')} Demnächst</div>`;
html += upcoming.map(w => _walkCardHTML(w)).join('');
}
@ -235,7 +236,7 @@ window.Page_walks = (() => {
_markers = [];
_data.forEach(w => {
const isFull = w.status === 'voll' || w.teilnehmer_count >= w.max_teilnehmer;
const color = _isToday(w.datum) ? '#C4843A' : (isFull ? '#6B7280' : '#22C55E');
const color = _isToday(w.datum) ? 'var(--c-primary)' : (isFull ? '#6B7280' : '#22C55E');
const icon = L.divIcon({
className: '',
html: `<div style="background:${color};color:#fff;font-size:14px;font-weight:700;