User avatar (Google picture), avatar in mobile You tab, /account page
- Capture the Google profile picture (picture claim) into users.avatar_url; an Avatar component shows it, falling back to the initial. Used in the desktop header and the mobile "You" tab (which now shows the user when signed in). - Move account/settings to its own route /account (robust + scrolls to top), reached by the desktop avatar and the mobile You tab; drop the inline "You" sheet. AccountPanel gains a Sign out action; the page links to Saved/History/ Boundaries via home intent params (?view= / ?open=). - db: users.avatar_url (schema + idempotent migration). 118 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import AccountPanel from '$lib/components/AccountPanel.svelte';
|
||||
import { auth, refresh } from '$lib/auth.svelte.js';
|
||||
|
||||
onMount(() => {
|
||||
if (!auth.ready) refresh();
|
||||
});
|
||||
// Once auth resolves, send anonymous visitors back home.
|
||||
$effect(() => {
|
||||
if (auth.ready && !auth.user) goto('/', { replaceState: true });
|
||||
});
|
||||
</script>
|
||||
|
||||
<header class="bar">
|
||||
<div class="container inner">
|
||||
<a class="brand" href="/" aria-label="Upbeat Bytes — home">
|
||||
<img class="logo" src="/logo.svg" alt="Upbeat Bytes" />
|
||||
</a>
|
||||
<a class="back" href="/">← Back</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container page">
|
||||
{#if auth.user}
|
||||
<h1>You</h1>
|
||||
<nav class="quick">
|
||||
<a href="/?view=saved">Saved</a>
|
||||
<a href="/?open=history">History</a>
|
||||
<a href="/?open=boundaries">Boundaries</a>
|
||||
</nav>
|
||||
<AccountPanel onclose={() => goto('/')} />
|
||||
{/if}
|
||||
</main>
|
||||
|
||||
<style>
|
||||
.bar {
|
||||
background: var(--surface);
|
||||
border-bottom: 1px solid var(--line);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 20;
|
||||
}
|
||||
.inner { display: flex; align-items: center; justify-content: space-between; height: 64px; }
|
||||
.logo { height: 40px; width: auto; display: block; }
|
||||
.back { color: var(--accent-deep); font-size: 0.9rem; }
|
||||
.page { padding: 22px 20px 60px; }
|
||||
h1 { font-size: clamp(2rem, 5vw, 2.6rem); margin: 8px 0 14px; }
|
||||
.quick { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 20px; }
|
||||
.quick a {
|
||||
border: 1px solid var(--line); background: var(--surface); color: var(--ink);
|
||||
border-radius: 999px; padding: 7px 15px; font-size: 0.9rem;
|
||||
}
|
||||
.quick a:hover { border-color: var(--accent); color: var(--accent-deep); }
|
||||
</style>
|
||||
Reference in New Issue
Block a user