Add admin hooks, components, and tests for statistics, navigation, and access control

- Introduced `useAdminStats`, `useAdminUsers`, and `useAdminOrganizations` hooks for admin data fetching with React Query.
- Added `AdminSidebar`, `Breadcrumbs`, and related navigation components for the admin section.
- Implemented comprehensive unit and integration tests for admin components.
- Created E2E tests for admin access control, navigation, and dashboard functionality.
- Updated exports to include new admin components.
This commit is contained in:
Felipe Cardoso
2025-11-06 00:35:11 +01:00
parent 11a78dfcc3
commit 67860c68e3
17 changed files with 2264 additions and 62 deletions

View File

@@ -1,12 +1,14 @@
/**
* Admin Route Group Layout
* Wraps all admin routes with AuthGuard requiring superuser privileges
* Includes sidebar navigation and breadcrumbs
*/
import type { Metadata } from 'next';
import { AuthGuard } from '@/components/auth';
import { Header } from '@/components/layout/Header';
import { Footer } from '@/components/layout/Footer';
import { AdminSidebar, Breadcrumbs } from '@/components/admin';
export const metadata: Metadata = {
title: {
@@ -24,9 +26,15 @@ export default function AdminLayout({
<AuthGuard requireAdmin>
<div className="flex min-h-screen flex-col">
<Header />
<main className="flex-1">
{children}
</main>
<div className="flex flex-1">
<AdminSidebar />
<div className="flex flex-1 flex-col">
<Breadcrumbs />
<main className="flex-1 overflow-y-auto">
{children}
</main>
</div>
</div>
<Footer />
</div>
</AuthGuard>

View File

@@ -0,0 +1,62 @@
/**
* Admin Organizations Page
* Displays and manages all organizations
* Protected by AuthGuard in layout with requireAdmin=true
*/
/* istanbul ignore next - Next.js type import for metadata */
import type { Metadata } from 'next';
import Link from 'next/link';
import { ArrowLeft } from 'lucide-react';
import { Button } from '@/components/ui/button';
/* istanbul ignore next - Next.js metadata, not executable code */
export const metadata: Metadata = {
title: 'Organizations',
};
export default function AdminOrganizationsPage() {
return (
<div className="container mx-auto px-6 py-8">
<div className="space-y-6">
{/* Back Button + Header */}
<div className="flex items-center gap-4">
<Link href="/admin">
<Button variant="outline" size="icon">
<ArrowLeft className="h-4 w-4" />
</Button>
</Link>
<div>
<h1 className="text-3xl font-bold tracking-tight">
Organizations
</h1>
<p className="mt-2 text-muted-foreground">
Manage organizations and their members
</p>
</div>
</div>
{/* Placeholder Content */}
<div className="rounded-lg border bg-card p-12 text-center">
<h3 className="text-xl font-semibold mb-2">
Organization Management Coming Soon
</h3>
<p className="text-muted-foreground max-w-md mx-auto">
This page will allow you to view all organizations, manage their
members, and perform administrative tasks.
</p>
<p className="text-sm text-muted-foreground mt-4">
Features will include:
</p>
<ul className="text-sm text-muted-foreground mt-2 max-w-sm mx-auto text-left">
<li> Organization list with search and filtering</li>
<li> View organization details and members</li>
<li> Manage organization memberships</li>
<li> Organization statistics and activity</li>
<li> Bulk operations</li>
</ul>
</div>
</div>
</div>
);
}

View File

@@ -1,11 +1,14 @@
/**
* Admin Dashboard Page
* Placeholder for future admin functionality
* Displays admin statistics and management options
* Protected by AuthGuard in layout with requireAdmin=true
*/
/* istanbul ignore next - Next.js type import for metadata */
import type { Metadata } from 'next';
import Link from 'next/link';
import { DashboardStats } from '@/components/admin';
import { Users, Building2, Settings } from 'lucide-react';
/* istanbul ignore next - Next.js metadata, not executable code */
export const metadata: Metadata = {
@@ -14,8 +17,9 @@ export const metadata: Metadata = {
export default function AdminPage() {
return (
<div className="container mx-auto px-4 py-8">
<div className="space-y-6">
<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
@@ -25,35 +29,48 @@ export default function AdminPage() {
</p>
</div>
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
<div className="rounded-lg border bg-card p-6">
<h3 className="font-semibold text-lg mb-2">Users</h3>
<p className="text-sm text-muted-foreground">
Manage user accounts and permissions
</p>
<p className="text-xs text-muted-foreground mt-4">
Coming soon...
</p>
</div>
{/* Stats Grid */}
<DashboardStats />
<div className="rounded-lg border bg-card p-6">
<h3 className="font-semibold text-lg mb-2">Organizations</h3>
<p className="text-sm text-muted-foreground">
View and manage organizations
</p>
<p className="text-xs text-muted-foreground mt-4">
Coming soon...
</p>
</div>
{/* 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" />
<h3 className="font-semibold">User Management</h3>
</div>
<p className="text-sm text-muted-foreground">
View, create, and manage user accounts
</p>
</div>
</Link>
<div className="rounded-lg border bg-card p-6">
<h3 className="font-semibold text-lg mb-2">System</h3>
<p className="text-sm text-muted-foreground">
System settings and configuration
</p>
<p className="text-xs text-muted-foreground mt-4">
Coming soon...
</p>
<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" />
<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" />
<h3 className="font-semibold">System Settings</h3>
</div>
<p className="text-sm text-muted-foreground">
Configure system-wide settings
</p>
</div>
</Link>
</div>
</div>
</div>

View File

@@ -0,0 +1,62 @@
/**
* Admin Settings Page
* System-wide settings and configuration
* Protected by AuthGuard in layout with requireAdmin=true
*/
/* istanbul ignore next - Next.js type import for metadata */
import type { Metadata } from 'next';
import Link from 'next/link';
import { ArrowLeft } from 'lucide-react';
import { Button } from '@/components/ui/button';
/* istanbul ignore next - Next.js metadata, not executable code */
export const metadata: Metadata = {
title: 'System Settings',
};
export default function AdminSettingsPage() {
return (
<div className="container mx-auto px-6 py-8">
<div className="space-y-6">
{/* Back Button + Header */}
<div className="flex items-center gap-4">
<Link href="/admin">
<Button variant="outline" size="icon">
<ArrowLeft className="h-4 w-4" />
</Button>
</Link>
<div>
<h1 className="text-3xl font-bold tracking-tight">
System Settings
</h1>
<p className="mt-2 text-muted-foreground">
Configure system-wide settings and preferences
</p>
</div>
</div>
{/* Placeholder Content */}
<div className="rounded-lg border bg-card p-12 text-center">
<h3 className="text-xl font-semibold mb-2">
System Settings Coming Soon
</h3>
<p className="text-muted-foreground max-w-md mx-auto">
This page will allow you to configure system-wide settings,
preferences, and advanced options.
</p>
<p className="text-sm text-muted-foreground mt-4">
Features will include:
</p>
<ul className="text-sm text-muted-foreground mt-2 max-w-sm mx-auto text-left">
<li> General system configuration</li>
<li> Email and notification settings</li>
<li> Security and authentication options</li>
<li> API and integration settings</li>
<li> Maintenance and backup tools</li>
</ul>
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,62 @@
/**
* Admin Users Page
* Displays and manages all users
* Protected by AuthGuard in layout with requireAdmin=true
*/
/* istanbul ignore next - Next.js type import for metadata */
import type { Metadata } from 'next';
import Link from 'next/link';
import { ArrowLeft } from 'lucide-react';
import { Button } from '@/components/ui/button';
/* istanbul ignore next - Next.js metadata, not executable code */
export const metadata: Metadata = {
title: 'User Management',
};
export default function AdminUsersPage() {
return (
<div className="container mx-auto px-6 py-8">
<div className="space-y-6">
{/* Back Button + Header */}
<div className="flex items-center gap-4">
<Link href="/admin">
<Button variant="outline" size="icon">
<ArrowLeft className="h-4 w-4" />
</Button>
</Link>
<div>
<h1 className="text-3xl font-bold tracking-tight">
User Management
</h1>
<p className="mt-2 text-muted-foreground">
View, create, and manage user accounts
</p>
</div>
</div>
{/* Placeholder Content */}
<div className="rounded-lg border bg-card p-12 text-center">
<h3 className="text-xl font-semibold mb-2">
User Management Coming Soon
</h3>
<p className="text-muted-foreground max-w-md mx-auto">
This page will allow you to view all users, create new accounts,
manage permissions, and perform bulk operations.
</p>
<p className="text-sm text-muted-foreground mt-4">
Features will include:
</p>
<ul className="text-sm text-muted-foreground mt-2 max-w-sm mx-auto text-left">
<li> User list with search and filtering</li>
<li> Create/edit/delete user accounts</li>
<li> Activate/deactivate users</li>
<li> Role and permission management</li>
<li> Bulk operations</li>
</ul>
</div>
</div>
</div>
);
}