web/src/routes/+layout.svelte (view raw)
1<script lang="ts">
2 import { onMount } from 'svelte';
3 import { logout } from '$lib/api';
4
5 let { children } = $props();
6
7 let loggedIn = $state(false);
8 let checking = $state(true);
9
10 onMount(() => {
11 fetch('/api/images?per_page=1', { credentials: 'include' })
12 .then((r) => {
13 if (r.ok) loggedIn = true;
14 })
15 .catch(() => {})
16 .finally(() => { checking = false; });
17 });
18
19 async function handleLogout() {
20 await logout();
21 loggedIn = false;
22 window.location.href = '/login';
23 }
24</script>
25
26<nav>
27 <a href="/">weimar</a>
28 <div class="nav-links">
29 <a href="/browse">Browse</a>
30 <a href="/upload">Upload</a>
31 {#if !checking}
32 {#if loggedIn}
33 <button class="link logout" onclick={handleLogout}>Logout</button>
34 {:else}
35 <a href="/login">Login</a>
36 {/if}
37 {/if}
38 </div>
39</nav>
40
41<main>
42 {@render children()}
43</main>
44
45<style>
46 nav {
47 display: flex;
48 align-items: center;
49 justify-content: space-between;
50 padding: 0.75rem 1.5rem;
51 background: #1a1a2e;
52 color: #eee;
53 }
54 nav a {
55 color: #eee;
56 text-decoration: none;
57 }
58 nav a:hover {
59 text-decoration: underline;
60 }
61 .nav-links {
62 display: flex;
63 gap: 1rem;
64 align-items: center;
65 }
66 .logout {
67 background: none;
68 border: none;
69 color: #eee;
70 cursor: pointer;
71 font-size: inherit;
72 padding: 0;
73 text-decoration: none;
74 }
75 .logout:hover {
76 text-decoration: underline;
77 }
78 main {
79 max-width: 1200px;
80 margin: 0 auto;
81 padding: 1.5rem;
82 }
83</style>