Files
weather/app/public/index.html
T

316 lines
13 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<title>Weather</title>
<link rel="manifest" href="/manifest.json">
<link rel="apple-touch-icon" href="/icons/icon.svg">
<meta name="theme-color" content="#f5f2ec" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#191510" media="(prefers-color-scheme: dark)">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="Weather">
<meta name="mobile-web-app-capable" content="yes">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700&family=Playfair+Display:wght@500;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="app">
<header class="masthead">
<h1>Weather</h1>
<span class="tagline">Open-Meteo · RainViewer</span>
</header>
<!-- Search bar (shared, always visible) -->
<div class="search-wrap">
<div class="search-row">
<input id="search-input" type="text" placeholder="City, region, or country…" autocomplete="off" spellcheck="false">
<button id="search-btn">Search</button>
<button id="locate-btn" title="Use my location">⌖</button>
<button id="units-btn" title="Toggle units">US</button>
</div>
<ul id="suggestions" class="suggestions hidden"></ul>
<p id="error-msg" class="error hidden"></p>
</div>
<!-- Loading -->
<div id="loading" class="loading hidden">
<span class="loading-dot"></span>Fetching weather data…
</div>
<!-- ── TAB: CONDITIONS ── -->
<div id="tab-conditions" class="tab-panel">
<div id="weather" class="hidden">
<div class="loc-header">
<div>
<div id="loc-name" class="loc-name"></div>
<div id="loc-sub" class="loc-sub"></div>
</div>
<div class="loc-actions">
<div id="loc-time" class="loc-time"></div>
<button id="share-btn" class="link-btn" type="button">Share location</button>
</div>
</div>
<!-- Current hero -->
<div class="current-grid">
<div class="current-temp">
<div class="temp-big"><span id="cur-temp">--</span><span class="deg">°F</span></div>
<div class="feels">Feels like <span id="cur-feels">--</span>°F</div>
<div class="hi-lo">↑<span id="cur-hi">--</span>° · ↓<span id="cur-lo">--</span>°</div>
</div>
<div class="current-cond">
<div id="cur-icon" class="cond-icon"></div>
<div id="cur-desc" class="cond-desc"></div>
<div id="cur-precip" class="cond-sub"></div>
</div>
</div>
<!-- Stats -->
<div class="stats-bar">
<div class="stat"><div class="stat-label">Humidity</div><div class="stat-val"><span id="cur-hum">--</span><span class="unit">%</span></div></div>
<div class="stat"><div class="stat-label">Wind</div><div class="stat-val"><span id="cur-wind">--</span><span class="unit">mph</span></div></div>
<div class="stat"><div class="stat-label">Pressure</div><div class="stat-val"><span id="cur-pres">--</span><span class="unit">hPa</span></div></div>
<div class="stat"><div class="stat-label">Visibility</div><div class="stat-val"><span id="cur-vis">--</span><span class="unit">mi</span></div></div>
<div class="stat"><div class="stat-label">UV Index</div><div class="stat-val"><span id="cur-uv">--</span></div></div>
<div class="stat"><div class="stat-label">Cloud Cover</div><div class="stat-val"><span id="cur-cloud">--</span><span class="unit">%</span></div></div>
</div>
<div class="astro-grid">
<div class="astro-card"><div class="stat-label">Sunrise</div><div id="sunrise-val" class="astro-val">--</div></div>
<div class="astro-card"><div class="stat-label">Sunset</div><div id="sunset-val" class="astro-val">--</div></div>
<div class="astro-card"><div class="stat-label">Moon Phase</div><div id="moon-phase-val" class="astro-val">--</div></div>
</div>
<div class="aq-grid">
<div class="aq-card"><div class="stat-label">US AQI</div><div id="aqi-us" class="aq-val">--</div></div>
<div class="aq-card"><div class="stat-label">PM2.5</div><div id="pm25" class="aq-val">--</div></div>
<div class="aq-card"><div class="stat-label">Pollen</div><div id="pollen" class="aq-val">--</div></div>
</div>
<!-- Embedded radar panel -->
<div class="section-head">
<span class="section-label">Radar</span>
<span class="section-note">
<button class="link-btn" id="open-radar-tab">Open full radar →</button>
</span>
</div>
<div class="radar-embed-wrap">
<div id="radar-embed" class="radar-map"></div>
<div class="radar-controls">
<button id="embed-play" class="radar-btn play-btn" title="Play/Pause">▶</button>
<button id="embed-layer" class="radar-btn layer-btn" title="Toggle radar/satellite">R</button>
<div class="radar-timeline" id="embed-timeline"></div>
<span id="embed-timestamp" class="radar-ts">--</span>
</div>
</div>
<!-- Hourly -->
<div class="section-head" style="margin-top:1.5rem">
<span class="section-label">Hourly Forecast</span>
<span class="section-note">next 24 hours</span>
</div>
<p id="hourly-summary" class="hourly-summary">--</p>
<div id="hourly-scroll" class="hourly-scroll">
<div id="hourly-track" class="hourly-track"></div>
</div>
<!-- 7-day -->
<div class="section-head">
<span id="daily-forecast-label" class="section-label">7-Day Forecast</span>
<span class="section-note">
<button id="daily-forecast-toggle" class="link-btn hidden" type="button">Show full forecast</button>
</span>
</div>
<div id="daily-list" class="daily-list"></div>
<div class="footer-note">
Weather: <a href="https://open-meteo.com" target="_blank">Open-Meteo</a> ·
Radar: <a href="https://www.rainviewer.com" target="_blank">RainViewer</a> ·
Updated <span id="updated-at"></span>
</div>
</div>
</div>
<!-- ── TAB: FULL RADAR ── -->
<div id="tab-radar-full" class="tab-panel hidden">
<div class="radar-full-wrap">
<div id="radar-full" class="radar-map radar-map-full"></div>
<div class="radar-controls radar-controls-full">
<button id="full-play" class="radar-btn play-btn" title="Play/Pause">▶</button>
<button id="full-layer" class="radar-btn layer-btn" title="Toggle radar/satellite">R</button>
<div class="radar-timeline" id="full-timeline"></div>
<span id="full-timestamp" class="radar-ts">--</span>
<div class="radar-legend">
<span class="legend-label">Light</span>
<div class="legend-bar"></div>
<span class="legend-label">Heavy</span>
</div>
</div>
</div>
<p class="radar-attribution">Radar tiles © <a href="https://www.rainviewer.com" target="_blank">RainViewer</a> · Map © <a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a></p>
</div>
<!-- ── TAB: MAPS ── -->
<div id="tab-maps" class="tab-panel hidden">
<div class="maps-wrap">
<div id="map-overview" class="radar-map map-overview"></div>
<div class="maps-controls">
<label class="maps-control">
<span>Radar opacity</span>
<input id="radar-opacity" type="range" min="15" max="90" step="5" value="65">
</label>
<label class="maps-control">
<span>Lightning age</span>
<select id="lightning-age">
<option value="5">Last 5m</option>
<option value="15" selected>Last 15m</option>
<option value="30">Last 30m</option>
</select>
</label>
</div>
<div class="maps-meta">
<div class="maps-card">
<div class="stat-label">Data Source Location</div>
<div id="maps-location" class="maps-value">--</div>
</div>
<div class="maps-card">
<div class="stat-label">Current Wind</div>
<div id="maps-wind" class="maps-value">--</div>
</div>
</div>
<div class="wind-legend" aria-hidden="true">
<span>Wind legend</span>
<div class="wind-legend-scale"><i></i></div>
</div>
<p class="panel-note">Toggle lightning strikes and wind overlay in Settings. Lightning overlay uses active thunderstorm alert geometry.</p>
</div>
</div>
<!-- ── TAB: ALERTS ── -->
<div id="tab-alerts" class="tab-panel hidden">
<div id="alerts-wrap" class="alerts-wrap hidden">
<div class="section-head">
<span class="section-label">Weather Alerts</span>
<span class="section-actions">
<button id="notify-btn" class="link-btn" type="button">Enable notifications</button>
<button id="push-test-btn" class="link-btn" type="button">Send test push</button>
</span>
</div>
<div id="alerts-list" class="alerts-list"></div>
</div>
<p id="alerts-empty" class="panel-note">No active alerts for this location.</p>
</div>
<!-- ── TAB: SETTINGS ── -->
<div id="tab-settings" class="tab-panel hidden">
<div class="settings-wrap">
<div class="saved-wrap">
<div class="saved-head">
<span>Saved locations</span>
<button id="save-current-btn" class="link-btn" type="button">Save current</button>
</div>
<p class="saved-help">Use star for default, arrows to reorder.</p>
<div id="saved-locations" class="saved-locations"></div>
</div>
<div class="settings-row">
<span class="settings-label">Auto-detect location on startup</span>
<label class="auto-detect-toggle" for="auto-detect-toggle">
<input id="auto-detect-toggle" type="checkbox" checked>
<span>Enabled</span>
</label>
</div>
<div class="settings-row">
<span class="settings-label">Data source location</span>
<span id="settings-location" class="settings-value">--</span>
</div>
<div class="settings-row">
<span class="settings-label">Default city</span>
<span id="default-city" class="settings-value">None</span>
</div>
<div class="settings-row">
<span class="settings-label">Units</span>
<button id="units-btn-settings" class="settings-btn" type="button">US</button>
</div>
<div class="settings-row">
<span class="settings-label">Lightning strikes on map</span>
<label class="toggle-label" for="lightning-toggle">
<input id="lightning-toggle" type="checkbox">
<span id="lightning-status">Off</span>
</label>
</div>
<div class="settings-row">
<span class="settings-label">Wind overlay on map</span>
<label class="toggle-label" for="wind-toggle">
<input id="wind-toggle" type="checkbox">
<span id="wind-status">Off</span>
</label>
</div>
<div class="settings-row">
<span class="settings-label">High contrast mode</span>
<label class="toggle-label" for="contrast-toggle">
<input id="contrast-toggle" type="checkbox">
<span id="contrast-status">Off</span>
</label>
</div>
</div>
</div>
<nav class="tabs" aria-label="Primary navigation">
<button class="tab active" data-tab="conditions" aria-label="Conditions">
<span class="tab-icon" aria-hidden="true">🌤</span>
<span class="tab-text">Now</span>
</button>
<button class="tab" data-tab="radar-full" aria-label="Radar">
<span class="tab-icon" aria-hidden="true">🛰</span>
<span class="tab-text">Radar</span>
</button>
<button class="tab" data-tab="maps" aria-label="Maps">
<span class="tab-icon" aria-hidden="true">🗺</span>
<span class="tab-text">Maps</span>
</button>
<button class="tab" data-tab="alerts" aria-label="Alerts">
<span class="tab-icon" aria-hidden="true">⚠️</span>
<span class="tab-text">Alerts</span>
</button>
<button class="tab" data-tab="settings" aria-label="Settings">
<span class="tab-icon" aria-hidden="true">⚙️</span>
<span class="tab-text">Settings</span>
</button>
</nav>
</div><!-- .app -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="app.js"></script>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js').then(reg => {
reg.update().catch(() => {});
});
let refreshing = false;
navigator.serviceWorker.addEventListener('controllerchange', () => {
if (refreshing) return;
refreshing = true;
window.location.reload();
});
});
}
</script>
</body>
</html>