mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-03 07:48:34 +02:00
fix(i18n, dashboard): Internationalize recent activity chart dates
This commit is contained in:
@@ -35,18 +35,31 @@ interface DailyActivity {
|
|||||||
count: number;
|
count: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertRecentActivity(timeBuckets: TimeBucket[]): DailyActivity[] {
|
function convertRecentActivity(timeBuckets: TimeBucket[], locale: string): DailyActivity[] {
|
||||||
|
const dateFormatter = new Intl.DateTimeFormat(locale, {
|
||||||
|
month: 'short',
|
||||||
|
day: 'numeric',
|
||||||
|
});
|
||||||
|
|
||||||
return timeBuckets.map(bucket => {
|
return timeBuckets.map(bucket => {
|
||||||
const date = new Date(bucket.timestamp_ms);
|
const date = new Date(bucket.timestamp_ms);
|
||||||
const mm = String(date.getMonth() + 1).padStart(2, '0');
|
|
||||||
const dd = String(date.getDate()).padStart(2, '0');
|
|
||||||
return {
|
return {
|
||||||
date: `${mm}-${dd}`,
|
date: dateFormatter.format(date),
|
||||||
count: bucket.count,
|
count: bucket.count,
|
||||||
|
timestamp_ms: bucket.timestamp_ms,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const formatTooltipDate = (timestamp_ms: number, locale: string): string => {
|
||||||
|
const date = new Date(timestamp_ms);
|
||||||
|
return new Intl.DateTimeFormat(locale, {
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
day: 'numeric',
|
||||||
|
}).format(date);
|
||||||
|
};
|
||||||
|
|
||||||
const COLORS = ['#3b82f6', '#10b981', '#f59e0b', '#ef4444'];
|
const COLORS = ['#3b82f6', '#10b981', '#f59e0b', '#ef4444'];
|
||||||
|
|
||||||
// Skeleton Components
|
// Skeleton Components
|
||||||
@@ -94,7 +107,10 @@ export default function MailArchiveDashboard() {
|
|||||||
queryFn: get_dashboard_stats,
|
queryFn: get_dashboard_stats,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
|
|
||||||
|
const currentLocale = i18n.resolvedLanguage || i18n.language || navigator.language;
|
||||||
|
|
||||||
const totalAttachments = (stats?.with_attachment_count ?? 0) + (stats?.without_attachment_count ?? 0);
|
const totalAttachments = (stats?.with_attachment_count ?? 0) + (stats?.without_attachment_count ?? 0);
|
||||||
const attachmentRatio = totalAttachments > 0 ? (stats?.with_attachment_count ?? 0) / totalAttachments : 0;
|
const attachmentRatio = totalAttachments > 0 ? (stats?.with_attachment_count ?? 0) / totalAttachments : 0;
|
||||||
|
|
||||||
@@ -253,12 +269,25 @@ export default function MailArchiveDashboard() {
|
|||||||
<CardContent className="h-80">
|
<CardContent className="h-80">
|
||||||
{hasRecentActivity ? (
|
{hasRecentActivity ? (
|
||||||
<ResponsiveContainer width="100%" height="100%">
|
<ResponsiveContainer width="100%" height="100%">
|
||||||
<BarChart data={convertRecentActivity(stats!.recent_activity)} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
|
<BarChart data={convertRecentActivity(stats!.recent_activity, currentLocale)} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
|
||||||
<CartesianGrid strokeDasharray="3 3" />
|
<CartesianGrid strokeDasharray="3 3" />
|
||||||
<XAxis dataKey="date" tick={{ fontSize: 12 }} />
|
<XAxis dataKey="date" tick={{ fontSize: 12 }} interval="preserveStart" tickCount={10} />
|
||||||
<YAxis tick={{ fontSize: 12 }} />
|
<YAxis tick={{ fontSize: 12 }} />
|
||||||
<Tooltip
|
<Tooltip
|
||||||
formatter={(v) => formatNumber(v as number)}
|
formatter={(v) => formatNumber(v as number)}
|
||||||
|
content={({ payload }) => {
|
||||||
|
if (payload && payload.length) {
|
||||||
|
const dataPoint = payload[0].payload;
|
||||||
|
const fullDate = formatTooltipDate(dataPoint.timestamp_ms, currentLocale);
|
||||||
|
return (
|
||||||
|
<div className="p-2 border rounded-lg shadow-md bg-white dark:bg-gray-800">
|
||||||
|
<p className="font-semibold text-sm mb-1">{fullDate}</p>
|
||||||
|
<p className="text-xs">{t('dashboard.emails')}: {formatNumber(dataPoint.count)}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}}
|
||||||
contentStyle={{
|
contentStyle={{
|
||||||
backgroundColor: 'hsl(var(--background))',
|
backgroundColor: 'hsl(var(--background))',
|
||||||
border: '1px solid hsl(var(--border))',
|
border: '1px solid hsl(var(--border))',
|
||||||
|
|||||||
Reference in New Issue
Block a user