feat: /profile dashboard with tabbed preferences, account, bookmarks, collections (0.18.0)
Tabbed user dashboard at `/profile` that absorbs `/settings` and surfaces bookmarks + collections in one place. - New `/profile` shell with tabs: Overview (counts), Preferences (theme + reader prefs, ported from /settings; works for guests via localStorage), Account (password change; auth-gated), Bookmarks, Collections. Guest tab list is filtered to what they can actually use. - `/settings` is a 308 redirect to `/profile/preferences` so old bookmarks land cleanly. The "Settings" link in the top nav is replaced by a Profile link between Upload and Bookmarks; Bookmarks + Collections stay as shortcuts per the user spec. - Extracts `lib/components/BookmarkList.svelte` and `lib/components/CollectionsGrid.svelte` so the top-level /bookmarks + /collections routes and the new profile tabs render the same UI without duplication. Both layers use a three-state load (authenticated / guest / error) to handle network hiccups inline. - Deep links preserved via `?next=` on every sign-in CTA. 88 frontend unit tests + svelte-check clean; 12 of 12 e2e tests in profile.spec.ts and reader-mode.spec.ts pass (8 other e2e failures predate this branch and stay flagged for cleanup). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,9 +6,9 @@
|
||||
import { session } from '$lib/session.svelte';
|
||||
import { theme } from '$lib/theme.svelte';
|
||||
import Upload from '@lucide/svelte/icons/upload';
|
||||
import UserCircle from '@lucide/svelte/icons/user-circle';
|
||||
import Bookmark from '@lucide/svelte/icons/bookmark';
|
||||
import FolderOpen from '@lucide/svelte/icons/folder-open';
|
||||
import Settings from '@lucide/svelte/icons/settings';
|
||||
import LogOut from '@lucide/svelte/icons/log-out';
|
||||
import '$lib/styles/tokens.css';
|
||||
|
||||
@@ -53,6 +53,10 @@
|
||||
<Upload size={18} aria-hidden="true" />
|
||||
<span>Upload</span>
|
||||
</a>
|
||||
<a class="nav-link" href="/profile" data-testid="nav-profile">
|
||||
<UserCircle size={18} aria-hidden="true" />
|
||||
<span>Profile</span>
|
||||
</a>
|
||||
<a class="nav-link" href="/bookmarks">
|
||||
<Bookmark size={18} aria-hidden="true" />
|
||||
<span>Bookmarks</span>
|
||||
@@ -67,10 +71,6 @@
|
||||
<span data-testid="session-loading" aria-busy="true">…</span>
|
||||
{:else if session.user}
|
||||
<span class="username" data-testid="session-user">{session.user.username}</span>
|
||||
<a class="nav-link" href="/settings" data-testid="nav-settings">
|
||||
<Settings size={18} aria-hidden="true" />
|
||||
<span>Settings</span>
|
||||
</a>
|
||||
<button
|
||||
class="icon-btn"
|
||||
type="button"
|
||||
|
||||
Reference in New Issue
Block a user