feat: Initial commit - Hladinator (Water Reservoir Dashboard)
continuous-integration/drone/push Build encountered an error

- Setup React project with Vite and TypeScript
- Built dynamic UI supporting Dark/Light mode and CS/EN localization
- Added Lakes Overview grid with mock data for 40+ reservoirs
- Created interactive Recharts charts for water levels and flow rates
- Designed fully responsive premium mobile layout with custom SVG KPIs
- Developed TypeScript scraper scripts to fetch reservoir data
This commit is contained in:
David Fencl
2026-06-05 21:36:38 +02:00
parent ac43c24f20
commit a5bd4985d1
22 changed files with 4369 additions and 958 deletions
+71 -24
View File
@@ -1,31 +1,78 @@
import { useState } from 'react'
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
import LoadingScreen from './components/LoadingScreen'
import Home from './components/Home'
import Navbar from './components/Navbar'
import TimeBreaker from './components/TimeBreaker'
import { type Language } from './translations'
import './App.css'
import { useState, useEffect } from 'react';
import LakeDetail from './components/LakeDetail';
import LakesOverview from './components/LakesOverview';
import Sidebar from './components/Sidebar';
import Topbar from './components/Topbar';
import SettingsModal from './components/SettingsModal';
import { type Language } from './translations';
import './App.css';
function App() {
const [isLoading, setIsLoading] = useState(true)
const [language, setLanguage] = useState<Language>('en')
const [language, setLanguage] = useState<Language>('en');
const [theme, setTheme] = useState<'dark' | 'light'>('dark');
const [isSettingsOpen, setIsSettingsOpen] = useState(false);
const [activeView, setActiveView] = useState<'overview' | 'detail'>('overview');
const [activeLakeId, setActiveLakeId] = useState<string | null>(null);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
useEffect(() => {
if (theme === 'light') {
document.body.classList.add('light-mode');
} else {
document.body.classList.remove('light-mode');
}
}, [theme]);
const handleSelectLake = (id: string) => {
setActiveLakeId(id);
setActiveView('detail');
setIsMobileMenuOpen(false);
};
const handleNavigate = (view: 'overview' | 'detail') => {
setActiveView(view);
setIsMobileMenuOpen(false);
};
return (
<>
{isLoading ? (
<LoadingScreen onLoaded={() => setIsLoading(false)} />
) : (
<Router>
<Navbar language={language} setLanguage={setLanguage} />
<Routes>
<Route path="/" element={<Home language={language} />} />
<Route path="/time-breaker" element={<TimeBreaker language={language} />} />
</Routes>
</Router>
<div className="dashboard-container">
{/* Mobile overlay */}
{isMobileMenuOpen && (
<div
style={{ position: 'fixed', top: 0, left: 0, width: '100%', height: '100%', backgroundColor: 'rgba(0,0,0,0.5)', zIndex: 999 }}
onClick={() => setIsMobileMenuOpen(false)}
></div>
)}
</>
)
<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} />
) : (
<LakeDetail language={language} lakeId={activeLakeId} />
)}
</div>
{isSettingsOpen && (
<SettingsModal
language={language}
setLanguage={setLanguage}
theme={theme}
setTheme={setTheme}
onClose={() => setIsSettingsOpen(false)}
/>
)}
</div>
);
}
export default App
export default App;