feat: add URL-based tab navigation for admin settings

This commit is contained in:
2026-01-06 13:36:35 -06:00
parent 8dcb42184a
commit ae83569fd7
2 changed files with 25 additions and 6 deletions
+9 -2
View File
@@ -11,10 +11,17 @@ export const load: LayoutServerLoad = async ({ request, url }) => {
const sessionUser = request.headers.get("x-session-user"); const sessionUser = request.headers.get("x-session-user");
if (!sessionUser) { if (!sessionUser) {
// Not authenticated - redirect to login with next parameter const targetPath = url.pathname + url.search;
// If redirecting to /admin (the default), omit the next parameter
if (targetPath === "/admin") {
throw redirect(302, "/admin/login");
}
// For other paths, include next parameter
throw redirect( throw redirect(
302, 302,
`/admin/login?next=${encodeURIComponent(url.pathname + url.search)}` `/admin/login?next=${encodeURIComponent(targetPath)}`
); );
} }
@@ -1,4 +1,6 @@
<script lang="ts"> <script lang="ts">
import { goto } from "$app/navigation";
import { page } from "$app/stores";
import Button from "$lib/components/admin/Button.svelte"; import Button from "$lib/components/admin/Button.svelte";
import Input from "$lib/components/admin/Input.svelte"; import Input from "$lib/components/admin/Input.svelte";
import { getSettings, updateSettings } from "$lib/api"; import { getSettings, updateSettings } from "$lib/api";
@@ -15,7 +17,13 @@
let settings = $state<SiteSettings | null>(null); let settings = $state<SiteSettings | null>(null);
let loading = $state(true); let loading = $state(true);
let saving = $state(false); let saving = $state(false);
let activeTab = $state<Tab>("identity");
// Read tab from URL, default to "identity"
let activeTab = $derived.by(() => {
const params = $page.params as { tab?: string };
const tab = params.tab as Tab | undefined;
return tab && ["identity", "social", "admin"].includes(tab) ? tab : "identity";
});
// Form state - will be populated when settings load // Form state - will be populated when settings load
let formData = $state<SiteSettings | null>(null); let formData = $state<SiteSettings | null>(null);
@@ -88,6 +96,10 @@
return "https://example.com/pgp-key.asc"; return "https://example.com/pgp-key.asc";
} }
} }
function navigateToTab(tab: Tab) {
goto(`/admin/settings/${tab}`, { replaceState: true });
}
</script> </script>
<svelte:head> <svelte:head>
@@ -117,7 +129,7 @@
? "border-indigo-500 text-zinc-50" ? "border-indigo-500 text-zinc-50"
: "border-transparent text-zinc-400 hover:text-zinc-300 hover:border-zinc-700" : "border-transparent text-zinc-400 hover:text-zinc-300 hover:border-zinc-700"
)} )}
onclick={() => (activeTab = "identity")} onclick={() => navigateToTab("identity")}
> >
Identity Identity
</button> </button>
@@ -129,7 +141,7 @@
? "border-indigo-500 text-zinc-50" ? "border-indigo-500 text-zinc-50"
: "border-transparent text-zinc-400 hover:text-zinc-300 hover:border-zinc-700" : "border-transparent text-zinc-400 hover:text-zinc-300 hover:border-zinc-700"
)} )}
onclick={() => (activeTab = "social")} onclick={() => navigateToTab("social")}
> >
Social Links Social Links
</button> </button>
@@ -141,7 +153,7 @@
? "border-indigo-500 text-zinc-50" ? "border-indigo-500 text-zinc-50"
: "border-transparent text-zinc-400 hover:text-zinc-300 hover:border-zinc-700" : "border-transparent text-zinc-400 hover:text-zinc-300 hover:border-zinc-700"
)} )}
onclick={() => (activeTab = "admin")} onclick={() => navigateToTab("admin")}
> >
Admin Preferences Admin Preferences
</button> </button>