/** * Namespace Overview — presentational view. Pure: renders per-namespace fact / * entity counts as a ranked bar list + summary tiles. No data fetching, no * clock, no RNG. */ import { useT } from '../../lib/i18n/I18nContext'; import type { NamespaceOverviewReport } from '../../lib/memory/namespaceOverview'; import Button from '../ui/Button'; const MAX_ROWS = 50; interface NamespaceOverviewPanelProps { report: NamespaceOverviewReport | null; loading?: boolean; error?: string | null; onRetry?: () => void; } const NamespaceOverviewPanel = ({ report, loading, error, onRetry, }: NamespaceOverviewPanelProps) => { const { t } = useT(); const intro = (

{t('namespaceOverview.title')}

{t('namespaceOverview.intro')}

); if (loading) { return (
{intro}
{[0, 1, 2].map(i => (
))}
{[0, 1, 2].map(i => (
))}
); } if (error) { return (
{intro}

{t('namespaceOverview.errorPrefix')} {error}

{onRetry && ( )}
); } if (!report || report.namespaceCount === 0) { return (
{intro}

{t('namespaceOverview.empty')}

{t('namespaceOverview.emptyHint')}

); } const maxFacts = report.namespaces[0]?.factCount || 1; const rows = report.namespaces.slice(0, MAX_ROWS); const truncated = report.namespaces.length > MAX_ROWS; return (
{intro} {/* Summary tiles */}
{[ { label: t('namespaceOverview.metricNamespaces'), value: report.namespaceCount }, { label: t('namespaceOverview.metricFacts'), value: report.totalFacts }, { label: t('namespaceOverview.metricEntities'), value: report.totalEntities }, ].map(tile => (
{tile.label}
{tile.value}
))}
{/* Ranked namespace list */}

{t('namespaceOverview.heading')}

    {rows.map(stat => (
  • {stat.namespace ?? t('namespaceOverview.unnamespaced')}
    {stat.factCount} {t('namespaceOverview.entitiesShort').replace('{count}', String(stat.entityCount))}
  • ))}
{truncated && (

{t('namespaceOverview.truncated') .replace('{shown}', String(rows.length)) .replace('{total}', String(report.namespaces.length))}

)}
); }; export default NamespaceOverviewPanel;