diff --git a/backend/static/js/app.js b/backend/static/js/app.js index 4294f1c..7b28961 100644 --- a/backend/static/js/app.js +++ b/backend/static/js/app.js @@ -3,7 +3,7 @@ Router, State-Management, Navigation, Initialisierung. ============================================================ */ -const APP_VER = '463'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '464'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const App = (() => { diff --git a/backend/static/js/pages/litters.js b/backend/static/js/pages/litters.js index 1f60e0f..93cc09e 100644 --- a/backend/static/js/pages/litters.js +++ b/backend/static/js/pages/litters.js @@ -465,20 +465,95 @@ window.Page_litters = (() => { el.innerHTML = `

Noch keine Messungen eingetragen.

`; return; } + + // Chronologisch für Chart (API liefert DESC) + const asc = [...weights].reverse(); + const first = asc[0].gewicht_g; + const last = asc[asc.length - 1].gewicht_g; + const gain = last - first; + const days = asc.length > 1 + ? Math.max(1, (new Date(asc[asc.length-1].gemessen_am) - new Date(asc[0].gemessen_am)) / 86400000) + : 1; + const dailyGain = asc.length > 1 ? (gain / days).toFixed(1) : '—'; + + // SVG Sparkline + const W = 400, H = 80; + const minW = Math.min(...asc.map(w => w.gewicht_g)); + const maxW = Math.max(...asc.map(w => w.gewicht_g)); + const range = maxW - minW || 1; + const pts = asc.map((w, i) => { + const x = asc.length === 1 ? W/2 : (i / (asc.length - 1)) * W; + const y = H - 8 - ((w.gewicht_g - minW) / range) * (H - 16); + return `${x.toFixed(1)},${y.toFixed(1)}`; + }).join(' '); + const firstDate = asc[0].gemessen_am?.slice(5) || ''; + const lastDate = asc[asc.length-1].gemessen_am?.slice(5) || ''; + el.innerHTML = ` + +
+
+
Aktuell
+
${last} g
+
+
+
Zunahme
+
+ ${gain >= 0 ? '+' : ''}${gain} g +
+
+
+
Ø tägl.
+
${dailyGain} g
+
+
+
Messungen
+
${weights.length}
+
+
+ + + ${asc.length > 1 ? ` +
+ + + + ${asc.map((w, i) => { + const x = (i / (asc.length - 1)) * W; + const y = H - 8 - ((w.gewicht_g - minW) / range) * (H - 16); + return ``; + }).join('')} + +
+ ${firstDate}${lastDate} +
+
` : ''} + + + - ${weights.map((w, i) => ` - - - - `).join('')} + ${weights.map((w, i) => { + const prev = weights[i + 1]; + const diff = prev ? w.gewicht_g - prev.gewicht_g : null; + const diffStr = diff === null ? '—' + : `${diff >= 0 ? '+' : ''}${diff} g`; + return ` + + + + + `; + }).join('')}
Datum GewichtVeränderung
${_fmtDate(w.gemessen_am)}${w.gewicht_g} g
${_fmtDate(w.gemessen_am)}${w.gewicht_g} g${diffStr}
`; } catch (err) { diff --git a/backend/static/sw.js b/backend/static/sw.js index 74e602c..32743f0 100644 --- a/backend/static/sw.js +++ b/backend/static/sw.js @@ -3,7 +3,7 @@ Offline-Cache + Push Notifications + Tile-Cache ============================================================ */ -const CACHE_VERSION = 'by-v486'; +const CACHE_VERSION = 'by-v487'; const CACHE_STATIC = `${CACHE_VERSION}-static`; const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten