feat: add rivers overview component and sync lake volume data across the dataset

This commit is contained in:
David Fencl
2026-06-08 19:36:54 +02:00
parent ec540e056d
commit 62c861e610
71 changed files with 139421 additions and 29818 deletions
+67 -1
View File
@@ -1,4 +1,5 @@
import { FiArrowUp, FiArrowDown } from 'react-icons/fi';
import { TbRipple } from 'react-icons/tb';
import { type Language, t } from '../translations';
import { useState, useEffect } from 'react';
import { CircularProgress } from './CircularProgress';
@@ -22,9 +23,10 @@ interface Props {
data: KpiData;
language: Language;
lakeName?: string;
isRiver?: boolean;
}
const KpiCards = ({ data, language, lakeName = 'Lipno 1' }: Props) => {
const KpiCards = ({ data, language, lakeName = 'Lipno 1', isRiver = false }: Props) => {
const [showTooltip, setShowTooltip] = useState(false);
const dict = t[language].kpi;
const flowDiff = data.inflow - data.outflow;
@@ -38,6 +40,70 @@ const KpiCards = ({ data, language, lakeName = 'Lipno 1' }: Props) => {
}
}, [showTooltip]);
if (isRiver) {
return (
<>
{/* CARD 1: WATER LEVEL */}
<div className="kpi-card">
<div style={{ fontSize: '1rem', color: 'var(--text-muted)', marginBottom: '1rem' }}>
{dict.waterLevel} {lakeName}
</div>
<div style={{ fontSize: '2.5rem', fontWeight: 'bold', color: 'var(--color-cyan)', lineHeight: 1, whiteSpace: 'nowrap' }}>
{data.level.toFixed(0)} <span style={{ fontSize: '1rem', color: 'var(--text-muted)', fontWeight: 'normal' }}>cm</span>
</div>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.3rem', alignContent: 'flex-start', marginTop: '0.5rem' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.3rem', background: 'rgba(0,0,0,0.15)', padding: '0.2rem 0.4rem', borderRadius: '6px' }}>
<span style={{ fontSize: '0.75rem', color: 'var(--text-muted)', fontWeight: 'bold' }}>1D</span>
<span style={{ fontSize: '0.85rem', fontWeight: 'bold', color: (data.levelDiff24h ?? 0) >= 0 ? 'var(--color-green)' : 'var(--color-red)' }}>
{(data.levelDiff24h ?? 0) > 0 ? '+' : ''}{(data.levelDiff24h ?? 0).toFixed(0)} cm
</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.3rem', background: 'rgba(0,0,0,0.15)', padding: '0.2rem 0.4rem', borderRadius: '6px' }}>
<span style={{ fontSize: '0.75rem', color: 'var(--text-muted)', fontWeight: 'bold' }}>7D</span>
<span style={{ fontSize: '0.85rem', fontWeight: 'bold', color: (data.levelDiff7d ?? 0) >= 0 ? 'var(--color-green)' : 'var(--color-red)' }}>
{(data.levelDiff7d ?? 0) > 0 ? '+' : ''}{(data.levelDiff7d ?? 0).toFixed(0)} cm
</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.3rem', background: 'rgba(0,0,0,0.15)', padding: '0.2rem 0.4rem', borderRadius: '6px' }}>
<span style={{ fontSize: '0.75rem', color: 'var(--text-muted)', fontWeight: 'bold' }}>30D</span>
<span style={{ fontSize: '0.85rem', fontWeight: 'bold', color: (data.levelDiff30d ?? 0) >= 0 ? 'var(--color-green)' : 'var(--color-red)' }}>
{(data.levelDiff30d ?? 0) > 0 ? '+' : ''}{(data.levelDiff30d ?? 0).toFixed(0)} cm
</span>
</div>
</div>
</div>
{/* CARD 2: FLOW */}
<div className="kpi-card">
<div style={{ fontSize: '1rem', color: 'var(--text-muted)', marginBottom: '1rem' }}>
{dict.currentFlow}
</div>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<div>
<div style={{ fontSize: '2.5rem', fontWeight: 'bold', color: 'var(--color-cyan)', lineHeight: 1, whiteSpace: 'nowrap', marginBottom: '0.5rem' }}>
{data.outflow.toFixed(1)} <span style={{ fontSize: '1.25rem', color: 'var(--text-muted)', fontWeight: 'normal' }}>m³/s</span>
</div>
{data.avgOutflow24h !== undefined && (
<div style={{ fontSize: '0.85rem', color: 'var(--text-muted)' }}>
Ø 24h: <span style={{ fontWeight: 'bold', color: 'var(--text-main)' }}>{data.avgOutflow24h.toFixed(1)} m³/s</span>
</div>
)}
</div>
<div style={{
width: '70px', height: '70px', borderRadius: '50%',
backgroundColor: 'rgba(6, 182, 212, 0.1)',
border: '2px dashed var(--color-cyan)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
color: 'var(--color-cyan)', flexShrink: 0
}}>
<TbRipple size={36} />
</div>
</div>
</div>
</>
);
}
return (
<>
{/* CARD 1: WATER LEVEL */}