fooder-app/src/routes/(app)/+layout.svelte
2026-04-01 23:51:16 +02:00

107 lines
4.3 KiB
Svelte

<script lang="ts">
import { goto } from '$app/navigation';
import { auth } from '$lib/auth/store.svelte';
import { logout } from '$lib/api/auth';
import { useQueryClient } from '@tanstack/svelte-query';
import { today } from '$lib/utils/date';
import { page } from '$app/state';
import { onMount } from 'svelte';
let { children } = $props();
const queryClient = useQueryClient();
onMount(() => {
if (!auth.isAuthenticated) goto('/login');
});
function handleLogout() {
logout();
queryClient.clear();
goto('/login');
}
const isDiary = $derived(page.url.pathname.startsWith('/diary'));
const isPresets = $derived(page.url.pathname.startsWith('/presets'));
</script>
{#if auth.isAuthenticated}
<div class="lg:flex min-h-screen">
<!-- Sidebar (desktop only) -->
<aside class="hidden lg:flex flex-col w-52 shrink-0 fixed inset-y-0 border-r border-zinc-800 bg-zinc-950 px-3 py-6 z-20">
<div class="px-2 mb-8">
<span class="text-lg font-bold text-green-400">fooder</span>
</div>
<nav class="flex-1 space-y-1">
<a
href="/diary/{today()}"
class="flex items-center gap-2.5 px-3 py-2 rounded-xl text-sm font-medium transition-colors
{isDiary ? 'bg-zinc-800 text-zinc-100' : 'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-900'}"
>
<svg class="w-4 h-4 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
Diary
</a>
<a
href="/presets"
class="flex items-center gap-2.5 px-3 py-2 rounded-xl text-sm font-medium transition-colors
{isPresets ? 'bg-zinc-800 text-zinc-100' : 'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-900'}"
>
<svg class="w-4 h-4 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 5a2 2 0 012-2h10a2 2 0 012 2v16l-7-3.5L5 21V5z" />
</svg>
Presets
</a>
</nav>
<button
onclick={handleLogout}
class="flex items-center gap-2.5 px-3 py-2 rounded-xl text-sm font-medium text-zinc-400 hover:text-zinc-200 hover:bg-zinc-900 transition-colors"
>
<svg class="w-4 h-4 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
</svg>
Log out
</button>
</aside>
<!-- Main content -->
<div class="flex-1 lg:ml-52 flex flex-col min-h-screen">
{@render children()}
</div>
<!-- Bottom tab bar (mobile only) -->
<nav class="lg:hidden fixed bottom-0 left-0 right-0 z-20 bg-zinc-950 border-t border-zinc-800 flex items-center pb-[var(--safe-bottom)]">
<a
href="/diary/{today()}"
class="flex-1 flex flex-col items-center gap-1 py-3 text-xs font-medium transition-colors
{isDiary ? 'text-green-400' : 'text-zinc-500 hover:text-zinc-300'}"
>
<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="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
Diary
</a>
<a
href="/presets"
class="flex-1 flex flex-col items-center gap-1 py-3 text-xs font-medium transition-colors
{isPresets ? 'text-green-400' : 'text-zinc-500 hover:text-zinc-300'}"
>
<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="M5 5a2 2 0 012-2h10a2 2 0 012 2v16l-7-3.5L5 21V5z" />
</svg>
Presets
</a>
<button
onclick={handleLogout}
class="flex-1 flex flex-col items-center gap-1 py-3 text-xs font-medium text-zinc-500 hover:text-zinc-300 transition-colors"
>
<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="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
</svg>
Log out
</button>
</nav>
</div>
{/if}