import { useEffect, useState } from 'react'; import { apiGet } from '../api.js'; import { SkeletonRows } from '../components/Skeleton.jsx'; import { IconTrophy, IconLevel } from '../icons.jsx'; import EmptyState from '../components/EmptyState.jsx'; import { useT, useFmt } from '../i18n.jsx'; /** Muss der Formel in src/bot/levels.js entsprechen */ function xpForLevel(level) { let total = 0; for (let n = 0; n < level; n++) total += 5 * n * n + 50 * n + 100; return total; } // Platz 1–3 bekommen einen Pokal in Gold/Silber/Bronze, danach schlicht die Nummer const MEDAL_COLORS = ['#f5c518', '#c0c4cc', '#c07a3e']; /** Nachrichten/Tag der letzten 30 Tage als Balken */ function ActivityChart({ stats }) { const { t } = useT(); const { zahl } = useFmt(); const byDay = new Map(stats.days.map((d) => [d.day, d])); const days = []; for (let i = 29; i >= 0; i--) { const key = new Date(Date.now() - i * 86400000).toISOString().slice(0, 10); days.push({ key, ...(byDay.get(key) ?? { messages: 0, joins: 0, leaves: 0 }) }); } const max = Math.max(1, ...days.map((d) => d.messages)); const total = days.reduce((s, d) => s + d.messages, 0); return (
{t('level.subtitle').split('%s')[0]}/rank{t('level.subtitle').split('%s')[1]}
{t('level.error')}
} {!error && !rows &&