fix+feat: SPA routing, theme system, modern UI, setup wizard improvements
Fixes: - Go server now serves index.html for all non-asset paths (SPA fallback) - Null guard on data.documents prevents undefined.length TypeError - App.vue waits for checkStatus() before rendering AppLayout (race condition) - PWA manifest no longer references missing icon files - index.html applies theme class before paint to prevent flash Features: - Theme store: dark/light toggle + 6 accent color presets + custom hex picker - ThemeToggle component in header dropdown - CSS custom properties for accent color (--accent-400/500/600/700) - Tailwind accent-* color utilities driven by CSS vars - SetupWizard: 3-step flow, password confirmation, LDAP test button, animated toggle, review step, proper error/success states - Sidebar: loading skeleton, active page highlight, null-safe document list - Global .input, .btn-primary, .btn-secondary, .card component classes - Stub GraphQL responses for setup/login/testLdapConnection Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,25 +1,33 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import Sidebar from './Sidebar.vue'
|
||||
import ThemeToggle from './ThemeToggle.vue'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
|
||||
const app = useAppStore()
|
||||
const sidebarOpen = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex h-screen overflow-hidden bg-surface-900 text-slate-100">
|
||||
<div class="flex h-screen overflow-hidden bg-white dark:bg-slate-900 text-slate-900 dark:text-slate-100">
|
||||
|
||||
<!-- Mobile overlay -->
|
||||
<transition name="fade">
|
||||
<div
|
||||
v-if="sidebarOpen"
|
||||
class="fixed inset-0 z-20 bg-black/60 lg:hidden"
|
||||
class="fixed inset-0 z-20 bg-black/50 backdrop-blur-sm lg:hidden"
|
||||
@click="sidebarOpen = false"
|
||||
/>
|
||||
</transition>
|
||||
|
||||
<!-- Sidebar — slide-over on mobile, static on desktop -->
|
||||
<!-- Sidebar -->
|
||||
<aside
|
||||
:class="[
|
||||
'fixed inset-y-0 left-0 z-30 w-64 flex-shrink-0 bg-surface-800 border-r border-slate-700 transform transition-transform duration-200',
|
||||
'fixed inset-y-0 left-0 z-30 w-64 flex-shrink-0',
|
||||
'bg-slate-50 dark:bg-slate-800/50',
|
||||
'border-r border-slate-200 dark:border-slate-700/60',
|
||||
'backdrop-blur-md',
|
||||
'transform transition-transform duration-250 ease-in-out',
|
||||
'lg:static lg:translate-x-0',
|
||||
sidebarOpen ? 'translate-x-0' : '-translate-x-full',
|
||||
]"
|
||||
@@ -27,20 +35,39 @@ const sidebarOpen = ref(false)
|
||||
<Sidebar @close="sidebarOpen = false" />
|
||||
</aside>
|
||||
|
||||
<!-- Main content -->
|
||||
<!-- Main area -->
|
||||
<div class="flex flex-col flex-1 min-w-0 overflow-hidden">
|
||||
<!-- Mobile top bar -->
|
||||
<header class="flex items-center gap-3 p-3 border-b border-slate-700 lg:hidden">
|
||||
|
||||
<!-- Top bar (always visible on mobile, only shows breadcrumb on desktop) -->
|
||||
<header class="flex items-center gap-2 px-4 py-3 border-b border-slate-200 dark:border-slate-700/60 bg-white/80 dark:bg-slate-900/80 backdrop-blur-md">
|
||||
<!-- Hamburger (mobile only) -->
|
||||
<button
|
||||
class="p-1.5 rounded hover:bg-surface-700"
|
||||
class="btn-ghost p-2 -ml-2 lg:hidden"
|
||||
aria-label="Open navigation"
|
||||
@click="sidebarOpen = true"
|
||||
>
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
|
||||
</svg>
|
||||
</button>
|
||||
<span class="font-semibold">Archivum</span>
|
||||
|
||||
<span class="font-semibold text-slate-900 dark:text-white lg:hidden">Archivum</span>
|
||||
|
||||
<div class="flex-1" />
|
||||
|
||||
<!-- Right side controls -->
|
||||
<ThemeToggle />
|
||||
|
||||
<div class="flex items-center gap-1 pl-2 border-l border-slate-200 dark:border-slate-700 ml-1">
|
||||
<span class="text-sm text-slate-500 dark:text-slate-400 hidden sm:block">
|
||||
{{ app.username ?? 'Guest' }}
|
||||
</span>
|
||||
<button
|
||||
v-if="app.token"
|
||||
class="btn-ghost text-xs"
|
||||
@click="app.logout()"
|
||||
>Sign out</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="flex-1 overflow-auto">
|
||||
|
||||
Reference in New Issue
Block a user