import { ts } from '../../i18n/server'; import { getEnumValueColor } from '../../lib/consts'; function shortenAxisLabel(label: string, total: number): string { if (label.length <= 3) return label; const parts = label.split(/[\s/&-]+/).filter(Boolean); if (parts.length > 1) { return parts .map((part) => Array.from(part)[0]) .join('') .slice(0, 3); } return Array.from(label) .slice(0, total <= 5 ? 3 : 2) .join(''); } export default function EnumBarChart({ counts, globalCounts, featureName, compact = false, }: { counts: Record; globalCounts?: Record; featureName: string; compact?: boolean; }) { const entries = Object.entries(counts).sort(([, countA], [, countB]) => countB - countA); if (entries.length === 0) return null; const localTotal = entries.reduce((sum, [, c]) => sum + c, 0); // When global counts are available, normalize both to percentages for comparison const globalTotal = globalCounts ? Object.values(globalCounts).reduce((sum, c) => sum + c, 0) : 0; const hasGlobal = globalCounts && globalTotal > 0; // Compute max percentage across both datasets for consistent bar scaling const maxPct = entries.reduce((max, [label, count]) => { const localPct = localTotal > 0 ? count / localTotal : 0; const globalPct = hasGlobal ? (globalCounts[label] ?? 0) / globalTotal : 0; return Math.max(max, localPct, globalPct); }, 0); // Fallback to raw count scaling when no global data const maxCount = Math.max(...entries.map(([, count]) => count), 1); if (compact) { const title = entries .map(([label, count]) => { const localPct = localTotal > 0 ? (count / localTotal) * 100 : 0; const globalPct = hasGlobal && globalTotal > 0 ? ((globalCounts[label] ?? 0) / globalTotal) * 100 : null; return `${ts(label)}: ${count.toLocaleString()} (${localPct.toFixed(1)}%)${ globalPct != null ? ` / ${globalPct.toFixed(1)}%` : '' }`; }) .join('\n'); return (
{entries.map(([label, count]) => { const localPct = localTotal > 0 ? count / localTotal : 0; const globalPct = hasGlobal ? (globalCounts[label] ?? 0) / globalTotal : 0; const localHeight = hasGlobal ? maxPct > 0 ? (localPct / maxPct) * 100 : 0 : (count / maxCount) * 100; const globalHeight = hasGlobal && maxPct > 0 ? (globalPct / maxPct) * 100 : 0; const color = getEnumValueColor(featureName, label); return (
{hasGlobal && (
0 ? 8 : 0)}%` }} /> )} {count > 0 && (
)}
); })}
{entries.map(([label]) => { const translated = ts(label); return ( {shortenAxisLabel(translated, entries.length)} ); })}
); } return (
{entries.map(([label, count]) => { const localPct = localTotal > 0 ? count / localTotal : 0; const globalPct = hasGlobal ? (globalCounts[label] ?? 0) / globalTotal : 0; const localWidth = hasGlobal ? maxPct > 0 ? (localPct / maxPct) * 100 : 0 : (count / maxCount) * 100; const globalWidth = hasGlobal && maxPct > 0 ? (globalPct / maxPct) * 100 : 0; const color = getEnumValueColor(featureName, label); const barStyle = `rgb(${color[0]},${color[1]},${color[2]})`; return (
{ts(label)}
{hasGlobal && (
)}
{count}
); })}
); }