feat: implement Open-Meteo weather integration with backfill scripts and updated lake data models.
continuous-integration/drone/push Build encountered an error

This commit is contained in:
David Fencl
2026-06-05 23:34:13 +02:00
parent 8193ce818a
commit 57e9bf12ca
24 changed files with 1122 additions and 758 deletions
+22 -18
View File
@@ -1,4 +1,5 @@
import { useState, useEffect } from 'react';
import { Routes, Route, useParams, useLocation, useNavigate, Navigate } from 'react-router-dom';
import LakeDetail from './components/LakeDetail';
import LakesOverview from './components/LakesOverview';
import LakeMap from './components/LakeMap';
@@ -6,14 +7,23 @@ import Sidebar from './components/Sidebar';
import Topbar from './components/Topbar';
import SettingsModal from './components/SettingsModal';
import { type Language } from './translations';
import { lakesConfig } from '../scripts/lakesConfig';
import { slugify } from './utils/slugify';
import './App.css';
const LakeDetailWrapper = ({ language }: { language: Language }) => {
const { slug } = useParams();
const lake = lakesConfig.find(l => slugify(l.text) === slug);
if (!lake) return <Navigate to="/" replace />;
return <LakeDetail language={language} lakeId={lake.id} />;
};
function App() {
const [language, setLanguage] = useState<Language>('en');
const [theme, setTheme] = useState<'dark' | 'light'>('dark');
const [isSettingsOpen, setIsSettingsOpen] = useState(false);
const [activeView, setActiveView] = useState<'overview' | 'detail' | 'map'>('overview');
const [activeLakeId, setActiveLakeId] = useState<string | null>(null);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
useEffect(() => {
@@ -22,19 +32,13 @@ function App() {
} else {
document.body.classList.remove('light-mode');
}
// Clean up empty hash from URL (e.g. if the user clicked an empty anchor)
if (window.location.href.endsWith('#')) {
window.history.replaceState(null, '', window.location.href.slice(0, -1));
}
}, [theme]);
const handleSelectLake = (id: string) => {
setActiveLakeId(id);
setActiveView('detail');
setIsMobileMenuOpen(false);
};
const handleNavigate = (view: 'overview' | 'detail' | 'map') => {
setActiveView(view);
setIsMobileMenuOpen(false);
};
return (
<div className="dashboard-container">
{/* Mobile overlay */}
@@ -48,17 +52,17 @@ function App() {
<Sidebar
language={language}
onOpenSettings={() => setIsSettingsOpen(true)}
activeView={activeView}
onNavigate={handleNavigate}
isMobileMenuOpen={isMobileMenuOpen}
onCloseMobileMenu={() => setIsMobileMenuOpen(false)}
/>
<div className="main-content">
<Topbar language={language} onToggleMobileMenu={() => setIsMobileMenuOpen(!isMobileMenuOpen)} />
{activeView === 'overview' && <LakesOverview language={language} onSelectLake={handleSelectLake} />}
{activeView === 'detail' && <LakeDetail language={language} lakeId={activeLakeId} />}
{activeView === 'map' && <LakeMap language={language} onSelectLake={handleSelectLake} />}
<Routes>
<Route path="/" element={<LakesOverview language={language} />} />
<Route path="/map" element={<LakeMap language={language} />} />
<Route path="/:slug" element={<LakeDetailWrapper language={language} />} />
</Routes>
</div>
{isSettingsOpen && (