So many things
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
<script lang="ts">
|
||||
import { page } from "$app/stores";
|
||||
import "../../styles/admin.css";
|
||||
|
||||
import type { PermissionMap } from "$lib/permissions";
|
||||
|
||||
export let data: {
|
||||
user: {
|
||||
id: string;
|
||||
name?: string;
|
||||
email?: string;
|
||||
[key: string]: unknown;
|
||||
} | null;
|
||||
permissions: PermissionMap;
|
||||
};
|
||||
|
||||
$: permissions = data.permissions;
|
||||
$: userName = data.user?.name || "Admin";
|
||||
|
||||
// Tab definitions — each gated by a permission
|
||||
const allTabs = [
|
||||
{ label: "Overview", href: "/admin", exact: true, permission: null },
|
||||
{
|
||||
label: "Users",
|
||||
href: "/admin/users",
|
||||
exact: false,
|
||||
permission: "admin.users.view",
|
||||
},
|
||||
{
|
||||
label: "Roles",
|
||||
href: "/admin/roles",
|
||||
exact: false,
|
||||
permission: "admin.roles.view",
|
||||
},
|
||||
{
|
||||
label: "Credential Types",
|
||||
href: "/admin/credential-types",
|
||||
exact: false,
|
||||
permission: "admin.credential-types.view",
|
||||
},
|
||||
] as const;
|
||||
|
||||
// Only show tabs the user has permission for
|
||||
$: visibleTabs = allTabs.filter(
|
||||
(t) => t.permission === null || permissions[t.permission] === true,
|
||||
);
|
||||
|
||||
function isActive(
|
||||
tab: { href: string; exact?: boolean },
|
||||
pathname: string,
|
||||
): boolean {
|
||||
if (tab.exact) return pathname === tab.href;
|
||||
return pathname.startsWith(tab.href);
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Admin — Project Optima</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="admin-page">
|
||||
<div class="admin-pane">
|
||||
<!-- Pane header -->
|
||||
<div class="admin-header">
|
||||
<div class="admin-header-left">
|
||||
<svg
|
||||
class="admin-header-icon"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<circle cx="12" cy="12" r="3" />
|
||||
<path
|
||||
d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"
|
||||
/>
|
||||
</svg>
|
||||
<h2 class="admin-title">Administration</h2>
|
||||
<span class="admin-subtitle">Welcome back, {userName}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab bar -->
|
||||
<div class="tab-bar" role="tablist">
|
||||
{#each visibleTabs as tab}
|
||||
<a
|
||||
href={tab.href}
|
||||
class="tab-btn"
|
||||
class:active={isActive(tab, $page.url.pathname)}
|
||||
role="tab"
|
||||
aria-selected={isActive(tab, $page.url.pathname)}
|
||||
>
|
||||
{tab.label}
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<!-- Tab content -->
|
||||
<div class="admin-body">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user