230 lines
11 KiB
HTML
230 lines
11 KiB
HTML
<!doctype html>
|
||
<html lang="de" data-theme="dark">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<meta name="description" content="HexaWetter – Selfhosted Wetterportal mit DWD Radar, Warnungen und Forecast" />
|
||
<title>HexaWetter</title>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
||
<link rel="stylesheet" href="style.css" />
|
||
</head>
|
||
<body>
|
||
<header class="site-header">
|
||
<div class="container header-inner">
|
||
<a class="brand-link" href="index.html">
|
||
<div class="brand-logo" aria-hidden="true">H</div>
|
||
<div>
|
||
<div class="brand-sub">HexaHost · Selfhosted Weather</div>
|
||
<div class="brand-title">HexaWetter</div>
|
||
</div>
|
||
</a>
|
||
<div class="header-actions">
|
||
<div class="status-pill" id="health">API: prüfe…</div>
|
||
<button id="themeToggle" class="btn btn-ghost icon-btn" title="Theme wechseln" aria-label="Theme wechseln">🌙</button>
|
||
<a href="admin.html" class="btn btn-secondary">Admin</a>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="app-main">
|
||
<div class="container">
|
||
<section class="hero-copy">
|
||
<h1>Wetter für deinen Standort</h1>
|
||
<p>Forecast, DWD-Beobachtungen, interaktive Radar-Karte mit Zeitleiste und standortgenaue Warnungen – gehostet auf deiner Infrastruktur.</p>
|
||
</section>
|
||
|
||
<section class="glass-card controls">
|
||
<div class="search-wrap">
|
||
<label for="placeSearch">Ortssuche / PLZ</label>
|
||
<input id="placeSearch" type="search" placeholder="z.B. Hauzenberg, 94051 Passau…" autocomplete="off" />
|
||
<ul id="searchResults" class="search-results hidden" role="listbox"></ul>
|
||
</div>
|
||
<div>
|
||
<label for="place">Ort / Label</label>
|
||
<input id="place" value="Hauzenberg" />
|
||
</div>
|
||
<div>
|
||
<label for="lat">Latitude</label>
|
||
<input id="lat" type="number" step="0.0001" value="48.6546" />
|
||
</div>
|
||
<div>
|
||
<label for="lon">Longitude</label>
|
||
<input id="lon" type="number" step="0.0001" value="13.6252" />
|
||
</div>
|
||
<div class="control-actions">
|
||
<button id="geoBtn" class="btn btn-secondary icon-btn" title="Browser-Standort">📍</button>
|
||
<button id="favBtn" class="btn btn-secondary icon-btn" title="Favorit">★</button>
|
||
<button id="loadBtn" class="btn btn-primary">Aktualisieren</button>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="glass-card favorites-panel hidden" id="favoritesPanel">
|
||
<div class="section-head">
|
||
<h2>Gespeicherte Orte</h2>
|
||
<span class="muted">Klicken zum Laden</span>
|
||
</div>
|
||
<div id="favoritesList" class="chip-row"></div>
|
||
</section>
|
||
|
||
<nav class="tabs" aria-label="Ansichten">
|
||
<button class="tab active" data-view="dashboard">Übersicht</button>
|
||
<button class="tab" data-view="radar">Karte</button>
|
||
<button class="tab" data-view="warnings">Warnungen</button>
|
||
<button class="tab" data-view="hourly">Stunden</button>
|
||
<button class="tab" data-view="daily">7 Tage</button>
|
||
<button class="tab" data-view="settings">Einstellungen</button>
|
||
</nav>
|
||
|
||
<section class="view active" data-view="dashboard">
|
||
<section class="grid">
|
||
<article class="glass-card card card-accent"><h2>Aktuelles Wetter</h2><p class="big" id="currentTemp">–</p><p id="currentMeta" class="muted">Lade…</p></article>
|
||
<article class="glass-card card card-accent"><h2>Regen · 24 h</h2><p class="big" id="rainOutlookBig">–</p><p id="rainOutlookMeta" class="muted">Lade…</p></article>
|
||
<article class="glass-card card"><h2>DWD-Beobachtung</h2><p class="big" id="obsTemp">–</p><p id="obsMeta" class="muted">Lade…</p></article>
|
||
<article class="glass-card card"><h2>Warnungen</h2><p class="big" id="warnCount">–</p><p id="warnMeta" class="muted">Lade…</p></article>
|
||
</section>
|
||
<section class="glass-card">
|
||
<div class="section-head"><h2>Details aktuell</h2><span class="muted" id="forecastSource"></span></div>
|
||
<div class="metrics" id="currentDetails"></div>
|
||
</section>
|
||
<section class="glass-card">
|
||
<div class="section-head"><h2>Kurzvorschau</h2><span class="muted">Nächste Stunden</span></div>
|
||
<div class="hour-strip" id="hourStrip"></div>
|
||
</section>
|
||
</section>
|
||
|
||
<section class="view" data-view="radar">
|
||
<section class="glass-card map-panel">
|
||
<div class="section-head">
|
||
<div>
|
||
<h2>Wetterkarte</h2>
|
||
<p class="muted no-margin">DWD-Radar · Open-Meteo-Regenvorhersage · OpenStreetMap</p>
|
||
</div>
|
||
<span class="muted" id="mapMeta">Lade…</span>
|
||
</div>
|
||
<div class="map-mode-toggle" role="tablist" aria-label="Kartenmodus">
|
||
<button type="button" class="map-mode-btn active" data-map-mode="radar">Radar · Vergangenheit</button>
|
||
<button type="button" class="map-mode-btn" data-map-mode="forecast">Regenvorhersage · Zukunft</button>
|
||
</div>
|
||
<div id="map"></div>
|
||
<div class="panel-inner" id="radarTimeline">
|
||
<div class="section-head"><strong id="timelineTitle">Zeitleiste</strong><span class="muted" id="radarTimeLabel">–</span></div>
|
||
<div class="timeline-controls">
|
||
<button id="radarFirstBtn" class="btn btn-secondary icon-btn">⏮</button>
|
||
<button id="radarPrevBtn" class="btn btn-secondary icon-btn">◀</button>
|
||
<button id="radarPlayBtn" class="btn btn-secondary icon-btn">▶</button>
|
||
<button id="radarNextBtn" class="btn btn-secondary icon-btn">▶</button>
|
||
<button id="radarLastBtn" class="btn btn-secondary icon-btn">⏭</button>
|
||
<input id="radarSlider" type="range" min="0" max="0" value="0" />
|
||
</div>
|
||
<div class="timeline-meta">
|
||
<label class="inline-check map-mode-radar-only"><input type="checkbox" id="showWarningsOnMap" checked /> Warnungen</label>
|
||
<span class="muted" id="radarFrameInfo"></span>
|
||
</div>
|
||
<p class="muted no-margin" id="timelineHint" style="margin-top:8px;font-size:0.85rem">Vergangenheit · 5-Min-Schritte · DWD-Radar</p>
|
||
<div class="precip-legend map-mode-forecast-only hidden" id="precipLegend">
|
||
<span><i class="swatch light"></i> leicht</span>
|
||
<span><i class="swatch medium"></i> mäßig</span>
|
||
<span><i class="swatch heavy"></i> stark</span>
|
||
<span class="muted">Modell · ~25 km · Open-Meteo</span>
|
||
</div>
|
||
</div>
|
||
<div class="map-actions">
|
||
<button id="centerMapBtn" class="btn btn-secondary">Auf Standort zentrieren</button>
|
||
<button id="reloadRadarLayersBtn" class="btn btn-secondary">Karte neu laden</button>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
|
||
<section class="view" data-view="warnings">
|
||
<section class="glass-card">
|
||
<div class="section-head">
|
||
<div>
|
||
<h2>Wetterwarnungen</h2>
|
||
<p class="muted no-margin">Standortgenau via DWD-Warncell-IDs (WFS)</p>
|
||
</div>
|
||
<label class="inline-check"><input type="checkbox" id="warningsLocalOnly" checked /> Nur Standort</label>
|
||
</div>
|
||
<div id="warncellInfo" class="warncell-info hidden"></div>
|
||
<div id="warningsList" class="warnings-list"></div>
|
||
</section>
|
||
</section>
|
||
|
||
<section class="view" data-view="hourly">
|
||
<section class="glass-card">
|
||
<div class="section-head">
|
||
<h2>Stundenansicht</h2>
|
||
<span class="muted">48 Stunden · Temperatur, Regen & Wind</span>
|
||
</div>
|
||
<div class="hourly-chart-wrap">
|
||
<canvas id="hourlyChart" aria-label="Stundenverlauf Temperatur, Regen und Wind"></canvas>
|
||
</div>
|
||
<div class="table-wrap">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Zeit</th><th>Wetter</th><th>Temp.</th><th>Regen</th><th>Wolken</th><th>Wind</th><th>Böen</th></tr>
|
||
</thead>
|
||
<tbody id="hourlyTable"></tbody>
|
||
</table>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
|
||
<section class="view" data-view="daily">
|
||
<section class="glass-card daily-forecast-panel">
|
||
<div class="section-head">
|
||
<div>
|
||
<h2>7-Tage Forecast</h2>
|
||
<p class="muted no-margin">Temperatur, Regen & Wind · Open-Meteo</p>
|
||
</div>
|
||
<span class="muted" id="dailySource"></span>
|
||
</div>
|
||
<div class="days days-forecast" id="dailyForecast"></div>
|
||
</section>
|
||
</section>
|
||
|
||
<section class="view" data-view="settings">
|
||
<section class="glass-card">
|
||
<h2>Einstellungen</h2>
|
||
<div class="settings-grid">
|
||
<label>Temperatureinheit<select id="unitTemp"><option value="celsius">°C</option><option value="fahrenheit">°F</option></select></label>
|
||
<label>Windeinheit<select id="unitWind"><option value="kmh">km/h</option><option value="ms">m/s</option><option value="kn">kn</option></select></label>
|
||
<label>Radar-Zeitleiste<select id="radarMinutes"><option value="60">60 Min.</option><option value="90">90 Min.</option><option value="120" selected>120 Min.</option></select></label>
|
||
<label>Regen-Karte<select id="forecastHours"><option value="6">6 h</option><option value="12">12 h</option><option value="24" selected>24 h</option></select></label>
|
||
<label>Standard-Standort<button id="saveDefaultLocationBtn" class="btn btn-secondary full-width">Aktuellen Ort speichern</button></label>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
</div>
|
||
</main>
|
||
|
||
<footer class="site-footer">
|
||
<div class="container footer-grid">
|
||
<div>
|
||
<strong>HexaWetter</strong>
|
||
<p>Selfhosted Wetterportal von HexaHost. Keine amtliche Wetterberatung.</p>
|
||
<p class="muted">Daten: DWD Open Data · Open-Meteo · Bright Sky · OpenStreetMap</p>
|
||
</div>
|
||
<div>
|
||
<strong>Rechtliches</strong>
|
||
<ul>
|
||
<li><a href="impressum.html">Impressum</a></li>
|
||
<li><a href="datenschutz.html">Datenschutz</a></li>
|
||
</ul>
|
||
</div>
|
||
<div>
|
||
<strong>System</strong>
|
||
<ul>
|
||
<li><a href="admin.html">Admin-Bereich</a></li>
|
||
<li><a href="/api/health" target="_blank" rel="noopener">API Health</a></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
|
||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.7/dist/chart.umd.min.js"></script>
|
||
<script src="app.js"></script>
|
||
</body>
|
||
</html>
|