modified: __pycache__/app.cpython-310.pyc

modified:   app.py
	modified:   requirements.txt
	modified:   static/css/style.css
	modified:   templates/base.html
	modified:   templates/index.html
	modified:   templates/weather.html
This commit is contained in:
SimolZimol
2026-04-21 11:34:19 +02:00
parent 55bda8ea5e
commit 164d0eb6a8
7 changed files with 364 additions and 189 deletions

View File

@@ -3,15 +3,15 @@
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>{% block title %}Wetter{% endblock %}</title>
<title>{% block title %}Skywatcher{% endblock %}</title>
<link rel="preconnect" href="https://fonts.googleapis.com"/>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;900&display=swap" rel="stylesheet"/>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}?v=2"/>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}?v=4"/>
{% block head %}{% endblock %}
</head>
<body>
<nav class="nav">
<a href="/" class="nav-logo">DWD<span>Wetter</span></a>
<a href="/" class="nav-logo">Sky<span>watcher</span></a>
<form class="nav-search" action="/wetter" method="get" autocomplete="off">
<div class="nav-search-wrap">
<svg class="nav-search-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
@@ -24,7 +24,7 @@
<main>{% block content %}{% endblock %}</main>
<footer class="footer">
Daten: <a href="https://opendata.dwd.de" target="_blank">Deutscher Wetterdienst Open Data</a>
Wetterdaten: <a href="https://opendata.dwd.de" target="_blank">Deutscher Wetterdienst Open Data (MOSMIX)</a>
</footer>
<script>

View File

@@ -1,12 +1,12 @@
{% extends "base.html" %}
{% block title %}DWD Wetter{% endblock %}
{% block title %}Skywatcher Wetter für Deutschland{% endblock %}
{% block content %}
<div class="home-wrap">
<div class="home-bg-text" aria-hidden="true">WETTER</div>
<div class="home-center">
<p class="home-eyebrow">Deutscher Wetterdienst · Open Data</p>
<p class="home-eyebrow">Präzise Vorhersagen · Daten via DWD Open Data</p>
<h1 class="home-title">Wo willst du<br>das Wetter wissen?</h1>
<form class="home-form" action="/wetter" method="get" autocomplete="off">
@@ -25,11 +25,15 @@
{% if error %}<p class="home-error">{{ error }}</p>{% endif %}
<div class="home-chips">
<div class="home-chips" id="home-chips">
{% for city in ["Berlin","Hamburg","München","Köln","Frankfurt","Dresden","Düsseldorf","Stuttgart"] %}
<a href="/wetter?ort={{ city }}" class="chip">{{ city }}</a>
{% endfor %}
</div>
<button class="btn-location" id="btn-location" title="Meinen Standort nutzen">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M12 2v3M12 19v3M2 12h3M19 12h3"/><circle cx="12" cy="12" r="9" opacity=".3"/></svg>
Meinen Standort nutzen
</button>
</div>
<div class="home-deco" aria-hidden="true">
@@ -44,5 +48,38 @@
{% endblock %}
{% block scripts %}
<script>
// Standort-Button
document.getElementById("btn-location").addEventListener("click", function() {
if (!navigator.geolocation) { alert("Geolocation nicht unterstützt."); return; }
this.textContent = "Wird ermittelt …";
this.disabled = true;
navigator.geolocation.getCurrentPosition(
pos => { window.location = `/wetter?lat=${pos.coords.latitude}&lon=${pos.coords.longitude}&ort=Mein+Standort`; },
() => { this.textContent = "Standort nicht verfügbar"; this.disabled = false; }
);
});
// Letzte Suchen aus localStorage als Chips anzeigen
(function(){
const recent = JSON.parse(localStorage.getItem("sw_recent") || "[]");
if (!recent.length) return;
const wrap = document.getElementById("home-chips");
const div = document.createElement("div");
div.className = "recent-label";
div.textContent = "Zuletzt gesucht:";
wrap.before(div);
const strip = document.createElement("div");
strip.className = "home-chips home-chips--recent";
recent.forEach(name => {
const a = document.createElement("a");
a.href = `/wetter?ort=${encodeURIComponent(name)}`;
a.className = "chip chip--recent";
a.textContent = name;
strip.appendChild(a);
});
wrap.before(strip);
})();
</script>
<script>setupAC(document.getElementById("home-ort"), document.getElementById("home-ac"));</script>
{% endblock %}

View File

@@ -1,5 +1,5 @@
{% extends "base.html" %}
{% block title %}{{ display_name.split(',')[0] }} DWD Wetter{% endblock %}
{% block title %}{{ display_name.split(',')[0] }} Skywatcher{% endblock %}
{% block head %}
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.2/dist/chart.umd.min.js"></script>
@@ -44,7 +44,7 @@
<div class="hero-metrics">
{% set items = [
("Gefühlt wie", (current.temp_c|string + " °C") if current.temp_c is not none else ""),
("Gefühlt wie", (current.feels_like|string + " °C") if current.feels_like is not none else ""),
("Böen", (current.gust_kmh|string + " km/h") if current.gust_kmh is not none else ""),
("Niederschlag", (current.precip_mm|string + " mm") if (current.precip_mm is not none and current.precip_mm > 0) else ((current.rain_prob|string + " %") if (current.rain_prob is not none and current.rain_prob > 0) else "0 mm")),
("Sonne", (current.sun_min|string + " min/h") if (current.sun_min is not none and current.sun_min > 0) else ""),
@@ -59,10 +59,30 @@
</div>
<div class="hero-station">
📡 Station <strong>{{ station_name }}</strong> ({{ station_dist }} km) · ID {{ station_id }}
📡 Station <strong>{{ station_name }}</strong> ({{ station_dist }} km)
{% if sunrise %}
&nbsp;·&nbsp; 🌅 {{ sunrise }} &nbsp;·&nbsp; 🌇 {{ sunset }}
{% endif %}
{% if current.uv_index is not none %}
&nbsp;·&nbsp; UV {{ current.uv_index }}
{% endif %}
</div>
</header>
{% if warnings %}
<div class="warnings">
{% for w in warnings %}
<div class="warn-item warn-lvl-{{ w.level }}">
<span class="warn-icon">{{ '⚠️' if w.level == 1 else ('🟠' if w.level == 2 else ('🔴' if w.level >= 3 else '⚠️')) }}</span>
<div>
<strong>{{ w.headline }}</strong>
{% if w.description %}<p class="warn-desc">{{ w.description[:140] }}{% if w.description|length > 140 %}…{% endif %}</p>{% endif %}
</div>
</div>
{% endfor %}
</div>
{% endif %}
<!-- STÜNDLICH -->
<section class="section">
<h2 class="section-title">Stundenweise</h2>
@@ -93,6 +113,9 @@
{% if h.wind_kmh is not none %}
<div class="hcard-wind">{{ h.wind_kmh }}<small>km/h</small></div>
{% endif %}
{% if h.uv_index is not none and h.uv_index > 0 %}
<div class="hcard-uv">UV {{ h.uv_index }}</div>
{% endif %}
</div>
{% endfor %}
</div>
@@ -159,6 +182,9 @@
{% elif d.rain_prob is not none and d.rain_prob > 0 %}
<span class="drow-precip">💧 {{ d.rain_prob }}%</span>
{% endif %}
{% if d.uv_max is not none and d.uv_max > 0 %}
<span class="drow-uv">UV {{ d.uv_max }}</span>
{% endif %}
</div>
</div>
{% endfor %}
@@ -166,12 +192,22 @@
</section>
<p class="data-note">
Alle Daten: <a href="https://opendata.dwd.de" target="_blank">Deutscher Wetterdienst Open Data (MOSMIX)</a>
Wetterdaten: <a href="https://opendata.dwd.de" target="_blank">Deutscher Wetterdienst Open Data (MOSMIX)</a>
</p>
{% endblock %}
{% block scripts %}
<script>
// ── Letzte Suchen speichern ──────────────────────────────────────────────────
(function(){
const key = "sw_recent";
const ort = {{ ort | tojson }};
let recent = JSON.parse(localStorage.getItem(key) || "[]");
recent = [ort, ...recent.filter(x => x !== ort)].slice(0, 6);
localStorage.setItem(key, JSON.stringify(recent));
})();
</script>
<script>
(function() {
const labels = {{ chart_labels | tojson }};
const temps = {{ chart_temps | tojson }};