Rebuild admin pages around DataTable/AdminModal; restructure categories/groups and v2 groups API
Remove the generic $lib/svelte-admin CRUD layer and AdminTable.svelte; each admin route now owns its own form/modal logic. Add DataTable.svelte, superform-errors.ts, and profile-specific modal/field components. Flatten proclamation categories/groups and drop subscription levels; add the v2 groups API; update v1/v2 endpoints, serializers, auth, and regenerated Prisma client with the new migrations. Document the overhaul plan in docs/ADMIN_OVERHAUL.md.
This commit is contained in:
@@ -1,74 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/state';
|
||||
import { canAccessAdmin } from '$lib/svelte-admin/roles';
|
||||
import { getAllModelConfigs } from '$lib/svelte-admin/registry';
|
||||
import type { LayoutData } from './$types';
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
let { children, data } = $props<{ children: any; data: LayoutData }>();
|
||||
|
||||
const isAdmin = $derived(canAccessAdmin(data.userRoleId));
|
||||
const adminModels = getAllModelConfigs();
|
||||
|
||||
const navLinks = [
|
||||
{ href: '/dashboard', label: 'Dashboard' },
|
||||
{ href: '/account', label: 'Account' },
|
||||
{ href: '/proclamations', label: 'Proclamations' },
|
||||
{ href: '/license-keys', label: 'License Keys' }
|
||||
];
|
||||
|
||||
function isActive(href: string): boolean {
|
||||
return page.url.pathname === href || page.url.pathname.startsWith(href + '/');
|
||||
}
|
||||
let { children }: { children: Snippet } = $props();
|
||||
</script>
|
||||
|
||||
<div class="flex min-h-0 flex-1">
|
||||
<!-- Sidebar -->
|
||||
<nav class="mt-12 mr-12 flex flex-col gap-1">
|
||||
{#each navLinks as link}
|
||||
<a
|
||||
href={link.href}
|
||||
class="rounded px-3 py-1.5 text-sm font-medium transition-colors {isActive(link.href)
|
||||
? 'bg-blue-50 text-blue-700 dark:bg-gray-800 dark:text-gray-100'
|
||||
: 'text-gray-600 hover:bg-gray-50 hover:text-gray-900 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-100'}"
|
||||
>
|
||||
{link.label}
|
||||
</a>
|
||||
{/each}
|
||||
{#if isAdmin}
|
||||
<div class="mt-4 flex flex-col gap-1">
|
||||
<a
|
||||
href="/admin"
|
||||
class="rounded px-3 py-1.5 text-sm font-medium transition-colors {isActive('/admin')
|
||||
? 'bg-blue-50 text-blue-700 dark:bg-gray-800 dark:text-gray-100'
|
||||
: 'text-gray-700 hover:bg-gray-50 hover:text-gray-900 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-100'}"
|
||||
>
|
||||
Admin Panel
|
||||
</a>
|
||||
<div class="ml-3 flex flex-col gap-0.5">
|
||||
{#each adminModels as model}
|
||||
<a
|
||||
href="/admin/{model.slug}"
|
||||
class="rounded px-3 py-1 text-sm transition-colors {isActive('/admin/' + model.slug)
|
||||
? 'bg-blue-50 text-blue-700 dark:bg-gray-800 dark:text-gray-100'
|
||||
: 'text-blue-600 hover:bg-gray-50 hover:text-blue-800 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-100'}"
|
||||
>
|
||||
{model.displayName}
|
||||
</a>
|
||||
{/each}
|
||||
<a
|
||||
href="/admin/api-keys"
|
||||
class="rounded px-3 py-1 text-sm transition-colors {isActive('/admin/api-keys')
|
||||
? 'bg-blue-50 text-blue-700 dark:bg-gray-800 dark:text-gray-100'
|
||||
: 'text-blue-600 hover:bg-gray-50 hover:text-blue-800 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-100'}"
|
||||
>
|
||||
API Keys
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</nav>
|
||||
<!-- Page content -->
|
||||
<div class="min-h-0 flex-1 overflow-auto">
|
||||
<div class="min-h-screen bg-slate-50 text-slate-900">
|
||||
<main class="mx-auto w-full max-w-6xl px-4 py-6 sm:px-6 sm:py-8">
|
||||
{@render children()}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user