docs(ui): Add UI layout refactor plan and OpenSpec changes

- Update decision-log with UI layout decisions (Feb 18, 2026)
- Update architecture with frontend layout patterns
- Update config.yaml with TDD, documentation, UI standards rules
- Create p00-api-documentation change (Scribe annotations)
- Create p01-ui-foundation change (types, stores, Lucide)
- Create p02-app-layout change (AppLayout, Sidebar, TopBar)
- Create p03-dashboard-enhancement change (PageHeader, StatCard)
- Create p04-content-patterns change (DataTable, FilterBar)
- Create p05-page-migrations change (page migrations)
- Fix E2E auth tests (11/11 passing)
- Add JWT expiry validation to dashboard guard
This commit is contained in:
2026-02-18 13:03:08 -05:00
parent f935754df4
commit 3e36ea8888
29 changed files with 3341 additions and 59 deletions

View File

@@ -2,15 +2,25 @@
import { goto } from '$app/navigation';
import { isAuthenticated } from '$lib/stores/auth';
import { browser } from '$app/environment';
import { page } from '$app/stores';
import { onMount } from 'svelte';
// Redirect based on auth state
$: if (browser) {
if ($isAuthenticated) {
goto('/dashboard');
} else {
goto('/login');
// Only redirect when actually on the root page, not during navigation
onMount(() => {
if (browser) {
const unsubscribe = isAuthenticated.subscribe((authenticated) => {
// Only redirect if we're actually on the root page
if ($page.url.pathname === '/') {
if (authenticated) {
goto('/dashboard');
} else {
goto('/login');
}
}
});
return unsubscribe;
}
}
});
</script>
<div class="flex items-center justify-center min-h-screen">

View File

@@ -0,0 +1,5 @@
<script lang="ts">
let { children }: { children: import('svelte').Snippet } = $props();
</script>
{@render children()}

View File

@@ -1,17 +1,21 @@
import { browser } from '$app/environment';
import { goto } from '$app/navigation';
import { getAccessToken } from '$lib/services/api';
import { redirect } from '@sveltejs/kit';
import { clearTokens, getAccessToken, isJwtExpired, isValidJwtFormat } from '$lib/services/api';
import type { LayoutLoad } from './$types';
export const ssr = false;
export const load: LayoutLoad = async () => {
// Check authentication on client side using localStorage (source of truth)
if (browser) {
const token = getAccessToken();
if (!token) {
goto('/login');
return { authenticated: false };
}
if (!browser) {
return { authenticated: false };
}
const token = getAccessToken();
const isAuthenticated = Boolean(token && isValidJwtFormat(token) && !isJwtExpired(token));
if (!isAuthenticated) {
clearTokens();
throw redirect(307, '/login');
}
return { authenticated: true };