Enhance dashboard overview with activity summary and sidebar commands

- Integrated activity summary into the Guild Overview page, displaying message count, voice minutes, and active user count for the last 7 days.
- Updated sidebar to include a new "Commands" link for easier navigation.
- Added corresponding localization keys for activity metrics in both English and German JSON files.
This commit is contained in:
smueller
2026-07-22 15:54:03 +02:00
parent e0b4077552
commit 39cca96fed
8 changed files with 785 additions and 8 deletions

View File

@@ -0,0 +1,13 @@
import { Skeleton } from '@/components/ui/skeleton';
export default function CommandsLoading() {
return (
<div className="space-y-6">
<div className="space-y-2">
<Skeleton className="h-8 w-48" />
<Skeleton className="h-4 w-80" />
</div>
<Skeleton className="h-96 rounded-lg" />
</div>
);
}

View File

@@ -0,0 +1,22 @@
import { CommandsManager } from '@/components/modules/commands-manager';
import { getLocale, t } from '@/lib/i18n';
import { listCommandOverridesDashboard } from '@/lib/module-configs/commands';
interface CommandsPageProps {
params: Promise<{ guildId: string }>;
}
export default async function CommandsPage({ params }: CommandsPageProps) {
const { guildId } = await params;
const [locale, commands] = await Promise.all([getLocale(), listCommandOverridesDashboard(guildId)]);
return (
<div className="space-y-6">
<div>
<h1 className="text-2xl font-semibold">{t(locale, 'modulePages.commands.title')}</h1>
<p className="text-sm text-muted-foreground">{t(locale, 'modulePages.commands.description')}</p>
</div>
<CommandsManager guildId={guildId} initialCommands={commands} />
</div>
);
}

View File

@@ -1,4 +1,5 @@
import Link from 'next/link';
import { getActivitySummary } from '@/lib/activity';
import { Badge } from '@/components/ui/badge';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { listRecentDashboardAudit } from '@/lib/audit';
@@ -19,15 +20,41 @@ function formatDate(iso: string, locale: string): string {
export default async function GuildOverviewPage({ params }: OverviewPageProps) {
const { guildId } = await params;
const locale = await getLocale();
const [modules, auditEntries] = await Promise.all([
const [modules, auditEntries, activitySummary] = await Promise.all([
getModuleStatuses(guildId),
listRecentDashboardAudit(guildId, 10)
listRecentDashboardAudit(guildId, 10),
getActivitySummary(guildId)
]);
return (
<div className="space-y-8">
<h1 className="text-2xl font-semibold">{t(locale, 'dashboard.overview.title')}</h1>
<section className="space-y-4">
<h2 className="text-lg font-medium">{t(locale, 'dashboard.overview.activityTitle')}</h2>
<div className="grid gap-3 sm:grid-cols-3">
<Card>
<CardContent className="p-4">
<p className="text-xs text-muted-foreground">{t(locale, 'dashboard.overview.activityMessages')}</p>
<p className="text-2xl font-semibold">{activitySummary.messageCount.toLocaleString(locale === 'de' ? 'de-DE' : 'en-US')}</p>
</CardContent>
</Card>
<Card>
<CardContent className="p-4">
<p className="text-xs text-muted-foreground">{t(locale, 'dashboard.overview.activityVoiceMinutes')}</p>
<p className="text-2xl font-semibold">{activitySummary.voiceMinutes.toLocaleString(locale === 'de' ? 'de-DE' : 'en-US')}</p>
</CardContent>
</Card>
<Card>
<CardContent className="p-4">
<p className="text-xs text-muted-foreground">{t(locale, 'dashboard.overview.activityActiveUsers')}</p>
<p className="text-2xl font-semibold">{activitySummary.activeUserCount.toLocaleString(locale === 'de' ? 'de-DE' : 'en-US')}</p>
</CardContent>
</Card>
</div>
<p className="text-xs text-muted-foreground">{t(locale, 'dashboard.overview.activityHint')}</p>
</section>
<section className="space-y-4">
<div className="flex items-center justify-between">
<h2 className="text-lg font-medium">{t(locale, 'dashboard.overview.moduleStatusTitle')}</h2>