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

@@ -0,0 +1,92 @@
/**
* Admin Breadcrumbs
* Displays navigation breadcrumb trail for admin pages
*/
'use client';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { ChevronRight } from 'lucide-react';
interface BreadcrumbItem {
label: string;
href: string;
}
const pathLabels: Record<string, string> = {
admin: 'Admin',
users: 'Users',
organizations: 'Organizations',
settings: 'Settings',
};
export function Breadcrumbs() {
const pathname = usePathname();
// Generate breadcrumb items from pathname
const generateBreadcrumbs = (): BreadcrumbItem[] => {
const segments = pathname.split('/').filter(Boolean);
const breadcrumbs: BreadcrumbItem[] = [];
let currentPath = '';
segments.forEach((segment) => {
currentPath += `/${segment}`;
const label = pathLabels[segment] || segment;
breadcrumbs.push({
label,
href: currentPath,
});
});
return breadcrumbs;
};
const breadcrumbs = generateBreadcrumbs();
if (breadcrumbs.length === 0) {
return null;
}
return (
<nav
aria-label="Breadcrumb"
className="border-b bg-background px-6 py-3"
data-testid="breadcrumbs"
>
<ol className="flex items-center space-x-2 text-sm">
{breadcrumbs.map((breadcrumb, index) => {
const isLast = index === breadcrumbs.length - 1;
return (
<li key={breadcrumb.href} className="flex items-center">
{index > 0 && (
<ChevronRight
className="mx-2 h-4 w-4 text-muted-foreground"
aria-hidden="true"
/>
)}
{isLast ? (
<span
className="font-medium text-foreground"
aria-current="page"
data-testid={`breadcrumb-${breadcrumb.label.toLowerCase()}`}
>
{breadcrumb.label}
</span>
) : (
<Link
href={breadcrumb.href}
className="text-muted-foreground hover:text-foreground transition-colors"
data-testid={`breadcrumb-${breadcrumb.label.toLowerCase()}`}
>
{breadcrumb.label}
</Link>
)}
</li>
);
})}
</ol>
</nav>
);
}