Accounts Phase 1c: sign-in UI, magic-link landing, auth store
- Shared reactive auth store (auth.user) + postJSON helper (sends the cookie). - SignIn modal: email -> "check your inbox" (calm, no password); Google slots in here in Phase 2. - /auth/verify route exchanges the magic-link token for a session, then home. - Header shows "Sign in" or an account avatar; the You sheet gains "Signed in as …" + Sign out (or a Sign in row). Anonymous browsing is unchanged.
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import { verifyToken } from '$lib/auth.svelte.js';
|
||||
|
||||
let status = $state('verifying'); // verifying | error
|
||||
let error = $state('');
|
||||
|
||||
onMount(async () => {
|
||||
const token = new URLSearchParams(window.location.search).get('token');
|
||||
if (!token) {
|
||||
status = 'error';
|
||||
error = 'This sign-in link is missing its token.';
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await verifyToken(token);
|
||||
goto('/', { replaceState: true }); // signed in — back home
|
||||
} catch (e) {
|
||||
status = 'error';
|
||||
error = e?.message || 'This sign-in link is invalid or has expired.';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<main class="container verify">
|
||||
{#if status === 'verifying'}
|
||||
<p class="muted">Signing you in…</p>
|
||||
{:else}
|
||||
<h1>Couldn't sign you in</h1>
|
||||
<p class="muted">{error}</p>
|
||||
<a class="back" href="/">← Back to Upbeat Bytes</a>
|
||||
{/if}
|
||||
</main>
|
||||
|
||||
<style>
|
||||
.verify {
|
||||
min-height: 60vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
gap: 12px;
|
||||
padding: 60px 20px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
.back {
|
||||
color: var(--accent-deep);
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user