feat: reskin admin pages to zine design system

Migrate the entire admin section from the dark guild-* Tailwind theme
to the zine design system (dashed borders, CSS custom properties,
Brygada 1918 + Commit Mono, cream/dark mode palette).

- Replace admin top-nav layout with sidebar matching default layout
- Reskin dashboard, members, events, series management pages
- Reskin events/create and series/create form pages
- Add dev-only test login endpoint (GET /api/dev/test-login)
- Redirect duplicate admin/dashboard.vue to /admin
- Update CLAUDE.md design system docs
This commit is contained in:
Jennie Robinson Faber 2026-04-03 10:56:01 +01:00
parent f16f9ada64
commit fcd6f4cdf4
23 changed files with 3845 additions and 3827 deletions

View file

@ -1,118 +1,43 @@
<template>
<div class="min-h-screen bg-guild-900">
<div class="landing">
<!-- Horizontal Navigation -->
<nav class="w-full px-6 md:px-8 py-4">
<div class="max-w-6xl mx-auto flex items-center justify-between">
<!-- Logo/Wordmark -->
<NuxtLink to="/" class="text-display-sm font-bold text-candlelight-400 warm-text tracking-wide">
Ghost Guild
</NuxtLink>
<!-- Desktop Navigation Links -->
<div class="hidden md:flex items-center gap-8">
<NuxtLink
to="/about"
class="text-guild-300 hover:text-guild-100 transition-colors text-sm"
>
About
</NuxtLink>
<NuxtLink
to="/events"
class="text-guild-300 hover:text-guild-100 transition-colors text-sm"
>
Events
</NuxtLink>
<nav class="landing-nav">
<div class="landing-nav-inner">
<NuxtLink to="/" class="landing-brand">Ghost Guild</NuxtLink>
<div class="landing-links">
<NuxtLink to="/about">About</NuxtLink>
<NuxtLink to="/events">Events</NuxtLink>
<template v-if="isAuthenticated">
<NuxtLink
to="/member/dashboard"
class="text-primary-400 hover:text-primary-300 transition-colors text-sm font-medium"
>
Dashboard
</NuxtLink>
<NuxtLink to="/member/dashboard" class="landing-cta">Dashboard</NuxtLink>
</template>
<template v-else>
<button
@click="openLoginModal"
class="text-primary-400 hover:text-primary-300 transition-colors text-sm font-medium"
>
Sign In
</button>
<button class="landing-cta" @click="openLoginModal">Sign In</button>
</template>
</div>
<!-- Mobile Menu Button -->
<UButton
icon="i-lucide-menu"
color="neutral"
variant="ghost"
size="md"
class="md:hidden"
@click="isMobileMenuOpen = true"
aria-label="Open menu"
/>
<button class="btn landing-menu-btn" @click="isMobileMenuOpen = true">Menu</button>
</div>
</nav>
<!-- Main Content -->
<main>
<slot />
</main>
<!-- Footer -->
<footer class="border-t border-guild-800 py-8 px-6 md:px-8">
<div class="max-w-6xl mx-auto flex flex-col md:flex-row justify-between items-center gap-4">
<p class="text-guild-500 text-sm">
&copy; {{ currentYear }} Ghost Guild
</p>
<a
href="mailto:hello@ghostguild.org"
class="text-guild-500 hover:text-guild-300 transition-colors text-sm"
>
hello@ghostguild.org
</a>
</div>
</footer>
<!-- Mobile Navigation Drawer -->
<USlideover v-model:open="isMobileMenuOpen" side="right">
<template #body>
<div class="p-6 space-y-6">
<NuxtLink
to="/about"
class="block text-guild-200 hover:text-guild-100 transition-colors text-lg"
@click="isMobileMenuOpen = false"
>
About
</NuxtLink>
<NuxtLink
to="/events"
class="block text-guild-200 hover:text-guild-100 transition-colors text-lg"
@click="isMobileMenuOpen = false"
>
Events
</NuxtLink>
<div class="landing-mobile-nav">
<NuxtLink to="/about" @click="isMobileMenuOpen = false">About</NuxtLink>
<NuxtLink to="/events" @click="isMobileMenuOpen = false">Events</NuxtLink>
<template v-if="isAuthenticated">
<NuxtLink
to="/member/dashboard"
class="block text-primary-400 hover:text-primary-300 transition-colors text-lg font-medium"
@click="isMobileMenuOpen = false"
>
Dashboard
</NuxtLink>
<NuxtLink to="/member/dashboard" @click="isMobileMenuOpen = false">Dashboard</NuxtLink>
</template>
<template v-else>
<button
@click="handleMobileSignIn"
class="block text-primary-400 hover:text-primary-300 transition-colors text-lg font-medium"
>
Sign In
</button>
<button @click="handleMobileSignIn">Sign In</button>
</template>
</div>
</template>
</USlideover>
<!-- Login Modal -->
<LoginModal />
</div>
</template>
@ -122,10 +47,101 @@ const { isAuthenticated } = useAuth()
const { openLoginModal } = useLoginModal()
const isMobileMenuOpen = ref(false)
const currentYear = new Date().getFullYear()
const handleMobileSignIn = () => {
isMobileMenuOpen.value = false
openLoginModal()
}
</script>
<style scoped>
.landing {
min-height: 100vh;
background: var(--bg);
color: var(--text);
}
.landing-nav {
border-bottom: 1px dashed var(--border);
padding: 0 32px;
}
.landing-nav-inner {
max-width: 960px;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 0;
}
.landing-brand {
font-family: 'Brygada 1918', serif;
font-size: 16px;
font-weight: 600;
color: var(--candle);
text-decoration: none;
}
.landing-brand:hover { text-decoration: none; }
.landing-links {
display: flex;
align-items: center;
gap: 24px;
}
.landing-links a,
.landing-links button {
font-family: 'Commit Mono', monospace;
font-size: 13px;
color: var(--text-dim);
text-decoration: none;
background: none;
border: none;
cursor: pointer;
padding: 0;
transition: color 0.15s;
}
.landing-links a:hover,
.landing-links button:hover {
color: var(--text-bright);
text-decoration: none;
}
.landing-cta {
color: var(--candle) !important;
}
.landing-menu-btn {
display: none;
}
.landing-mobile-nav {
padding: 24px;
display: flex;
flex-direction: column;
gap: 20px;
}
.landing-mobile-nav a,
.landing-mobile-nav button {
font-family: 'Commit Mono', monospace;
font-size: 16px;
color: var(--text);
text-decoration: none;
background: none;
border: none;
cursor: pointer;
padding: 0;
text-align: left;
}
.landing-mobile-nav a:hover,
.landing-mobile-nav button:hover {
color: var(--candle);
}
@media (max-width: 768px) {
.landing-links { display: none; }
.landing-menu-btn { display: block; }
.landing-nav { padding: 0 20px; }
}
</style>