← Back
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...