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:
13
apps/webui/src/app/dashboard/[guildId]/commands/loading.tsx
Normal file
13
apps/webui/src/app/dashboard/[guildId]/commands/loading.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
22
apps/webui/src/app/dashboard/[guildId]/commands/page.tsx
Normal file
22
apps/webui/src/app/dashboard/[guildId]/commands/page.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user