import { useMemo } from 'react'; import { Text, View } from 'react-native'; import { useTranslation } from 'react-i18next'; import { useColors } from '../../lib/theme'; import type { BlockedByDayEntry } from '../../hooks/useMailStats'; type Props = { data: BlockedByDayEntry[]; granularity?: 'day' | 'week' | 'month'; }; const BAR_AREA_HEIGHT = 64; const MIN_BAR_HEIGHT = 3; function formatAxisLabel(dateStr: string): string { const d = new Date(dateStr + 'T00:00:00'); return `${d.getDate()}.${d.getMonth() + 1}.`; } function headingKey(granularity: 'day' | 'week' | 'month'): string { if (granularity === 'week') return 'mail.stats.blocked_per_week_heading'; if (granularity === 'month') return 'mail.stats.blocked_per_month_heading'; return 'mail.stats.blocked_per_day_heading'; } export function MailBlockedByDayChart({ data, granularity = 'day' }: Props) { const { t } = useTranslation(); const colors = useColors(); const allZero = data.every((d) => d.count === 0); const total = data.reduce((s, d) => s + d.count, 0); const weekAvg = data.length >= 7 ? Math.round(data.slice(-7).reduce((s, d) => s + d.count, 0)) : total; const maxCount = useMemo(() => Math.max(...data.map((d) => d.count), 1), [data]); const axisIndices = useMemo(() => { if (data.length === 0) return []; const step = Math.floor(data.length / 4); return [0, step, step * 2, step * 3, data.length - 1].filter( (v, i, arr) => arr.indexOf(v) === i, ); }, [data]); return ( {t(headingKey(granularity))} {allZero ? ( {t('mail.stats.empty_title')} {t('mail.stats.empty_body')} ) : ( <> {/* Bar chart */} {data.map((entry) => { const barH = entry.count > 0 ? Math.max(MIN_BAR_HEIGHT, Math.round((entry.count / maxCount) * BAR_AREA_HEIGHT)) : MIN_BAR_HEIGHT; return ( 0 ? colors.error : colors.border, }} /> ); })} {/* Axis labels */} {axisIndices.map((idx) => { const pct = data.length > 1 ? idx / (data.length - 1) : 0; return ( {formatAxisLabel(data[idx].date)} ); })} {/* Summary line */} {t('mail.stats.blocked_per_day_sublabel', { total, avg: weekAvg })} )} ); }