import type { ScreenerStats } from '../../types/market';
import { formatVolume, truncate } from '../../utils/format';
import { useT } from '../../i18n/LanguageContext';
interface Props {
stats: ScreenerStats | null;
loading: boolean;
}
export default function KPIBar({ stats, loading }: Props) {
const { t } = useT();
if (loading || !stats) {
return (
<div className="kpi-bar">
{[1, 2, 3, 4].map(i => (
<div key={i} className="kpi-card kpi-skeleton">
<div className="kpi-value skeleton-line" />
<div className="kpi-label skeleton-line" />
</div>
))}
</div>
);
}
// Defensive: a stale PWA-cached stats response (old shape) shouldn't crash the
// whole tab via ErrorBoundary — coerce every field with safe fallbacks.
const totalMarkets = Number(stats.total_markets) || 0;
const vol24 = Number(stats.total_volume_24h) || 0;
const endingToday = Number(stats.ending_today) || 0;
const topQ = stats.top_volume?.question ?? '—';
return (
<div className="kpi-bar">
<div className="kpi-card">
<div className="kpi-value">{totalMarkets.toLocaleString()}</div>
<div className="kpi-label">{t('mkt.kpiActive')}</div>
</div>
<div className="kpi-card">
<div className="kpi-value">{formatVolume(vol24)}</div>
<div className="kpi-label">{t('mkt.kpiVol24')}</div>
</div>
<div className="kpi-card">
<div className="kpi-value kpi-mover" title={topQ}>
{truncate(topQ, 28)}
</div>
<div className="kpi-label">{t('mkt.kpiTop')}</div>
</div>
<div className="kpi-card">
<div className="kpi-value">{endingToday.toLocaleString()}</div>
<div className="kpi-label">{t('mkt.kpiEnding')}</div>
</div>
</div>
);
}
📜 Git History
6c47fa4chore: local Polikopi project home + Phase 1 redesign artifacts12 days ago
Show last diff
Loading...