2026-03-19 03:36:46 +01:00
|
|
|
import { A, useLocation, useNavigate } from '@solidjs/router';
|
|
|
|
|
import { createSignal, onMount, type JSX } from 'solid-js';
|
2026-03-16 23:20:54 +01:00
|
|
|
import AdminSidebar from './AdminSidebar';
|
2026-03-19 03:36:46 +01:00
|
|
|
import { clearAdminSession, hasAdminSession } from '~/lib/admin-session';
|
2026-03-16 23:20:54 +01:00
|
|
|
|
|
|
|
|
export default function AdminShell(props: { children: JSX.Element }) {
|
2026-03-19 03:36:46 +01:00
|
|
|
const location = useLocation();
|
|
|
|
|
const navigate = useNavigate();
|
|
|
|
|
const [checkedSession, setCheckedSession] = createSignal(false);
|
|
|
|
|
const tabs = [
|
|
|
|
|
{ href: '/admin/runtime-roles', label: 'View Roles' },
|
|
|
|
|
{ href: '/admin/runtime-roles/new', label: 'Create Role' },
|
|
|
|
|
{ href: '/admin/role-ui-configs', label: 'Inspector' },
|
|
|
|
|
{ href: '/admin/onboarding-schemas', label: 'Onboarding' },
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const isTabActive = (href: string) => {
|
|
|
|
|
if (href === '/admin/runtime-roles') {
|
|
|
|
|
return location.pathname === href || (location.pathname.startsWith('/admin/runtime-roles/') && location.pathname !== '/admin/runtime-roles/new');
|
|
|
|
|
}
|
|
|
|
|
return location.pathname === href || location.pathname.startsWith(`${href}/`);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
onMount(() => {
|
|
|
|
|
if (!hasAdminSession()) {
|
|
|
|
|
const from = encodeURIComponent(location.pathname + location.search);
|
|
|
|
|
navigate(`/login?from=${from}`, { replace: true });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
setCheckedSession(true);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const onLogout = () => {
|
|
|
|
|
clearAdminSession();
|
|
|
|
|
navigate('/login', { replace: true });
|
|
|
|
|
};
|
|
|
|
|
|
2026-03-16 23:20:54 +01:00
|
|
|
return (
|
2026-03-19 03:36:46 +01:00
|
|
|
<div class="admin-root">
|
|
|
|
|
<header class="admin-header">
|
|
|
|
|
<div class="admin-header-inner">
|
|
|
|
|
<div class="admin-brand">
|
|
|
|
|
<img src="/nxtgauge-logo.png" alt="NXTGAUGE" />
|
|
|
|
|
<div>
|
|
|
|
|
<p class="admin-brand-kicker">Administration</p>
|
|
|
|
|
<h1>NXTGAUGE Admin Panel</h1>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="admin-header-actions">
|
|
|
|
|
<p class="admin-role-chip">Super Admin</p>
|
|
|
|
|
<button class="btn" type="button" onClick={onLogout}>Logout</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
{checkedSession() ? (
|
|
|
|
|
<div class="shell">
|
|
|
|
|
<AdminSidebar />
|
|
|
|
|
<main class="main">
|
|
|
|
|
<div class="admin-tab-wrap">
|
|
|
|
|
<nav class="admin-tabs">
|
|
|
|
|
{tabs.map((tab) => (
|
|
|
|
|
<A href={tab.href} class={`admin-tab ${isTabActive(tab.href) ? 'active' : ''}`}>
|
|
|
|
|
{tab.label}
|
|
|
|
|
</A>
|
|
|
|
|
))}
|
|
|
|
|
</nav>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="main-inner">{props.children}</div>
|
|
|
|
|
</main>
|
|
|
|
|
</div>
|
|
|
|
|
) : (
|
|
|
|
|
<div class="shell">
|
|
|
|
|
<main class="main">
|
|
|
|
|
<div class="card">
|
|
|
|
|
<p class="notice">Checking session...</p>
|
|
|
|
|
</div>
|
|
|
|
|
</main>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2026-03-16 23:20:54 +01:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|