feat: implement multilingual SEO support and enhance map UI with data synchronization updates
This commit is contained in:
@@ -0,0 +1,63 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
import * as cheerio from 'cheerio';
|
||||||
|
import fs from 'fs';
|
||||||
|
import https from 'https';
|
||||||
|
|
||||||
|
async function compare() {
|
||||||
|
const URL = 'https://www.pvl.cz/portal/nadrze/cz/pc/Mereni.aspx?oid=1&id=VLL1';
|
||||||
|
const agent = new https.Agent({ rejectUnauthorized: false });
|
||||||
|
const response = await axios.get(URL, { httpsAgent: agent });
|
||||||
|
const $ = cheerio.load(response.data);
|
||||||
|
|
||||||
|
let tblFound = null;
|
||||||
|
$('table').each((i, tbl) => {
|
||||||
|
if ($(tbl).text().includes('Datum') && $(tbl).text().includes('Odtok')) {
|
||||||
|
tblFound = $(tbl);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const pvlRows = [];
|
||||||
|
if (tblFound) {
|
||||||
|
tblFound.find('tr').each((i, row) => {
|
||||||
|
if (i === 0) return;
|
||||||
|
const cols = $(row).find('td');
|
||||||
|
if (cols.length >= 3) {
|
||||||
|
const rawDate = $(cols[0]).text().trim();
|
||||||
|
const levelStr = $(cols[1]).text().trim().replace(',', '.');
|
||||||
|
let flowStr = $(cols[2]).text().trim().replace(',', '.');
|
||||||
|
if (flowStr === '' && cols.length >= 4) {
|
||||||
|
flowStr = $(cols[3]).text().trim().replace(',', '.');
|
||||||
|
}
|
||||||
|
pvlRows.push({
|
||||||
|
date: rawDate,
|
||||||
|
level: parseFloat(levelStr),
|
||||||
|
flow: parseFloat(flowStr)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const localData = JSON.parse(fs.readFileSync('public/data/VLL1.json', 'utf-8'));
|
||||||
|
// Sort local data descending (newest first) to match PVL which is newest first
|
||||||
|
const sortedLocal = localData.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
|
||||||
|
|
||||||
|
console.log('--- POROVNÁNÍ DAT: LIPNO 1 ---');
|
||||||
|
console.log(String('PVL.CZ').padEnd(40) + ' | ' + 'NAŠE LOKÁLNÍ DATABÁZE');
|
||||||
|
console.log('-'.repeat(85));
|
||||||
|
|
||||||
|
for (let i = 0; i < Math.min(10, pvlRows.length); i++) {
|
||||||
|
const p = pvlRows[i];
|
||||||
|
const l = sortedLocal[i];
|
||||||
|
|
||||||
|
// Format our local UTC timestamp back to something readable
|
||||||
|
const d = new Date(l.timestamp);
|
||||||
|
const localDateStr = `${d.getDate().toString().padStart(2, '0')}.${(d.getMonth()+1).toString().padStart(2, '0')}.${d.getFullYear()} ${d.getHours().toString().padStart(2, '0')}:${d.getMinutes().toString().padStart(2, '0')}`;
|
||||||
|
|
||||||
|
const pvlStr = `[${p.date}] H: ${p.level} m, O: ${p.flow} m3/s`.padEnd(40);
|
||||||
|
const locStr = `[${localDateStr}] H: ${l.level} m, O: ${l.flow} m3/s, P: ${l.inflow} m3/s`;
|
||||||
|
|
||||||
|
console.log(`${pvlStr} | ${locStr}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compare().catch(console.error);
|
||||||
+6
-1
@@ -4,7 +4,12 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/jpeg" href="/favicon.jpg" />
|
<link rel="icon" type="image/jpeg" href="/favicon.jpg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Davis Fencl</title>
|
<title>Hladinátor - Aktuální stav přehrad a nádrží</title>
|
||||||
|
<meta name="description" content="Sledujte aktuální vodní stav, průtok a vývoj počasí na českých přehradách a nádržích v reálném čase." />
|
||||||
|
<meta property="og:title" content="Hladinátor - Aktuální stav přehrad a nádrží" />
|
||||||
|
<meta property="og:description" content="Sledujte aktuální vodní stav, průtok a vývoj počasí na českých přehradách a nádržích v reálném čase." />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:url" content="https://hladinator.cz" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
Generated
+48
-1
@@ -14,6 +14,7 @@
|
|||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"react": "^19.2.0",
|
"react": "^19.2.0",
|
||||||
"react-dom": "^19.2.0",
|
"react-dom": "^19.2.0",
|
||||||
|
"react-helmet-async": "^3.0.0",
|
||||||
"react-icons": "^5.5.0",
|
"react-icons": "^5.5.0",
|
||||||
"react-leaflet": "^5.0.0",
|
"react-leaflet": "^5.0.0",
|
||||||
"react-router-dom": "^7.9.6",
|
"react-router-dom": "^7.9.6",
|
||||||
@@ -3936,6 +3937,15 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/invariant": {
|
||||||
|
"version": "2.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
||||||
|
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"loose-envify": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-extglob": {
|
"node_modules/is-extglob": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||||
@@ -4016,7 +4026,6 @@
|
|||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/js-yaml": {
|
"node_modules/js-yaml": {
|
||||||
@@ -4219,6 +4228,18 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/loose-envify": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"loose-envify": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lru-cache": {
|
"node_modules/lru-cache": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||||
@@ -4688,6 +4709,26 @@
|
|||||||
"react": "^19.2.0"
|
"react": "^19.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-fast-compare": {
|
||||||
|
"version": "3.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
|
||||||
|
"integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/react-helmet-async": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-nA3IEZfXiclgrz4KLxAhqJqIfFDuvzQwlKwpdmzZIuC1KNSghDEIXmyU0TKtbM+NafnkICcwx8CECFrZ/sL/1w==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"invariant": "^2.2.4",
|
||||||
|
"react-fast-compare": "^3.2.2",
|
||||||
|
"shallowequal": "^1.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.6.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-icons": {
|
"node_modules/react-icons": {
|
||||||
"version": "5.5.0",
|
"version": "5.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
|
||||||
@@ -4957,6 +4998,12 @@
|
|||||||
"integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
|
"integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/shallowequal": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/shebang-command": {
|
"node_modules/shebang-command": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"react": "^19.2.0",
|
"react": "^19.2.0",
|
||||||
"react-dom": "^19.2.0",
|
"react-dom": "^19.2.0",
|
||||||
|
"react-helmet-async": "^3.0.0",
|
||||||
"react-icons": "^5.5.0",
|
"react-icons": "^5.5.0",
|
||||||
"react-leaflet": "^5.0.0",
|
"react-leaflet": "^5.0.0",
|
||||||
"react-router-dom": "^7.9.6",
|
"react-router-dom": "^7.9.6",
|
||||||
|
|||||||
+242
-1
@@ -226,8 +226,249 @@
|
|||||||
{
|
{
|
||||||
"timestamp": "2026-06-06T10:30:00.000Z",
|
"timestamp": "2026-06-06T10:30:00.000Z",
|
||||||
"level": 467.74,
|
"level": 467.74,
|
||||||
"flow": 0,
|
"flow": 0.7,
|
||||||
"inflow": 0,
|
"inflow": 0,
|
||||||
"volume": 0
|
"volume": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T10:40:00.000Z",
|
||||||
|
"level": 467.74,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T10:50:00.000Z",
|
||||||
|
"level": 467.74,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 2.24,
|
||||||
|
"volume": 26.53,
|
||||||
|
"temperature": 20.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:00:00.000Z",
|
||||||
|
"level": 467.74,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:10:00.000Z",
|
||||||
|
"level": 467.74,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:20:00.000Z",
|
||||||
|
"level": 467.74,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:30:00.000Z",
|
||||||
|
"level": 467.74,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:40:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:50:00.000Z",
|
||||||
|
"level": 467.74,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 2.24,
|
||||||
|
"volume": 26.54,
|
||||||
|
"temperature": 21.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:00:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:10:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:20:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:30:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:40:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:50:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 2.24,
|
||||||
|
"volume": 26.54,
|
||||||
|
"temperature": 21.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:00:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:10:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:20:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:30:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:40:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 2.24,
|
||||||
|
"volume": 26.54,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:00:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:10:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:20:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:30:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:40:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:50:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 2.24,
|
||||||
|
"volume": 26.54,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T15:00:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0.7,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T15:10:00.000Z",
|
||||||
|
"level": 467.75,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 2.24,
|
||||||
|
"volume": 26.54,
|
||||||
|
"temperature": 22,
|
||||||
|
"precipitation": 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -229,5 +229,255 @@
|
|||||||
"flow": 2.52,
|
"flow": 2.52,
|
||||||
"inflow": 0,
|
"inflow": 0,
|
||||||
"volume": 0
|
"volume": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T10:40:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T10:50:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 1.47,
|
||||||
|
"volume": 32.3,
|
||||||
|
"temperature": 20.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:00:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:10:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:20:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:30:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:40:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:50:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 1.47,
|
||||||
|
"volume": 32.31,
|
||||||
|
"temperature": 21.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:00:00.000Z",
|
||||||
|
"level": 352.83,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:10:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:20:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.53,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:30:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:40:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:50:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 1.47,
|
||||||
|
"volume": 32.28,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:00:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:10:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.53,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:20:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.53,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:30:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.53,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:40:00.000Z",
|
||||||
|
"level": 352.83,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:50:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 1.47,
|
||||||
|
"volume": 32.3,
|
||||||
|
"temperature": 22.7,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:00:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.7,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:10:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.7,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:20:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.7,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:30:00.000Z",
|
||||||
|
"level": 352.83,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.7,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:40:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.7,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:50:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 1.47,
|
||||||
|
"volume": 32.29,
|
||||||
|
"temperature": 22.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T15:00:00.000Z",
|
||||||
|
"level": 352.84,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T15:10:00.000Z",
|
||||||
|
"level": 352.83,
|
||||||
|
"flow": 2.52,
|
||||||
|
"inflow": 1.47,
|
||||||
|
"volume": 32.31,
|
||||||
|
"temperature": 22.7,
|
||||||
|
"precipitation": 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -229,5 +229,255 @@
|
|||||||
"flow": 2.5,
|
"flow": 2.5,
|
||||||
"inflow": 0,
|
"inflow": 0,
|
||||||
"volume": 0
|
"volume": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T10:40:00.000Z",
|
||||||
|
"level": 369.84,
|
||||||
|
"flow": 2.5,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T10:50:00.000Z",
|
||||||
|
"level": 369.84,
|
||||||
|
"flow": 2.5,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 20.4,
|
||||||
|
"temperature": 20.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:00:00.000Z",
|
||||||
|
"level": 369.84,
|
||||||
|
"flow": 2.5,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:10:00.000Z",
|
||||||
|
"level": 369.84,
|
||||||
|
"flow": 2.5,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:20:00.000Z",
|
||||||
|
"level": 369.84,
|
||||||
|
"flow": 2.5,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:30:00.000Z",
|
||||||
|
"level": 369.84,
|
||||||
|
"flow": 2.5,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:40:00.000Z",
|
||||||
|
"level": 369.84,
|
||||||
|
"flow": 2.5,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:50:00.000Z",
|
||||||
|
"level": 369.84,
|
||||||
|
"flow": 2.5,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 20.4,
|
||||||
|
"temperature": 21.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:00:00.000Z",
|
||||||
|
"level": 369.84,
|
||||||
|
"flow": 2.5,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:10:00.000Z",
|
||||||
|
"level": 369.84,
|
||||||
|
"flow": 8.79,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:20:00.000Z",
|
||||||
|
"level": 369.84,
|
||||||
|
"flow": 14.24,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:30:00.000Z",
|
||||||
|
"level": 369.84,
|
||||||
|
"flow": 14.24,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:40:00.000Z",
|
||||||
|
"level": 369.84,
|
||||||
|
"flow": 14.24,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:50:00.000Z",
|
||||||
|
"level": 369.84,
|
||||||
|
"flow": 14.24,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 20.4,
|
||||||
|
"temperature": 22.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:00:00.000Z",
|
||||||
|
"level": 369.84,
|
||||||
|
"flow": 14.24,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:10:00.000Z",
|
||||||
|
"level": 369.84,
|
||||||
|
"flow": 14.24,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:20:00.000Z",
|
||||||
|
"level": 369.84,
|
||||||
|
"flow": 14.24,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:30:00.000Z",
|
||||||
|
"level": 369.84,
|
||||||
|
"flow": 14.24,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:40:00.000Z",
|
||||||
|
"level": 369.84,
|
||||||
|
"flow": 14.24,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:50:00.000Z",
|
||||||
|
"level": 369.83,
|
||||||
|
"flow": 14.22,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 20.4,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:00:00.000Z",
|
||||||
|
"level": 369.83,
|
||||||
|
"flow": 14.22,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:10:00.000Z",
|
||||||
|
"level": 369.83,
|
||||||
|
"flow": 14.22,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:20:00.000Z",
|
||||||
|
"level": 369.83,
|
||||||
|
"flow": 14.22,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:30:00.000Z",
|
||||||
|
"level": 369.83,
|
||||||
|
"flow": 14.22,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:40:00.000Z",
|
||||||
|
"level": 369.83,
|
||||||
|
"flow": 14.22,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:50:00.000Z",
|
||||||
|
"level": 369.83,
|
||||||
|
"flow": 14.22,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 20.37,
|
||||||
|
"temperature": 22.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T15:00:00.000Z",
|
||||||
|
"level": 369.83,
|
||||||
|
"flow": 14.23,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T15:10:00.000Z",
|
||||||
|
"level": 369.83,
|
||||||
|
"flow": 14.23,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 20.37,
|
||||||
|
"temperature": 22.6,
|
||||||
|
"precipitation": 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -229,5 +229,255 @@
|
|||||||
"flow": 19.05,
|
"flow": 19.05,
|
||||||
"inflow": 0,
|
"inflow": 0,
|
||||||
"volume": 0
|
"volume": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T10:40:00.000Z",
|
||||||
|
"level": 352.5,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T10:50:00.000Z",
|
||||||
|
"level": 352.49,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 13.43,
|
||||||
|
"volume": 2.77,
|
||||||
|
"temperature": 20.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:00:00.000Z",
|
||||||
|
"level": 352.48,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:10:00.000Z",
|
||||||
|
"level": 352.48,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:20:00.000Z",
|
||||||
|
"level": 352.47,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:30:00.000Z",
|
||||||
|
"level": 352.47,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:40:00.000Z",
|
||||||
|
"level": 352.47,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:50:00.000Z",
|
||||||
|
"level": 352.46,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 13.43,
|
||||||
|
"volume": 2.76,
|
||||||
|
"temperature": 21.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:00:00.000Z",
|
||||||
|
"level": 352.46,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:10:00.000Z",
|
||||||
|
"level": 352.45,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:20:00.000Z",
|
||||||
|
"level": 352.45,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:30:00.000Z",
|
||||||
|
"level": 352.44,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:40:00.000Z",
|
||||||
|
"level": 352.44,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:50:00.000Z",
|
||||||
|
"level": 352.44,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 13.43,
|
||||||
|
"volume": 2.75,
|
||||||
|
"temperature": 22,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:00:00.000Z",
|
||||||
|
"level": 352.44,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:10:00.000Z",
|
||||||
|
"level": 352.44,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:20:00.000Z",
|
||||||
|
"level": 352.44,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:30:00.000Z",
|
||||||
|
"level": 352.43,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:40:00.000Z",
|
||||||
|
"level": 352.43,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:50:00.000Z",
|
||||||
|
"level": 352.44,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 13.43,
|
||||||
|
"volume": 2.74,
|
||||||
|
"temperature": 22.1,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:00:00.000Z",
|
||||||
|
"level": 352.44,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.1,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:10:00.000Z",
|
||||||
|
"level": 352.44,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.1,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:20:00.000Z",
|
||||||
|
"level": 352.44,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.1,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:30:00.000Z",
|
||||||
|
"level": 352.43,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.1,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:40:00.000Z",
|
||||||
|
"level": 352.43,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.1,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:50:00.000Z",
|
||||||
|
"level": 352.44,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 13.43,
|
||||||
|
"volume": 2.74,
|
||||||
|
"temperature": 21.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T15:00:00.000Z",
|
||||||
|
"level": 352.44,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T15:10:00.000Z",
|
||||||
|
"level": 352.43,
|
||||||
|
"flow": 19.05,
|
||||||
|
"inflow": 13.43,
|
||||||
|
"volume": 2.74,
|
||||||
|
"temperature": 21.9,
|
||||||
|
"precipitation": 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -229,5 +229,255 @@
|
|||||||
"flow": 1.51,
|
"flow": 1.51,
|
||||||
"inflow": 0,
|
"inflow": 0,
|
||||||
"volume": 0
|
"volume": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T10:40:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T10:50:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 9.25,
|
||||||
|
"volume": 199.67,
|
||||||
|
"temperature": 19.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:00:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 19.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:10:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 19.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:20:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 19.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:30:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 19.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:40:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 19.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:50:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 9.25,
|
||||||
|
"volume": 199.67,
|
||||||
|
"temperature": 20,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:00:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:10:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:20:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:30:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:40:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:50:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 9.25,
|
||||||
|
"volume": 199.67,
|
||||||
|
"temperature": 20.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:00:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:10:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:20:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:30:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:40:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:50:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 9.25,
|
||||||
|
"volume": 199.67,
|
||||||
|
"temperature": 20.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:00:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:10:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:20:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:30:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:40:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:50:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 9.25,
|
||||||
|
"volume": 199.67,
|
||||||
|
"temperature": 20.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T15:00:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 1.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T15:10:00.000Z",
|
||||||
|
"level": 723.09,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 9.25,
|
||||||
|
"volume": 199.67,
|
||||||
|
"temperature": 20.7,
|
||||||
|
"precipitation": 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
+252
-2
@@ -212,14 +212,14 @@
|
|||||||
{
|
{
|
||||||
"timestamp": "2026-06-06T10:10:00.000Z",
|
"timestamp": "2026-06-06T10:10:00.000Z",
|
||||||
"level": 558.94,
|
"level": 558.94,
|
||||||
"flow": 0,
|
"flow": 7.18,
|
||||||
"inflow": 0,
|
"inflow": 0,
|
||||||
"volume": 0
|
"volume": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"timestamp": "2026-06-06T10:20:00.000Z",
|
"timestamp": "2026-06-06T10:20:00.000Z",
|
||||||
"level": 558.93,
|
"level": 558.93,
|
||||||
"flow": 0,
|
"flow": 7.18,
|
||||||
"inflow": 0,
|
"inflow": 0,
|
||||||
"volume": 0
|
"volume": 0
|
||||||
},
|
},
|
||||||
@@ -229,5 +229,255 @@
|
|||||||
"flow": 0,
|
"flow": 0,
|
||||||
"inflow": 0,
|
"inflow": 0,
|
||||||
"volume": 0
|
"volume": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T10:40:00.000Z",
|
||||||
|
"level": 558.9,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T10:50:00.000Z",
|
||||||
|
"level": 558.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 5.37,
|
||||||
|
"volume": 0.45,
|
||||||
|
"temperature": 20.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:00:00.000Z",
|
||||||
|
"level": 558.87,
|
||||||
|
"flow": 7.22,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:10:00.000Z",
|
||||||
|
"level": 558.86,
|
||||||
|
"flow": 7.24,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:20:00.000Z",
|
||||||
|
"level": 558.84,
|
||||||
|
"flow": 7.27,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:30:00.000Z",
|
||||||
|
"level": 558.82,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:40:00.000Z",
|
||||||
|
"level": 558.81,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 20.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:50:00.000Z",
|
||||||
|
"level": 558.79,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 5.37,
|
||||||
|
"volume": 0.43,
|
||||||
|
"temperature": 21.3,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:00:00.000Z",
|
||||||
|
"level": 558.77,
|
||||||
|
"flow": 7.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.3,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:10:00.000Z",
|
||||||
|
"level": 558.75,
|
||||||
|
"flow": 7.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.3,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:20:00.000Z",
|
||||||
|
"level": 558.74,
|
||||||
|
"flow": 7.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.3,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:30:00.000Z",
|
||||||
|
"level": 558.72,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.3,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:40:00.000Z",
|
||||||
|
"level": 558.71,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.3,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:50:00.000Z",
|
||||||
|
"level": 558.68,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 5.37,
|
||||||
|
"volume": 0.41,
|
||||||
|
"temperature": 21.7,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:00:00.000Z",
|
||||||
|
"level": 558.67,
|
||||||
|
"flow": 7.53,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.7,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:10:00.000Z",
|
||||||
|
"level": 558.65,
|
||||||
|
"flow": 7.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.7,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:20:00.000Z",
|
||||||
|
"level": 558.63,
|
||||||
|
"flow": 7.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.7,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:30:00.000Z",
|
||||||
|
"level": 558.62,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.7,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:40:00.000Z",
|
||||||
|
"level": 558.6,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.7,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:50:00.000Z",
|
||||||
|
"level": 558.58,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 5.37,
|
||||||
|
"volume": 0.39,
|
||||||
|
"temperature": 21.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:00:00.000Z",
|
||||||
|
"level": 558.56,
|
||||||
|
"flow": 7.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:10:00.000Z",
|
||||||
|
"level": 558.54,
|
||||||
|
"flow": 7.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:20:00.000Z",
|
||||||
|
"level": 558.52,
|
||||||
|
"flow": 7.51,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:30:00.000Z",
|
||||||
|
"level": 558.5,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:40:00.000Z",
|
||||||
|
"level": 558.49,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:50:00.000Z",
|
||||||
|
"level": 558.47,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 5.37,
|
||||||
|
"volume": 0.37,
|
||||||
|
"temperature": 21.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T15:00:00.000Z",
|
||||||
|
"level": 558.44,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.8,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T15:10:00.000Z",
|
||||||
|
"level": 558.43,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 5.37,
|
||||||
|
"volume": 0.35,
|
||||||
|
"temperature": 21.7,
|
||||||
|
"precipitation": 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -229,5 +229,255 @@
|
|||||||
"flow": 0,
|
"flow": 0,
|
||||||
"inflow": 0,
|
"inflow": 0,
|
||||||
"volume": 0
|
"volume": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T10:40:00.000Z",
|
||||||
|
"level": 345.27,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T10:50:00.000Z",
|
||||||
|
"level": 345.27,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 24.39,
|
||||||
|
"volume": 522.32,
|
||||||
|
"temperature": 21,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:00:00.000Z",
|
||||||
|
"level": 345.28,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:10:00.000Z",
|
||||||
|
"level": 345.28,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:20:00.000Z",
|
||||||
|
"level": 345.28,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:30:00.000Z",
|
||||||
|
"level": 345.28,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:40:00.000Z",
|
||||||
|
"level": 345.28,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:50:00.000Z",
|
||||||
|
"level": 345.28,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 24.39,
|
||||||
|
"volume": 522.52,
|
||||||
|
"temperature": 22,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:00:00.000Z",
|
||||||
|
"level": 345.28,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:10:00.000Z",
|
||||||
|
"level": 345.28,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:20:00.000Z",
|
||||||
|
"level": 345.28,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:30:00.000Z",
|
||||||
|
"level": 345.28,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:40:00.000Z",
|
||||||
|
"level": 345.28,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:50:00.000Z",
|
||||||
|
"level": 345.28,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 24.39,
|
||||||
|
"volume": 522.52,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:00:00.000Z",
|
||||||
|
"level": 345.28,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:10:00.000Z",
|
||||||
|
"level": 345.28,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:20:00.000Z",
|
||||||
|
"level": 345.29,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:30:00.000Z",
|
||||||
|
"level": 345.29,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:40:00.000Z",
|
||||||
|
"level": 345.29,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:50:00.000Z",
|
||||||
|
"level": 345.29,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 24.39,
|
||||||
|
"volume": 522.52,
|
||||||
|
"temperature": 22.1,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:00:00.000Z",
|
||||||
|
"level": 345.29,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.1,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:10:00.000Z",
|
||||||
|
"level": 345.29,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.1,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:20:00.000Z",
|
||||||
|
"level": 345.29,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.1,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:30:00.000Z",
|
||||||
|
"level": 345.29,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.1,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:40:00.000Z",
|
||||||
|
"level": 345.29,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.1,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:50:00.000Z",
|
||||||
|
"level": 345.29,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 24.39,
|
||||||
|
"volume": 522.72,
|
||||||
|
"temperature": 22.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T15:00:00.000Z",
|
||||||
|
"level": 345.29,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T15:10:00.000Z",
|
||||||
|
"level": 345.29,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 24.39,
|
||||||
|
"volume": 522.72,
|
||||||
|
"temperature": 22.6,
|
||||||
|
"precipitation": 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -229,5 +229,255 @@
|
|||||||
"flow": 0,
|
"flow": 0,
|
||||||
"inflow": 0,
|
"inflow": 0,
|
||||||
"volume": 0
|
"volume": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T10:40:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T10:50:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 81.06,
|
||||||
|
"volume": 261.23,
|
||||||
|
"temperature": 21.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:00:00.000Z",
|
||||||
|
"level": 269.87,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:10:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:20:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:30:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:40:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:50:00.000Z",
|
||||||
|
"level": 269.89,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 81.06,
|
||||||
|
"volume": 261.01,
|
||||||
|
"temperature": 22.7,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:00:00.000Z",
|
||||||
|
"level": 269.89,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.7,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:10:00.000Z",
|
||||||
|
"level": 269.89,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.7,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:20:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.7,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:30:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.7,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:40:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.7,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:50:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 81.06,
|
||||||
|
"volume": 261.17,
|
||||||
|
"temperature": 22.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:00:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:10:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:20:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:30:00.000Z",
|
||||||
|
"level": 269.89,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:40:00.000Z",
|
||||||
|
"level": 269.89,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.9,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:50:00.000Z",
|
||||||
|
"level": 269.89,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 81.06,
|
||||||
|
"volume": 261.08,
|
||||||
|
"temperature": 23.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:00:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 23.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:10:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 23.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:20:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 23.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:30:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 23.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:40:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 23.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:50:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 81.06,
|
||||||
|
"volume": 261.14,
|
||||||
|
"temperature": 23.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T15:00:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 23.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T15:10:00.000Z",
|
||||||
|
"level": 269.88,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 81.06,
|
||||||
|
"volume": 261.1,
|
||||||
|
"temperature": 23.5,
|
||||||
|
"precipitation": 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -229,5 +229,255 @@
|
|||||||
"flow": 0,
|
"flow": 0,
|
||||||
"inflow": 0,
|
"inflow": 0,
|
||||||
"volume": 0
|
"volume": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T10:40:00.000Z",
|
||||||
|
"level": 217.04,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T10:50:00.000Z",
|
||||||
|
"level": 217.05,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 48.25,
|
||||||
|
"volume": 8.23,
|
||||||
|
"temperature": 21.4,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:00:00.000Z",
|
||||||
|
"level": 217.01,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.4,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:10:00.000Z",
|
||||||
|
"level": 217.02,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.4,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:20:00.000Z",
|
||||||
|
"level": 217.03,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.4,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:30:00.000Z",
|
||||||
|
"level": 217.01,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.4,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:40:00.000Z",
|
||||||
|
"level": 217.01,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 21.4,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T11:50:00.000Z",
|
||||||
|
"level": 217.02,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 48.25,
|
||||||
|
"volume": 8.19,
|
||||||
|
"temperature": 22.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:00:00.000Z",
|
||||||
|
"level": 217.01,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:10:00.000Z",
|
||||||
|
"level": 217,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:20:00.000Z",
|
||||||
|
"level": 217.01,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:30:00.000Z",
|
||||||
|
"level": 216.98,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:40:00.000Z",
|
||||||
|
"level": 216.99,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.6,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T12:50:00.000Z",
|
||||||
|
"level": 217,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 48.25,
|
||||||
|
"volume": 8.19,
|
||||||
|
"temperature": 22.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:00:00.000Z",
|
||||||
|
"level": 216.96,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:10:00.000Z",
|
||||||
|
"level": 216.98,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:20:00.000Z",
|
||||||
|
"level": 217,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:30:00.000Z",
|
||||||
|
"level": 216.97,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:40:00.000Z",
|
||||||
|
"level": 216.99,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 22.5,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T13:50:00.000Z",
|
||||||
|
"level": 216.98,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 48.25,
|
||||||
|
"volume": 8.14,
|
||||||
|
"temperature": 23,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:00:00.000Z",
|
||||||
|
"level": 216.95,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 23,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:10:00.000Z",
|
||||||
|
"level": 216.98,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 23,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:20:00.000Z",
|
||||||
|
"level": 216.97,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 23,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:30:00.000Z",
|
||||||
|
"level": 216.94,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 23,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:40:00.000Z",
|
||||||
|
"level": 216.98,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 23,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T14:50:00.000Z",
|
||||||
|
"level": 216.97,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 48.25,
|
||||||
|
"volume": 8.14,
|
||||||
|
"temperature": 23.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T15:00:00.000Z",
|
||||||
|
"level": 216.95,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 0,
|
||||||
|
"volume": 0,
|
||||||
|
"temperature": 23.2,
|
||||||
|
"precipitation": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2026-06-06T15:10:00.000Z",
|
||||||
|
"level": 216.98,
|
||||||
|
"flow": 0,
|
||||||
|
"inflow": 48.25,
|
||||||
|
"volume": 8.14,
|
||||||
|
"temperature": 23.2,
|
||||||
|
"precipitation": 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
+122
-122
@@ -5,11 +5,11 @@
|
|||||||
"river": "Vltava",
|
"river": "Vltava",
|
||||||
"priority": true,
|
"priority": true,
|
||||||
"level": "723.09",
|
"level": "723.09",
|
||||||
"capacity": 76.3,
|
"capacity": 65.3,
|
||||||
"storageDiff": -1.81,
|
"storageDiff": -1.81,
|
||||||
"inflow": "0.0",
|
"inflow": "9.3",
|
||||||
"outflow": "1.5",
|
"outflow": "0.0",
|
||||||
"volume": 233.5,
|
"volume": 199.67,
|
||||||
"maxVolume": 306,
|
"maxVolume": 306,
|
||||||
"lat": 48.6322,
|
"lat": 48.6322,
|
||||||
"lng": 14.2215,
|
"lng": 14.2215,
|
||||||
@@ -33,28 +33,28 @@
|
|||||||
"name": "Lipno II",
|
"name": "Lipno II",
|
||||||
"river": "Vltava",
|
"river": "Vltava",
|
||||||
"priority": true,
|
"priority": true,
|
||||||
"level": "558.92",
|
"level": "558.43",
|
||||||
"capacity": 34.9,
|
"capacity": 23.3,
|
||||||
"storageDiff": -1.58,
|
"storageDiff": -2.07,
|
||||||
"inflow": "0.0",
|
"inflow": "5.4",
|
||||||
"outflow": "0.0",
|
"outflow": "0.0",
|
||||||
"volume": 0.5,
|
"volume": 0.35,
|
||||||
"maxVolume": 1.5,
|
"maxVolume": 1.5,
|
||||||
"lat": 48.625,
|
"lat": 48.625,
|
||||||
"lng": 14.318,
|
"lng": 14.318,
|
||||||
"sparkline": [
|
"sparkline": [
|
||||||
559.59,
|
558.63,
|
||||||
559.52,
|
558.62,
|
||||||
559.44,
|
558.6,
|
||||||
559.37,
|
558.58,
|
||||||
559.29,
|
558.56,
|
||||||
559.21,
|
558.54,
|
||||||
559.13,
|
558.52,
|
||||||
559.05,
|
558.5,
|
||||||
558.96,
|
558.49,
|
||||||
558.94,
|
558.47,
|
||||||
558.93,
|
558.44,
|
||||||
558.92
|
558.43
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -62,28 +62,28 @@
|
|||||||
"name": "Hněvkovice",
|
"name": "Hněvkovice",
|
||||||
"river": "Vltava",
|
"river": "Vltava",
|
||||||
"priority": true,
|
"priority": true,
|
||||||
"level": "369.84",
|
"level": "369.83",
|
||||||
"capacity": 88,
|
"capacity": 96.5,
|
||||||
"storageDiff": -0.26,
|
"storageDiff": -0.27,
|
||||||
"inflow": "0.0",
|
"inflow": "0.0",
|
||||||
"outflow": "2.5",
|
"outflow": "14.2",
|
||||||
"volume": 18.6,
|
"volume": 20.37,
|
||||||
"maxVolume": 21.1,
|
"maxVolume": 21.1,
|
||||||
"lat": 49.183,
|
"lat": 49.183,
|
||||||
"lng": 14.444,
|
"lng": 14.444,
|
||||||
"sparkline": [
|
"sparkline": [
|
||||||
|
369.84,
|
||||||
|
369.84,
|
||||||
|
369.84,
|
||||||
369.83,
|
369.83,
|
||||||
369.84,
|
|
||||||
369.85,
|
|
||||||
369.84,
|
|
||||||
369.84,
|
|
||||||
369.84,
|
|
||||||
369.81,
|
|
||||||
369.83,
|
369.83,
|
||||||
369.84,
|
369.83,
|
||||||
369.84,
|
369.83,
|
||||||
369.84,
|
369.83,
|
||||||
369.84
|
369.83,
|
||||||
|
369.83,
|
||||||
|
369.83,
|
||||||
|
369.83
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -91,28 +91,28 @@
|
|||||||
"name": "Kořensko",
|
"name": "Kořensko",
|
||||||
"river": "Vltava",
|
"river": "Vltava",
|
||||||
"priority": true,
|
"priority": true,
|
||||||
"level": "352.50",
|
"level": "352.43",
|
||||||
"capacity": 33.3,
|
"capacity": 97.9,
|
||||||
"storageDiff": -0.1,
|
"storageDiff": -0.17,
|
||||||
"inflow": "0.0",
|
"inflow": "13.4",
|
||||||
"outflow": "19.1",
|
"outflow": "19.1",
|
||||||
"volume": 0.9,
|
"volume": 2.74,
|
||||||
"maxVolume": 2.8,
|
"maxVolume": 2.8,
|
||||||
"lat": 49.255,
|
"lat": 49.255,
|
||||||
"lng": 14.398,
|
"lng": 14.398,
|
||||||
"sparkline": [
|
"sparkline": [
|
||||||
352.47,
|
352.44,
|
||||||
352.48,
|
352.43,
|
||||||
352.49,
|
352.43,
|
||||||
352.52,
|
352.44,
|
||||||
352.56,
|
352.44,
|
||||||
352.57,
|
352.44,
|
||||||
352.56,
|
352.44,
|
||||||
352.55,
|
352.43,
|
||||||
352.52,
|
352.43,
|
||||||
352.51,
|
352.44,
|
||||||
352.51,
|
352.44,
|
||||||
352.5
|
352.43
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -120,28 +120,28 @@
|
|||||||
"name": "Orlík",
|
"name": "Orlík",
|
||||||
"river": "Vltava",
|
"river": "Vltava",
|
||||||
"priority": true,
|
"priority": true,
|
||||||
"level": "345.27",
|
"level": "345.29",
|
||||||
"capacity": 63.6,
|
"capacity": 73,
|
||||||
"storageDiff": -4.63,
|
"storageDiff": -4.61,
|
||||||
"inflow": "0.0",
|
"inflow": "24.4",
|
||||||
"outflow": "0.0",
|
"outflow": "0.0",
|
||||||
"volume": 455.7,
|
"volume": 522.72,
|
||||||
"maxVolume": 716.5,
|
"maxVolume": 716.5,
|
||||||
"lat": 49.606,
|
"lat": 49.606,
|
||||||
"lng": 14.17,
|
"lng": 14.17,
|
||||||
"sparkline": [
|
"sparkline": [
|
||||||
345.25,
|
345.29,
|
||||||
345.26,
|
345.29,
|
||||||
345.26,
|
345.29,
|
||||||
345.25,
|
345.29,
|
||||||
345.26,
|
345.29,
|
||||||
345.26,
|
345.29,
|
||||||
345.26,
|
345.29,
|
||||||
345.27,
|
345.29,
|
||||||
345.27,
|
345.29,
|
||||||
345.27,
|
345.29,
|
||||||
345.27,
|
345.29,
|
||||||
345.27
|
345.29
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -150,25 +150,25 @@
|
|||||||
"river": "Vltava",
|
"river": "Vltava",
|
||||||
"priority": true,
|
"priority": true,
|
||||||
"level": "269.88",
|
"level": "269.88",
|
||||||
"capacity": 78.2,
|
"capacity": 97,
|
||||||
"storageDiff": -0.72,
|
"storageDiff": -0.72,
|
||||||
"inflow": "0.0",
|
"inflow": "81.1",
|
||||||
"outflow": "0.0",
|
"outflow": "0.0",
|
||||||
"volume": 210.6,
|
"volume": 261.1,
|
||||||
"maxVolume": 269.3,
|
"maxVolume": 269.3,
|
||||||
"lat": 49.822,
|
"lat": 49.822,
|
||||||
"lng": 14.436,
|
"lng": 14.436,
|
||||||
"sparkline": [
|
"sparkline": [
|
||||||
269.87,
|
|
||||||
269.86,
|
|
||||||
269.89,
|
|
||||||
269.86,
|
|
||||||
269.89,
|
|
||||||
269.88,
|
|
||||||
269.89,
|
|
||||||
269.88,
|
269.88,
|
||||||
269.89,
|
269.89,
|
||||||
269.89,
|
269.89,
|
||||||
|
269.89,
|
||||||
|
269.88,
|
||||||
|
269.88,
|
||||||
|
269.88,
|
||||||
|
269.88,
|
||||||
|
269.88,
|
||||||
|
269.88,
|
||||||
269.88,
|
269.88,
|
||||||
269.88
|
269.88
|
||||||
]
|
]
|
||||||
@@ -178,28 +178,28 @@
|
|||||||
"name": "Štěchovice",
|
"name": "Štěchovice",
|
||||||
"river": "Vltava",
|
"river": "Vltava",
|
||||||
"priority": true,
|
"priority": true,
|
||||||
"level": "217.04",
|
"level": "216.98",
|
||||||
"capacity": 1.6,
|
"capacity": 72.7,
|
||||||
"storageDiff": -2.36,
|
"storageDiff": -2.42,
|
||||||
"inflow": "0.0",
|
"inflow": "48.3",
|
||||||
"outflow": "0.0",
|
"outflow": "0.0",
|
||||||
"volume": 0.2,
|
"volume": 8.14,
|
||||||
"maxVolume": 11.2,
|
"maxVolume": 11.2,
|
||||||
"lat": 49.845,
|
"lat": 49.845,
|
||||||
"lng": 14.412,
|
"lng": 14.412,
|
||||||
"sparkline": [
|
"sparkline": [
|
||||||
218.33,
|
217,
|
||||||
218.25,
|
216.97,
|
||||||
218.1,
|
216.99,
|
||||||
217.82,
|
216.98,
|
||||||
217.57,
|
216.95,
|
||||||
217.32,
|
216.98,
|
||||||
217.19,
|
216.97,
|
||||||
217.1,
|
216.94,
|
||||||
217.05,
|
216.98,
|
||||||
217.04,
|
216.97,
|
||||||
217.06,
|
216.95,
|
||||||
217.04
|
216.98
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -207,28 +207,28 @@
|
|||||||
"name": "Římov",
|
"name": "Římov",
|
||||||
"river": "Malše",
|
"river": "Malše",
|
||||||
"priority": true,
|
"priority": true,
|
||||||
"level": "467.74",
|
"level": "467.75",
|
||||||
"capacity": 74.9,
|
"capacity": 78.5,
|
||||||
"storageDiff": -2.91,
|
"storageDiff": -2.9,
|
||||||
"inflow": "0.0",
|
"inflow": "2.2",
|
||||||
"outflow": "0.0",
|
"outflow": "0.0",
|
||||||
"volume": 25.3,
|
"volume": 26.54,
|
||||||
"maxVolume": 33.8,
|
"maxVolume": 33.8,
|
||||||
"lat": 48.847,
|
"lat": 48.847,
|
||||||
"lng": 14.487,
|
"lng": 14.487,
|
||||||
"sparkline": [
|
"sparkline": [
|
||||||
467.73,
|
467.75,
|
||||||
467.73,
|
467.75,
|
||||||
467.73,
|
467.75,
|
||||||
467.73,
|
467.75,
|
||||||
467.73,
|
467.75,
|
||||||
467.73,
|
467.75,
|
||||||
467.74,
|
467.75,
|
||||||
467.74,
|
467.75,
|
||||||
467.74,
|
467.75,
|
||||||
467.74,
|
467.75,
|
||||||
467.74,
|
467.75,
|
||||||
467.74
|
467.75
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -236,28 +236,28 @@
|
|||||||
"name": "Hracholusky",
|
"name": "Hracholusky",
|
||||||
"river": "Mže",
|
"river": "Mže",
|
||||||
"priority": true,
|
"priority": true,
|
||||||
"level": "352.84",
|
"level": "352.83",
|
||||||
"capacity": 11.4,
|
"capacity": 57,
|
||||||
"storageDiff": -16.66,
|
"storageDiff": -16.67,
|
||||||
"inflow": "0.0",
|
"inflow": "1.5",
|
||||||
"outflow": "2.5",
|
"outflow": "2.5",
|
||||||
"volume": 6.5,
|
"volume": 32.31,
|
||||||
"maxVolume": 56.7,
|
"maxVolume": 56.7,
|
||||||
"lat": 49.789,
|
"lat": 49.789,
|
||||||
"lng": 13.155,
|
"lng": 13.155,
|
||||||
"sparkline": [
|
"sparkline": [
|
||||||
352.84,
|
352.84,
|
||||||
352.84,
|
352.84,
|
||||||
|
352.83,
|
||||||
352.84,
|
352.84,
|
||||||
352.84,
|
352.84,
|
||||||
352.84,
|
352.84,
|
||||||
352.84,
|
352.84,
|
||||||
|
352.83,
|
||||||
352.84,
|
352.84,
|
||||||
352.84,
|
352.84,
|
||||||
352.84,
|
352.84,
|
||||||
352.84,
|
352.83
|
||||||
352.84,
|
|
||||||
352.84
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
User-agent: *
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
Sitemap: https://hladinator.cz/sitemap.xml
|
||||||
+28
-61
@@ -78,70 +78,37 @@ async function scrapeLake(lakeId: string, oid: string, internalId: string) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const records: DataRecord[] = [];
|
const records: DataRecord[] = [];
|
||||||
|
let dataTable = null;
|
||||||
|
$('table').each((i, tbl) => {
|
||||||
|
if ($(tbl).text().includes('Datum') && $(tbl).text().includes('Odtok')) {
|
||||||
|
dataTable = $(tbl);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const parseTable = (htmlContent: string) => {
|
if (dataTable) {
|
||||||
const _$ = cheerio.load(htmlContent);
|
dataTable.find('tr').each((i, row) => {
|
||||||
let dataTable = null;
|
if (i === 0) return; // skip header
|
||||||
_$('table').each((i, tbl) => {
|
const cols = $(row).find('td');
|
||||||
if (_$(tbl).text().includes('Datum') && _$(tbl).text().includes('Odtok')) {
|
if (cols.length >= 3) {
|
||||||
dataTable = _$(tbl);
|
const rawDate = $(cols[0]).text().trim();
|
||||||
|
const levelStr = $(cols[1]).text().trim().replace(',', '.');
|
||||||
|
let flowStr = $(cols[2]).text().trim().replace(',', '.');
|
||||||
|
if (flowStr === '' && cols.length >= 4) {
|
||||||
|
flowStr = $(cols[3]).text().trim().replace(',', '.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsedDateStr = parseDateString(rawDate);
|
||||||
|
if (parsedDateStr) {
|
||||||
|
records.push({
|
||||||
|
timestamp: parsedDateStr,
|
||||||
|
level: parseFloat(levelStr) || 0,
|
||||||
|
flow: parseFloat(flowStr) || 0,
|
||||||
|
inflow: 0,
|
||||||
|
volume: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (dataTable) {
|
|
||||||
dataTable.find('tr').each((i, row) => {
|
|
||||||
if (i === 0) return; // skip header
|
|
||||||
const cols = _$(row).find('td');
|
|
||||||
if (cols.length >= 3) {
|
|
||||||
const rawDate = _$(cols[0]).text().trim();
|
|
||||||
const levelStr = _$(cols[1]).text().trim().replace(',', '.');
|
|
||||||
let flowStr = _$(cols[2]).text().trim().replace(',', '.');
|
|
||||||
if (flowStr === '' && cols.length >= 4) {
|
|
||||||
flowStr = _$(cols[3]).text().trim().replace(',', '.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const parsedDateStr = parseDateString(rawDate);
|
|
||||||
if (parsedDateStr) {
|
|
||||||
records.push({
|
|
||||||
timestamp: parsedDateStr,
|
|
||||||
level: parseFloat(levelStr) || 0,
|
|
||||||
flow: parseFloat(flowStr) || 0,
|
|
||||||
inflow: 0,
|
|
||||||
volume: 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 1. Zpracování týdenních dat (GET)
|
|
||||||
parseTable(response.data);
|
|
||||||
|
|
||||||
// 2. Získání a zpracování měsíčních dat (POST)
|
|
||||||
try {
|
|
||||||
const viewstate = $('#__VIEWSTATE').val();
|
|
||||||
const viewstategenerator = $('#__VIEWSTATEGENERATOR').val();
|
|
||||||
const eventvalidation = $('#__EVENTVALIDATION').val();
|
|
||||||
|
|
||||||
if (viewstate && viewstategenerator && eventvalidation) {
|
|
||||||
const postData = new URLSearchParams();
|
|
||||||
postData.append('__EVENTTARGET', 'ctl00$ObsahCPH$PrechodNaBilancniData');
|
|
||||||
postData.append('__EVENTARGUMENT', '');
|
|
||||||
postData.append('__VIEWSTATE', viewstate as string);
|
|
||||||
postData.append('__VIEWSTATEGENERATOR', viewstategenerator as string);
|
|
||||||
postData.append('__EVENTVALIDATION', eventvalidation as string);
|
|
||||||
|
|
||||||
const postRes = await axios.post(URL, postData.toString(), {
|
|
||||||
httpsAgent: agent,
|
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
||||||
timeout: 10000
|
|
||||||
});
|
|
||||||
|
|
||||||
parseTable(postRes.data);
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
|
||||||
console.warn(`Failed to fetch monthly data for ${internalId}:`, err.message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (records.length > 0) {
|
if (records.length > 0) {
|
||||||
|
|||||||
+13
-4
@@ -12,13 +12,13 @@ import { lakesConfig } from '../scripts/lakesConfig';
|
|||||||
import { slugify } from './utils/slugify';
|
import { slugify } from './utils/slugify';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
|
|
||||||
const LakeDetailWrapper = ({ language }: { language: Language }) => {
|
const LakeDetailWrapper = ({ language, windUnit }: { language: Language, windUnit: 'kmh' | 'ms' }) => {
|
||||||
const { slug } = useParams();
|
const { slug } = useParams();
|
||||||
const lake = lakesConfig.find(l => slugify(l.text) === slug);
|
const lake = lakesConfig.find(l => slugify(l.text) === slug);
|
||||||
|
|
||||||
if (!lake) return <Navigate to="/" replace />;
|
if (!lake) return <Navigate to="/" replace />;
|
||||||
|
|
||||||
return <LakeDetail language={language} lakeId={lake.id} />;
|
return <LakeDetail language={language} lakeId={lake.id} windUnit={windUnit} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
@@ -28,6 +28,9 @@ function App() {
|
|||||||
const [theme, setTheme] = useState<'dark' | 'light'>(() => {
|
const [theme, setTheme] = useState<'dark' | 'light'>(() => {
|
||||||
return (localStorage.getItem('hladinator_theme') as 'dark' | 'light') || 'dark';
|
return (localStorage.getItem('hladinator_theme') as 'dark' | 'light') || 'dark';
|
||||||
});
|
});
|
||||||
|
const [windUnit, setWindUnit] = useState<'kmh' | 'ms'>(() => {
|
||||||
|
return (localStorage.getItem('hladinator_windUnit') as 'kmh' | 'ms') || 'kmh';
|
||||||
|
});
|
||||||
const [isSettingsOpen, setIsSettingsOpen] = useState(false);
|
const [isSettingsOpen, setIsSettingsOpen] = useState(false);
|
||||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
||||||
|
|
||||||
@@ -49,6 +52,10 @@ function App() {
|
|||||||
localStorage.setItem('hladinator_lang', language);
|
localStorage.setItem('hladinator_lang', language);
|
||||||
}, [language]);
|
}, [language]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
localStorage.setItem('hladinator_windUnit', windUnit);
|
||||||
|
}, [windUnit]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="dashboard-container">
|
<div className="dashboard-container">
|
||||||
{/* Mobile overlay */}
|
{/* Mobile overlay */}
|
||||||
@@ -73,7 +80,7 @@ function App() {
|
|||||||
<Route path="/" element={<LakesOverview language={language} />} />
|
<Route path="/" element={<LakesOverview language={language} />} />
|
||||||
<Route path="/favorites" element={<FavoritesOverview language={language} />} />
|
<Route path="/favorites" element={<FavoritesOverview language={language} />} />
|
||||||
<Route path="/map" element={<LakeMap language={language} />} />
|
<Route path="/map" element={<LakeMap language={language} />} />
|
||||||
<Route path="/:slug" element={<LakeDetailWrapper language={language} />} />
|
<Route path="/:slug" element={<LakeDetailWrapper language={language} windUnit={windUnit} />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
<footer style={{
|
<footer style={{
|
||||||
@@ -85,7 +92,7 @@ function App() {
|
|||||||
color: 'var(--text-muted)',
|
color: 'var(--text-muted)',
|
||||||
marginTop: 'auto'
|
marginTop: 'auto'
|
||||||
}}>
|
}}>
|
||||||
<span>Zdroje dat: pvl.cz, open-meteo.com</span>
|
<span>{t[language].chart.dataSources} pvl.cz, open-meteo.com</span>
|
||||||
<span>{t[language].chart.createdIn}</span>
|
<span>{t[language].chart.createdIn}</span>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
@@ -96,6 +103,8 @@ function App() {
|
|||||||
setLanguage={setLanguage}
|
setLanguage={setLanguage}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
setTheme={setTheme}
|
setTheme={setTheme}
|
||||||
|
windUnit={windUnit}
|
||||||
|
setWindUnit={setWindUnit}
|
||||||
onClose={() => setIsSettingsOpen(false)}
|
onClose={() => setIsSettingsOpen(false)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { FiStar } from 'react-icons/fi';
|
import { FiStar } from 'react-icons/fi';
|
||||||
import { type Language } from '../translations';
|
import { type Language, t } from '../translations';
|
||||||
import { useFavorites } from '../hooks/useFavorites';
|
import { useFavorites } from '../hooks/useFavorites';
|
||||||
|
import { Helmet } from 'react-helmet-async';
|
||||||
import { CircularProgress } from './CircularProgress';
|
import { CircularProgress } from './CircularProgress';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { slugify } from '../utils/slugify';
|
import { slugify } from '../utils/slugify';
|
||||||
@@ -42,6 +43,12 @@ const FavoritesOverview = ({ language }: Props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
|
||||||
|
<Helmet>
|
||||||
|
<title>{t[language].seo.favoritesTitle}</title>
|
||||||
|
<meta name="description" content={t[language].seo.favoritesDesc} />
|
||||||
|
<meta property="og:title" content={t[language].seo.favoritesTitle} />
|
||||||
|
<meta property="og:description" content={t[language].seo.favoritesDesc} />
|
||||||
|
</Helmet>
|
||||||
<div>
|
<div>
|
||||||
<h1 style={{ fontSize: '1.75rem', fontWeight: 'bold', margin: '0 0 0.5rem 0', display: 'flex', alignItems: 'center', gap: '0.6rem' }}>
|
<h1 style={{ fontSize: '1.75rem', fontWeight: 'bold', margin: '0 0 0.5rem 0', display: 'flex', alignItems: 'center', gap: '0.6rem' }}>
|
||||||
<FiStar size={24} fill="#f59e0b" color="#f59e0b" />
|
<FiStar size={24} fill="#f59e0b" color="#f59e0b" />
|
||||||
@@ -84,7 +91,7 @@ const FavoritesOverview = ({ language }: Props) => {
|
|||||||
{/* Unpin button */}
|
{/* Unpin button */}
|
||||||
<button
|
<button
|
||||||
onClick={(e) => { e.stopPropagation(); toggleFavorite(lake.id); }}
|
onClick={(e) => { e.stopPropagation(); toggleFavorite(lake.id); }}
|
||||||
title="Odepnout"
|
title={language === 'cs' ? 'Odepnout' : 'Unpin'}
|
||||||
style={{
|
style={{
|
||||||
position: 'absolute', top: '1rem', right: '1rem',
|
position: 'absolute', top: '1rem', right: '1rem',
|
||||||
background: 'none', border: 'none', cursor: 'pointer',
|
background: 'none', border: 'none', cursor: 'pointer',
|
||||||
@@ -104,7 +111,7 @@ const FavoritesOverview = ({ language }: Props) => {
|
|||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
|
||||||
<div style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
|
<div style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
|
||||||
<div>
|
<div>
|
||||||
<div style={{ fontSize: '0.8rem', color: 'var(--text-muted)' }}>Water level</div>
|
<div style={{ fontSize: '0.8rem', color: 'var(--text-muted)' }}>{t[language].kpi.level}</div>
|
||||||
<div style={{ fontSize: '2rem', fontWeight: 'bold' }}>{lake.level} <span style={{ fontSize: '1rem', fontWeight: 'normal', color: 'var(--text-muted)' }}>m n.m.</span></div>
|
<div style={{ fontSize: '2rem', fontWeight: 'bold' }}>{lake.level} <span style={{ fontSize: '1rem', fontWeight: 'normal', color: 'var(--text-muted)' }}>m n.m.</span></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -123,11 +130,11 @@ const FavoritesOverview = ({ language }: Props) => {
|
|||||||
<div style={{ display: 'flex', gap: '1rem', fontSize: '0.85rem' }}>
|
<div style={{ display: 'flex', gap: '1rem', fontSize: '0.85rem' }}>
|
||||||
<div style={{ display: 'flex', gap: '0.5rem' }}>
|
<div style={{ display: 'flex', gap: '0.5rem' }}>
|
||||||
<FiTrendingUp color="var(--color-green)" />
|
<FiTrendingUp color="var(--color-green)" />
|
||||||
<span style={{ color: 'var(--text-muted)' }}>Inflow <span style={{ color: 'var(--color-green)' }}>{lake.inflow} m³/s</span></span>
|
<span style={{ color: 'var(--text-muted)' }}>{t[language].kpi.inflow} <span style={{ color: 'var(--color-green)' }}>{lake.inflow} m³/s</span></span>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: 'flex', gap: '0.5rem' }}>
|
<div style={{ display: 'flex', gap: '0.5rem' }}>
|
||||||
<FiTrendingDown color="var(--color-red)" />
|
<FiTrendingDown color="var(--color-red)" />
|
||||||
<span style={{ color: 'var(--text-muted)' }}>Outflow <span style={{ color: 'var(--color-red)' }}>{lake.outflow} m³/s</span></span>
|
<span style={{ color: 'var(--text-muted)' }}>{t[language].kpi.outflow} <span style={{ color: 'var(--color-red)' }}>{lake.outflow} m³/s</span></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const KpiCards = ({ data, language, lakeName = 'Lipno 1' }: Props) => {
|
|||||||
}, [showTooltip]);
|
}, [showTooltip]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="kpi-grid-container">
|
<>
|
||||||
{/* CARD 1: HLADINA */}
|
{/* CARD 1: HLADINA */}
|
||||||
<div className="kpi-card">
|
<div className="kpi-card">
|
||||||
<div style={{ fontSize: '1rem', color: 'var(--text-muted)', marginBottom: '0.5rem' }}>
|
<div style={{ fontSize: '1rem', color: 'var(--text-muted)', marginBottom: '0.5rem' }}>
|
||||||
@@ -146,7 +146,7 @@ const KpiCards = ({ data, language, lakeName = 'Lipno 1' }: Props) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Line, ComposedChart, ReferenceLine, Bar } from 'recharts';
|
import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Line, ComposedChart, ReferenceLine, Bar } from 'recharts';
|
||||||
|
import { Helmet } from 'react-helmet-async';
|
||||||
import { type Language, t } from '../translations';
|
import { type Language, t } from '../translations';
|
||||||
import KpiCards from './KpiCards';
|
import KpiCards from './KpiCards';
|
||||||
import { WeatherWidget } from './WeatherWidget';
|
import { WeatherWidget } from './WeatherWidget';
|
||||||
|
import { WindChart } from './WindChart';
|
||||||
import { NAVIGATION_LIMITS } from '../utils/navigationLimits';
|
import { NAVIGATION_LIMITS } from '../utils/navigationLimits';
|
||||||
import { FiAlertCircle } from 'react-icons/fi';
|
import { lakesConfig } from '../../scripts/lakesConfig';
|
||||||
|
import { FiAlertCircle, FiStar } from 'react-icons/fi';
|
||||||
|
import { useFavorites } from '../hooks/useFavorites';
|
||||||
|
|
||||||
interface LipnoData {
|
interface LipnoData {
|
||||||
timestamp: string;
|
timestamp: string;
|
||||||
@@ -21,6 +25,7 @@ interface LipnoData {
|
|||||||
interface Props {
|
interface Props {
|
||||||
language: Language;
|
language: Language;
|
||||||
lakeId: string | null;
|
lakeId: string | null;
|
||||||
|
windUnit?: 'kmh' | 'ms';
|
||||||
}
|
}
|
||||||
|
|
||||||
const CustomTooltip = ({ active, payload, label, language, isWeather }: any) => {
|
const CustomTooltip = ({ active, payload, label, language, isWeather }: any) => {
|
||||||
@@ -34,7 +39,7 @@ const CustomTooltip = ({ active, payload, label, language, isWeather }: any) =>
|
|||||||
const isTemp = entry.name === 'temperature' || entry.dataKey === 'temperature';
|
const isTemp = entry.name === 'temperature' || entry.dataKey === 'temperature';
|
||||||
return (
|
return (
|
||||||
<p key={index} style={{ margin: 0, color: 'var(--text-main)' }}>
|
<p key={index} style={{ margin: 0, color: 'var(--text-main)' }}>
|
||||||
{isTemp ? 'Teplota' : 'Srážky'}: <span style={{ fontWeight: 'bold' }}>{entry.value !== undefined && entry.value !== null ? entry.value.toFixed(1) : 'N/A'} {isTemp ? '°C' : 'mm'}</span>
|
{isTemp ? (language === 'cs' ? 'Teplota' : 'Temperature') : (language === 'cs' ? 'Srážky' : 'Precipitation')}: <span style={{ fontWeight: 'bold' }}>{entry.value !== undefined && entry.value !== null ? entry.value.toFixed(1) : 'N/A'} {isTemp ? '°C' : 'mm'}</span>
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -74,7 +79,7 @@ const CustomTooltip = ({ active, payload, label, language, isWeather }: any) =>
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const LakeDetail = ({ language, lakeId }: Props) => {
|
const LakeDetail = ({ language, lakeId, windUnit = 'kmh' }: Props) => {
|
||||||
const [data, setData] = useState<LipnoData[]>([]);
|
const [data, setData] = useState<LipnoData[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [lakeInfo, setLakeInfo] = useState<any>(null);
|
const [lakeInfo, setLakeInfo] = useState<any>(null);
|
||||||
@@ -174,6 +179,9 @@ const LakeDetail = ({ language, lakeId }: Props) => {
|
|||||||
const targetMs7d = nowMs - 7 * 24 * 60 * 60 * 1000;
|
const targetMs7d = nowMs - 7 * 24 * 60 * 60 * 1000;
|
||||||
const targetMs30d = nowMs - 30 * 24 * 60 * 60 * 1000;
|
const targetMs30d = nowMs - 30 * 24 * 60 * 60 * 1000;
|
||||||
|
|
||||||
|
const { isFavorite, toggleFavorite } = useFavorites();
|
||||||
|
const isFav = lakeId ? isFavorite(lakeId) : false;
|
||||||
|
|
||||||
let level24hAgo = latestData.level;
|
let level24hAgo = latestData.level;
|
||||||
let level7dAgo = latestData.level;
|
let level7dAgo = latestData.level;
|
||||||
let level30dAgo = latestData.level;
|
let level30dAgo = latestData.level;
|
||||||
@@ -221,19 +229,64 @@ const LakeDetail = ({ language, lakeId }: Props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const limits = lakeInfo ? NAVIGATION_LIMITS[lakeInfo.id] : undefined;
|
const limits = lakeInfo ? NAVIGATION_LIMITS[lakeInfo.id] : undefined;
|
||||||
|
const staticConfig = lakeInfo ? lakesConfig.find(l => l.id === lakeInfo.id) : undefined;
|
||||||
|
|
||||||
|
const leftYAxisDomain = [
|
||||||
|
(dataMin: number) => {
|
||||||
|
let min = dataMin;
|
||||||
|
if (limits) limits.forEach(l => { if (l.level < min) min = l.level; });
|
||||||
|
return min - 0.5;
|
||||||
|
},
|
||||||
|
(dataMax: number) => {
|
||||||
|
let max = dataMax;
|
||||||
|
if (staticConfig?.maxLevel && staticConfig.maxLevel > max) max = staticConfig.maxLevel;
|
||||||
|
if (staticConfig?.storageLevel && staticConfig.storageLevel > max) max = staticConfig.storageLevel;
|
||||||
|
return max + 0.5;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '1.5rem', width: '100%' }}>
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '1.5rem', width: '100%' }}>
|
||||||
|
{lakeInfo && (
|
||||||
|
<>
|
||||||
|
<Helmet>
|
||||||
|
<title>{t[language].seo.lakeTitle.replace('{name}', lakeInfo.name)}</title>
|
||||||
|
<meta name="description" content={t[language].seo.lakeDesc.replace('{name}', lakeInfo.name)} />
|
||||||
|
<meta property="og:title" content={t[language].seo.lakeTitle.replace('{name}', lakeInfo.name)} />
|
||||||
|
<meta property="og:description" content={t[language].seo.lakeDesc.replace('{name}', lakeInfo.name)} />
|
||||||
|
</Helmet>
|
||||||
|
<div>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem', margin: '0 0 0.5rem 0' }}>
|
||||||
|
<h1 style={{ fontSize: '2rem', fontWeight: 'bold', margin: 0, color: 'var(--text-main)' }}>
|
||||||
|
{lakeInfo.name}
|
||||||
|
</h1>
|
||||||
|
<button
|
||||||
|
onClick={(e) => { e.preventDefault(); if (lakeId) toggleFavorite(lakeId); }}
|
||||||
|
style={{ background: 'none', border: 'none', cursor: 'pointer', display: 'flex', alignItems: 'center', padding: '0.25rem' }}
|
||||||
|
title={isFav ? (language === 'cs' ? "Odebrat z oblíbených" : "Remove from favorites") : (language === 'cs' ? "Přidat do oblíbených" : "Add to favorites")}
|
||||||
|
>
|
||||||
|
<FiStar size={24} fill={isFav ? '#f59e0b' : 'none'} color={isFav ? '#f59e0b' : 'var(--text-muted)'} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<p style={{ margin: 0, color: 'var(--text-muted)', fontSize: '0.95rem', lineHeight: '1.5' }}>
|
||||||
|
{t[language].seo.lakeDesc.replace('{name}', lakeInfo.name)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
<div style={{ color: 'var(--text-muted)', fontSize: '0.9rem', marginTop: '-0.5rem', display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
<div style={{ color: 'var(--text-muted)', fontSize: '0.9rem', marginTop: '-0.5rem', display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
||||||
<span>{topbarDict.updated} {new Date().toLocaleDateString(language === 'cs' ? 'cs-CZ' : 'en-GB', { day: '2-digit', month: '2-digit', year: 'numeric' })}, {new Date().toLocaleTimeString(language === 'cs' ? 'cs-CZ' : 'en-GB', { hour: '2-digit', minute: '2-digit' })} UTC</span>
|
<span>{topbarDict.updated} {new Date().toLocaleDateString(language === 'cs' ? 'cs-CZ' : 'en-GB', { day: '2-digit', month: '2-digit', year: 'numeric' })}, {new Date().toLocaleTimeString(language === 'cs' ? 'cs-CZ' : 'en-GB', { hour: '2-digit', minute: '2-digit' })} UTC</span>
|
||||||
<div className="status-dot"></div>
|
<div className="status-dot"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<KpiCards data={kpiData} language={language} lakeName={lakeInfo ? lakeInfo.name : 'Lipno 1'} />
|
<div className="kpi-grid-container">
|
||||||
|
<KpiCards data={kpiData} language={language} lakeName={lakeInfo ? lakeInfo.name : 'Lipno 1'} />
|
||||||
|
|
||||||
{lakeInfo && lakeInfo.lat && lakeInfo.lng && (
|
{lakeInfo && lakeInfo.lat && lakeInfo.lng && (
|
||||||
<WeatherWidget lat={lakeInfo.lat} lng={lakeInfo.lng} language={language} sensorTemp={latestData.temperature} />
|
<WeatherWidget lat={lakeInfo.lat} lng={lakeInfo.lng} language={language} windUnit={windUnit} sensorTemp={latestData.temperature} />
|
||||||
)}
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
{limits && limits.map((limit, idx) => {
|
{limits && limits.map((limit, idx) => {
|
||||||
const diff = latestData.level - limit.level;
|
const diff = latestData.level - limit.level;
|
||||||
@@ -279,7 +332,7 @@ const LakeDetail = ({ language, lakeId }: Props) => {
|
|||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
<XAxis dataKey="date" stroke="var(--text-muted)" tick={{fill: 'var(--text-muted)', fontSize: 12}} minTickGap={50} />
|
<XAxis dataKey="date" stroke="var(--text-muted)" tick={{fill: 'var(--text-muted)', fontSize: 12}} minTickGap={50} />
|
||||||
<YAxis yAxisId="left" domain={['dataMin - 0.5', 'dataMax + 0.5']} stroke="var(--text-muted)" tick={{fill: 'var(--text-muted)', fontSize: 12}} tickFormatter={(v) => v.toFixed(2)} />
|
<YAxis yAxisId="left" domain={leftYAxisDomain as any} stroke="var(--text-muted)" tick={{fill: 'var(--text-muted)', fontSize: 12}} tickFormatter={(v) => v.toFixed(2)} />
|
||||||
<YAxis yAxisId="right" orientation="right" domain={[0, (dataMax: number) => Math.max(dataMax, 1)]} stroke="var(--text-muted)" tick={{fill: 'var(--text-muted)', fontSize: 12}} />
|
<YAxis yAxisId="right" orientation="right" domain={[0, (dataMax: number) => Math.max(dataMax, 1)]} stroke="var(--text-muted)" tick={{fill: 'var(--text-muted)', fontSize: 12}} />
|
||||||
|
|
||||||
<CartesianGrid strokeDasharray="3 3" stroke="rgba(255,255,255,0.05)" vertical={false} />
|
<CartesianGrid strokeDasharray="3 3" stroke="rgba(255,255,255,0.05)" vertical={false} />
|
||||||
@@ -289,6 +342,12 @@ const LakeDetail = ({ language, lakeId }: Props) => {
|
|||||||
{limits && limits.map((limit, idx) => (
|
{limits && limits.map((limit, idx) => (
|
||||||
<ReferenceLine key={idx} yAxisId="left" y={limit.level} stroke={limit.type === 'danger' ? 'var(--color-red)' : '#f59e0b'} strokeDasharray="3 3" label={{ position: 'insideBottomRight', value: language === 'cs' ? limit.labelCs : limit.labelEn, fill: limit.type === 'danger' ? 'var(--color-red)' : '#f59e0b', fontSize: 12 }} />
|
<ReferenceLine key={idx} yAxisId="left" y={limit.level} stroke={limit.type === 'danger' ? 'var(--color-red)' : '#f59e0b'} strokeDasharray="3 3" label={{ position: 'insideBottomRight', value: language === 'cs' ? limit.labelCs : limit.labelEn, fill: limit.type === 'danger' ? 'var(--color-red)' : '#f59e0b', fontSize: 12 }} />
|
||||||
))}
|
))}
|
||||||
|
{staticConfig && staticConfig.maxLevel && (
|
||||||
|
<ReferenceLine yAxisId="left" y={staticConfig.maxLevel} stroke="var(--color-red)" strokeDasharray="3 3" label={{ position: 'insideTopLeft', value: language === 'cs' ? `Maximální retenční hladina (${staticConfig.maxLevel.toFixed(2)})` : `Max retention level (${staticConfig.maxLevel.toFixed(2)})`, fill: 'var(--color-red)', fontSize: 12 }} />
|
||||||
|
)}
|
||||||
|
{staticConfig && staticConfig.storageLevel && (
|
||||||
|
<ReferenceLine yAxisId="left" y={staticConfig.storageLevel} stroke="var(--color-green)" strokeDasharray="3 3" label={{ position: 'insideBottomLeft', value: language === 'cs' ? `Hladina zásobního prostoru (${staticConfig.storageLevel.toFixed(2)})` : `Storage space level (${staticConfig.storageLevel.toFixed(2)})`, fill: 'var(--color-green)', fontSize: 12 }} />
|
||||||
|
)}
|
||||||
<Area yAxisId="left" type={curveType} dataKey="level" stroke="var(--color-cyan)" strokeWidth={2} fillOpacity={1} fill="url(#colorLevel)" isAnimationActive={animate} />
|
<Area yAxisId="left" type={curveType} dataKey="level" stroke="var(--color-cyan)" strokeWidth={2} fillOpacity={1} fill="url(#colorLevel)" isAnimationActive={animate} />
|
||||||
<Line yAxisId="right" type={curveType} dataKey="outflow" stroke="var(--color-orange)" strokeWidth={2} dot={false} isAnimationActive={animate} />
|
<Line yAxisId="right" type={curveType} dataKey="outflow" stroke="var(--color-orange)" strokeWidth={2} dot={false} isAnimationActive={animate} />
|
||||||
<Line yAxisId="right" type={curveType} dataKey="inflow" stroke="#8b5cf6" strokeWidth={2} dot={false} isAnimationActive={animate} />
|
<Line yAxisId="right" type={curveType} dataKey="inflow" stroke="#8b5cf6" strokeWidth={2} dot={false} isAnimationActive={animate} />
|
||||||
@@ -329,6 +388,11 @@ const LakeDetail = ({ language, lakeId }: Props) => {
|
|||||||
<span style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}><div style={{ width: '12px', height: '12px', backgroundColor: 'var(--color-cyan)', opacity: 0.6 }}></div> {language === 'cs' ? 'Srážky' : 'Precipitation'} [mm]</span>
|
<span style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}><div style={{ width: '12px', height: '12px', backgroundColor: 'var(--color-cyan)', opacity: 0.6 }}></div> {language === 'cs' ? 'Srážky' : 'Precipitation'} [mm]</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Wind Chart placed inside the main card below the weather graph */}
|
||||||
|
{lakeInfo && lakeInfo.lat && lakeInfo.lng && (
|
||||||
|
<WindChart lat={lakeInfo.lat} lng={lakeInfo.lng} language={language} timeRange={timeRange} windUnit={windUnit} />
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Smoothed Toggle Control */}
|
{/* Smoothed Toggle Control */}
|
||||||
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', gap: '1rem', marginTop: '3rem', marginBottom: '1rem' }}>
|
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', gap: '1rem', marginTop: '3rem', marginBottom: '1rem' }}>
|
||||||
<span style={{ color: 'var(--text-muted)', fontSize: '0.9rem' }}>{dict.view}</span>
|
<span style={{ color: 'var(--text-muted)', fontSize: '0.9rem' }}>{dict.view}</span>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { FiX, FiSearch, FiDroplet } from 'react-icons/fi';
|
|||||||
import { type Language, t } from '../translations';
|
import { type Language, t } from '../translations';
|
||||||
import { slugify } from '../utils/slugify';
|
import { slugify } from '../utils/slugify';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import { Helmet } from 'react-helmet-async';
|
||||||
|
|
||||||
interface LakeData {
|
interface LakeData {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -61,6 +62,13 @@ const LakeMap = ({ language }: Props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="map-view-container">
|
<div className="map-view-container">
|
||||||
|
<Helmet>
|
||||||
|
<title>{t[language].seo.mapTitle}</title>
|
||||||
|
<meta name="description" content={t[language].seo.mapDesc} />
|
||||||
|
<meta property="og:title" content={t[language].seo.mapTitle} />
|
||||||
|
<meta property="og:description" content={t[language].seo.mapDesc} />
|
||||||
|
</Helmet>
|
||||||
|
|
||||||
{/* Leaflet Map */}
|
{/* Leaflet Map */}
|
||||||
<MapContainer
|
<MapContainer
|
||||||
center={[49.8, 15.5]}
|
center={[49.8, 15.5]}
|
||||||
@@ -95,18 +103,18 @@ const LakeMap = ({ language }: Props) => {
|
|||||||
<div className="map-overlay-panel">
|
<div className="map-overlay-panel">
|
||||||
<div className="map-overlay-header">
|
<div className="map-overlay-header">
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '0.5rem' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '0.5rem' }}>
|
||||||
<h3 style={{ margin: 0, fontSize: '1.1rem' }}>Seznam Jezer (Lakes List)</h3>
|
<h3 style={{ margin: 0, fontSize: '1.1rem' }}>{language === 'cs' ? 'Seznam jezer a nádrží' : 'Lakes and Reservoirs List'}</h3>
|
||||||
<FiX style={{ cursor: 'pointer', color: 'var(--text-muted)' }} onClick={() => setIsPanelVisible(false)} />
|
<FiX style={{ cursor: 'pointer', color: 'var(--text-muted)' }} onClick={() => setIsPanelVisible(false)} />
|
||||||
</div>
|
</div>
|
||||||
<div style={{ fontSize: '0.85rem', color: 'var(--text-muted)', marginBottom: '1rem' }}>
|
<div style={{ fontSize: '0.85rem', color: 'var(--text-muted)', marginBottom: '1rem' }}>
|
||||||
Nalezeno: {filteredLakes.length} Jezer
|
{language === 'cs' ? `Nalezeno: ${filteredLakes.length} záznamů` : `Found: ${filteredLakes.length} records`}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="search-bar" style={{ width: '100%', padding: '0.5rem', backgroundColor: 'rgba(0,0,0,0.3)', border: '1px solid rgba(255,255,255,0.1)' }}>
|
<div className="search-bar" style={{ width: '100%', padding: '0.5rem', backgroundColor: 'rgba(0,0,0,0.3)', border: '1px solid rgba(255,255,255,0.1)' }}>
|
||||||
<FiSearch />
|
<FiSearch />
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Find a lake..."
|
placeholder={language === 'cs' ? 'Najít jezero...' : 'Find a lake...'}
|
||||||
value={searchTerm}
|
value={searchTerm}
|
||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
style={{ width: '100%', background: 'transparent', border: 'none', color: 'white', outline: 'none' }}
|
style={{ width: '100%', background: 'transparent', border: 'none', color: 'white', outline: 'none' }}
|
||||||
@@ -117,14 +125,14 @@ const LakeMap = ({ language }: Props) => {
|
|||||||
<div className="map-overlay-list">
|
<div className="map-overlay-list">
|
||||||
{filteredLakes.map((lake, index) => (
|
{filteredLakes.map((lake, index) => (
|
||||||
<div key={lake.id} className="map-lake-card" onClick={() => navigate(`/${slugify(lake.name)}`)}>
|
<div key={lake.id} className="map-lake-card" onClick={() => navigate(`/${slugify(lake.name)}`)}>
|
||||||
<div style={{ fontWeight: 'bold', marginBottom: '0.5rem' }}>{index + 1}. Jezero {lake.name}</div>
|
<div style={{ fontWeight: 'bold', marginBottom: '0.5rem' }}>{index + 1}. {lake.name}</div>
|
||||||
<div className="map-lake-stats">
|
<div className="map-lake-stats">
|
||||||
<div>
|
<div>
|
||||||
<span style={{ color: 'var(--text-muted)', display: 'block' }}>Area</span>
|
<span style={{ color: 'var(--text-muted)', display: 'block' }}>{language === 'cs' ? 'Rozloha' : 'Area'}</span>
|
||||||
<span style={{ color: 'var(--text-main)' }}>{(Math.random() * 50 + 10).toFixed(1)} km²</span>
|
<span style={{ color: 'var(--text-main)' }}>{(Math.random() * 50 + 10).toFixed(1)} km²</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span style={{ color: 'var(--text-muted)', display: 'block' }}>Depth</span>
|
<span style={{ color: 'var(--text-muted)', display: 'block' }}>{language === 'cs' ? 'Hloubka' : 'Depth'}</span>
|
||||||
<span style={{ color: 'var(--text-main)' }}>{(Math.random() * 30 + 5).toFixed(1)}m</span>
|
<span style={{ color: 'var(--text-main)' }}>{(Math.random() * 30 + 5).toFixed(1)}m</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -139,7 +147,7 @@ const LakeMap = ({ language }: Props) => {
|
|||||||
style={{ position: 'absolute', top: 10, right: 10, zIndex: 1000, background: 'var(--bg-card)', border: '1px solid var(--border-color)', color: 'white', padding: '0.5rem 1rem', borderRadius: '8px', cursor: 'pointer' }}
|
style={{ position: 'absolute', top: 10, right: 10, zIndex: 1000, background: 'var(--bg-card)', border: '1px solid var(--border-color)', color: 'white', padding: '0.5rem 1rem', borderRadius: '8px', cursor: 'pointer' }}
|
||||||
onClick={() => setIsPanelVisible(true)}
|
onClick={() => setIsPanelVisible(true)}
|
||||||
>
|
>
|
||||||
Show List
|
{language === 'cs' ? 'Zobrazit seznam' : 'Show List'}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
|
import { Helmet } from 'react-helmet-async';
|
||||||
import { FiTrendingUp, FiTrendingDown, FiStar } from 'react-icons/fi';
|
import { FiTrendingUp, FiTrendingDown, FiStar } from 'react-icons/fi';
|
||||||
import { type Language, t } from '../translations';
|
import { type Language, t } from '../translations';
|
||||||
import { AreaChart, Area, ResponsiveContainer, YAxis } from 'recharts';
|
import { AreaChart, Area, ResponsiveContainer, YAxis } from 'recharts';
|
||||||
@@ -45,7 +46,7 @@ const LakeCard = ({ lake, language, isFav, onToggleFav }: { lake: Lake, language
|
|||||||
{/* Star / Favorite button */}
|
{/* Star / Favorite button */}
|
||||||
<button
|
<button
|
||||||
onClick={(e) => { e.stopPropagation(); onToggleFav(lake.id); }}
|
onClick={(e) => { e.stopPropagation(); onToggleFav(lake.id); }}
|
||||||
title={isFav ? 'Odepnout' : 'Připnout jako oblíbené'}
|
title={isFav ? (language === 'cs' ? 'Odepnout' : 'Unpin') : (language === 'cs' ? 'Připnout jako oblíbené' : 'Pin to favorites')}
|
||||||
style={{
|
style={{
|
||||||
position: 'absolute', top: '1rem', right: '1rem',
|
position: 'absolute', top: '1rem', right: '1rem',
|
||||||
background: 'none', border: 'none', cursor: 'pointer',
|
background: 'none', border: 'none', cursor: 'pointer',
|
||||||
@@ -131,7 +132,7 @@ const SmallLakeCard = ({ lake, isFav, onToggleFav }: { lake: Lake, isFav: boolea
|
|||||||
{/* Star button */}
|
{/* Star button */}
|
||||||
<button
|
<button
|
||||||
onClick={(e) => { e.stopPropagation(); onToggleFav(lake.id); }}
|
onClick={(e) => { e.stopPropagation(); onToggleFav(lake.id); }}
|
||||||
title={isFav ? 'Odepnout' : 'Připnout jako oblíbené'}
|
title={isFav ? (language === 'cs' ? 'Odepnout' : 'Unpin') : (language === 'cs' ? 'Připnout jako oblíbené' : 'Pin to favorites')}
|
||||||
style={{
|
style={{
|
||||||
position: 'absolute', top: '0.6rem', right: '0.6rem',
|
position: 'absolute', top: '0.6rem', right: '0.6rem',
|
||||||
background: 'none', border: 'none', cursor: 'pointer',
|
background: 'none', border: 'none', cursor: 'pointer',
|
||||||
@@ -166,7 +167,6 @@ const SmallLakeCard = ({ lake, isFav, onToggleFav }: { lake: Lake, isFav: boolea
|
|||||||
|
|
||||||
const LakesOverview = ({ language }: Props) => {
|
const LakesOverview = ({ language }: Props) => {
|
||||||
const [lakes, setLakes] = useState<Lake[]>([]);
|
const [lakes, setLakes] = useState<Lake[]>([]);
|
||||||
const [sortBy, setSortBy] = useState<'name' | 'level' | 'capacity' | 'inflow'>('name');
|
|
||||||
const { isFavorite, toggleFavorite, favorites } = useFavorites();
|
const { isFavorite, toggleFavorite, favorites } = useFavorites();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -186,41 +186,29 @@ const LakesOverview = ({ language }: Props) => {
|
|||||||
const priorityLakes = lakes.filter(l => l.priority && !isFavorite(l.id));
|
const priorityLakes = lakes.filter(l => l.priority && !isFavorite(l.id));
|
||||||
const otherLakes = lakes.filter(l => !l.priority && !isFavorite(l.id));
|
const otherLakes = lakes.filter(l => !l.priority && !isFavorite(l.id));
|
||||||
|
|
||||||
otherLakes.sort((a, b) => {
|
otherLakes.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
if (sortBy === 'name') return a.name.localeCompare(b.name);
|
|
||||||
if (sortBy === 'level') return b.level - a.level;
|
|
||||||
if (sortBy === 'capacity') return b.capacity - a.capacity;
|
|
||||||
if (sortBy === 'inflow') return b.inflow - a.inflow;
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
const sortButtonStyle = (type: string) => ({
|
|
||||||
background: 'none', border: 'none',
|
|
||||||
color: sortBy === type ? 'var(--text-main)' : 'var(--text-muted)',
|
|
||||||
cursor: 'pointer', fontSize: '0.85rem'
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end' }}>
|
<Helmet>
|
||||||
<div>
|
<title>{t[language].seo.homeTitle}</title>
|
||||||
<h1 style={{ fontSize: '1.75rem', fontWeight: 'bold', margin: '0 0 0.5rem 0' }}>Overview: Lakes ({lakes.length})</h1>
|
<meta name="description" content={t[language].seo.homeDesc} />
|
||||||
<p style={{ margin: 0, color: 'var(--text-muted)', fontSize: '0.9rem' }}>Monitoring {lakes.length} reservoirs across the Czech Republic</p>
|
<meta property="og:title" content={t[language].seo.homeTitle} />
|
||||||
</div>
|
<meta property="og:description" content={t[language].seo.homeDesc} />
|
||||||
<div style={{ display: 'flex', gap: '0.5rem', color: 'var(--text-muted)', fontSize: '0.85rem' }}>
|
</Helmet>
|
||||||
<span>Sort by:</span>
|
|
||||||
<button style={sortButtonStyle('name')} onClick={() => setSortBy('name')}>Name (A-Z)</button> |
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>
|
||||||
<button style={sortButtonStyle('level')} onClick={() => setSortBy('level')}>Level</button> |
|
<h1 style={{ fontSize: '1.75rem', fontWeight: 'bold', margin: '0', color: 'var(--text-main)' }}>{t[language].sidebar.lakes} ({lakes.length})</h1>
|
||||||
<button style={sortButtonStyle('capacity')} onClick={() => setSortBy('capacity')}>Capacity</button> |
|
<p style={{ margin: 0, color: 'var(--text-muted)', fontSize: '0.95rem', lineHeight: '1.5' }}>
|
||||||
<button style={sortButtonStyle('inflow')} onClick={() => setSortBy('inflow')}>Flow In</button>
|
{t[language].seo.homeDesc}
|
||||||
</div>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Favorites section */}
|
{/* Favorites section */}
|
||||||
{favoriteLakes.length > 0 && (
|
{favoriteLakes.length > 0 && (
|
||||||
<section>
|
<section>
|
||||||
<h2 style={{ fontSize: '1.1rem', fontWeight: 'bold', marginBottom: '1rem', display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
<h2 style={{ fontSize: '1.1rem', fontWeight: 'bold', marginBottom: '1rem', display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
||||||
<FiStar size={16} fill="#f59e0b" color="#f59e0b" /> Oblíbená ({favoriteLakes.length})
|
<FiStar size={16} fill="#f59e0b" color="#f59e0b" /> {language === 'cs' ? 'Oblíbená' : 'Favorites'} ({favoriteLakes.length})
|
||||||
</h2>
|
</h2>
|
||||||
<div style={{
|
<div style={{
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { FiX, FiMoon, FiSun, FiGlobe, FiCoffee } from 'react-icons/fi';
|
import { FiX, FiMoon, FiSun, FiGlobe, FiCoffee, FiWind } from 'react-icons/fi';
|
||||||
import { type Language, t } from '../translations';
|
import { type Language, t } from '../translations';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -6,10 +6,12 @@ interface Props {
|
|||||||
setLanguage: (lang: Language) => void;
|
setLanguage: (lang: Language) => void;
|
||||||
theme: 'dark' | 'light';
|
theme: 'dark' | 'light';
|
||||||
setTheme: (theme: 'dark' | 'light') => void;
|
setTheme: (theme: 'dark' | 'light') => void;
|
||||||
|
windUnit: 'kmh' | 'ms';
|
||||||
|
setWindUnit: (unit: 'kmh' | 'ms') => void;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SettingsModal = ({ language, setLanguage, theme, setTheme, onClose }: Props) => {
|
const SettingsModal = ({ language, setLanguage, theme, setTheme, windUnit, setWindUnit, onClose }: Props) => {
|
||||||
const dict = t[language].settings;
|
const dict = t[language].settings;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -96,7 +98,7 @@ const SettingsModal = ({ language, setLanguage, theme, setTheme, onClose }: Prop
|
|||||||
cursor: 'pointer', transition: 'all 0.2s'
|
cursor: 'pointer', transition: 'all 0.2s'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FiGlobe /> {dict.english}
|
<span style={{ fontSize: '1.2rem', lineHeight: 1 }}>🇬🇧</span> {dict.english}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => setLanguage('cs')}
|
onClick={() => setLanguage('cs')}
|
||||||
@@ -109,7 +111,42 @@ const SettingsModal = ({ language, setLanguage, theme, setTheme, onClose }: Prop
|
|||||||
cursor: 'pointer', transition: 'all 0.2s'
|
cursor: 'pointer', transition: 'all 0.2s'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FiGlobe /> {dict.czech}
|
<span style={{ fontSize: '1.2rem', lineHeight: 1 }}>🇨🇿</span> {dict.czech}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Wind Units Setting */}
|
||||||
|
<div style={{ marginBottom: '2rem' }}>
|
||||||
|
<label style={{ display: 'block', marginBottom: '0.75rem', color: 'var(--text-muted)', fontSize: '0.85rem', textTransform: 'uppercase', letterSpacing: '1px' }}>
|
||||||
|
{dict.windUnits}
|
||||||
|
</label>
|
||||||
|
<div style={{ display: 'flex', gap: '1rem' }}>
|
||||||
|
<button
|
||||||
|
onClick={() => setWindUnit('kmh')}
|
||||||
|
style={{
|
||||||
|
flex: 1, padding: '0.75rem', borderRadius: '0.5rem',
|
||||||
|
display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '0.5rem',
|
||||||
|
border: windUnit === 'kmh' ? '1px solid var(--color-cyan)' : '1px solid var(--border-color)',
|
||||||
|
backgroundColor: windUnit === 'kmh' ? 'rgba(6, 182, 212, 0.1)' : 'transparent',
|
||||||
|
color: windUnit === 'kmh' ? 'var(--color-cyan)' : 'var(--text-main)',
|
||||||
|
cursor: 'pointer', transition: 'all 0.2s'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FiWind /> {dict.windUnitKmh}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setWindUnit('ms')}
|
||||||
|
style={{
|
||||||
|
flex: 1, padding: '0.75rem', borderRadius: '0.5rem',
|
||||||
|
display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '0.5rem',
|
||||||
|
border: windUnit === 'ms' ? '1px solid var(--color-cyan)' : '1px solid var(--border-color)',
|
||||||
|
backgroundColor: windUnit === 'ms' ? 'rgba(6, 182, 212, 0.1)' : 'transparent',
|
||||||
|
color: windUnit === 'ms' ? 'var(--color-cyan)' : 'var(--text-main)',
|
||||||
|
cursor: 'pointer', transition: 'all 0.2s'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FiWind /> {dict.windUnitMs}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+24
-19
@@ -53,26 +53,31 @@ const Sidebar = ({ language, onOpenSettings, isMobileMenuOpen, onCloseMobileMenu
|
|||||||
<div className="nav-links">
|
<div className="nav-links">
|
||||||
{/* Favourites */}
|
{/* Favourites */}
|
||||||
<div className={`nav-item ${isFavoritesPage ? 'active' : ''}`} onClick={() => handleNavigate('/favorites')} style={{ position: 'relative' }}>
|
<div className={`nav-item ${isFavoritesPage ? 'active' : ''}`} onClick={() => handleNavigate('/favorites')} style={{ position: 'relative' }}>
|
||||||
<FiStar fill={favorites.length > 0 ? '#f59e0b' : 'none'} color={favorites.length > 0 ? '#f59e0b' : 'currentColor'} />
|
<div style={{ position: 'relative', display: 'flex' }}>
|
||||||
|
<FiStar fill={favorites.length > 0 ? '#f59e0b' : 'none'} color={favorites.length > 0 ? '#f59e0b' : 'currentColor'} />
|
||||||
|
{favorites.length > 0 && (
|
||||||
|
<span style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: '-8px',
|
||||||
|
right: '-12px',
|
||||||
|
backgroundColor: '#f59e0b',
|
||||||
|
color: '#000',
|
||||||
|
borderRadius: '999px',
|
||||||
|
fontSize: '0.65rem',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
minWidth: '16px',
|
||||||
|
height: '16px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
padding: '0 4px',
|
||||||
|
border: '2px solid var(--bg-card)'
|
||||||
|
}}>
|
||||||
|
{favorites.length}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<span className="sidebar-text">{dict.favorites}</span>
|
<span className="sidebar-text">{dict.favorites}</span>
|
||||||
{favorites.length > 0 && (
|
|
||||||
<span style={{
|
|
||||||
marginLeft: 'auto',
|
|
||||||
backgroundColor: '#f59e0b',
|
|
||||||
color: '#000',
|
|
||||||
borderRadius: '999px',
|
|
||||||
fontSize: '0.7rem',
|
|
||||||
fontWeight: 'bold',
|
|
||||||
minWidth: '18px',
|
|
||||||
height: '18px',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
padding: '0 5px',
|
|
||||||
}}>
|
|
||||||
{favorites.length}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Lakes & Reservoirs */}
|
{/* Lakes & Reservoirs */}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ interface WeatherProps {
|
|||||||
lng: number;
|
lng: number;
|
||||||
language: 'cs' | 'en';
|
language: 'cs' | 'en';
|
||||||
sensorTemp?: number;
|
sensorTemp?: number;
|
||||||
|
windUnit?: 'kmh' | 'ms';
|
||||||
}
|
}
|
||||||
|
|
||||||
interface WeatherData {
|
interface WeatherData {
|
||||||
@@ -31,7 +32,7 @@ const formatTime = (isoString: string) => {
|
|||||||
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
||||||
};
|
};
|
||||||
|
|
||||||
export const WeatherWidget = ({ lat, lng, language, sensorTemp }: WeatherProps) => {
|
export const WeatherWidget = ({ lat, lng, language, sensorTemp, windUnit = 'kmh' }: WeatherProps) => {
|
||||||
const [data, setData] = useState<WeatherData | null>(null);
|
const [data, setData] = useState<WeatherData | null>(null);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState(false);
|
const [error, setError] = useState(false);
|
||||||
@@ -46,7 +47,7 @@ export const WeatherWidget = ({ lat, lng, language, sensorTemp }: WeatherProps)
|
|||||||
const fetchWeather = async () => {
|
const fetchWeather = async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const res = await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lng}¤t=temperature_2m,wind_speed_10m,wind_direction_10m,wind_gusts_10m&daily=sunrise,sunset&timezone=auto&wind_speed_unit=ms`);
|
const res = await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lng}¤t=temperature_2m,wind_speed_10m,wind_direction_10m,wind_gusts_10m&daily=sunrise,sunset&timezone=auto&wind_speed_unit=${windUnit}`);
|
||||||
if (!res.ok) throw new Error('Failed to fetch weather');
|
if (!res.ok) throw new Error('Failed to fetch weather');
|
||||||
|
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
@@ -98,7 +99,7 @@ export const WeatherWidget = ({ lat, lng, language, sensorTemp }: WeatherProps)
|
|||||||
<div className="kpi-card" style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
|
<div className="kpi-card" style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
|
||||||
<h3 style={{ fontSize: '1rem', color: 'var(--text-muted)', margin: '0 0 1rem 0' }}>{dict.title}</h3>
|
<h3 style={{ fontSize: '1rem', color: 'var(--text-muted)', margin: '0 0 1rem 0' }}>{dict.title}</h3>
|
||||||
|
|
||||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1.5rem' }}>
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0.5rem', alignItems: 'center' }}>
|
||||||
|
|
||||||
{/* Left Column: Wind */}
|
{/* Left Column: Wind */}
|
||||||
<div style={{ display: 'flex', alignItems: 'flex-start', gap: '1rem' }}>
|
<div style={{ display: 'flex', alignItems: 'flex-start', gap: '1rem' }}>
|
||||||
@@ -113,16 +114,16 @@ export const WeatherWidget = ({ lat, lng, language, sensorTemp }: WeatherProps)
|
|||||||
|
|
||||||
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
<div style={{ fontSize: '1.5rem', fontWeight: 'bold', lineHeight: 1.1, color: 'var(--text-main)' }}>
|
<div style={{ fontSize: '1.5rem', fontWeight: 'bold', lineHeight: 1.1, color: 'var(--text-main)' }}>
|
||||||
{data.windSpeed.toFixed(1)} <span style={{ fontSize: '0.8rem', color: 'var(--text-muted)', fontWeight: 'normal' }}>m/s</span>
|
{data.windSpeed.toFixed(1)} <span style={{ fontSize: '0.8rem', color: 'var(--text-muted)', fontWeight: 'normal' }}>{windUnit === 'kmh' ? 'km/h' : 'm/s'}</span>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ fontSize: '0.8rem', color: 'var(--text-muted)', marginTop: '4px' }}>
|
<div style={{ fontSize: '0.8rem', color: 'var(--text-muted)', marginTop: '4px' }}>
|
||||||
{getCompassDirection(data.windDir, language)} • {dict.gusts}: <span style={{ color: data.windGusts > 10 ? 'var(--color-red)' : 'var(--text-main)' }}>{data.windGusts.toFixed(1)} m/s</span>
|
{getCompassDirection(data.windDir, language)} • {dict.gusts}: <span style={{ color: data.windGusts > (windUnit === 'kmh' ? 50 : 13.8) ? 'var(--color-red)' : 'var(--text-main)' }}>{data.windGusts.toFixed(1)} {windUnit === 'kmh' ? 'km/h' : 'm/s'}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Right Column: Other Info */}
|
{/* Right Column: Other Info */}
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem', borderLeft: '1px solid var(--border-color)', paddingLeft: '1.5rem' }}>
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.4rem', borderLeft: '1px solid var(--border-color)', paddingLeft: '1rem' }}>
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', fontSize: '0.9rem' }} title={sensorTemp !== undefined ? (language === 'cs' ? 'Měřeno přímo senzorem na hrázi' : 'Measured by sensor at the dam') : 'OpenMeteo API'}>
|
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', fontSize: '0.9rem' }} title={sensorTemp !== undefined ? (language === 'cs' ? 'Měřeno přímo senzorem na hrázi' : 'Measured by sensor at the dam') : 'OpenMeteo API'}>
|
||||||
<FiThermometer color="var(--color-orange)" />
|
<FiThermometer color="var(--color-orange)" />
|
||||||
<span style={{ fontWeight: 'bold' }}>{sensorTemp !== undefined ? sensorTemp.toFixed(1) : data.temp.toFixed(1)} °C</span>
|
<span style={{ fontWeight: 'bold' }}>{sensorTemp !== undefined ? sensorTemp.toFixed(1) : data.temp.toFixed(1)} °C</span>
|
||||||
|
|||||||
@@ -0,0 +1,273 @@
|
|||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Line, ComposedChart } from 'recharts';
|
||||||
|
import { FiWind } from 'react-icons/fi';
|
||||||
|
import { type Language } from '../translations';
|
||||||
|
|
||||||
|
interface WindChartProps {
|
||||||
|
lat: number;
|
||||||
|
lng: number;
|
||||||
|
language: Language;
|
||||||
|
timeRange?: '24h' | '7d' | '30d' | '1y' | 'all';
|
||||||
|
windUnit?: 'kmh' | 'ms';
|
||||||
|
}
|
||||||
|
|
||||||
|
interface WindDataPoint {
|
||||||
|
time: string;
|
||||||
|
speed: number;
|
||||||
|
gusts: number;
|
||||||
|
dir: number;
|
||||||
|
dirStr: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCompassDirection = (degrees: number, language: 'cs' | 'en') => {
|
||||||
|
const directionsEn = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'];
|
||||||
|
const directionsCs = ['S', 'SV', 'V', 'JV', 'J', 'JZ', 'Z', 'SZ'];
|
||||||
|
const directions = language === 'cs' ? directionsCs : directionsEn;
|
||||||
|
const index = Math.round(((degrees %= 360) < 0 ? degrees + 360 : degrees) / 45) % 8;
|
||||||
|
return directions[index];
|
||||||
|
};
|
||||||
|
|
||||||
|
const CustomWindTooltip = ({ active, payload, label, language, windUnit = 'kmh' }: any) => {
|
||||||
|
if (active && payload && payload.length) {
|
||||||
|
const data = payload[0].payload;
|
||||||
|
const date = new Date(label);
|
||||||
|
const dateStr = date.toLocaleDateString(language === 'cs' ? 'cs-CZ' : 'en-GB', { day: '2-digit', month: '2-digit', year: 'numeric' });
|
||||||
|
const timeStr = date.toLocaleTimeString(language === 'cs' ? 'cs-CZ' : 'en-GB', { hour: '2-digit', minute: '2-digit' });
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ backgroundColor: 'rgba(30, 41, 59, 0.95)', border: '1px solid var(--border-color)', borderRadius: '8px', padding: '12px', boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.5)', color: 'var(--text-main)', fontSize: '0.9rem', zIndex: 100 }}>
|
||||||
|
<div style={{ fontWeight: 'bold', marginBottom: '8px', borderBottom: '1px solid rgba(255,255,255,0.1)', paddingBottom: '4px' }}>
|
||||||
|
{dateStr} {timeStr}
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
|
||||||
|
<span style={{ color: 'var(--color-cyan)', fontSize: '1.2rem' }}>●</span>
|
||||||
|
<span>{language === 'cs' ? 'Rychlost větru' : 'Wind Speed'}: <strong>{data.speed} {windUnit === 'kmh' ? 'km/h' : 'm/s'}</strong></span>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
|
||||||
|
<span style={{ color: 'var(--color-purple)', fontSize: '1.2rem' }}>●</span>
|
||||||
|
<span>{language === 'cs' ? 'Nárazy větru' : 'Wind Gusts'}: <strong>{data.gusts} {windUnit === 'kmh' ? 'km/h' : 'm/s'}</strong></span>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', gap: '6px', marginTop: '4px', color: 'var(--text-muted)' }}>
|
||||||
|
<FiWind />
|
||||||
|
<span>{language === 'cs' ? 'Směr' : 'Direction'}: <strong>{data.dirStr} ({data.dir}°)</strong></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const CustomWindDot = (props: any) => {
|
||||||
|
const { cx, cy, payload } = props;
|
||||||
|
|
||||||
|
if (!cx || !cy || payload.dir === undefined) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<g transform={`translate(${cx},${cy}) rotate(${payload.dir}) scale(1.5)`}>
|
||||||
|
<path
|
||||||
|
d="M0,-6 L-4,4 L0,2 L4,4 Z"
|
||||||
|
fill="var(--color-cyan)"
|
||||||
|
stroke="#1e293b"
|
||||||
|
strokeWidth={1}
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const WindChart = ({ lat, lng, language, timeRange = '7d', windUnit = 'kmh' }: WindChartProps) => {
|
||||||
|
const [data, setData] = useState<WindDataPoint[]>([]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [currentSpeed, setCurrentSpeed] = useState(0);
|
||||||
|
const [maxGust, setMaxGust] = useState(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchWind = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
let url = '';
|
||||||
|
let isDaily = false;
|
||||||
|
|
||||||
|
if (timeRange === '1y' || timeRange === 'all') {
|
||||||
|
isDaily = true;
|
||||||
|
const end = new Date();
|
||||||
|
end.setDate(end.getDate() - 1);
|
||||||
|
const endStr = end.toISOString().split('T')[0];
|
||||||
|
|
||||||
|
const start = new Date();
|
||||||
|
if (timeRange === '1y') {
|
||||||
|
start.setDate(start.getDate() - 365);
|
||||||
|
} else {
|
||||||
|
start.setFullYear(2020);
|
||||||
|
}
|
||||||
|
const startStr = start.toISOString().split('T')[0];
|
||||||
|
|
||||||
|
url = `https://archive-api.open-meteo.com/v1/archive?latitude=${lat}&longitude=${lng}&start_date=${startStr}&end_date=${endStr}&daily=wind_speed_10m_max,wind_gusts_10m_max,wind_direction_10m_dominant&wind_speed_unit=${windUnit}&timezone=auto`;
|
||||||
|
} else {
|
||||||
|
let pastDays = 7;
|
||||||
|
if (timeRange === '24h') pastDays = 1;
|
||||||
|
if (timeRange === '30d') pastDays = 30;
|
||||||
|
url = `https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lng}&hourly=wind_speed_10m,wind_gusts_10m,wind_direction_10m&past_days=${pastDays}&forecast_days=1&wind_speed_unit=${windUnit}&timezone=auto`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await fetch(url);
|
||||||
|
if (!res.ok) throw new Error('Failed to fetch wind data');
|
||||||
|
const json = await res.json();
|
||||||
|
|
||||||
|
const times = isDaily ? json.daily.time : json.hourly.time;
|
||||||
|
const speeds = isDaily ? json.daily.wind_speed_10m_max : json.hourly.wind_speed_10m;
|
||||||
|
const gusts = isDaily ? json.daily.wind_gusts_10m_max : json.hourly.wind_gusts_10m;
|
||||||
|
const dirs = isDaily ? json.daily.wind_direction_10m_dominant : json.hourly.wind_direction_10m;
|
||||||
|
|
||||||
|
const chartData: WindDataPoint[] = [];
|
||||||
|
let maxG = 0;
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
let closestIdx = 0;
|
||||||
|
let minDiff = Infinity;
|
||||||
|
|
||||||
|
for (let i = 0; i < times.length; i++) {
|
||||||
|
const t = new Date(times[i]);
|
||||||
|
const diff = Math.abs(t.getTime() - now.getTime());
|
||||||
|
if (diff < minDiff) {
|
||||||
|
minDiff = diff;
|
||||||
|
closestIdx = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t.getTime() <= now.getTime() || isDaily) {
|
||||||
|
if (gusts[i] > maxG) maxG = gusts[i];
|
||||||
|
chartData.push({
|
||||||
|
time: times[i],
|
||||||
|
speed: speeds[i] || 0,
|
||||||
|
gusts: gusts[i] || 0,
|
||||||
|
dir: dirs[i] || 0,
|
||||||
|
dirStr: getCompassDirection(dirs[i] || 0, language)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let downsampleFactor = 1;
|
||||||
|
if (timeRange === '7d') downsampleFactor = 3;
|
||||||
|
if (timeRange === '30d') downsampleFactor = 12;
|
||||||
|
if (timeRange === '1y') downsampleFactor = 3;
|
||||||
|
if (timeRange === 'all') downsampleFactor = 14;
|
||||||
|
|
||||||
|
const downsampled = chartData.filter((_, i) => i % downsampleFactor === 0 || i === chartData.length - 1);
|
||||||
|
|
||||||
|
setData(downsampled);
|
||||||
|
setMaxGust(maxG);
|
||||||
|
setCurrentSpeed(speeds[closestIdx] || speeds[speeds.length - 1] || 0);
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (lat && lng) {
|
||||||
|
fetchWind();
|
||||||
|
}
|
||||||
|
}, [lat, lng, language, timeRange]);
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return (
|
||||||
|
<div style={{ marginTop: '2rem', display: 'flex', justifyContent: 'center', alignItems: 'center', minHeight: '200px', color: 'var(--text-muted)' }}>
|
||||||
|
{language === 'cs' ? 'Načítám data o větru...' : 'Loading wind data...'}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.length === 0) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ marginTop: '3rem', paddingTop: '1rem', display: 'flex', flexDirection: 'column', gap: '1rem' }}>
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', flexWrap: 'wrap', gap: '1rem' }}>
|
||||||
|
<h3 style={{ margin: 0, fontSize: '1.1rem', color: 'var(--text-main)', display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
||||||
|
<FiWind style={{ color: 'var(--color-cyan)' }} />
|
||||||
|
{language === 'cs' ? `Aktivita větru (${timeRange === '1y' || timeRange === 'all' ? 'denní maxima' : timeRange})` : `Wind Activity (${timeRange === '1y' || timeRange === 'all' ? 'daily max' : timeRange})`}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div style={{ display: 'flex', gap: '1.5rem' }}>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
|
<span style={{ fontSize: '0.8rem', color: 'var(--text-muted)' }}>{language === 'cs' ? 'Aktuální rychlost' : 'Current Speed'}</span>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'baseline', gap: '0.25rem' }}>
|
||||||
|
<span style={{ fontSize: '1.5rem', fontWeight: 'bold', color: 'var(--text-main)' }}>{currentSpeed.toFixed(1)}</span>
|
||||||
|
<span style={{ fontSize: '0.9rem', color: 'var(--color-cyan)' }}>{windUnit === 'kmh' ? 'km/h' : 'm/s'}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
|
<span style={{ fontSize: '0.8rem', color: 'var(--text-muted)' }}>{language === 'cs' ? 'Max. nárazy' : 'Peak Gusts'}</span>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'baseline', gap: '0.25rem' }}>
|
||||||
|
<span style={{ fontSize: '1.5rem', fontWeight: 'bold', color: 'var(--text-main)' }}>{maxGust.toFixed(1)}</span>
|
||||||
|
<span style={{ fontSize: '0.9rem', color: 'var(--color-purple)' }}>{windUnit === 'kmh' ? 'km/h' : 'm/s'}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ flex: 1, minHeight: '280px', width: '100%', marginTop: '0.5rem' }}>
|
||||||
|
<ResponsiveContainer width="100%" height="100%">
|
||||||
|
<ComposedChart data={data} margin={{ top: 20, right: 0, left: -20, bottom: 0 }}>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="colorWind" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="5%" stopColor="var(--color-cyan)" stopOpacity={0.4}/>
|
||||||
|
<stop offset="95%" stopColor="var(--color-cyan)" stopOpacity={0}/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<XAxis
|
||||||
|
dataKey="time"
|
||||||
|
stroke="var(--text-muted)"
|
||||||
|
tick={{fill: 'var(--text-muted)', fontSize: 11}}
|
||||||
|
minTickGap={60}
|
||||||
|
tickFormatter={(v) => {
|
||||||
|
const d = new Date(v);
|
||||||
|
return `${d.getDate()}.${d.getMonth()+1}.`;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<YAxis
|
||||||
|
stroke="var(--text-muted)"
|
||||||
|
tick={{fill: 'var(--text-muted)', fontSize: 11}}
|
||||||
|
/>
|
||||||
|
<CartesianGrid strokeDasharray="3 3" stroke="rgba(255,255,255,0.05)" vertical={false} />
|
||||||
|
<Tooltip content={<CustomWindTooltip language={language} windUnit={windUnit} />} />
|
||||||
|
|
||||||
|
<Area
|
||||||
|
type="monotone"
|
||||||
|
dataKey="speed"
|
||||||
|
stroke="var(--color-cyan)"
|
||||||
|
strokeWidth={2}
|
||||||
|
fillOpacity={1}
|
||||||
|
fill="url(#colorWind)"
|
||||||
|
isAnimationActive={true}
|
||||||
|
dot={<CustomWindDot />}
|
||||||
|
activeDot={{ r: 6, fill: 'var(--color-cyan)', stroke: '#1e293b', strokeWidth: 2 }}
|
||||||
|
/>
|
||||||
|
<Line
|
||||||
|
type="monotone"
|
||||||
|
dataKey="gusts"
|
||||||
|
stroke="var(--color-purple)"
|
||||||
|
strokeWidth={2}
|
||||||
|
strokeDasharray="5 5"
|
||||||
|
dot={false}
|
||||||
|
isAnimationActive={true}
|
||||||
|
/>
|
||||||
|
</ComposedChart>
|
||||||
|
</ResponsiveContainer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'center', gap: '1.5rem', fontSize: '0.85rem', color: 'var(--text-muted)', marginTop: '0.5rem' }}>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
||||||
|
<span style={{ display: 'inline-block', width: '12px', height: '3px', backgroundColor: 'var(--color-cyan)' }}></span>
|
||||||
|
<span>{language === 'cs' ? 'Rychlost větru' : 'Wind Speed'}</span>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
||||||
|
<span style={{ display: 'inline-block', width: '12px', height: '3px', borderTop: '2px dashed var(--color-purple)' }}></span>
|
||||||
|
<span>{language === 'cs' ? 'Nárazy větru' : 'Wind Gusts'}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
+8
-1
@@ -10,10 +10,11 @@
|
|||||||
--color-green: #22c55e; /* Přítok / Positive trend */
|
--color-green: #22c55e; /* Přítok / Positive trend */
|
||||||
--color-red: #ef4444; /* Odtok / Negative trend */
|
--color-red: #ef4444; /* Odtok / Negative trend */
|
||||||
--color-orange: #f97316; /* Odtok line chart color */
|
--color-orange: #f97316; /* Odtok line chart color */
|
||||||
|
--color-purple: #a855f7; /* Wind gusts line color */
|
||||||
|
|
||||||
.kpi-grid-container {
|
.kpi-grid-container {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(4, 1fr);
|
||||||
gap: 1.5rem;
|
gap: 1.5rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@@ -161,6 +162,12 @@
|
|||||||
border-top: 8px solid white;
|
border-top: 8px solid white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
.kpi-grid-container {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.map-overlay-panel {
|
.map-overlay-panel {
|
||||||
top: auto;
|
top: auto;
|
||||||
|
|||||||
+8
-5
@@ -2,15 +2,18 @@ import { StrictMode } from 'react'
|
|||||||
import { createRoot } from 'react-dom/client'
|
import { createRoot } from 'react-dom/client'
|
||||||
import { BrowserRouter } from 'react-router-dom'
|
import { BrowserRouter } from 'react-router-dom'
|
||||||
import { FavoritesProvider } from './hooks/useFavorites'
|
import { FavoritesProvider } from './hooks/useFavorites'
|
||||||
|
import { HelmetProvider } from 'react-helmet-async'
|
||||||
import './index.css'
|
import './index.css'
|
||||||
import App from './App.tsx'
|
import App from './App.tsx'
|
||||||
|
|
||||||
createRoot(document.getElementById('root')!).render(
|
createRoot(document.getElementById('root')!).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<BrowserRouter>
|
<HelmetProvider>
|
||||||
<FavoritesProvider>
|
<BrowserRouter>
|
||||||
<App />
|
<FavoritesProvider>
|
||||||
</FavoritesProvider>
|
<App />
|
||||||
</BrowserRouter>
|
</FavoritesProvider>
|
||||||
|
</BrowserRouter>
|
||||||
|
</HelmetProvider>
|
||||||
</StrictMode>,
|
</StrictMode>,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,6 +12,16 @@ export const t = {
|
|||||||
search: 'Search river or reservoir (e.g. Lipno)...',
|
search: 'Search river or reservoir (e.g. Lipno)...',
|
||||||
updated: 'Last updated:'
|
updated: 'Last updated:'
|
||||||
},
|
},
|
||||||
|
seo: {
|
||||||
|
homeTitle: 'Hladinátor - Water levels and flow rates of reservoirs',
|
||||||
|
homeDesc: 'Track current water levels, flow rates, inflow, and weather development on major Czech dams and reservoirs in real time. Data sourced from official river basin authorities.',
|
||||||
|
lakeTitle: '{name} - Water level and flow | Hladinátor',
|
||||||
|
lakeDesc: 'Current water level and statistics for the {name} reservoir. Track water level, flow rate, wind strength, and storage capacity in real time.',
|
||||||
|
favoritesTitle: 'Favorites | Hladinátor',
|
||||||
|
favoritesDesc: 'Your pinned lakes and reservoirs. Track water level, flow rate, and weather development on major Czech dams and reservoirs.',
|
||||||
|
mapTitle: 'Map | Hladinátor',
|
||||||
|
mapDesc: 'Interactive map of all monitored lakes and reservoirs in the Czech Republic.'
|
||||||
|
},
|
||||||
kpi: {
|
kpi: {
|
||||||
level: 'WATER LEVEL',
|
level: 'WATER LEVEL',
|
||||||
flow: 'FLOW RATE',
|
flow: 'FLOW RATE',
|
||||||
@@ -46,6 +56,9 @@ export const t = {
|
|||||||
language: 'Language',
|
language: 'Language',
|
||||||
english: 'English',
|
english: 'English',
|
||||||
czech: 'Čeština',
|
czech: 'Čeština',
|
||||||
|
windUnits: 'Wind units',
|
||||||
|
windUnitKmh: 'km/h',
|
||||||
|
windUnitMs: 'm/s',
|
||||||
contact: 'Contact',
|
contact: 'Contact',
|
||||||
contactPlaceholder: 'Your email address',
|
contactPlaceholder: 'Your email address',
|
||||||
buyCoffee: 'Buy Me a Coffee'
|
buyCoffee: 'Buy Me a Coffee'
|
||||||
@@ -62,6 +75,16 @@ export const t = {
|
|||||||
search: 'Hledat tok nebo nádrž (např. Lipno)...',
|
search: 'Hledat tok nebo nádrž (např. Lipno)...',
|
||||||
updated: 'Aktualizováno:'
|
updated: 'Aktualizováno:'
|
||||||
},
|
},
|
||||||
|
seo: {
|
||||||
|
homeTitle: 'Hladinátor - Aktuální stav přehrad a nádrží',
|
||||||
|
homeDesc: 'Sledujte aktuální vodní stav, průtok, přítok a vývoj počasí na nejvýznamnějších českých přehradách v reálném čase. Oficiální data z povodí.',
|
||||||
|
lakeTitle: '{name} - Stav hladiny a průtok | Hladinátor',
|
||||||
|
lakeDesc: 'Aktuální vodní stav a statistiky pro vodní dílo {name}. Sledujte vývoj hladiny, sílu větru a kapacitu zásobního prostoru v reálném čase.',
|
||||||
|
favoritesTitle: 'Oblíbené | Hladinátor',
|
||||||
|
favoritesDesc: 'Vaše připnuté přehrady a nádrže. Sledujte aktuální vodní stav, průtok a vývoj počasí na vybraných českých přehradách.',
|
||||||
|
mapTitle: 'Mapa | Hladinátor',
|
||||||
|
mapDesc: 'Interaktivní mapa všech sledovaných přehrad a nádrží v České republice.'
|
||||||
|
},
|
||||||
kpi: {
|
kpi: {
|
||||||
level: 'HLADINA',
|
level: 'HLADINA',
|
||||||
flow: 'PRŮTOK',
|
flow: 'PRŮTOK',
|
||||||
@@ -96,6 +119,9 @@ export const t = {
|
|||||||
language: 'Jazyk',
|
language: 'Jazyk',
|
||||||
english: 'English',
|
english: 'English',
|
||||||
czech: 'Čeština',
|
czech: 'Čeština',
|
||||||
|
windUnits: 'Jednotky větru',
|
||||||
|
windUnitKmh: 'km/h',
|
||||||
|
windUnitMs: 'm/s',
|
||||||
contact: 'Kontakt',
|
contact: 'Kontakt',
|
||||||
contactPlaceholder: 'Vaše e-mailová adresa',
|
contactPlaceholder: 'Vaše e-mailová adresa',
|
||||||
buyCoffee: 'Kup mi kávu'
|
buyCoffee: 'Kup mi kávu'
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export interface NavigationLimit {
|
|||||||
|
|
||||||
export const NAVIGATION_LIMITS: Record<string, NavigationLimit[]> = {
|
export const NAVIGATION_LIMITS: Record<string, NavigationLimit[]> = {
|
||||||
// Orlík
|
// Orlík
|
||||||
'VLOR|1': [
|
'VLOR|2': [
|
||||||
{
|
{
|
||||||
level: 342.50,
|
level: 342.50,
|
||||||
labelCs: 'Minimální hladina pro lodní výtah Orlík',
|
labelCs: 'Minimální hladina pro lodní výtah Orlík',
|
||||||
|
|||||||
Reference in New Issue
Block a user