UMBRA/frontend/src/components/admin/AdminPortal.tsx
Kyle Pope 2ec70d9344 Add Phase 7 admin portal frontend (IAM, Config, Dashboard)
Creates 7 files: useAdmin hook with TanStack Query v5, AdminPortal
layout with horizontal tab nav, IAMPage with user table + stat cards
+ system settings, UserActionsMenu with two-click confirms, CreateUserDialog,
ConfigPage with paginated audit log + action filter, AdminDashboardPage
with stats + recent logins/actions tables.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 18:40:16 +08:00

65 lines
2.4 KiB
TypeScript

import { NavLink, Routes, Route, Navigate, useLocation } from 'react-router-dom';
import { Users, Settings2, LayoutDashboard, ShieldCheck } from 'lucide-react';
import { cn } from '@/lib/utils';
import IAMPage from './IAMPage';
import ConfigPage from './ConfigPage';
import AdminDashboardPage from './AdminDashboardPage';
const tabs = [
{ label: 'IAM Management', path: '/admin/iam', icon: Users },
{ label: 'Configuration', path: '/admin/config', icon: Settings2 },
{ label: 'Management Dashboard', path: '/admin/dashboard', icon: LayoutDashboard },
];
export default function AdminPortal() {
const location = useLocation();
return (
<div className="flex flex-col h-full animate-fade-in">
{/* Portal header with tab navigation */}
<div className="shrink-0 border-b bg-card">
<div className="px-6 h-16 flex items-center gap-4">
<div className="flex items-center gap-2 mr-6">
<div className="p-1.5 rounded-md bg-red-500/10">
<ShieldCheck className="h-5 w-5 text-red-400" />
</div>
<h1 className="font-heading text-2xl font-bold tracking-tight">Admin Portal</h1>
</div>
{/* Horizontal tab navigation */}
<nav className="flex items-center gap-1 h-full">
{tabs.map(({ label, path, icon: Icon }) => {
const isActive = location.pathname.startsWith(path);
return (
<NavLink
key={path}
to={path}
className={cn(
'flex items-center gap-2 px-4 h-full text-sm font-medium transition-colors duration-150 border-b-2 -mb-px',
isActive
? 'text-accent border-accent'
: 'text-muted-foreground hover:text-foreground border-transparent'
)}
>
<Icon className="h-4 w-4" />
{label}
</NavLink>
);
})}
</nav>
</div>
</div>
{/* Page content */}
<div className="flex-1 overflow-y-auto">
<Routes>
<Route index element={<Navigate to="iam" replace />} />
<Route path="iam" element={<IAMPage />} />
<Route path="config" element={<ConfigPage />} />
<Route path="dashboard" element={<AdminDashboardPage />} />
</Routes>
</div>
</div>
);
}