Files
pragma-stack/frontend/src/app/[locale]/admin/page.tsx
Felipe Cardoso a05def5906 Add registration_activity chart and enhance admin statistics
- Introduced `RegistrationActivityChart` to display user registration trends over 14 days.
- Enhanced `AdminStatsResponse` with `registration_activity`, providing improved insights for admin users.
- Updated demo data to include realistic registration activity and organization details.
- Refactored admin page to use updated statistics data model and improved query handling.
- Fixed inconsistent timezone handling in statistical analytics and demo user timestamps.
2025-11-24 17:42:43 +01:00

142 lines
4.8 KiB
TypeScript

/**
* Admin Dashboard Page
* Displays admin statistics and management options
* Protected by AuthGuard in layout with requireAdmin=true
*/
'use client';
import { Link } from '@/lib/i18n/routing';
import { DashboardStats } from '@/components/admin';
import {
UserGrowthChart,
OrganizationDistributionChart,
RegistrationActivityChart,
UserStatusChart,
} from '@/components/charts';
import { Users, Building2, Settings } from 'lucide-react';
import { useQuery } from '@tanstack/react-query';
import { getAdminStats } from '@/lib/api/admin';
export default function AdminPage() {
console.log('[AdminPage] Component rendering');
const {
data: stats,
isLoading,
error,
status,
fetchStatus,
} = useQuery({
queryKey: ['admin', 'analytics'], // Changed from 'stats' to avoid collision with useAdminStats hook
queryFn: async () => {
console.log('[AdminPage] QueryFn executing - fetching stats...');
try {
const response = await getAdminStats();
console.log('[AdminPage] Stats response received:', response);
return response.data;
} catch (err) {
console.error('[AdminPage] Error fetching stats:', err);
throw err;
}
},
enabled: true, // Explicitly enable the query
retry: 1,
staleTime: 60000, // Cache for 1 minute
});
console.log('[AdminPage] Current state:', {
isLoading,
hasError: Boolean(error),
error: error?.message,
hasData: Boolean(stats),
dataKeys: stats ? Object.keys(stats) : null,
status,
fetchStatus,
});
return (
<div className="container mx-auto px-6 py-8">
<div className="space-y-8">
{/* Page Header */}
<div>
<h1 className="text-3xl font-bold tracking-tight">Admin Dashboard</h1>
<p className="mt-2 text-muted-foreground">
Manage users, organizations, and system settings
</p>
</div>
{/* Stats Grid */}
<DashboardStats />
{/* Quick Actions */}
<div>
<h2 className="text-xl font-semibold mb-4">Quick Actions</h2>
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
<Link href="/admin/users" className="block">
<div className="rounded-lg border bg-card p-6 transition-colors hover:bg-accent cursor-pointer">
<div className="flex items-center gap-3 mb-2">
<Users className="h-5 w-5 text-primary" aria-hidden="true" />
<h3 className="font-semibold">User Management</h3>
</div>
<p className="text-sm text-muted-foreground">
View, create, and manage user accounts
</p>
</div>
</Link>
<Link href="/admin/organizations" className="block">
<div className="rounded-lg border bg-card p-6 transition-colors hover:bg-accent cursor-pointer">
<div className="flex items-center gap-3 mb-2">
<Building2 className="h-5 w-5 text-primary" aria-hidden="true" />
<h3 className="font-semibold">Organizations</h3>
</div>
<p className="text-sm text-muted-foreground">
Manage organizations and their members
</p>
</div>
</Link>
<Link href="/admin/settings" className="block">
<div className="rounded-lg border bg-card p-6 transition-colors hover:bg-accent cursor-pointer">
<div className="flex items-center gap-3 mb-2">
<Settings className="h-5 w-5 text-primary" aria-hidden="true" />
<h3 className="font-semibold">System Settings</h3>
</div>
<p className="text-sm text-muted-foreground">Configure system-wide settings</p>
</div>
</Link>
</div>
</div>
{/* Analytics Charts */}
<div>
<h2 className="text-xl font-semibold mb-4">Analytics Overview</h2>
<div className="grid gap-6 md:grid-cols-2">
<UserGrowthChart
data={stats?.user_growth}
loading={isLoading}
error={error ? (error as Error).message : null}
/>
<RegistrationActivityChart
data={stats?.registration_activity}
loading={isLoading}
error={error ? (error as Error).message : null}
/>
<OrganizationDistributionChart
data={stats?.organization_distribution}
loading={isLoading}
error={error ? (error as Error).message : null}
/>
<UserStatusChart
data={stats?.user_status}
loading={isLoading}
error={error ? (error as Error).message : null}
/>
</div>
</div>
</div>
</div>
);
}