113 lines
4.0 KiB
Svelte
113 lines
4.0 KiB
Svelte
<script lang="ts">
|
|
import { page } from "$app/state";
|
|
import { _ } from "svelte-i18n";
|
|
import { Avatar, AvatarImage, AvatarFallback } from "$lib/components/ui/avatar";
|
|
import { getUserInitials } from "$lib/utils";
|
|
import { getAssetUrl } from "$lib/api";
|
|
|
|
const { children, data } = $props();
|
|
|
|
const navLinks = $derived([
|
|
{ name: $_("me.nav.profile"), href: "/me/profile", icon: "icon-[ri--user-line]" },
|
|
{ name: $_("me.nav.security"), href: "/me/security", icon: "icon-[ri--shield-keyhole-line]" },
|
|
...(data.isModel
|
|
? [
|
|
{
|
|
name: $_("me.nav.analytics"),
|
|
href: "/me/analytics",
|
|
icon: "icon-[ri--line-chart-line]",
|
|
},
|
|
]
|
|
: []),
|
|
]);
|
|
|
|
function isActive(href: string) {
|
|
return page.url.pathname.startsWith(href);
|
|
}
|
|
|
|
const user = $derived(data.authStatus.user!);
|
|
const avatarUrl = $derived(
|
|
user.avatar ? (getAssetUrl(user.avatar, "thumbnail") ?? undefined) : undefined,
|
|
);
|
|
const displayName = $derived(user.artist_name ?? user.email);
|
|
</script>
|
|
|
|
<div class="min-h-screen bg-gradient-to-br from-background via-primary/5 to-accent/5">
|
|
<div class="container mx-auto px-4">
|
|
<!-- Mobile top nav -->
|
|
<div class="lg:hidden border-b border-border/40">
|
|
<div class="flex items-center gap-1 overflow-x-auto py-2 scrollbar-none">
|
|
<a
|
|
href="/"
|
|
class="shrink-0 flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors px-2"
|
|
>
|
|
<span class="icon-[ri--arrow-left-line] h-4 w-4"></span>
|
|
<span class="hidden sm:inline">{$_("me.nav.back_mobile")}</span>
|
|
</a>
|
|
{#each navLinks as link (link.href)}
|
|
<a
|
|
href={link.href}
|
|
class={`shrink-0 flex items-center gap-1.5 rounded-lg px-2.5 py-1.5 text-sm font-medium transition-colors ${
|
|
isActive(link.href)
|
|
? "bg-primary/10 text-primary"
|
|
: "text-muted-foreground hover:text-foreground hover:bg-muted/50"
|
|
}`}
|
|
>
|
|
<span class={`${link.icon} h-4 w-4 shrink-0`}></span>
|
|
<span class="hidden sm:inline">{link.name}</span>
|
|
</a>
|
|
{/each}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Desktop layout -->
|
|
<div class="flex min-h-screen">
|
|
<!-- Sidebar (desktop only) -->
|
|
<aside class="hidden lg:flex w-56 shrink-0 flex-col border-r border-border/40">
|
|
<div class="px-4 py-5 border-b border-border/40">
|
|
<a
|
|
href="/"
|
|
class="flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors"
|
|
>
|
|
<span class="icon-[ri--arrow-left-line] h-3.5 w-3.5"></span>
|
|
{$_("me.nav.back_to_site")}
|
|
</a>
|
|
<div class="mt-3 flex items-center gap-3">
|
|
<Avatar class="h-9 w-9 shrink-0">
|
|
<AvatarImage src={avatarUrl} alt={displayName} />
|
|
<AvatarFallback class="text-xs">
|
|
{getUserInitials(displayName)}
|
|
</AvatarFallback>
|
|
</Avatar>
|
|
<div class="min-w-0">
|
|
<p class="text-sm font-semibold text-foreground truncate">{displayName}</p>
|
|
<p class="text-xs text-muted-foreground">{$_("me.title")}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<nav class="flex-1 p-3 space-y-1">
|
|
{#each navLinks as link (link.href)}
|
|
<a
|
|
href={link.href}
|
|
class={`flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-colors ${
|
|
isActive(link.href)
|
|
? "bg-primary/10 text-primary"
|
|
: "text-muted-foreground hover:text-foreground hover:bg-muted/50"
|
|
}`}
|
|
>
|
|
<span class={`${link.icon} h-4 w-4`}></span>
|
|
{link.name}
|
|
</a>
|
|
{/each}
|
|
</nav>
|
|
</aside>
|
|
|
|
<!-- Main content -->
|
|
<main class="flex-1 min-w-0">
|
|
{@render children()}
|
|
</main>
|
|
</div>
|
|
</div>
|
|
</div>
|