import { useMemo } from 'react'; import { Text, View } from 'react-native'; import { useTranslation } from 'react-i18next'; import { useColors } from '../../lib/theme'; import { HalfDonut } from '../common/HalfDonut'; import type { BlockedByConnectionEntry } from '../../hooks/useMailStats'; type Props = { data: BlockedByConnectionEntry[]; hero?: boolean; totalBlocked?: number; accountCount?: number; isLegend?: boolean; }; const SLICE_COLORS = ['#ef4444', '#3b82f6', '#f59e0b', '#8b5cf6']; const OTHER_COLOR = '#a3a3a3'; const MAX_LEGEND_ENTRIES = 3; const DONUT_WIDTH = 200; function formatCompact(n: number): string { if (n < 1000) return n.toLocaleString(); const k = n / 1000; if (k < 10) return `${Math.floor(k * 10) / 10}k+`; return `${Math.floor(k)}k+`; } function domainFromEmail(email: string): string { return email.split('@')[1] ?? email; } function displayLabel(entry: BlockedByConnectionEntry): string { return entry.title ?? domainFromEmail(entry.email); } export function MailDistributionChart({ data, hero, totalBlocked, isLegend }: Props) { const { t } = useTranslation(); const colors = useColors(); const total = data.reduce((s, d) => s + d.count, 0); const slices = useMemo(() => { if (data.length === 0 || total === 0) return []; const sorted = [...data].sort((a, b) => b.count - a.count); if (sorted.length <= MAX_LEGEND_ENTRIES) { return sorted.map((e, i) => ({ label: displayLabel(e), count: e.count, color: SLICE_COLORS[i] ?? OTHER_COLOR, isOther: false, })); } const top3 = sorted.slice(0, MAX_LEGEND_ENTRIES); const rest = sorted.slice(MAX_LEGEND_ENTRIES); const restCount = rest.reduce((s, e) => s + e.count, 0); const restConnectionCount = rest.length; const items = top3.map((e, i) => ({ label: displayLabel(e), count: e.count, color: SLICE_COLORS[i], isOther: false, })); items.push({ label: t('mail.stats.distribution_other_n', { n: restConnectionCount }), count: restCount, color: OTHER_COLOR, isOther: true, }); return items; }, [data, total, t]); if (data.length <= 1 || total === 0) return null; const displayTotal = totalBlocked ?? total; const centerValue = formatCompact(displayTotal); const centerLabel = t('mail.stats.distribution_center_label'); const segments = slices.map((s) => ({ value: s.count, color: s.color })); if (hero) { return ( {slices.map((slice) => ( ))} ); } return ( {slices.map((slice) => ( ))} ); } function LegendRow({ slice, colors, }: { slice: { label: string; count: number; color: string; isOther: boolean }; colors: ReturnType; }) { return ( {slice.label} {slice.count} ); }