feat: update historical lake sensor data and improve wind chart component rendering

This commit is contained in:
David Fencl
2026-06-08 20:49:01 +02:00
parent 7a7abdd3e5
commit 48b44cd642
57 changed files with 2892 additions and 323 deletions
+45
View File
@@ -2344,5 +2344,50 @@
"volume": 0, "volume": 0,
"temperature": 25.7, "temperature": 25.7,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T17:40:00.000Z",
"level": 97,
"flow": 9,
"inflow": 0,
"volume": 0,
"temperature": 25.4,
"precipitation": 0
},
{
"timestamp": "2026-06-08T17:50:00.000Z",
"level": 97,
"flow": 9.076,
"inflow": 0,
"volume": 0,
"temperature": 25,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 97,
"flow": 9.076,
"inflow": 0,
"volume": 0,
"temperature": 25,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 97,
"flow": 9.076,
"inflow": 0,
"volume": 0,
"temperature": 24.5,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 97,
"flow": 9.076,
"inflow": 0,
"volume": 0,
"temperature": 23.9,
"precipitation": 0
} }
] ]
+45
View File
@@ -2225,5 +2225,50 @@
"volume": 0, "volume": 0,
"temperature": 25.2, "temperature": 25.2,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 91,
"flow": 4.97,
"inflow": 0,
"volume": 0,
"temperature": 24.8,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 91,
"flow": 5.02,
"inflow": 0,
"volume": 0,
"temperature": 24.1,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 91,
"flow": 5.07,
"inflow": 0,
"volume": 0,
"temperature": 23.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 92,
"flow": 5.095,
"temperature": 23.3,
"precipitation": 0,
"inflow": 0,
"volume": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 92,
"flow": 5.095,
"inflow": 0,
"volume": 0,
"temperature": 22.5,
"precipitation": 0
} }
] ]
+45
View File
@@ -2297,5 +2297,50 @@
"volume": 0, "volume": 0,
"temperature": 24.4, "temperature": 24.4,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T17:40:00.000Z",
"level": 151,
"flow": 6.42,
"inflow": 0,
"volume": 0,
"temperature": 24,
"precipitation": 0
},
{
"timestamp": "2026-06-08T17:50:00.000Z",
"level": 150,
"flow": 6.354,
"inflow": 0,
"volume": 0,
"temperature": 23.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 150,
"flow": 6.289,
"inflow": 0,
"volume": 0,
"temperature": 23.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 150,
"flow": 6.226,
"inflow": 0,
"volume": 0,
"temperature": 22.6,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 149,
"flow": 6.163,
"inflow": 0,
"volume": 0,
"temperature": 21.8,
"precipitation": 0
} }
] ]
+27
View File
@@ -8233,5 +8233,32 @@
"volume": 0, "volume": 0,
"temperature": 23.4, "temperature": 23.4,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 463.42,
"flow": 0,
"inflow": 0,
"volume": 0,
"temperature": 22.8,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:15:00.000Z",
"level": 463.42,
"flow": 0,
"inflow": 0,
"volume": 0,
"temperature": 22.8,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 463.42,
"flow": 0,
"inflow": 0,
"volume": 0,
"temperature": 22,
"precipitation": 0
} }
] ]
+45
View File
@@ -8944,5 +8944,50 @@
"volume": 2.44, "volume": 2.44,
"temperature": 21.5, "temperature": 21.5,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 521.28,
"flow": 0.65,
"inflow": 0.6,
"volume": 2.44,
"temperature": 20.2,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 521.28,
"flow": 0.65,
"temperature": 20.2,
"precipitation": 0,
"inflow": 0.6,
"volume": 2.44
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 521.28,
"flow": 0.65,
"inflow": 0.6,
"volume": 2.44,
"temperature": 20.2,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 521.28,
"flow": 0.64,
"inflow": 0.6,
"volume": 2.44,
"temperature": 19.4,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 521.28,
"flow": 0.65,
"inflow": 0.6,
"volume": 2.44,
"temperature": 18.6,
"precipitation": 0
} }
] ]
+46 -1
View File
@@ -8906,7 +8906,52 @@
"flow": 0, "flow": 0,
"inflow": 0, "inflow": 0,
"volume": 0.09, "volume": 0.09,
"temperature": 23.5, "temperature": 23,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 416.72,
"flow": 0,
"temperature": 23,
"precipitation": 0,
"inflow": 0,
"volume": 0.09
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 416.72,
"flow": 0,
"inflow": 0,
"volume": 0.09,
"temperature": 22.4,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 416.72,
"flow": 0,
"inflow": 0,
"volume": 0.09,
"temperature": 22.4,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 416.72,
"flow": 0,
"inflow": 0,
"volume": 0.09,
"temperature": 21.6,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 416.72,
"flow": 0,
"inflow": 0,
"volume": 0.09,
"temperature": 20.8,
"precipitation": 0 "precipitation": 0
} }
] ]
+46 -1
View File
@@ -8879,7 +8879,52 @@
"flow": 0, "flow": 0,
"inflow": 0, "inflow": 0,
"volume": 0.67, "volume": 0.67,
"temperature": 23.4, "temperature": 23,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 448.8,
"flow": 0,
"temperature": 23,
"precipitation": 0,
"inflow": 0,
"volume": 0.67
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 448.8,
"flow": 0,
"inflow": 0,
"volume": 0.67,
"temperature": 22.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 448.8,
"flow": 0,
"inflow": 0,
"volume": 0.67,
"temperature": 22.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 448.8,
"flow": 0,
"inflow": 0,
"volume": 0.67,
"temperature": 21.5,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 448.8,
"flow": 0,
"inflow": 0,
"volume": 0.67,
"temperature": 20.8,
"precipitation": 0 "precipitation": 0
} }
] ]
+37 -1
View File
@@ -8105,7 +8105,43 @@
"flow": 0, "flow": 0,
"inflow": 0, "inflow": 0,
"volume": 0.03, "volume": 0.03,
"temperature": 22.8, "temperature": 22.5,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 580.92,
"flow": 0,
"inflow": 0,
"volume": 0.03,
"temperature": 21,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 580.91,
"flow": 0,
"temperature": 21,
"precipitation": 0,
"inflow": 0,
"volume": 0.03
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 580.9,
"flow": 0,
"temperature": 21,
"precipitation": 0,
"inflow": 0,
"volume": 0.03
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 580.89,
"flow": 0,
"inflow": 0,
"volume": 0.03,
"temperature": 20.1,
"precipitation": 0 "precipitation": 0
} }
] ]
+45
View File
@@ -8953,5 +8953,50 @@
"volume": 1.68, "volume": 1.68,
"temperature": 22.3, "temperature": 22.3,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 447.1,
"flow": 0.22,
"inflow": 0.64,
"volume": 1.68,
"temperature": 21.9,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 447.1,
"flow": 0.23,
"inflow": 0.64,
"volume": 1.68,
"temperature": 21.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 447.1,
"flow": 0.23,
"inflow": 0.64,
"volume": 1.68,
"temperature": 21.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 447.1,
"flow": 0.22,
"inflow": 0.64,
"volume": 1.68,
"temperature": 20.4,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 447.1,
"flow": 0,
"inflow": 0.64,
"volume": 1.68,
"temperature": 19.6,
"precipitation": 0
} }
] ]
+36
View File
@@ -8986,5 +8986,41 @@
"volume": 0.14, "volume": 0.14,
"temperature": 22, "temperature": 22,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 407.64,
"flow": 0.2,
"inflow": 0.4,
"volume": 0.14,
"temperature": 21.5,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 407.64,
"flow": 0.2,
"inflow": 0.4,
"volume": 0.14,
"temperature": 21,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 407.64,
"flow": 0.2,
"inflow": 0.4,
"volume": 0.14,
"temperature": 21,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 407.64,
"flow": 0,
"inflow": 0.4,
"volume": 0.14,
"temperature": 19.6,
"precipitation": 0
} }
] ]
+47 -2
View File
@@ -8930,7 +8930,7 @@
{ {
"timestamp": "2026-06-08T17:40:00.000Z", "timestamp": "2026-06-08T17:40:00.000Z",
"level": 292.89, "level": 292.89,
"flow": 0, "flow": 0.02,
"temperature": 23.5, "temperature": 23.5,
"precipitation": 0, "precipitation": 0,
"inflow": -0.03, "inflow": -0.03,
@@ -8939,10 +8939,55 @@
{ {
"timestamp": "2026-06-08T17:50:00.000Z", "timestamp": "2026-06-08T17:50:00.000Z",
"level": 292.89, "level": 292.89,
"flow": 0.02,
"inflow": -0.03,
"volume": 7.48,
"temperature": 23.1,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 292.89,
"flow": 0.02,
"temperature": 23.1,
"precipitation": 0,
"inflow": -0.03,
"volume": 7.48
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 292.89,
"flow": 0.02,
"inflow": -0.03,
"volume": 7.48,
"temperature": 22.5,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 292.89,
"flow": 0.02,
"inflow": -0.03,
"volume": 7.48,
"temperature": 22.5,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 292.89,
"flow": 0.02,
"inflow": -0.03,
"volume": 7.48,
"temperature": 21.8,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 292.89,
"flow": 0, "flow": 0,
"inflow": -0.03, "inflow": -0.03,
"volume": 7.48, "volume": 7.48,
"temperature": 23.5, "temperature": 21,
"precipitation": 0 "precipitation": 0
} }
] ]
+37 -1
View File
@@ -8231,7 +8231,43 @@
"flow": 0, "flow": 0,
"inflow": 0, "inflow": 0,
"volume": 0, "volume": 0,
"temperature": 21.4, "temperature": 21,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 632.76,
"flow": 0,
"inflow": 0,
"volume": 0,
"temperature": 20,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 632.76,
"flow": 0,
"temperature": 20,
"precipitation": 0,
"inflow": 0,
"volume": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 632.76,
"flow": 0,
"temperature": 20,
"precipitation": 0,
"inflow": 0,
"volume": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 632.76,
"flow": 0,
"inflow": 0,
"volume": 0,
"temperature": 19.5,
"precipitation": 0 "precipitation": 0
} }
] ]
+37 -1
View File
@@ -8231,7 +8231,43 @@
"flow": 0, "flow": 0,
"inflow": 0, "inflow": 0,
"volume": 0, "volume": 0,
"temperature": 21.7, "temperature": 21.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 635.7,
"flow": 0,
"inflow": 0,
"volume": 0,
"temperature": 20.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 635.7,
"flow": 0,
"temperature": 20.3,
"precipitation": 0,
"inflow": 0,
"volume": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 635.7,
"flow": 0,
"temperature": 20.3,
"precipitation": 0,
"inflow": 0,
"volume": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 635.7,
"flow": 0,
"inflow": 0,
"volume": 0,
"temperature": 19.8,
"precipitation": 0 "precipitation": 0
} }
] ]
+46 -1
View File
@@ -8933,7 +8933,52 @@
"flow": 0.57, "flow": 0.57,
"inflow": 0.59, "inflow": 0.59,
"volume": 0.67, "volume": 0.67,
"temperature": 24, "temperature": 23.6,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 345.02,
"flow": 0.57,
"temperature": 23.6,
"precipitation": 0,
"inflow": 0.59,
"volume": 0.67
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 345.02,
"flow": 0.57,
"inflow": 0.59,
"volume": 0.67,
"temperature": 23.2,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 345.02,
"flow": 0.57,
"inflow": 0.59,
"volume": 0.67,
"temperature": 23.2,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 345.02,
"flow": 0.57,
"inflow": 0.59,
"volume": 0.67,
"temperature": 22.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 345.02,
"flow": 0.57,
"inflow": 0.59,
"volume": 0.67,
"temperature": 22.2,
"precipitation": 0 "precipitation": 0
} }
] ]
+46 -1
View File
@@ -8969,7 +8969,52 @@
"flow": 0.01, "flow": 0.01,
"inflow": 0.01, "inflow": 0.01,
"volume": 0.73, "volume": 0.73,
"temperature": 21, "temperature": 20.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 640.65,
"flow": 0.01,
"temperature": 20.7,
"precipitation": 0,
"inflow": 0.01,
"volume": 0.73
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 640.65,
"flow": 0.01,
"inflow": 0.01,
"volume": 0.73,
"temperature": 20.4,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 640.65,
"flow": 0.01,
"inflow": 0.01,
"volume": 0.73,
"temperature": 20.4,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 640.65,
"flow": 0.01,
"inflow": 0.01,
"volume": 0.73,
"temperature": 20.2,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 640.65,
"flow": 0.01,
"inflow": 0.01,
"volume": 0.73,
"temperature": 20,
"precipitation": 0 "precipitation": 0
} }
] ]
+45
View File
@@ -2272,5 +2272,50 @@
"volume": 0, "volume": 0,
"temperature": 23.7, "temperature": 23.7,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 83,
"flow": 2.944,
"inflow": 0,
"volume": 0,
"temperature": 23.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 81,
"flow": 2.602,
"inflow": 0,
"volume": 0,
"temperature": 23,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 81,
"flow": 2.514,
"inflow": 0,
"volume": 0,
"temperature": 23,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 82,
"flow": 2.79,
"inflow": 0,
"volume": 0,
"temperature": 22.6,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 85,
"flow": 3.216,
"inflow": 0,
"volume": 0,
"temperature": 22.1,
"precipitation": 0
} }
] ]
+45
View File
@@ -1986,5 +1986,50 @@
"volume": 0, "volume": 0,
"temperature": 23.8, "temperature": 23.8,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T17:30:00.000Z",
"level": 51,
"flow": 3.92,
"temperature": 23.8,
"precipitation": 0,
"inflow": 0,
"volume": 0
},
{
"timestamp": "2026-06-08T17:40:00.000Z",
"level": 51,
"flow": 3.92,
"inflow": 0,
"volume": 0,
"temperature": 23,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 50,
"flow": 3.7,
"inflow": 0,
"volume": 0,
"temperature": 22.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 50,
"flow": 3.7,
"temperature": 22.3,
"precipitation": 0,
"inflow": 0,
"volume": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 50,
"flow": 3.7,
"inflow": 0,
"volume": 0,
"temperature": 21.6,
"precipitation": 0
} }
] ]
+45
View File
@@ -9277,5 +9277,50 @@
"volume": 26.61, "volume": 26.61,
"temperature": 23.9, "temperature": 23.9,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 467.79,
"flow": 0.7,
"inflow": 1.6,
"volume": 26.61,
"temperature": 23.1,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 467.79,
"flow": 0.7,
"inflow": 1.6,
"volume": 26.61,
"temperature": 23.1,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 467.79,
"flow": 0.7,
"temperature": 23.1,
"precipitation": 0,
"inflow": 1.6,
"volume": 26.61
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 467.79,
"flow": 0.7,
"inflow": 1.6,
"volume": 26.61,
"temperature": 22.5,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 467.79,
"flow": 0,
"inflow": 1.6,
"volume": 26.61,
"temperature": 21.7,
"precipitation": 0
} }
] ]
+36
View File
@@ -9304,5 +9304,41 @@
"volume": 32.11, "volume": 32.11,
"temperature": 24.5, "temperature": 24.5,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 352.78,
"flow": 2.52,
"inflow": 1.42,
"volume": 32.11,
"temperature": 24.2,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 352.78,
"flow": 2.52,
"inflow": 1.42,
"volume": 32.1,
"temperature": 23.8,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 352.78,
"flow": 2.52,
"inflow": 1.42,
"volume": 32.1,
"temperature": 23.8,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 352.78,
"flow": 2.52,
"inflow": 1.42,
"volume": 32.1,
"temperature": 22.7,
"precipitation": 0
} }
] ]
+45
View File
@@ -8944,5 +8944,50 @@
"volume": 2.92, "volume": 2.92,
"temperature": 22.6, "temperature": 22.6,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 530.66,
"flow": 0.49,
"inflow": 0.33,
"volume": 2.92,
"temperature": 22.2,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 530.66,
"flow": 0.49,
"inflow": 0.33,
"volume": 2.92,
"temperature": 21.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 530.65,
"flow": 0.49,
"inflow": 0.33,
"volume": 2.92,
"temperature": 21.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 530.65,
"flow": 0.48,
"inflow": 0.33,
"volume": 2.92,
"temperature": 21,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 530.65,
"flow": 0.48,
"inflow": 0.33,
"volume": 2.92,
"temperature": 20.2,
"precipitation": 0
} }
] ]
+38 -2
View File
@@ -8776,11 +8776,47 @@
}, },
{ {
"timestamp": "2026-06-08T17:50:00.000Z", "timestamp": "2026-06-08T17:50:00.000Z",
"level": 0, "level": 563.66,
"flow": 0.02, "flow": 0.02,
"inflow": 0, "inflow": 0,
"volume": 0.46, "volume": 0.46,
"temperature": 22.1, "temperature": 21.8,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 563.66,
"flow": 0.02,
"temperature": 21.8,
"precipitation": 0,
"inflow": 0,
"volume": 0.46
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 563.66,
"flow": 0.02,
"inflow": 0,
"volume": 0.46,
"temperature": 21.6,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 563.66,
"flow": 0,
"inflow": 0,
"volume": 0.46,
"temperature": 21.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 563.66,
"flow": 0,
"inflow": 0,
"volume": 0.46,
"temperature": 20.9,
"precipitation": 0 "precipitation": 0
} }
] ]
+45
View File
@@ -2279,5 +2279,50 @@
"volume": 0, "volume": 0,
"temperature": 24.6, "temperature": 24.6,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 44,
"flow": 4.89,
"inflow": 0,
"volume": 0,
"temperature": 24.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 44,
"flow": 4.89,
"inflow": 0,
"volume": 0,
"temperature": 23.8,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 46,
"flow": 5.486,
"inflow": 0,
"volume": 0,
"temperature": 23.8,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 46,
"flow": 5.354,
"inflow": 0,
"volume": 0,
"temperature": 23.1,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 44,
"flow": 5.011,
"inflow": 0,
"volume": 0,
"temperature": 22.5,
"precipitation": 0
} }
] ]
+45
View File
@@ -2344,5 +2344,50 @@
"volume": 0, "volume": 0,
"temperature": 22.5, "temperature": 22.5,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T17:40:00.000Z",
"level": 26,
"flow": 3.21,
"inflow": 0,
"volume": 0,
"temperature": 22,
"precipitation": 0
},
{
"timestamp": "2026-06-08T17:50:00.000Z",
"level": 25,
"flow": 2.95,
"inflow": 0,
"volume": 0,
"temperature": 21.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 25,
"flow": 2.95,
"inflow": 0,
"volume": 0,
"temperature": 21.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 25,
"flow": 2.95,
"inflow": 0,
"volume": 0,
"temperature": 20.6,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 26,
"flow": 3.21,
"inflow": 0,
"volume": 0,
"temperature": 19.9,
"precipitation": 0
} }
] ]
+1 -1
View File
@@ -8105,7 +8105,7 @@
"flow": 0, "flow": 0,
"inflow": 0, "inflow": 0,
"volume": 0, "volume": 0,
"temperature": 21.5, "temperature": 19.3,
"precipitation": 0 "precipitation": 0
} }
] ]
+45
View File
@@ -8944,5 +8944,50 @@
"volume": 2.93, "volume": 2.93,
"temperature": 24.8, "temperature": 24.8,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 313.42,
"flow": 1.03,
"inflow": 1.25,
"volume": 2.93,
"temperature": 24.4,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 313.43,
"flow": 1.03,
"inflow": 1.25,
"volume": 2.93,
"temperature": 23.9,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 313.43,
"flow": 1.03,
"inflow": 1.25,
"volume": 2.93,
"temperature": 23.9,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 313.42,
"flow": 1.03,
"inflow": 1.25,
"volume": 2.93,
"temperature": 23.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 0,
"flow": 1.03,
"inflow": 1.25,
"volume": 2.93,
"temperature": 22.7,
"precipitation": 0
} }
] ]
+45
View File
@@ -2297,5 +2297,50 @@
"volume": 0, "volume": 0,
"temperature": 23.4, "temperature": 23.4,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T17:40:00.000Z",
"level": 73,
"flow": 2.726,
"inflow": 0,
"volume": 0,
"temperature": 23,
"precipitation": 0
},
{
"timestamp": "2026-06-08T17:50:00.000Z",
"level": 73,
"flow": 2.712,
"inflow": 0,
"volume": 0,
"temperature": 22.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 73,
"flow": 2.698,
"inflow": 0,
"volume": 0,
"temperature": 22.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 73,
"flow": 2.698,
"inflow": 0,
"volume": 0,
"temperature": 21.5,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 73,
"flow": 2.684,
"inflow": 0,
"volume": 0,
"temperature": 20.7,
"precipitation": 0
} }
] ]
+45
View File
@@ -2254,5 +2254,50 @@
"volume": 0, "volume": 0,
"temperature": 23.3, "temperature": 23.3,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T17:50:00.000Z",
"level": 44,
"flow": 4.17,
"inflow": 0,
"volume": 0,
"temperature": 22.8,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 44,
"flow": 4.17,
"temperature": 22.8,
"precipitation": 0,
"inflow": 0,
"volume": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 44,
"flow": 4.17,
"inflow": 0,
"volume": 0,
"temperature": 22.1,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 44,
"flow": 4.17,
"inflow": 0,
"volume": 0,
"temperature": 21.4,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 44,
"flow": 4.145,
"inflow": 0,
"volume": 0,
"temperature": 20.6,
"precipitation": 0
} }
] ]
+46 -1
View File
@@ -8942,7 +8942,52 @@
"flow": 0.02, "flow": 0.02,
"inflow": 0, "inflow": 0,
"volume": 1.06, "volume": 1.06,
"temperature": 21.2, "temperature": 20.8,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 575.7,
"flow": 0.02,
"temperature": 20.8,
"precipitation": 0,
"inflow": 0,
"volume": 1.06
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 575.7,
"flow": 0.02,
"inflow": 0,
"volume": 1.06,
"temperature": 20.2,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 575.7,
"flow": 0.02,
"inflow": 0,
"volume": 1.06,
"temperature": 20.2,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 575.7,
"flow": 0.02,
"inflow": 0,
"volume": 1.06,
"temperature": 19.5,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 575.7,
"flow": 0.02,
"inflow": 0,
"volume": 1.06,
"temperature": 18.8,
"precipitation": 0 "precipitation": 0
} }
] ]
+45
View File
@@ -2297,5 +2297,50 @@
"volume": 0, "volume": 0,
"temperature": 23.1, "temperature": 23.1,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T17:40:00.000Z",
"level": 25,
"flow": 1.513,
"inflow": 0,
"volume": 0,
"temperature": 22.6,
"precipitation": 0
},
{
"timestamp": "2026-06-08T17:50:00.000Z",
"level": 25,
"flow": 1.502,
"inflow": 0,
"volume": 0,
"temperature": 22,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 25,
"flow": 1.491,
"inflow": 0,
"volume": 0,
"temperature": 22,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 25,
"flow": 1.48,
"inflow": 0,
"volume": 0,
"temperature": 21.1,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 25,
"flow": 1.48,
"inflow": 0,
"volume": 0,
"temperature": 20.3,
"precipitation": 0
} }
] ]
+45
View File
@@ -2297,5 +2297,50 @@
"volume": 0, "volume": 0,
"temperature": 23.7, "temperature": 23.7,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T17:40:00.000Z",
"level": 68,
"flow": 1.456,
"inflow": 0,
"volume": 0,
"temperature": 23.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T17:50:00.000Z",
"level": 68,
"flow": 1.46,
"inflow": 0,
"volume": 0,
"temperature": 22.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 68,
"flow": 1.46,
"inflow": 0,
"volume": 0,
"temperature": 22.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 68,
"flow": 1.46,
"inflow": 0,
"volume": 0,
"temperature": 22,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 68,
"flow": 1.465,
"inflow": 0,
"volume": 0,
"temperature": 21.2,
"precipitation": 0
} }
] ]
+45
View File
@@ -8953,5 +8953,50 @@
"volume": 0.1, "volume": 0.1,
"temperature": 23.3, "temperature": 23.3,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 534.69,
"flow": 0.06,
"inflow": 0.07,
"volume": 0.1,
"temperature": 22.2,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 534.7,
"flow": 0.06,
"inflow": 0.07,
"volume": 0.1,
"temperature": 22.2,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 534.7,
"flow": 0.06,
"temperature": 22.2,
"precipitation": 0,
"inflow": 0.07,
"volume": 0.1
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 534.69,
"flow": 0.06,
"inflow": 0.07,
"volume": 0.1,
"temperature": 21.4,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 0,
"flow": 0.06,
"inflow": 0.07,
"volume": 0.1,
"temperature": 20.6,
"precipitation": 0
} }
] ]
+54
View File
@@ -8917,5 +8917,59 @@
"volume": 0.41, "volume": 0.41,
"temperature": 23.7, "temperature": 23.7,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T17:50:00.000Z",
"level": 260.09,
"flow": 0.06,
"inflow": 0.07,
"volume": 0.41,
"temperature": 23.2,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 260.09,
"flow": 0.06,
"temperature": 23.2,
"precipitation": 0,
"inflow": 0.07,
"volume": 0.41
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 260.09,
"flow": 0.05,
"inflow": 0.07,
"volume": 0.41,
"temperature": 22.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 260.09,
"flow": 0.05,
"inflow": 0.07,
"volume": 0.41,
"temperature": 22.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 260.09,
"flow": 0.05,
"inflow": 0.07,
"volume": 0.41,
"temperature": 22,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 260.09,
"flow": 0.05,
"inflow": 0.07,
"volume": 0.41,
"temperature": 21.4,
"precipitation": 0
} }
] ]
+45
View File
@@ -8935,5 +8935,50 @@
"volume": 0.39, "volume": 0.39,
"temperature": 23.5, "temperature": 23.5,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T17:50:00.000Z",
"level": 668.4,
"flow": 0,
"inflow": 0,
"volume": 0.39,
"temperature": 23.1,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 668.4,
"flow": 0,
"inflow": 0,
"volume": 0.39,
"temperature": 22.5,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 668.4,
"flow": 0,
"inflow": 0,
"volume": 0.39,
"temperature": 22.5,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 668.4,
"flow": 0,
"inflow": 0,
"volume": 0.39,
"temperature": 21.8,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 668.4,
"flow": 0,
"inflow": 0,
"volume": 0.39,
"temperature": 21.1,
"precipitation": 0
} }
] ]
+45
View File
@@ -8656,5 +8656,50 @@
"volume": 0.84, "volume": 0.84,
"temperature": 22.1, "temperature": 22.1,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T17:50:00.000Z",
"level": 385.01,
"flow": 0.02,
"inflow": 0,
"volume": 0.84,
"temperature": 21.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 385.01,
"flow": 0.02,
"inflow": 0,
"volume": 0.84,
"temperature": 21.1,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 385.01,
"flow": 0.02,
"inflow": 0,
"volume": 0.84,
"temperature": 21.1,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 385.01,
"flow": 0.02,
"inflow": 0,
"volume": 0.84,
"temperature": 20.4,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 385.01,
"flow": 0.02,
"inflow": 0,
"volume": 0.84,
"temperature": 19.7,
"precipitation": 0
} }
] ]
+45
View File
@@ -8926,5 +8926,50 @@
"volume": 0.16, "volume": 0.16,
"temperature": 20.2, "temperature": 20.2,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T17:50:00.000Z",
"level": 678.6,
"flow": 0,
"inflow": 0,
"volume": 0.16,
"temperature": 19.8,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 678.6,
"flow": 0,
"inflow": 0,
"volume": 0.16,
"temperature": 19.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 678.6,
"flow": 0,
"inflow": 0,
"volume": 0.16,
"temperature": 19.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 678.6,
"flow": 0,
"inflow": 0,
"volume": 0.16,
"temperature": 18.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 678.6,
"flow": 0,
"inflow": 0,
"volume": 0.16,
"temperature": 18.1,
"precipitation": 0
} }
] ]
+45
View File
@@ -8989,5 +8989,50 @@
"volume": 0.32, "volume": 0.32,
"temperature": 22.7, "temperature": 22.7,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 588.38,
"flow": 0.08,
"inflow": 0,
"volume": 0.32,
"temperature": 21.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 588.39,
"flow": 0.08,
"temperature": 21.7,
"precipitation": 0,
"inflow": 0,
"volume": 0.32
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 588.39,
"flow": 0.08,
"inflow": 0,
"volume": 0.32,
"temperature": 21.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 588.39,
"flow": 0.08,
"inflow": 0,
"volume": 0.32,
"temperature": 20.9,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 0,
"flow": 0.08,
"inflow": 0,
"volume": 0.32,
"temperature": 20.2,
"precipitation": 0
} }
] ]
+45
View File
@@ -8944,5 +8944,50 @@
"volume": 9.28, "volume": 9.28,
"temperature": 22.3, "temperature": 22.3,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 505.63,
"flow": 0.22,
"inflow": 0.05,
"volume": 9.28,
"temperature": 22,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 505.63,
"flow": 0.22,
"inflow": 0.05,
"volume": 9.28,
"temperature": 21.5,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 505.63,
"flow": 0.22,
"inflow": 0.05,
"volume": 9.28,
"temperature": 21.5,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 505.63,
"flow": 0.22,
"inflow": 0.05,
"volume": 9.28,
"temperature": 21,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 505.63,
"flow": 0.22,
"inflow": 0.05,
"volume": 9.28,
"temperature": 20.5,
"precipitation": 0
} }
] ]
+47 -2
View File
@@ -8920,7 +8920,7 @@
}, },
{ {
"timestamp": "2026-06-08T17:40:00.000Z", "timestamp": "2026-06-08T17:40:00.000Z",
"level": 0, "level": 580.52,
"flow": 0.05, "flow": 0.05,
"inflow": 0, "inflow": 0,
"volume": 0.41, "volume": 0.41,
@@ -8929,11 +8929,56 @@
}, },
{ {
"timestamp": "2026-06-08T17:50:00.000Z", "timestamp": "2026-06-08T17:50:00.000Z",
"level": 580.52,
"flow": 0.05,
"inflow": 0,
"volume": 0.41,
"temperature": 20.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 580.52,
"flow": 0.05,
"inflow": 0,
"volume": 0.41,
"temperature": 20.2,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 580.52,
"flow": 0.05,
"temperature": 20.2,
"precipitation": 0,
"inflow": 0,
"volume": 0.41
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 580.52,
"flow": 0.05,
"inflow": 0,
"volume": 0.41,
"temperature": 20.2,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 580.52,
"flow": 0.05,
"inflow": 0,
"volume": 0.41,
"temperature": 19.6,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 0, "level": 0,
"flow": 0.05, "flow": 0.05,
"inflow": 0, "inflow": 0,
"volume": 0.41, "volume": 0.41,
"temperature": 21.1, "temperature": 18.9,
"precipitation": 0 "precipitation": 0
} }
] ]
+45
View File
@@ -8962,5 +8962,50 @@
"volume": 5.16, "volume": 5.16,
"temperature": 22.9, "temperature": 22.9,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 412.8,
"flow": 0.34,
"inflow": 0.34,
"volume": 5.16,
"temperature": 22.4,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 412.8,
"flow": 0.34,
"inflow": 0.34,
"volume": 5.16,
"temperature": 21.8,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 412.8,
"flow": 0.34,
"inflow": 0.34,
"volume": 5.16,
"temperature": 21.8,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 412.8,
"flow": 0.34,
"inflow": 0.34,
"volume": 5.16,
"temperature": 21.1,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 412.8,
"flow": 0.34,
"inflow": 0.34,
"volume": 5.16,
"temperature": 20.3,
"precipitation": 0
} }
] ]
+45
View File
@@ -8962,5 +8962,50 @@
"volume": 15.31, "volume": 15.31,
"temperature": 19.2, "temperature": 19.2,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 520.32,
"flow": 0.72,
"inflow": 0.53,
"volume": 15.31,
"temperature": 18.8,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 520.32,
"flow": 0.72,
"inflow": 0.53,
"volume": 15.31,
"temperature": 18.4,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 520.32,
"flow": 0.72,
"inflow": 0.53,
"volume": 15.31,
"temperature": 18.4,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 520.31,
"flow": 0.72,
"inflow": 0.53,
"volume": 15.31,
"temperature": 18.1,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 520.32,
"flow": 0,
"inflow": 0.53,
"volume": 15.31,
"temperature": 17.8,
"precipitation": 0
} }
] ]
+45
View File
@@ -1986,5 +1986,50 @@
"volume": 0, "volume": 0,
"temperature": 25.6, "temperature": 25.6,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T17:30:00.000Z",
"level": 106,
"flow": 5.97,
"temperature": 25.6,
"precipitation": 0,
"inflow": 0,
"volume": 0
},
{
"timestamp": "2026-06-08T17:40:00.000Z",
"level": 106,
"flow": 5.97,
"inflow": 0,
"volume": 0,
"temperature": 24.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 108,
"flow": 8.33,
"inflow": 0,
"volume": 0,
"temperature": 24.1,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 108,
"flow": 8.33,
"temperature": 24.1,
"precipitation": 0,
"inflow": 0,
"volume": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 105,
"flow": 10.15,
"inflow": 0,
"volume": 0,
"temperature": 23.5,
"precipitation": 0
} }
] ]
+45
View File
@@ -2270,5 +2270,50 @@
"volume": 0, "volume": 0,
"temperature": 25.9, "temperature": 25.9,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 45,
"flow": 49.6,
"inflow": 0,
"volume": 0,
"temperature": 25.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 46,
"flow": 54.44,
"inflow": 0,
"volume": 0,
"temperature": 25.4,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 45,
"flow": 51.71,
"inflow": 0,
"volume": 0,
"temperature": 25.4,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 45,
"flow": 51.98,
"inflow": 0,
"volume": 0,
"temperature": 25,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 46,
"flow": 53.88,
"inflow": 0,
"volume": 0,
"temperature": 24.6,
"precipitation": 0
} }
] ]
+45
View File
@@ -9241,5 +9241,50 @@
"volume": 19.77, "volume": 19.77,
"temperature": 24.1, "temperature": 24.1,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 369.6,
"flow": 15.26,
"inflow": 0,
"volume": 19.74,
"temperature": 23.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 369.6,
"flow": 15.28,
"inflow": 0,
"volume": 19.74,
"temperature": 23.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 369.6,
"flow": 15.28,
"temperature": 23.3,
"precipitation": 0,
"inflow": 0,
"volume": 19.74
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 369.59,
"flow": 15.28,
"inflow": 0,
"volume": 19.74,
"temperature": 22.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 369.59,
"flow": 15.28,
"inflow": 0,
"volume": 19.74,
"temperature": 22.1,
"precipitation": 0
} }
] ]
+46 -1
View File
@@ -8942,7 +8942,52 @@
"flow": 39.79, "flow": 39.79,
"inflow": 1.43, "inflow": 1.43,
"volume": 10.12, "volume": 10.12,
"temperature": 24.4, "temperature": 23.9,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 283.21,
"flow": 71.88,
"inflow": 1.43,
"volume": 10.33,
"temperature": 23.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 283.13,
"flow": 272.83,
"temperature": 23.3,
"precipitation": 0,
"inflow": 1.43,
"volume": 10.33
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 283.17,
"flow": 341.23,
"inflow": 1.43,
"volume": 10.33,
"temperature": 23.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 283.15,
"flow": 301.72,
"inflow": 1.43,
"volume": 10.33,
"temperature": 22.4,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 283.11,
"flow": 301.13,
"inflow": 1.43,
"volume": 10.33,
"temperature": 21.6,
"precipitation": 0 "precipitation": 0
} }
] ]
+45
View File
@@ -9277,5 +9277,50 @@
"volume": 2.77, "volume": 2.77,
"temperature": 23.6, "temperature": 23.6,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 352.52,
"flow": 19.11,
"inflow": 15.72,
"volume": 2.77,
"temperature": 22.8,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 352.52,
"flow": 19.11,
"inflow": 15.72,
"volume": 2.77,
"temperature": 22.8,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 352.52,
"flow": 19.11,
"temperature": 22.8,
"precipitation": 0,
"inflow": 15.72,
"volume": 2.77
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 352.52,
"flow": 19.11,
"inflow": 15.72,
"volume": 2.77,
"temperature": 22.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 352.52,
"flow": 19.11,
"inflow": 15.72,
"volume": 2.77,
"temperature": 21.8,
"precipitation": 0
} }
] ]
+57
View File
@@ -9250,5 +9250,62 @@
"volume": 198.92, "volume": 198.92,
"temperature": 22.1, "temperature": 22.1,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T17:50:00.000Z",
"level": 723.06,
"flow": 51.88,
"inflow": -2.61,
"volume": 198.92,
"temperature": 21.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 723.06,
"flow": 58.29,
"inflow": -2.61,
"volume": 198.39,
"temperature": 21.1,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 723.06,
"flow": 76.19,
"qn": "> Q1",
"inflow": -2.61,
"volume": 198.39,
"temperature": 21.1,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 723.06,
"flow": 87.28,
"qn": "> Q1",
"temperature": 21.1,
"precipitation": 0,
"inflow": -2.61,
"volume": 198.39
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 723.06,
"flow": 87.05,
"inflow": -2.61,
"volume": 198.39,
"temperature": 20.4,
"precipitation": 0,
"qn": "> Q1"
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 723.06,
"flow": 0,
"inflow": -2.61,
"volume": 198.39,
"temperature": 19.8,
"precipitation": 0
} }
] ]
+45
View File
@@ -9277,5 +9277,50 @@
"volume": 0.59, "volume": 0.59,
"temperature": 22.9, "temperature": 22.9,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 559.89,
"flow": 7.48,
"inflow": 2.61,
"volume": 0.67,
"temperature": 21.5,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 560,
"flow": 7.41,
"inflow": 2.61,
"volume": 0.67,
"temperature": 21.5,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 560.11,
"flow": 0,
"temperature": 21.5,
"precipitation": 0,
"inflow": 2.61,
"volume": 0.67
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 560.27,
"flow": 0,
"inflow": 2.61,
"volume": 0.67,
"temperature": 20.5,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 560.41,
"flow": 0,
"inflow": 2.61,
"volume": 0.67,
"temperature": 19.5,
"precipitation": 0
} }
] ]
+45
View File
@@ -9277,5 +9277,50 @@
"volume": 521.33, "volume": 521.33,
"temperature": 24, "temperature": 24,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T17:50:00.000Z",
"level": 345.22,
"flow": 148.7,
"inflow": 18.49,
"volume": 521.33,
"temperature": 23.8,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 345.21,
"flow": 149.5,
"inflow": 18.49,
"volume": 521.13,
"temperature": 23.5,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 345.21,
"flow": 147.29,
"inflow": 18.49,
"volume": 521.13,
"temperature": 23.5,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 345.21,
"flow": 147.15,
"inflow": 18.49,
"volume": 521.13,
"temperature": 23.1,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 345.21,
"flow": 146.7,
"inflow": 18.49,
"volume": 521.13,
"temperature": 22.7,
"precipitation": 0
} }
] ]
+45
View File
@@ -9277,5 +9277,50 @@
"volume": 260.55, "volume": 260.55,
"temperature": 24, "temperature": 24,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 269.78,
"flow": 239.53,
"inflow": 1.16,
"volume": 259.94,
"temperature": 22.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 269.78,
"flow": 243.22,
"temperature": 22.7,
"precipitation": 0,
"inflow": 1.16,
"volume": 259.94
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 269.79,
"flow": 243,
"inflow": 1.16,
"volume": 259.94,
"temperature": 22.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 269.79,
"flow": 244.1,
"inflow": 1.16,
"volume": 259.94,
"temperature": 21.9,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 269.77,
"flow": 244.35,
"inflow": 1.16,
"volume": 259.94,
"temperature": 20.9,
"precipitation": 0
} }
] ]
+45
View File
@@ -9277,5 +9277,50 @@
"volume": 7.56, "volume": 7.56,
"temperature": 23.3, "temperature": 23.3,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 217.04,
"flow": 51.47,
"inflow": 12.66,
"volume": 8.22,
"temperature": 22.1,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 217.12,
"flow": 71.33,
"temperature": 22.1,
"precipitation": 0,
"inflow": 12.66,
"volume": 8.22
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 217.26,
"flow": 124.25,
"inflow": 12.66,
"volume": 8.22,
"temperature": 22.1,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 217.33,
"flow": 160.01,
"inflow": 12.66,
"volume": 8.22,
"temperature": 21.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 217.38,
"flow": 159.47,
"inflow": 12.66,
"volume": 8.22,
"temperature": 20.6,
"precipitation": 0
} }
] ]
+45
View File
@@ -2317,5 +2317,50 @@
"volume": 0, "volume": 0,
"temperature": 23.3, "temperature": 23.3,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T17:40:00.000Z",
"level": 65,
"flow": 7.482,
"inflow": 0,
"volume": 0,
"temperature": 22.7,
"precipitation": 0
},
{
"timestamp": "2026-06-08T17:50:00.000Z",
"level": 65,
"flow": 7.482,
"inflow": 0,
"volume": 0,
"temperature": 21.9,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 65,
"flow": 7.482,
"inflow": 0,
"volume": 0,
"temperature": 21.9,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 65,
"flow": 7.41,
"inflow": 0,
"volume": 0,
"temperature": 20.9,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 63,
"flow": 7.06,
"inflow": 0,
"volume": 0,
"temperature": 19.9,
"precipitation": 0
} }
] ]
+45
View File
@@ -8980,5 +8980,50 @@
"volume": 9.02, "volume": 9.02,
"temperature": 24.3, "temperature": 24.3,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 199.31,
"flow": 39.66,
"inflow": 25.05,
"volume": 9.02,
"temperature": 23.9,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 199.33,
"flow": 39.72,
"inflow": 25.05,
"volume": 9.13,
"temperature": 23.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 199.33,
"flow": 39.75,
"inflow": 25.05,
"volume": 9.13,
"temperature": 23.3,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 199.34,
"flow": 39.68,
"inflow": 25.05,
"volume": 9.13,
"temperature": 22.4,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 199.34,
"flow": 39.74,
"inflow": 25.05,
"volume": 9.13,
"temperature": 21.5,
"precipitation": 0
} }
] ]
+55 -1
View File
@@ -8912,10 +8912,64 @@
{ {
"timestamp": "2026-06-08T17:40:00.000Z", "timestamp": "2026-06-08T17:40:00.000Z",
"level": 375.12, "level": 375.12,
"flow": 0, "flow": 0.44,
"inflow": 0.58, "inflow": 0.58,
"volume": 240.58, "volume": 240.58,
"temperature": 23.5, "temperature": 23.5,
"precipitation": 0 "precipitation": 0
},
{
"timestamp": "2026-06-08T17:50:00.000Z",
"level": 375.12,
"flow": 0,
"inflow": 0.58,
"volume": 240.58,
"temperature": 23.2,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:00:00.000Z",
"level": 375.12,
"flow": 0.44,
"temperature": 23.2,
"precipitation": 0,
"inflow": 0.58,
"volume": 240.58
},
{
"timestamp": "2026-06-08T18:10:00.000Z",
"level": 375.12,
"flow": 0.44,
"inflow": 0.58,
"volume": 240.58,
"temperature": 22.6,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:20:00.000Z",
"level": 375.12,
"flow": 0.44,
"inflow": 0.58,
"volume": 240.58,
"temperature": 22.6,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:30:00.000Z",
"level": 375.12,
"flow": 0,
"inflow": 0.58,
"volume": 240.58,
"temperature": 21.9,
"precipitation": 0
},
{
"timestamp": "2026-06-08T18:40:00.000Z",
"level": 375.12,
"flow": 0,
"inflow": 0.58,
"volume": 240.58,
"temperature": 21.2,
"precipitation": 0
} }
] ]
File diff suppressed because it is too large Load Diff
+36 -5
View File
@@ -374,7 +374,7 @@
.main-content { .main-content {
margin-left: 0 !important; margin-left: 0 !important;
padding: 1rem; padding: 1rem 0.5rem;
gap: 1rem; gap: 1rem;
} }
@@ -432,7 +432,7 @@
} }
.chart-card { .chart-card {
padding: 1rem; padding: 1rem 0;
} }
.chart-header { .chart-header {
@@ -468,11 +468,42 @@
.chart-legend-container { .chart-legend-container {
flex-wrap: wrap; flex-wrap: wrap;
gap: 1rem !important; gap: 0.6rem !important;
justify-content: flex-start !important; justify-content: center !important;
} }
.chart-legend-container>span { .chart-legend-container>span {
flex: 0 0 calc(50% - 0.5rem); flex: none !important;
padding: 0.5rem 0.85rem;
background-color: rgba(255, 255, 255, 0.03);
border: 1px solid var(--border-color);
border-radius: 20px;
display: inline-flex !important;
align-items: center;
justify-content: center;
min-height: 38px; /* Touch target optimized */
box-sizing: border-box;
}
}
/* Mobile Chart Optimizations */
@media (max-width: 768px) {
.chart-ref-label {
display: none !important;
}
.chart-tooltip {
padding: 0.6rem !important;
max-width: 280px !important;
}
.chart-tooltip p,
.chart-tooltip div {
font-size: 0.8rem !important;
margin-bottom: 2px !important;
}
.recharts-cartesian-axis-tick text {
font-size: 10px !important;
} }
} }
+270 -46
View File
@@ -36,7 +36,7 @@ const CustomTooltip = ({ active, payload, label, language, isWeather, isRiver }:
const dict = t[language as Language].chart; const dict = t[language as Language].chart;
if (isWeather) { if (isWeather) {
return ( return (
<div style={{ backgroundColor: 'var(--bg-card)', padding: '1rem', border: '1px solid var(--border-color)', borderRadius: '0.5rem', boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1)' }}> <div className="chart-tooltip" style={{ backgroundColor: 'var(--bg-card)', padding: '1rem', border: '1px solid var(--border-color)', borderRadius: '0.5rem', boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1)' }}>
<p style={{ margin: '0 0 0.5rem 0', fontWeight: 'bold', color: 'var(--text-main)' }}>{label}</p> <p style={{ margin: '0 0 0.5rem 0', fontWeight: 'bold', color: 'var(--text-main)' }}>{label}</p>
{payload.map((entry: any, index: number) => { {payload.map((entry: any, index: number) => {
const isTemp = entry.name === 'temperature' || entry.dataKey === 'temperature'; const isTemp = entry.name === 'temperature' || entry.dataKey === 'temperature';
@@ -50,7 +50,7 @@ const CustomTooltip = ({ active, payload, label, language, isWeather, isRiver }:
); );
} }
return ( return (
<div style={{ backgroundColor: 'var(--bg-card)', padding: '1rem', border: '1px solid var(--border-color)', borderRadius: '0.5rem', boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1)' }}> <div className="chart-tooltip" style={{ backgroundColor: 'var(--bg-card)', padding: '1rem', border: '1px solid var(--border-color)', borderRadius: '0.5rem', boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1)' }}>
<p style={{ margin: '0 0 0.5rem 0', fontWeight: 'bold', color: 'var(--text-main)' }}>{label}</p> <p style={{ margin: '0 0 0.5rem 0', fontWeight: 'bold', color: 'var(--text-main)' }}>{label}</p>
{[...payload].sort((a: any, b: any) => { {[...payload].sort((a: any, b: any) => {
const order = ['level', 'inflow', 'outflow', 'temperature', 'precipitation']; const order = ['level', 'inflow', 'outflow', 'temperature', 'precipitation'];
@@ -98,11 +98,11 @@ const CustomTooltip = ({ active, payload, label, language, isWeather, isRiver }:
})} })}
{payload[0]?.payload?.qn ? ( {payload[0]?.payload?.qn ? (
<div style={{ marginTop: '8px', paddingTop: '8px', borderTop: '1px solid var(--border-color)', fontSize: '0.8rem', color: '#f59e0b', display: 'flex', alignItems: 'center', gap: '4px' }}> <div style={{ marginTop: '8px', paddingTop: '8px', borderTop: '1px solid var(--border-color)', fontSize: '0.8rem', color: '#f59e0b', display: 'flex', alignItems: 'center', gap: '4px' }}>
{language === 'cs' ? `Neověřené měření (QN: ${payload[0].payload.qn})` : `Unverified measurement (QN: ${payload[0].payload.qn})`} {language === 'cs' ? 'Neověřené měření' : 'Unverified measurement'}
</div> </div>
) : ( ) : (
<div style={{ marginTop: '8px', paddingTop: '8px', borderTop: '1px solid var(--border-color)', fontSize: '0.8rem', color: 'var(--color-green)', display: 'flex', alignItems: 'center', gap: '4px' }}> <div style={{ marginTop: '8px', paddingTop: '8px', borderTop: '1px solid var(--border-color)', fontSize: '0.8rem', color: 'var(--color-green)', display: 'flex', alignItems: 'center', gap: '4px' }}>
{language === 'cs' ? 'Měření ověřeno dispečinkem' : 'Measurement verified'} {language === 'cs' ? 'Měření ověřeno' : 'Measurement verified'}
</div> </div>
)} )}
</div> </div>
@@ -117,6 +117,31 @@ const LakeDetail = ({ language, lakeId, windUnit = 'kmh' }: Props) => {
const [lakeInfo, setLakeInfo] = useState<any>(null); const [lakeInfo, setLakeInfo] = useState<any>(null);
const [isSmoothed, setIsSmoothed] = useState(true); const [isSmoothed, setIsSmoothed] = useState(true);
const [timeRange, setTimeRange] = useState<'24h' | '7d' | '30d' | '1y' | 'all'>('7d'); const [timeRange, setTimeRange] = useState<'24h' | '7d' | '30d' | '1y' | 'all'>('7d');
const [visibleSeries, setVisibleSeries] = useState({
level: true,
outflow: true,
inflow: true
});
const [visibleWeatherSeries, setVisibleWeatherSeries] = useState({
temp: true,
precip: true
});
const [isMobile, setIsMobile] = useState(false);
const [leftCustomDomain, setLeftCustomDomain] = useState<[number, number] | null>(null);
const [rightCustomDomain, setRightCustomDomain] = useState<[number, number] | null>(null);
useEffect(() => {
const handleResize = () => setIsMobile(window.innerWidth <= 768);
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
useEffect(() => {
setLeftCustomDomain(null);
setRightCustomDomain(null);
}, [timeRange, lakeId]);
const dict = t[language].chart; const dict = t[language].chart;
const topbarDict = t[language].topbar; const topbarDict = t[language].topbar;
@@ -303,6 +328,124 @@ const LakeDetail = ({ language, lakeId, windUnit = 'kmh' }: Props) => {
avgOutflow24h avgOutflow24h
}; };
const getDefaultLeftDomain = (): [number, number] => {
const levels = chartData.map(d => d.level).filter(v => v !== null && v !== undefined && !isNaN(v));
if (levels.length === 0) return [0, 100];
const dataMin = Math.min(...levels);
const dataMax = Math.max(...levels);
if (isRiver) {
return [Math.max(0, Math.floor(dataMin - 10)), Math.ceil(dataMax + 10)];
} else {
let min = dataMin;
if (limits) limits.forEach(l => { if (l.level < min) min = l.level; });
let max = dataMax;
if (staticConfig?.maxLevel && staticConfig.maxLevel > max) max = staticConfig.maxLevel;
if (staticConfig?.storageLevel && staticConfig.storageLevel > max) max = staticConfig.storageLevel;
return [min - 0.5, max + 0.5];
}
};
const getDefaultRightDomain = (): [number, number] => {
const flows = chartData.flatMap(d => [d.outflow, d.inflow]).filter(v => v !== null && v !== undefined && !isNaN(v));
if (flows.length === 0) return [0, 10];
const dataMax = Math.max(...flows);
return [0, Math.max(dataMax, 1)];
};
const handleAxisDragStart = (
e: React.MouseEvent | React.TouchEvent,
axis: 'left' | 'right'
) => {
e.preventDefault();
const isTouchEvent = 'touches' in e;
if (isTouchEvent && e.touches.length === 2) {
const touch1 = e.touches[0];
const touch2 = e.touches[1];
const dist = Math.abs(touch1.clientY - touch2.clientY);
const currentDomain = axis === 'left'
? (leftCustomDomain || getDefaultLeftDomain())
: (rightCustomDomain || getDefaultRightDomain());
const onTouchMove = (moveEvent: TouchEvent) => {
if (moveEvent.touches.length === 2) {
moveEvent.preventDefault(); // Stop native page zooming
const mTouch1 = moveEvent.touches[0];
const mTouch2 = moveEvent.touches[1];
const currentDist = Math.abs(mTouch1.clientY - mTouch2.clientY);
if (currentDist > 5) {
const factor = dist / currentDist;
const center = (currentDomain[0] + currentDomain[1]) / 2;
const range = currentDomain[1] - currentDomain[0];
const newMin = center - (range * factor) / 2;
const newMax = center + (range * factor) / 2;
if (axis === 'left') {
setLeftCustomDomain([newMin, newMax]);
} else {
setRightCustomDomain([Math.max(0, newMin), newMax]);
}
}
}
};
const onTouchEnd = () => {
window.removeEventListener('touchmove', onTouchMove);
window.removeEventListener('touchend', onTouchEnd);
};
window.addEventListener('touchmove', onTouchMove, { passive: false });
window.addEventListener('touchend', onTouchEnd);
return;
}
const startY = isTouchEvent ? e.touches[0].clientY : e.clientY;
const currentDomain = axis === 'left'
? (leftCustomDomain || getDefaultLeftDomain())
: (rightCustomDomain || getDefaultRightDomain());
const initialRange = currentDomain[1] - currentDomain[0];
const center = (currentDomain[1] + currentDomain[0]) / 2;
const onMove = (moveEvent: MouseEvent | TouchEvent) => {
if ('touches' in moveEvent) {
moveEvent.preventDefault(); // Stop native page scrolling
}
const clientY = 'touches' in moveEvent ? moveEvent.touches[0].clientY : moveEvent.clientY;
const deltaY = clientY - startY;
const factor = Math.pow(2.5, deltaY / 150);
const newMin = center - (initialRange * factor) / 2;
const newMax = center + (initialRange * factor) / 2;
if (axis === 'left') {
setLeftCustomDomain([newMin, newMax]);
} else {
setRightCustomDomain([Math.max(0, newMin), newMax]);
}
};
const onEnd = () => {
if (isTouchEvent) {
window.removeEventListener('touchmove', onMove);
window.removeEventListener('touchend', onEnd);
} else {
window.removeEventListener('mousemove', onMove);
window.removeEventListener('mouseup', onEnd);
}
};
if (isTouchEvent) {
window.addEventListener('touchmove', onMove, { passive: false });
window.addEventListener('touchend', onEnd);
} else {
window.addEventListener('mousemove', onMove);
window.addEventListener('mouseup', onEnd);
}
};
const leftYAxisDomain = isRiver const leftYAxisDomain = isRiver
? [ ? [
(dataMin: number) => Math.max(0, Math.floor(dataMin - 10)), (dataMin: number) => Math.max(0, Math.floor(dataMin - 10)),
@@ -361,36 +504,45 @@ const LakeDetail = ({ language, lakeId, windUnit = 'kmh' }: Props) => {
</> </>
)} )}
<div style={{ color: 'var(--text-muted)', fontSize: '0.9rem', marginTop: '-0.5rem', display: 'flex', alignItems: 'center', gap: '0.75rem', flexWrap: 'wrap' }}> <div style={{
color: 'var(--text-muted)',
fontSize: isMobile ? '0.75rem' : '0.9rem',
marginTop: isMobile ? '-1.1rem' : '-0.5rem',
marginBottom: isMobile ? '-0.5rem' : '0',
display: 'flex',
alignItems: 'center',
gap: isMobile ? '0.4rem' : '0.75rem',
flexWrap: 'wrap'
}}>
<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>
{latestData.qn ? ( {latestData.qn ? (
<span style={{ <span style={{
fontSize: '0.75rem', fontSize: isMobile ? '0.65rem' : '0.75rem',
padding: '0.15rem 0.4rem', padding: isMobile ? '0.1rem 0.3rem' : '0.15rem 0.4rem',
borderRadius: '4px', borderRadius: '4px',
backgroundColor: 'rgba(245, 158, 11, 0.1)', backgroundColor: 'rgba(245, 158, 11, 0.1)',
color: '#f59e0b', color: '#f59e0b',
border: '1px solid rgba(245, 158, 11, 0.2)', border: '1px solid rgba(245, 158, 11, 0.2)',
display: 'inline-flex', display: 'inline-flex',
alignItems: 'center', alignItems: 'center',
gap: '0.25rem' gap: '0.2rem'
}}> }}>
{language === 'cs' ? `Neověřená data (QN: ${latestData.qn})` : `Unverified data (QN: ${latestData.qn})`} {language === 'cs' ? 'Neověřená data' : 'Unverified data'}
</span> </span>
) : ( ) : (
<span style={{ <span style={{
fontSize: '0.75rem', fontSize: isMobile ? '0.65rem' : '0.75rem',
padding: '0.15rem 0.4rem', padding: isMobile ? '0.1rem 0.3rem' : '0.15rem 0.4rem',
borderRadius: '4px', borderRadius: '4px',
backgroundColor: 'rgba(34, 197, 94, 0.1)', backgroundColor: 'rgba(34, 197, 94, 0.1)',
color: 'var(--color-green)', color: 'var(--color-green)',
border: '1px solid rgba(34, 197, 94, 0.2)', border: '1px solid rgba(34, 197, 94, 0.2)',
display: 'inline-flex', display: 'inline-flex',
alignItems: 'center', alignItems: 'center',
gap: '0.25rem' gap: '0.2rem'
}}> }}>
{language === 'cs' ? 'Ověřená data dispečinkem' : 'Data verified by dispatch'} {language === 'cs' ? 'Měření ověřeno' : 'Data verified'}
</span> </span>
)} )}
</div> </div>
@@ -426,38 +578,56 @@ const LakeDetail = ({ language, lakeId, windUnit = 'kmh' }: Props) => {
{/* CHART SECTION */} {/* CHART SECTION */}
<div className="chart-card"> <div className="chart-card">
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '1.5rem', flexWrap: 'wrap', gap: '1rem' }}> <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '0.25rem', flexWrap: 'wrap', gap: '1rem', padding: isMobile ? '0 0.75rem' : '0' }}>
<h3 style={{ margin: 0, fontSize: '1.1rem', color: 'var(--text-main)' }}>{dict.title} {lakeInfo ? `${lakeInfo.name} ${lakeInfo.river ? `- ${lakeInfo.river}` : ''}` : 'Lipno 1 - Vltava'}</h3> <h3 style={{ margin: 0, fontSize: '1.1rem', color: 'var(--text-main)' }}>{dict.title} {lakeInfo ? `${lakeInfo.name} ${lakeInfo.river ? `- ${lakeInfo.river}` : ''}` : 'Lipno 1 - Vltava'}</h3>
<div className="top-time-controls" style={{ margin: 0 }}> <div className="top-time-controls" style={{ margin: 0, display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: '0.5rem' }}>
<button className={timeRange === '24h' ? 'active' : ''} onClick={() => setTimeRange('24h')}>24h</button> <button className={timeRange === '24h' ? 'active' : ''} onClick={() => setTimeRange('24h')}>24h</button>
<button className={timeRange === '7d' ? 'active' : ''} onClick={() => setTimeRange('7d')}>7d</button> <button className={timeRange === '7d' ? 'active' : ''} onClick={() => setTimeRange('7d')}>7d</button>
<button className={timeRange === '30d' ? 'active' : ''} onClick={() => setTimeRange('30d')}>30d</button> <button className={timeRange === '30d' ? 'active' : ''} onClick={() => setTimeRange('30d')}>30d</button>
<button className={timeRange === '1y' ? 'active' : ''} onClick={() => setTimeRange('1y')}>{dict.year}</button> <button className={timeRange === '1y' ? 'active' : ''} onClick={() => setTimeRange('1y')}>{dict.year}</button>
<button className={timeRange === 'all' ? 'active' : ''} onClick={() => setTimeRange('all')}>{dict.all}</button> <button className={timeRange === 'all' ? 'active' : ''} onClick={() => setTimeRange('all')}>{dict.all}</button>
{(leftCustomDomain !== null || rightCustomDomain !== null) && (
<button
onClick={() => { setLeftCustomDomain(null); setRightCustomDomain(null); }}
style={{
backgroundColor: 'rgba(239, 68, 68, 0.15)',
color: '#ef4444',
border: '1px solid rgba(239, 68, 68, 0.3)',
borderRadius: '0.375rem',
padding: '0.4rem 0.75rem',
fontSize: '0.85rem',
cursor: 'pointer',
fontWeight: 500,
transition: 'all 0.2s'
}}
>
Reset
</button>
)}
</div> </div>
</div> </div>
<div style={{ flex: 1, minHeight: '300px', width: '100%', marginTop: '1rem' }}> <div style={{ flex: 1, minHeight: '300px', width: '100%', marginTop: '0', position: 'relative' }}>
<ResponsiveContainer width="100%" height="100%"> <ResponsiveContainer width="100%" height="100%">
<ComposedChart data={chartData} margin={{ top: 20, right: 0, left: 10, bottom: 0 }}> <ComposedChart data={chartData} margin={isMobile ? { top: 5, right: 5, left: 5, bottom: 0 } : { top: 5, right: 0, left: 10, bottom: 0 }}>
<defs> <defs>
<linearGradient id="colorLevel" x1="0" y1="0" x2="0" y2="1"> <linearGradient id="colorLevel" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="var(--color-cyan)" stopOpacity={0.5}/> <stop offset="5%" stopColor="var(--color-cyan)" stopOpacity={0.5}/>
<stop offset="95%" stopColor="var(--color-cyan)" stopOpacity={0}/> <stop offset="95%" stopColor="var(--color-cyan)" stopOpacity={0}/>
</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: isMobile ? 10 : 12}} minTickGap={50} />
<YAxis yAxisId="left" domain={leftYAxisDomain as any} stroke="var(--text-muted)" tick={{fill: 'var(--text-muted)', fontSize: 12}} tickFormatter={(v) => v.toFixed(isRiver ? 0 : 2)} /> <YAxis yAxisId="left" domain={leftCustomDomain || (leftYAxisDomain as any)} stroke={visibleSeries.level ? "var(--text-muted)" : "transparent"} tick={{fill: visibleSeries.level ? 'var(--text-muted)' : 'transparent', fontSize: isMobile ? 10 : 12}} tickLine={visibleSeries.level ? { stroke: 'var(--text-muted)' } : { stroke: 'transparent' }} axisLine={visibleSeries.level ? { stroke: 'var(--text-muted)' } : { stroke: 'transparent' }} width={isMobile ? 42 : 60} tickFormatter={(v) => v.toFixed(isRiver ? 0 : 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={rightCustomDomain || [0, (dataMax: number) => Math.max(dataMax, 1)]} stroke={(visibleSeries.outflow || visibleSeries.inflow) ? "var(--text-muted)" : "transparent"} tick={{fill: (visibleSeries.outflow || visibleSeries.inflow) ? 'var(--text-muted)' : 'transparent', fontSize: isMobile ? 10 : 12}} tickLine={(visibleSeries.outflow || visibleSeries.inflow) ? { stroke: 'var(--text-muted)' } : { stroke: 'transparent' }} axisLine={(visibleSeries.outflow || visibleSeries.inflow) ? { stroke: 'var(--text-muted)' } : { stroke: 'transparent' }} width={isMobile ? 35 : 60} tickFormatter={(v) => v.toFixed(1)} />
<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} />
<Tooltip content={<CustomTooltip language={language} isRiver={isRiver} />} /> <Tooltip content={<CustomTooltip language={language} isRiver={isRiver} />} />
{/* Data Series */} {/* Data Series */}
{limits && limits.map((limit, idx) => ( {visibleSeries.level && 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: 'insideBottomLeft', value: language === 'cs' ? `${limit.labelCs} (${limit.level.toFixed(2)} m n. m.)` : `${limit.labelEn} (${limit.level.toFixed(2)} m a.s.l.)`, fill: limit.type === 'danger' ? 'var(--color-red)' : '#f59e0b', fontSize: 11 }} /> <ReferenceLine key={idx} yAxisId="left" y={limit.level} stroke={limit.type === 'danger' ? 'var(--color-red)' : '#f59e0b'} strokeDasharray="3 3" label={{ position: 'insideBottomLeft', value: language === 'cs' ? `${limit.labelCs} (${limit.level.toFixed(2)} m n. m.)` : `${limit.labelEn} (${limit.level.toFixed(2)} m a.s.l.)`, fill: limit.type === 'danger' ? 'var(--color-red)' : '#f59e0b', fontSize: 11, className: 'chart-ref-label' }} />
))} ))}
{!isRiver && staticConfig?.maxLevel && staticConfig?.storageLevel && Math.abs(staticConfig.maxLevel - staticConfig.storageLevel) < 0.05 ? ( {visibleSeries.level && !isRiver && staticConfig?.maxLevel && staticConfig?.storageLevel && Math.abs(staticConfig.maxLevel - staticConfig.storageLevel) < 0.05 ? (
<ReferenceLine <ReferenceLine
yAxisId="left" yAxisId="left"
y={staticConfig.maxLevel} y={staticConfig.maxLevel}
@@ -469,12 +639,13 @@ const LakeDetail = ({ language, lakeId, windUnit = 'kmh' }: Props) => {
? `Max. retenční / zásobní hladina (${staticConfig.maxLevel.toFixed(2)} m n. m.)` ? `Max. retenční / zásobní hladina (${staticConfig.maxLevel.toFixed(2)} m n. m.)`
: `Max retention / storage level (${staticConfig.maxLevel.toFixed(2)} m a.s.l.)`, : `Max retention / storage level (${staticConfig.maxLevel.toFixed(2)} m a.s.l.)`,
fill: 'var(--color-orange)', fill: 'var(--color-orange)',
fontSize: 11 fontSize: 11,
className: 'chart-ref-label'
}} }}
/> />
) : ( ) : (
<> <>
{!isRiver && staticConfig?.maxLevel && ( {visibleSeries.level && !isRiver && staticConfig?.maxLevel && (
<ReferenceLine <ReferenceLine
yAxisId="left" yAxisId="left"
y={staticConfig.maxLevel} y={staticConfig.maxLevel}
@@ -486,11 +657,12 @@ const LakeDetail = ({ language, lakeId, windUnit = 'kmh' }: Props) => {
? `Maximální retenční hladina (${staticConfig.maxLevel.toFixed(2)} m n. m.)` ? `Maximální retenční hladina (${staticConfig.maxLevel.toFixed(2)} m n. m.)`
: `Max retention level (${staticConfig.maxLevel.toFixed(2)} m a.s.l.)`, : `Max retention level (${staticConfig.maxLevel.toFixed(2)} m a.s.l.)`,
fill: 'var(--color-orange)', fill: 'var(--color-orange)',
fontSize: 11 fontSize: 11,
className: 'chart-ref-label'
}} }}
/> />
)} )}
{!isRiver && staticConfig?.storageLevel && ( {visibleSeries.level && !isRiver && staticConfig?.storageLevel && (
<ReferenceLine <ReferenceLine
yAxisId="left" yAxisId="left"
y={staticConfig.storageLevel} y={staticConfig.storageLevel}
@@ -502,31 +674,71 @@ const LakeDetail = ({ language, lakeId, windUnit = 'kmh' }: Props) => {
? `Hladina zásobního prostoru (${staticConfig.storageLevel.toFixed(2)} m n. m.)` ? `Hladina zásobního prostoru (${staticConfig.storageLevel.toFixed(2)} m n. m.)`
: `Storage space level (${staticConfig.storageLevel.toFixed(2)} m a.s.l.)`, : `Storage space level (${staticConfig.storageLevel.toFixed(2)} m a.s.l.)`,
fill: '#a855f7', fill: '#a855f7',
fontSize: 11 fontSize: 11,
className: 'chart-ref-label'
}} }}
/> />
)} )}
</> </>
)} )}
<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} hide={!visibleSeries.level} />
<Line yAxisId="right" type={curveType} dataKey="outflow" stroke="var(--color-red)" strokeWidth={2} dot={false} isAnimationActive={animate} /> <Line yAxisId="right" type={curveType} dataKey="outflow" stroke="var(--color-red)" strokeWidth={2} dot={false} isAnimationActive={animate} hide={!visibleSeries.outflow} />
{!isRiver && <Line yAxisId="right" type={curveType} dataKey="inflow" stroke="var(--color-green)" strokeWidth={2} dot={false} isAnimationActive={animate} />} {!isRiver && <Line yAxisId="right" type={curveType} dataKey="inflow" stroke="var(--color-green)" strokeWidth={2} dot={false} isAnimationActive={animate} hide={!visibleSeries.inflow} />}
</ComposedChart> </ComposedChart>
</ResponsiveContainer> </ResponsiveContainer>
<div
onMouseDown={(e) => handleAxisDragStart(e, 'left')}
onTouchStart={(e) => handleAxisDragStart(e, 'left')}
style={{
position: 'absolute',
left: 0,
top: 0,
bottom: isMobile ? 25 : 35,
width: isMobile ? 42 : 60,
cursor: 'ns-resize',
zIndex: 10,
background: 'transparent'
}}
title={language === 'cs' ? 'Táhněte pro změnu měřítka osy hladiny' : 'Drag to scale level axis'}
/>
<div
onMouseDown={(e) => handleAxisDragStart(e, 'right')}
onTouchStart={(e) => handleAxisDragStart(e, 'right')}
style={{
position: 'absolute',
right: 0,
top: 0,
bottom: isMobile ? 25 : 35,
width: isMobile ? 35 : 60,
cursor: 'ns-resize',
zIndex: 10,
background: 'transparent'
}}
title={language === 'cs' ? 'Táhněte pro změnu měřítka osy průtoku' : 'Drag to scale flow axis'}
/>
</div> </div>
{/* Chart Legend */} {/* Chart Legend */}
<div className="chart-legend-container" style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'center', gap: '1rem', marginTop: '1rem', fontSize: '0.85rem', color: 'var(--text-main)' }}> <div className="chart-legend-container" style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'center', gap: '1.5rem', marginTop: '1rem', fontSize: '0.85rem', color: 'var(--text-main)', padding: isMobile ? '0 0.75rem' : '0' }}>
<span style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}> <span
onClick={() => setVisibleSeries(prev => ({ ...prev, level: !prev.level }))}
style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', cursor: 'pointer', opacity: visibleSeries.level ? 1 : 0.4, transition: 'opacity 0.2s', userSelect: 'none' }}
>
<div style={{ width: '12px', height: '4px', backgroundColor: 'var(--color-cyan)' }}></div> <div style={{ width: '12px', height: '4px', backgroundColor: 'var(--color-cyan)' }}></div>
{isRiver ? (language === 'cs' ? 'Vodní stav' : 'Water level') : dict.level} {isRiver ? (language === 'cs' ? 'Vodní stav' : 'Water level') : dict.level}
</span> </span>
<span style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}> <span
onClick={() => setVisibleSeries(prev => ({ ...prev, outflow: !prev.outflow }))}
style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', cursor: 'pointer', opacity: visibleSeries.outflow ? 1 : 0.4, transition: 'opacity 0.2s', userSelect: 'none' }}
>
<div style={{ width: '12px', height: '4px', backgroundColor: 'var(--color-red)' }}></div> <div style={{ width: '12px', height: '4px', backgroundColor: 'var(--color-red)' }}></div>
{isRiver ? (language === 'cs' ? 'Průtok' : 'Flow') : dict.outflow} {isRiver ? (language === 'cs' ? 'Průtok' : 'Flow') : dict.outflow}
</span> </span>
{!isRiver && ( {!isRiver && (
<span style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}> <span
onClick={() => setVisibleSeries(prev => ({ ...prev, inflow: !prev.inflow }))}
style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', cursor: 'pointer', opacity: visibleSeries.inflow ? 1 : 0.4, transition: 'opacity 0.2s', userSelect: 'none' }}
>
<div style={{ width: '12px', height: '4px', backgroundColor: 'var(--color-green)' }}></div> <div style={{ width: '12px', height: '4px', backgroundColor: 'var(--color-green)' }}></div>
{dict.inflow} {dict.inflow}
</span> </span>
@@ -534,29 +746,41 @@ const LakeDetail = ({ language, lakeId, windUnit = 'kmh' }: Props) => {
</div> </div>
{/* WEATHER CHART SECTION */} {/* WEATHER CHART SECTION */}
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '1rem', marginTop: '2rem', flexWrap: 'wrap', gap: '1rem' }}> <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '0.25rem', marginTop: '1.5rem', flexWrap: 'wrap', gap: '1rem', padding: isMobile ? '0 0.75rem' : '0' }}>
<h3 style={{ margin: 0, fontSize: '1.1rem', color: 'var(--text-main)' }}>{language === 'cs' ? 'Počasí (Teplota a Srážky)' : 'Weather (Temperature & Precipitation)'}</h3> <h3 style={{ margin: 0, fontSize: '1.1rem', color: 'var(--text-main)' }}>{language === 'cs' ? 'Počasí (Teplota a Srážky)' : 'Weather (Temperature & Precipitation)'}</h3>
</div> </div>
<div style={{ flex: 1, minHeight: '200px', width: '100%', marginTop: '0.5rem' }}> <div style={{ flex: 1, minHeight: '200px', width: '100%', marginTop: '0' }}>
<ResponsiveContainer width="100%" height="100%"> <ResponsiveContainer width="100%" height="100%">
<ComposedChart data={chartData} margin={{ top: 10, right: 0, left: 10, bottom: 0 }}> <ComposedChart data={chartData} margin={isMobile ? { top: 5, right: 5, left: 5, bottom: 0 } : { top: 5, right: 0, left: 10, bottom: 0 }}>
<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: isMobile ? 10 : 12}} minTickGap={50} />
<YAxis yAxisId="temp" domain={['auto', 'auto']} stroke="var(--text-muted)" tick={{fill: 'var(--text-muted)', fontSize: 12}} tickFormatter={(v) => v.toFixed(1)} /> <YAxis yAxisId="temp" domain={['auto', 'auto']} stroke={visibleWeatherSeries.temp ? "var(--text-muted)" : "transparent"} tick={{fill: visibleWeatherSeries.temp ? 'var(--text-muted)' : 'transparent', fontSize: isMobile ? 10 : 12}} tickLine={visibleWeatherSeries.temp ? { stroke: 'var(--text-muted)' } : { stroke: 'transparent' }} axisLine={visibleWeatherSeries.temp ? { stroke: 'var(--text-muted)' } : { stroke: 'transparent' }} width={isMobile ? 42 : 60} tickFormatter={(v) => v.toFixed(1)} />
<YAxis yAxisId="precip" orientation="right" domain={[0, 'auto']} stroke="var(--text-muted)" tick={{fill: 'var(--text-muted)', fontSize: 12}} /> <YAxis yAxisId="precip" orientation="right" domain={[0, 'auto']} stroke={visibleWeatherSeries.precip ? "var(--text-muted)" : "transparent"} tick={{fill: visibleWeatherSeries.precip ? 'var(--text-muted)' : 'transparent', fontSize: isMobile ? 10 : 12}} tickLine={visibleWeatherSeries.precip ? { stroke: 'var(--text-muted)' } : { stroke: 'transparent' }} axisLine={visibleWeatherSeries.precip ? { stroke: 'var(--text-muted)' } : { stroke: 'transparent' }} width={isMobile ? 35 : 60} />
<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} />
<Tooltip content={<CustomTooltip language={language} isWeather={true} />} /> <Tooltip content={<CustomTooltip language={language} isWeather={true} />} />
<Bar yAxisId="precip" dataKey="precipitation" fill="var(--color-cyan)" fillOpacity={0.6} isAnimationActive={animate} /> <Bar yAxisId="precip" dataKey="precipitation" fill="var(--color-cyan)" fillOpacity={0.6} isAnimationActive={animate} hide={!visibleWeatherSeries.precip} />
<Line yAxisId="temp" type={curveType} dataKey="temperature" stroke="var(--color-red)" strokeWidth={2} dot={true} isAnimationActive={animate} /> <Line yAxisId="temp" type={curveType} dataKey="temperature" stroke="var(--color-red)" strokeWidth={2} dot={true} isAnimationActive={animate} hide={!visibleWeatherSeries.temp} />
</ComposedChart> </ComposedChart>
</ResponsiveContainer> </ResponsiveContainer>
</div> </div>
<div className="chart-legend-container" style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'center', gap: '1rem', marginTop: '1rem', fontSize: '0.85rem', color: 'var(--text-main)' }}> <div className="chart-legend-container" style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'center', gap: '1rem', marginTop: '1rem', fontSize: '0.85rem', color: 'var(--text-main)', padding: isMobile ? '0 0.75rem' : '0' }}>
<span style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}><div style={{ width: '12px', height: '4px', backgroundColor: 'var(--color-red)' }}></div> {language === 'cs' ? 'Teplota vzduchu' : 'Temperature'} [°C]</span> <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> onClick={() => setVisibleWeatherSeries(prev => ({ ...prev, temp: !prev.temp }))}
style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', cursor: 'pointer', opacity: visibleWeatherSeries.temp ? 1 : 0.4, transition: 'opacity 0.2s', userSelect: 'none' }}
>
<div style={{ width: '12px', height: '4px', backgroundColor: 'var(--color-red)' }}></div>
{language === 'cs' ? 'Teplota vzduchu' : 'Temperature'} [°C]
</span>
<span
onClick={() => setVisibleWeatherSeries(prev => ({ ...prev, precip: !prev.precip }))}
style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', cursor: 'pointer', opacity: visibleWeatherSeries.precip ? 1 : 0.4, transition: 'opacity 0.2s', userSelect: 'none' }}
>
<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 */} {/* Wind Chart placed inside the main card below the weather graph */}
+26 -10
View File
@@ -81,6 +81,14 @@ export const WindChart = ({ lat, lng, language, timeRange = '7d', windUnit = 'km
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [currentSpeed, setCurrentSpeed] = useState(0); const [currentSpeed, setCurrentSpeed] = useState(0);
const [maxGust, setMaxGust] = useState(0); const [maxGust, setMaxGust] = useState(0);
const [isMobile, setIsMobile] = useState(false);
useEffect(() => {
const handleResize = () => setIsMobile(window.innerWidth <= 768);
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
useEffect(() => { useEffect(() => {
const fetchWind = async () => { const fetchWind = async () => {
@@ -182,15 +190,21 @@ export const WindChart = ({ lat, lng, language, timeRange = '7d', windUnit = 'km
if (data.length === 0) return null; if (data.length === 0) return null;
return ( return (
<div style={{ marginTop: '3rem', paddingTop: '1rem', display: 'flex', flexDirection: 'column', gap: '1rem' }}> <div style={{ marginTop: '1.5rem', paddingTop: '0.5rem', display: 'flex', flexDirection: 'column', gap: '0' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', flexWrap: 'wrap', gap: '1rem' }}> <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', flexWrap: 'wrap', gap: '1rem', padding: isMobile ? '0 0.75rem' : '0', marginBottom: '0.25rem' }}>
<h3 style={{ margin: 0, fontSize: '1.1rem', color: 'var(--text-main)', display: 'flex', alignItems: 'center', gap: '0.5rem' }}> <h3 style={{ margin: 0, fontSize: '1.1rem', color: 'var(--text-main)', display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
<FiWind style={{ color: 'var(--color-cyan)' }} /> <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})`} {language === 'cs' ? `Aktivita větru (${timeRange === '1y' || timeRange === 'all' ? 'denní maxima' : timeRange})` : `Wind Activity (${timeRange === '1y' || timeRange === 'all' ? 'daily max' : timeRange})`}
</h3> </h3>
<div style={{ display: 'flex', gap: '1.5rem' }}> <div style={{
<div style={{ display: 'flex', flexDirection: 'column' }}> display: 'flex',
gap: isMobile ? '0' : '1.5rem',
justifyContent: isMobile ? 'space-around' : 'flex-end',
width: isMobile ? '100%' : 'auto',
marginTop: isMobile ? '0.5rem' : '0'
}}>
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
<span style={{ fontSize: '0.8rem', color: 'var(--text-muted)' }}>{language === 'cs' ? 'Aktuální rychlost' : 'Current Speed'}</span> <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' }}> <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: '1.5rem', fontWeight: 'bold', color: 'var(--text-main)' }}>{currentSpeed.toFixed(1)}</span>
@@ -198,7 +212,7 @@ export const WindChart = ({ lat, lng, language, timeRange = '7d', windUnit = 'km
</div> </div>
</div> </div>
<div style={{ display: 'flex', flexDirection: 'column' }}> <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
<span style={{ fontSize: '0.8rem', color: 'var(--text-muted)' }}>{language === 'cs' ? 'Max. nárazy' : 'Peak Gusts'}</span> <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' }}> <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: '1.5rem', fontWeight: 'bold', color: 'var(--text-main)' }}>{maxGust.toFixed(1)}</span>
@@ -208,9 +222,9 @@ export const WindChart = ({ lat, lng, language, timeRange = '7d', windUnit = 'km
</div> </div>
</div> </div>
<div style={{ flex: 1, minHeight: '280px', width: '100%', marginTop: '0.5rem' }}> <div style={{ flex: 1, minHeight: '280px', width: '100%', marginTop: '0' }}>
<ResponsiveContainer width="100%" height="100%"> <ResponsiveContainer width="100%" height="100%">
<ComposedChart data={data} margin={{ top: 20, right: 0, left: -20, bottom: 0 }}> <ComposedChart data={data} margin={isMobile ? { top: 5, right: 5, left: 5, bottom: 0 } : { top: 5, right: 0, left: -20, bottom: 0 }}>
<defs> <defs>
<linearGradient id="colorWind" x1="0" y1="0" x2="0" y2="1"> <linearGradient id="colorWind" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="var(--color-cyan)" stopOpacity={0.4}/> <stop offset="5%" stopColor="var(--color-cyan)" stopOpacity={0.4}/>
@@ -220,7 +234,7 @@ export const WindChart = ({ lat, lng, language, timeRange = '7d', windUnit = 'km
<XAxis <XAxis
dataKey="time" dataKey="time"
stroke="var(--text-muted)" stroke="var(--text-muted)"
tick={{fill: 'var(--text-muted)', fontSize: 11}} tick={{fill: 'var(--text-muted)', fontSize: isMobile ? 10 : 11}}
minTickGap={60} minTickGap={60}
tickFormatter={(v) => { tickFormatter={(v) => {
const d = new Date(v); const d = new Date(v);
@@ -229,7 +243,9 @@ export const WindChart = ({ lat, lng, language, timeRange = '7d', windUnit = 'km
/> />
<YAxis <YAxis
stroke="var(--text-muted)" stroke="var(--text-muted)"
tick={{fill: 'var(--text-muted)', fontSize: 11}} tick={{fill: 'var(--text-muted)', fontSize: isMobile ? 10 : 11}}
width={isMobile ? 35 : 60}
tickFormatter={(v) => v.toFixed(1)}
/> />
<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} />
<Tooltip content={<CustomWindTooltip language={language} windUnit={windUnit} />} /> <Tooltip content={<CustomWindTooltip language={language} windUnit={windUnit} />} />
@@ -258,7 +274,7 @@ export const WindChart = ({ lat, lng, language, timeRange = '7d', windUnit = 'km
</ResponsiveContainer> </ResponsiveContainer>
</div> </div>
<div style={{ display: 'flex', justifyContent: 'center', gap: '1.5rem', fontSize: '0.85rem', color: 'var(--text-muted)', marginTop: '0.5rem' }}> <div style={{ display: 'flex', justifyContent: 'center', gap: '1.5rem', fontSize: '0.85rem', color: 'var(--text-muted)', marginTop: '0.5rem', padding: isMobile ? '0 0.75rem' : '0' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '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 style={{ display: 'inline-block', width: '12px', height: '3px', backgroundColor: 'var(--color-cyan)' }}></span>
<span>{language === 'cs' ? 'Rychlost větru' : 'Wind Speed'}</span> <span>{language === 'cs' ? 'Rychlost větru' : 'Wind Speed'}</span>