auth-yes/ui/components/AdminLayout.tsx

227 lines
6.6 KiB
TypeScript

import { COMMON_CSS } from "./CommonStyles.ts";
export const AdminLayout = ({
children,
title,
currentPath,
}: {
children: any;
title: string;
currentPath: string;
}) => {
const adminNavItems = [
{ label: "Users", href: "/admin/users" },
{ label: "Applications", href: "/admin/apps" },
{ label: "Roles", href: "/admin/roles" },
{ label: "Invite Tokens", href: "/admin/invites" },
{ label: "AAGUID Allow-List", href: "/admin/aaguid" },
{ label: "Audit Logs", href: "/admin/audit-logs" },
];
return (
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<meta name="theme-color" content="#0f172a" />
<title>{title} - Auth-Yes Admin</title>
<style>
{`
${COMMON_CSS}
.admin-shell {
display: flex;
flex-direction: column;
min-height: 100vh;
}
/* Admin Top Header */
.admin-header {
background-color: var(--surface-card);
border-bottom: 1px solid var(--border-subtle);
padding: 0.75rem 1.25rem;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: var(--shadow-sm);
}
.admin-brand {
display: flex;
align-items: center;
gap: 0.65rem;
text-decoration: none;
color: var(--text-primary);
font-weight: 700;
font-size: 1.1rem;
}
.admin-badge {
background-color: #0f172a;
color: #38bdf8;
font-size: 0.75rem;
font-weight: 700;
padding: 0.2rem 0.5rem;
border-radius: var(--radius-sm);
letter-spacing: 0.05em;
text-transform: uppercase;
}
/* Sub-Navigation Pill Strip */
.admin-nav-bar {
background-color: var(--surface-card);
border-bottom: 1px solid var(--border-subtle);
padding: 0.5rem 1.25rem;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
display: flex;
gap: 0.5rem;
white-space: nowrap;
}
.admin-nav-bar::-webkit-scrollbar {
display: none;
}
.admin-nav-item {
display: inline-flex;
align-items: center;
padding: 0.4rem 0.85rem;
border-radius: var(--radius-full);
text-decoration: none;
color: var(--text-secondary);
font-size: 0.85rem;
font-weight: 600;
border: 1px solid transparent;
transition: all 0.15s ease;
}
.admin-nav-item:hover {
background-color: var(--surface-muted);
color: var(--text-primary);
}
.admin-nav-item.active {
background-color: var(--primary-light);
color: var(--primary);
border-color: var(--primary-ring);
}
/* Admin Main Container */
.admin-main-content {
flex: 1;
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 1.5rem 1rem;
box-sizing: border-box;
}
@media (min-width: 768px) {
.admin-header {
padding: 0.75rem 2rem;
}
.admin-nav-bar {
padding: 0.5rem 2rem;
}
.admin-main-content {
padding: 2.5rem 2rem;
}
}
/* Table Styles */
.table-container {
width: 100%;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
border-radius: var(--radius-md);
border: 1px solid var(--border-subtle);
}
table {
width: 100%;
border-collapse: collapse;
text-align: left;
}
th, td {
padding: 0.85rem 1rem;
border-bottom: 1px solid var(--border-subtle);
font-size: 0.875rem;
}
th {
background-color: var(--surface-muted);
color: var(--text-secondary);
font-weight: 600;
}
tr:last-child td {
border-bottom: none;
}
`}
</style>
</head>
<body>
<div class="admin-shell">
{/* Top Header */}
<header class="admin-header">
<div style="display: flex; align-items: center; gap: 0.75rem;">
<a
href="/admin/users"
class="admin-brand"
title="Auth-Yes Admin Console"
>
<span>Auth-Yes</span>
<span class="admin-badge">Admin</span>
</a>
</div>
<div style="display: flex; align-items: center; gap: 0.75rem;">
<a
href="/dashboard"
class="btn-outline"
style="padding: 0.35rem 0.75rem; font-size: 0.85rem; min-height: 36px; display: inline-flex; align-items: center; justify-content: center; text-decoration: none;"
>
← User Hub
</a>
<a
href="/logout"
class="btn-danger"
style="padding: 0.35rem 0.75rem; font-size: 0.85rem; min-height: 36px; display: inline-flex; align-items: center; justify-content: center; text-decoration: none;"
>
Logout
</a>
</div>
</header>
{/* Sub-Nav Scroller */}
<nav class="admin-nav-bar">
{adminNavItems.map((item) => {
const isActive = currentPath === item.href ||
currentPath.startsWith(item.href + "/");
return (
<a
href={item.href}
class={`admin-nav-item ${isActive ? "active" : ""}`}
>
{item.label}
</a>
);
})}
</nav>
{/* Main Content */}
<main class="admin-main-content">
{children}
</main>
</div>
</body>
</html>
);
};