Skip to content

Commit 9923e9c

Browse files
committed
change
1 parent e2ca21d commit 9923e9c

File tree

1 file changed

+164
-160
lines changed

1 file changed

+164
-160
lines changed

src/routes/(admin)/+layout.svelte

Lines changed: 164 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -1,181 +1,185 @@
11
<script lang="ts">
2-
import "../../app.css";
3-
import {
4-
BarChart3,
5-
DatabaseBackup,
6-
FileText,
7-
Folder,
8-
LayoutGrid,
9-
LogOut,
10-
Menu,
11-
Search,
12-
Settings,
13-
Sparkles,
14-
Users,
15-
} from "lucide-svelte";
16-
import { page } from "$app/state";
17-
import logo from "$lib/assets/logo.svg";
18-
import AdminSearchModal, { openSearch } from "$lib/components/admin-search-modal.svelte";
19-
import ConfirmModal from "$lib/components/confirm-modal.svelte";
20-
import { setupToast } from "$lib/components/toast/controls.svelte";
21-
import Toast from "$lib/components/toast/toast.svelte";
2+
import "../../app.css";
3+
import {
4+
BarChart3,
5+
DatabaseBackup,
6+
FileText,
7+
Folder,
8+
LayoutGrid,
9+
LogOut,
10+
Menu,
11+
Search,
12+
Sparkles,
13+
Users,
14+
} from "lucide-svelte";
15+
import { page } from "$app/state";
16+
import logo from "$lib/assets/logo.svg";
17+
import AdminSearchModal, { openSearch } from "$lib/components/admin-search-modal.svelte";
18+
import ConfirmModal from "$lib/components/confirm-modal.svelte";
19+
import { setupToast } from "$lib/components/toast/controls.svelte";
20+
import Toast from "$lib/components/toast/toast.svelte";
2221
23-
let { children, data } = $props();
22+
let { children, data } = $props();
2423
25-
// Instantiate toast context for all admin pages (must be called before any await)
26-
const toastControls = setupToast();
24+
// Instantiate toast context for all admin pages (must be called before any await)
25+
const toastControls = setupToast();
2726
28-
const session = $derived(data.session);
27+
const session = $derived(data.session);
2928
30-
const navItems = [
31-
{ href: "/admin", label: "Dashboard", icon: LayoutGrid, exact: true },
32-
{ href: "/admin/members", label: "Members", icon: Users, exact: false },
33-
{ href: "/admin/articles", label: "Articles", icon: FileText, exact: false },
34-
{ href: "/admin/projects", label: "Projects", icon: Folder, exact: false },
35-
{ href: "/admin/analytics", label: "Analytics", icon: BarChart3, exact: false },
36-
{ href: "/admin/settings", label: "Settings", icon: Settings, exact: false },
37-
{ href: "/admin/migrate", label: "Migration", icon: DatabaseBackup, exact: false },
38-
] as const;
29+
const navItems = [
30+
{ href: "/admin", label: "Dashboard", icon: LayoutGrid, exact: true },
31+
{ href: "/admin/members", label: "Members", icon: Users, exact: false },
32+
{ href: "/admin/articles", label: "Articles", icon: FileText, exact: false },
33+
{ href: "/admin/projects", label: "Projects", icon: Folder, exact: false },
34+
{ href: "/admin/analytics", label: "Analytics", icon: BarChart3, exact: false },
35+
{ href: "/admin/migrate", label: "Migration", icon: DatabaseBackup, exact: false },
36+
] as const;
3937
40-
function isActive(path: string, exact: boolean) {
41-
if (exact) return page.url.pathname === path;
42-
return page.url.pathname.startsWith(path);
43-
}
38+
function isActive(path: string, exact: boolean) {
39+
if (exact) return page.url.pathname === path;
40+
return page.url.pathname.startsWith(path);
41+
}
4442
</script>
4543

4644
<div class="drawer lg:drawer-open">
47-
<input id="admin-drawer" type="checkbox" class="drawer-toggle" />
45+
<input id="admin-drawer" type="checkbox" class="drawer-toggle" />
4846

49-
<!-- Main content -->
50-
<div class="gradient-mesh relative drawer-content">
51-
<!-- Mobile header -->
52-
<header class="sticky top-0 z-30 flex h-14 items-center gap-4 glass px-4 lg:hidden">
53-
<label for="admin-drawer" class="btn btn-square btn-ghost btn-sm">
54-
<Menu class="h-5 w-5" />
55-
</label>
56-
<a href="/" class="flex flex-1 items-center transition-opacity hover:opacity-70">
57-
<img src={logo} alt="ut.code();" class="h-7" />
58-
</a>
59-
<button type="button" onclick={openSearch} class="btn btn-square btn-ghost btn-sm">
60-
<Search class="h-5 w-5" />
61-
</button>
62-
</header>
47+
<!-- Main content -->
48+
<div class="gradient-mesh relative drawer-content">
49+
<!-- Mobile header -->
50+
<header class="sticky top-0 z-30 flex h-14 items-center gap-4 glass px-4 lg:hidden">
51+
<label for="admin-drawer" class="btn btn-square btn-ghost btn-sm">
52+
<Menu class="h-5 w-5" />
53+
</label>
54+
<a href="/" class="flex flex-1 items-center transition-opacity hover:opacity-70">
55+
<img src={logo} alt="ut.code();" class="h-7" />
56+
</a>
57+
<button type="button" onclick={openSearch} class="btn btn-square btn-ghost btn-sm">
58+
<Search class="h-5 w-5" />
59+
</button>
60+
</header>
6361

64-
<main class="min-h-screen">
65-
<div class="mx-auto max-w-5xl px-4 py-4 sm:px-6 sm:py-6 lg:py-8">
66-
{@render children()}
67-
</div>
68-
</main>
69-
</div>
62+
<main class="min-h-screen">
63+
<div class="mx-auto max-w-5xl px-4 py-4 sm:px-6 sm:py-6 lg:py-8">
64+
{@render children()}
65+
</div>
66+
</main>
67+
</div>
7068

71-
<!-- Sidebar -->
72-
<aside class="drawer-side z-40">
73-
<label for="admin-drawer" aria-label="close sidebar" class="drawer-overlay"></label>
74-
<nav class="gradient-dark relative flex h-full min-h-screen w-64 flex-col overflow-hidden">
75-
<!-- Decorative gradient orbs -->
76-
<div class="absolute -top-20 -right-20 h-40 w-40 rounded-full bg-primary/20 blur-3xl"></div>
77-
<div class="absolute top-1/3 -left-10 h-32 w-32 rounded-full bg-info/10 blur-3xl"></div>
69+
<!-- Sidebar -->
70+
<aside class="drawer-side z-40">
71+
<label for="admin-drawer" aria-label="close sidebar" class="drawer-overlay"></label>
72+
<nav class="gradient-dark relative flex h-full min-h-screen w-64 flex-col overflow-hidden">
73+
<!-- Decorative gradient orbs -->
74+
<div class="absolute -top-20 -right-20 h-40 w-40 rounded-full bg-primary/20 blur-3xl"></div>
75+
<div class="absolute top-1/3 -left-10 h-32 w-32 rounded-full bg-info/10 blur-3xl"></div>
7876

79-
<!-- Logo -->
80-
<div class="relative flex h-16 shrink-0 items-center gap-3 px-5">
81-
<a href="/" class="flex items-center gap-2 transition-all hover:opacity-80">
82-
<img src={logo} alt="ut.code();" class="h-8" />
83-
</a>
84-
<span class="gradient-primary badge badge-xs text-[10px] font-bold text-white"> CMS </span>
85-
</div>
77+
<!-- Logo -->
78+
<div class="relative flex h-16 shrink-0 items-center gap-3 px-5">
79+
<a href="/" class="flex items-center gap-2 transition-all hover:opacity-80">
80+
<img src={logo} alt="ut.code();" class="h-8" />
81+
</a>
82+
<span class="gradient-primary badge badge-xs text-[10px] font-bold text-white"> CMS </span>
83+
</div>
8684

87-
<!-- Search -->
88-
<div class="relative px-4 pt-2">
89-
<button
90-
type="button"
91-
onclick={openSearch}
92-
class="flex w-full items-center gap-3 rounded-xl bg-white/5 px-4 py-2.5 text-left text-sm text-white/50 transition-all hover:bg-white/10 hover:text-white/70"
93-
>
94-
<Search class="h-4 w-4" />
95-
<span class="flex-1">Search...</span>
96-
<kbd
97-
class="hidden rounded bg-white/10 px-1.5 py-0.5 font-mono text-[10px] text-white/40 lg:inline"
98-
>
99-
⌘K
100-
</kbd>
101-
</button>
102-
</div>
85+
<!-- Search -->
86+
<div class="relative px-4 pt-2">
87+
<button
88+
type="button"
89+
onclick={openSearch}
90+
class="flex w-full items-center gap-3 rounded-xl bg-white/5 px-4 py-2.5 text-left text-sm text-white/50 transition-all hover:bg-white/10 hover:text-white/70"
91+
>
92+
<Search class="h-4 w-4" />
93+
<span class="flex-1">Search...</span>
94+
<kbd
95+
class="hidden rounded bg-white/10 px-1.5 py-0.5 font-mono text-[10px] text-white/40 lg:inline"
96+
>
97+
⌘K
98+
</kbd>
99+
</button>
100+
</div>
103101

104-
<!-- Navigation -->
105-
<div class="relative flex-1 overflow-y-auto px-3 py-6">
106-
<div class="mb-3 px-3">
107-
<span class="font-mono text-[10px] font-semibold tracking-widest text-white/30 uppercase">
108-
Menu
109-
</span>
110-
</div>
111-
<ul class="space-y-1">
112-
{#each navItems as item (item.href)}
113-
{@const active = isActive(item.href, item.exact)}
114-
<li>
115-
<a
116-
href={item.href}
117-
class="group flex items-center gap-3 rounded-xl px-4 py-3 font-medium transition-all duration-200
102+
<!-- Navigation -->
103+
<div class="relative flex-1 overflow-y-auto px-3 py-6">
104+
<div class="mb-3 px-3">
105+
<span class="font-mono text-[10px] font-semibold tracking-widest text-white/30 uppercase">
106+
Menu
107+
</span>
108+
</div>
109+
<ul class="space-y-1">
110+
{#each navItems as item (item.href)}
111+
{@const active = isActive(item.href, item.exact)}
112+
<li>
113+
<a
114+
href={item.href}
115+
class="group flex items-center gap-3 rounded-xl px-4 py-3 font-medium transition-all duration-200
118116
{active
119-
? 'nav-active bg-white/10 text-white'
120-
: 'text-white/60 hover:bg-white/5 hover:text-white/90'}"
121-
>
122-
<div
123-
class="flex h-8 w-8 items-center justify-center rounded-lg transition-all duration-200
117+
? 'nav-active bg-white/10 text-white'
118+
: 'text-white/60 hover:bg-white/5 hover:text-white/90'}"
119+
>
120+
<div
121+
class="flex h-8 w-8 items-center justify-center rounded-lg transition-all duration-200
124122
{active
125-
? 'gradient-primary glow-primary'
126-
: 'bg-white/5 group-hover:bg-white/10'}"
127-
>
128-
<item.icon class="h-4 w-4 {active ? 'text-white' : 'text-white/70'}" />
129-
</div>
130-
{item.label}
131-
{#if active}
132-
<Sparkles class="ml-auto h-3 w-3 animate-pulse text-primary" />
133-
{/if}
134-
</a>
135-
</li>
136-
{/each}
137-
</ul>
138-
</div>
123+
? 'gradient-primary glow-primary'
124+
: 'bg-white/5 group-hover:bg-white/10'}"
125+
>
126+
<item.icon class="h-4 w-4 {active ? 'text-white' : 'text-white/70'}" />
127+
</div>
128+
{item.label}
129+
{#if active}
130+
<Sparkles class="ml-auto h-3 w-3 animate-pulse text-primary" />
131+
{/if}
132+
</a>
133+
</li>
134+
{/each}
135+
</ul>
136+
</div>
139137

140-
<!-- User section -->
141-
<div class="relative shrink-0 border-t border-white/10 p-4">
142-
<div class="flex items-center gap-3 rounded-xl bg-white/5 p-3 transition-colors duration-150">
143-
<a
144-
href="/admin/settings"
145-
class="group flex min-w-0 flex-1 items-center gap-3 transition-opacity hover:opacity-80"
146-
title="Personal Settings"
147-
>
148-
{#if session.user.image}
149-
<div class="avatar">
150-
<div
151-
class="aspect-square w-10 rounded-full ring-2 ring-primary/50 ring-offset-2 ring-offset-neutral"
152-
>
153-
<img src={session.user.image} alt={session.user.name ?? "User"} class="h-full w-full object-cover" />
154-
</div>
155-
</div>
156-
{:else}
157-
<div class="placeholder avatar">
158-
<div class="gradient-primary aspect-square w-10 rounded-full text-white">
159-
<span class="text-sm font-bold">{session.user.name?.charAt(0) ?? "?"}</span>
160-
</div>
161-
</div>
162-
{/if}
163-
<div class="min-w-0 flex-1">
164-
<p class="truncate text-sm font-semibold text-white">{session.user.name}</p>
165-
<p class="truncate text-xs text-white/40">{session.user.email}</p>
166-
</div>
167-
</a>
168-
<a
169-
href="/api/auth/sign-out"
170-
class="btn btn-circle text-white/40 btn-ghost btn-sm hover:bg-white/10 hover:text-white"
171-
title="Sign out"
172-
>
173-
<LogOut class="h-4 w-4" />
174-
</a>
175-
</div>
176-
</div>
177-
</nav>
178-
</aside>
138+
<!-- User section -->
139+
<div class="relative shrink-0 border-t border-white/10 p-4">
140+
<div
141+
class="flex items-center gap-3 rounded-xl bg-white/5 p-3 transition-colors duration-150"
142+
>
143+
<a
144+
href="/admin/settings"
145+
class="group flex min-w-0 flex-1 items-center gap-3 transition-opacity hover:opacity-80"
146+
title="Personal Settings"
147+
>
148+
{#if session.user.image}
149+
<div class="avatar">
150+
<div
151+
class="aspect-square w-10 rounded-full ring-2 ring-primary/50 ring-offset-2 ring-offset-neutral"
152+
>
153+
<img
154+
src={session.user.image}
155+
alt={session.user.name ?? "User"}
156+
class="h-full w-full object-cover"
157+
/>
158+
</div>
159+
</div>
160+
{:else}
161+
<div class="placeholder avatar">
162+
<div class="gradient-primary aspect-square w-10 rounded-full text-white">
163+
<span class="text-sm font-bold">{session.user.name?.charAt(0) ?? "?"}</span>
164+
</div>
165+
</div>
166+
{/if}
167+
<div class="min-w-0 flex-1">
168+
<p class="truncate text-sm font-semibold text-white">{session.user.name}</p>
169+
<p class="truncate text-xs text-white/40">{session.user.email}</p>
170+
</div>
171+
</a>
172+
<a
173+
href="/api/auth/sign-out"
174+
class="btn btn-circle text-white/40 btn-ghost btn-sm hover:bg-white/10 hover:text-white"
175+
title="Sign out"
176+
>
177+
<LogOut class="h-4 w-4" />
178+
</a>
179+
</div>
180+
</div>
181+
</nav>
182+
</aside>
179183
</div>
180184

181185
<ConfirmModal />

0 commit comments

Comments
 (0)