/**
* 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;