Feature: Meine Wetterrekorde Sektion auf Wetter-Seite (SW by-v694)
- Backend: GET /api/weather/records — liest diary-Einträge mit weather_json und berechnet Kältester/Heißester Gassi, Stürmischster Tag, Regentage - Frontend: #wttr-records 2×2 Grid-Karten unterhalb Hunde-Wetter (nur für eingeloggte User mit ≥3 Tagebucheinträgen mit Wetterdaten) - SW-Version auf by-v694 erhöht, APP_VER auf 694
This commit is contained in:
parent
d081029618
commit
6152d6bf0e
5 changed files with 173 additions and 12 deletions
|
|
@ -55,11 +55,12 @@ window.Page_wetter = (() => {
|
|||
// ----------------------------------------------------------
|
||||
// MODUL-STATE
|
||||
// ----------------------------------------------------------
|
||||
let _container = null;
|
||||
let _appState = null;
|
||||
let _data = null;
|
||||
let _selDay = 0;
|
||||
let _loading = false;
|
||||
let _container = null;
|
||||
let _appState = null;
|
||||
let _data = null;
|
||||
let _selDay = 0;
|
||||
let _loading = false;
|
||||
let _recordsLoaded = false;
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// INIT
|
||||
|
|
@ -76,7 +77,8 @@ window.Page_wetter = (() => {
|
|||
// REFRESH
|
||||
// ----------------------------------------------------------
|
||||
async function refresh() {
|
||||
_selDay = 0;
|
||||
_selDay = 0;
|
||||
_recordsLoaded = false;
|
||||
_renderShell();
|
||||
_tryAutoLocate();
|
||||
}
|
||||
|
|
@ -195,6 +197,10 @@ window.Page_wetter = (() => {
|
|||
<!-- Hunde-Wetter -->
|
||||
<div id="wttr-dog" class="section-card">
|
||||
</div>
|
||||
|
||||
<!-- Meine Wetterrekorde -->
|
||||
<div id="wttr-records">
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Strip-Klick-Events
|
||||
|
|
@ -211,6 +217,7 @@ window.Page_wetter = (() => {
|
|||
_renderDetail();
|
||||
_renderRainTimeline();
|
||||
_renderDog();
|
||||
_loadRecords();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
|
@ -972,6 +979,104 @@ window.Page_wetter = (() => {
|
|||
.replace(/"/g, '"');
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// MEINE WETTERREKORDE
|
||||
// ----------------------------------------------------------
|
||||
async function _loadRecords() {
|
||||
// Nur wenn User eingeloggt
|
||||
if (!_appState?.user) return;
|
||||
// Nur einmal pro Seitenaufruf laden
|
||||
if (_recordsLoaded) return;
|
||||
_recordsLoaded = true;
|
||||
try {
|
||||
const res = await API.get('/weather/records');
|
||||
_renderRecords(res?.records || null);
|
||||
} catch {
|
||||
// Stumm scheitern — Rekorde sind ein Nice-to-have
|
||||
}
|
||||
}
|
||||
|
||||
function _fmtDate(datum) {
|
||||
if (!datum) return '';
|
||||
try {
|
||||
return new Date(datum + 'T12:00').toLocaleDateString('de', {
|
||||
day: 'numeric', month: 'short', year: 'numeric'
|
||||
});
|
||||
} catch { return datum; }
|
||||
}
|
||||
|
||||
function _recordCard(emoji, title, value, subtitle, color) {
|
||||
return `
|
||||
<div style="background:var(--c-bg-card);border:1px solid var(--c-border);
|
||||
border-radius:var(--radius);padding:var(--space-3) var(--space-3);
|
||||
display:flex;flex-direction:column;gap:2px">
|
||||
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);
|
||||
display:flex;align-items:center;gap:4px;font-weight:600">
|
||||
<span>${emoji}</span>
|
||||
<span>${_esc(title)}</span>
|
||||
</div>
|
||||
<div style="font-size:var(--text-xl);font-weight:800;color:${color};line-height:1.1">
|
||||
${_esc(value)}
|
||||
</div>
|
||||
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);
|
||||
white-space:nowrap;overflow:hidden;text-overflow:ellipsis">
|
||||
${_esc(subtitle)}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function _renderRecords(records) {
|
||||
const el = _container.querySelector('#wttr-records');
|
||||
if (!el) return;
|
||||
|
||||
// Mindestens 3 Einträge nötig
|
||||
if (!records || (records.gesamt_eintraege || 0) < 3) {
|
||||
el.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
const cards = [];
|
||||
|
||||
if (records.kaeltester) {
|
||||
const e = records.kaeltester;
|
||||
const sub = e.titel ? `${e.titel} · ${_fmtDate(e.datum)}` : _fmtDate(e.datum);
|
||||
cards.push(_recordCard('🥶', 'Kältester Gassi', `${Math.round(e.temp_c)}°C`, sub, '#60A5FA'));
|
||||
}
|
||||
|
||||
if (records.heissester) {
|
||||
const e = records.heissester;
|
||||
const sub = e.titel ? `${e.titel} · ${_fmtDate(e.datum)}` : _fmtDate(e.datum);
|
||||
cards.push(_recordCard('🔥', 'Heißester Gassi', `${Math.round(e.temp_c)}°C`, sub, '#EF4444'));
|
||||
}
|
||||
|
||||
if (records.stuermischster) {
|
||||
const e = records.stuermischster;
|
||||
const sub = e.titel ? `${e.titel} · ${_fmtDate(e.datum)}` : _fmtDate(e.datum);
|
||||
cards.push(_recordCard('🌬️', 'Stürmischster Tag', `${Math.round(e.wind_kmh)} km/h`, sub, '#A78BFA'));
|
||||
}
|
||||
|
||||
const regenCount = records.regen_eintraege || 0;
|
||||
const gesamt = records.gesamt_eintraege || 0;
|
||||
cards.push(_recordCard('💧', 'Regentage', `${regenCount} Einträge`, `von ${gesamt} Tagebucheinträgen`, '#3B82F6'));
|
||||
|
||||
el.innerHTML = `
|
||||
<div style="margin-top:var(--space-5)">
|
||||
<h3 style="font-size:var(--text-base);font-weight:700;
|
||||
margin-bottom:var(--space-3);
|
||||
display:flex;align-items:center;gap:var(--space-2)">
|
||||
<svg class="ph-icon" style="width:1.1em;height:1.1em;vertical-align:-2px;color:var(--c-primary)">
|
||||
<use href="/icons/phosphor.svg#trophy"></use>
|
||||
</svg>
|
||||
Meine Wetterrekorde
|
||||
</h3>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:var(--space-2)">
|
||||
${cards.join('')}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// PUBLIC API
|
||||
// ----------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue