feat(dashboard): shadow apps + app-detail surfaces by role

Apps list: hide "New app" for members. App detail: hide New script for
viewers, Add domain + per-row Delete for non-admins, and the Members +
Settings tabs entirely for non-admins (with an effect that bounces a
stale activeTab back to Scripts).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-05-28 19:31:56 +02:00
parent bef4d34c43
commit d9c3d4d661
2 changed files with 75 additions and 46 deletions

View File

@@ -2,6 +2,11 @@
import { base } from '$app/paths';
import { api, ApiError, type App } from '$lib/api';
import { slugify, SLUG_MAX } from '$lib/slugify';
import { canCreateApp } from '$lib/capabilities';
import { currentUser } from '$lib/auth';
const me = $derived($currentUser);
const canCreate = $derived(canCreateApp(me));
let apps = $state<App[] | null>(null);
let listError = $state<string | null>(null);
@@ -99,18 +104,20 @@
<section>
<header class="page-header">
<h1>Apps</h1>
<button
type="button"
onclick={() => {
showCreate = !showCreate;
if (!showCreate) resetCreate();
}}
>
{showCreate ? 'Cancel' : 'New app'}
</button>
{#if canCreate}
<button
type="button"
onclick={() => {
showCreate = !showCreate;
if (!showCreate) resetCreate();
}}
>
{showCreate ? 'Cancel' : 'New app'}
</button>
{/if}
</header>
{#if showCreate}
{#if showCreate && canCreate}
<form class="create-form" onsubmit={(e) => submitCreate(e)}>
<div class="row">
<label>