feat: update lake index, sync scraping scripts, and prune unused data files

This commit is contained in:
David Fencl
2026-06-05 22:24:47 +02:00
parent 61a8af109c
commit 5411bd16ff
33 changed files with 1793 additions and 3127 deletions
+83 -52
View File
@@ -1,5 +1,6 @@
import { FiArrowUp, FiArrowDown } from 'react-icons/fi';
import { type Language, t } from '../translations';
import { useState, useEffect } from 'react';
interface KpiData {
level: number;
@@ -16,73 +17,103 @@ interface Props {
}
const KpiCards = ({ data, language, lakeName = 'Lipno 1' }: Props) => {
const [showTooltip, setShowTooltip] = useState(false);
const dict = t[language].kpi;
const flowDiff = data.inflow - data.outflow;
useEffect(() => {
if (showTooltip) {
const timer = setTimeout(() => {
setShowTooltip(false);
}, 3500);
return () => clearTimeout(timer);
}
}, [showTooltip]);
return (
<div className="kpi-container-mobile">
<div className="kpi-grid-container">
{/* CARD 1: HLADINA */}
<div className="kpi-card-full">
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<div>
<div style={{ fontSize: '1rem', color: 'var(--text-muted)', marginBottom: '0.5rem' }}>
{dict.level} {lakeName}
<div className="kpi-card">
<div style={{ fontSize: '1rem', color: 'var(--text-muted)', marginBottom: '0.5rem' }}>
{dict.level} {lakeName}
</div>
<div style={{ fontSize: '2.5rem', fontWeight: 'bold', color: 'var(--color-cyan)', lineHeight: 1, marginBottom: '0.5rem' }}>
{data.level.toFixed(2)} <span style={{ fontSize: '1rem', color: 'var(--text-muted)', fontWeight: 'normal' }}>m n. m.</span>
</div>
<div style={{ fontSize: '0.85rem', color: 'var(--color-green)' }}>
(+0.02 m / 24h)
</div>
{/* Decorative Circle for Level */}
<div style={{ position: 'absolute', right: '1.5rem', top: '1.5rem', width: '40px', height: '40px', borderRadius: '50%', border: '4px solid rgba(0, 195, 255, 0.2)', borderTopColor: 'var(--color-cyan)', transform: 'rotate(45deg)' }}></div>
</div>
{/* CARD 2: PRŮTOK */}
<div className="kpi-card">
<div style={{ fontSize: '1rem', color: 'var(--text-muted)', marginBottom: '0.5rem' }}>
{dict.flow}
</div>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', height: '100%' }}>
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.25rem', fontSize: '0.85rem' }}>
<div style={{ fontSize: '0.85rem', color: 'var(--text-muted)' }}>
{dict.inflow}: <span style={{ fontWeight: 'bold', color: 'var(--text-main)' }}>{data.inflow.toFixed(1)} m³/s</span>
</div>
<div style={{ fontSize: '2.5rem', fontWeight: 'bold', color: 'var(--color-cyan)', lineHeight: 1 }}>
{data.level.toFixed(2)} <span style={{ fontSize: '1.2rem', fontWeight: 'normal', color: 'var(--text-main)' }}>m n. m.</span>
</div>
<div style={{ fontSize: '0.9rem', color: 'var(--color-green)', marginTop: '0.5rem' }}>
(+0.02 m / 24h)
<div style={{ fontSize: '0.85rem', color: 'var(--text-muted)', marginTop: '0.25rem', display: 'flex', alignItems: 'center', gap: '0.25rem' }}>
{dict.outflow}: <span style={{ fontWeight: 'bold', color: 'var(--text-main)' }}>{data.outflow.toFixed(1)} m³/s</span>
{flowDiff > 0 ? <FiArrowUp color="var(--color-green)" /> : flowDiff < 0 ? <FiArrowDown color="var(--color-red)" /> : null}
</div>
</div>
{/* Decorative Circle */}
<div style={{ width: '60px', height: '60px', position: 'relative' }}>
<svg width="60" height="60" viewBox="0 0 60 60">
<circle cx="30" cy="30" r="26" fill="transparent" stroke="rgba(255,255,255,0.05)" strokeWidth="6" />
<circle cx="30" cy="30" r="26" fill="transparent" stroke="var(--color-cyan)" strokeWidth="6" strokeDasharray="163" strokeDashoffset="40" strokeLinecap="round" transform="rotate(-90 30 30)" />
</svg>
{/* Flow Circle */}
<div style={{ width: '40px', height: '40px', borderRadius: '50%', border: '4px solid rgba(0, 195, 255, 0.2)', borderTopColor: 'var(--color-cyan)', borderRightColor: 'var(--color-cyan)', display: 'flex', alignItems: 'center', justifyContent: 'center', transform: 'rotate(-45deg)' }}>
<span style={{ fontSize: '0.65rem', transform: 'rotate(45deg)', color: 'var(--text-main)', fontWeight: 'bold' }}>
<div style={{ lineHeight: 1 }}>{data.outflow.toFixed(1)}</div>
<div style={{ fontSize: '0.45rem', opacity: 0.7 }}>m³/s</div>
</span>
</div>
</div>
</div>
<div className="kpi-row-half">
{/* CARD 2: PRŮTOK */}
<div className="kpi-card-half">
<div style={{ fontSize: '1rem', color: 'var(--text-muted)', marginBottom: '0.5rem' }}>
{dict.flow}
</div>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', height: '100%' }}>
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.25rem', fontSize: '0.85rem' }}>
<span style={{ color: 'var(--text-main)' }}>{dict.inflow}: <span style={{ fontWeight: 'bold' }}>{data.inflow.toFixed(1)} m³/s</span></span>
<span style={{ color: 'var(--text-main)' }}>{dict.outflow}: <span style={{ fontWeight: 'bold' }}>{data.outflow.toFixed(1)} m³/s</span> <FiArrowDown color="var(--color-red)" /></span>
{/* CARD 3: NAPLNĚNOST */}
<div className="kpi-card">
<div style={{ fontSize: '1rem', color: 'var(--text-muted)', marginBottom: '0.5rem', display: 'flex', alignItems: 'center', gap: '0.4rem', position: 'relative' }}>
{dict.fullness}
<span
onClick={() => setShowTooltip(!showTooltip)}
style={{ cursor: 'pointer', fontSize: '0.85rem', opacity: 0.6, padding: '0 4px' }}
>
</span>
{showTooltip && (
<div
onClick={() => setShowTooltip(false)}
style={{
position: 'absolute',
bottom: '100%',
left: '50%',
transform: 'translateX(-50%)',
marginBottom: '8px',
backgroundColor: 'var(--bg-card)',
border: '1px solid var(--border-color)',
padding: '0.75rem',
borderRadius: '8px',
width: '250px',
zIndex: 100,
boxShadow: '0 4px 12px rgba(0,0,0,0.5)',
color: 'var(--text-main)',
fontSize: '0.85rem',
lineHeight: 1.4,
cursor: 'pointer'
}}>
{language === 'cs' ? "Odhad vypočítaný z aktuální výšky hladiny (mezi min. a max. kótou)." : "Estimate calculated from current water level (between min and max levels)."}
</div>
{/* Flow Circle */}
<div style={{ width: '50px', height: '50px', position: 'relative' }}>
<svg width="50" height="50" viewBox="0 0 50 50">
<circle cx="25" cy="25" r="22" fill="transparent" stroke="rgba(255,255,255,0.05)" strokeWidth="4" />
<circle cx="25" cy="25" r="22" fill="transparent" stroke="var(--color-cyan)" strokeWidth="4" strokeDasharray="138" strokeDashoffset="40" strokeLinecap="round" transform="rotate(-90 25 25)" />
</svg>
<div style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
<span style={{ fontSize: '0.8rem', fontWeight: 'bold', lineHeight: 1 }}>{Math.max(data.inflow, data.outflow).toFixed(1)}</span>
<span style={{ fontSize: '0.5rem', color: 'var(--text-muted)' }}>m³/s</span>
</div>
</div>
</div>
)}
</div>
{/* CARD 3: NAPLNĚNOST */}
<div className="kpi-card-half">
<div style={{ fontSize: '1rem', color: 'var(--text-muted)', marginBottom: '0.5rem' }}>
{dict.fullness}
</div>
<div style={{ fontSize: '2rem', fontWeight: 'bold', lineHeight: 1, marginBottom: '0.5rem' }}>
{data.fullness.toFixed(1)}%
</div>
<div style={{ fontSize: '0.85rem', color: 'var(--text-muted)' }}>
{dict.volume}: {data.volume.toFixed(1)} mil. m³
</div>
<div style={{ fontSize: '2rem', fontWeight: 'bold', lineHeight: 1, marginBottom: '0.5rem' }}>
{data.fullness > 0 ? `${data.fullness.toFixed(1)}%` : 'N/A'}
</div>
<div style={{ fontSize: '0.85rem', color: 'var(--text-muted)' }}>
{dict.volume}: {data.volume.toFixed(1)} mil. m³
</div>
</div>
</div>