diff --git a/package-lock.json b/package-lock.json index f960b710..9f882acf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "eslint-plugin-svelte": "^2.46.1", "globals": "^15.13.0", "jsdom": "^25.0.1", + "jwt-decode": "^4.0.0", "lucide-svelte": "^0.456.0", "msw": "^2.6.9", "postcss": "^8.4.49", @@ -3856,6 +3857,15 @@ "dev": true, "license": "MIT" }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "dev": true, + "engines": { + "node": ">=18" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", diff --git a/package.json b/package.json index 3bcb17eb..4b3b5b84 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "eslint-plugin-svelte": "^2.46.1", "globals": "^15.13.0", "jsdom": "^25.0.1", + "jwt-decode": "^4.0.0", "lucide-svelte": "^0.456.0", "msw": "^2.6.9", "postcss": "^8.4.49", diff --git a/src/lib/backend-api.ts b/src/lib/backend-api.ts index 68b2a32e..6f12df5e 100644 --- a/src/lib/backend-api.ts +++ b/src/lib/backend-api.ts @@ -90,7 +90,7 @@ export interface IAuthorController { } export interface IBackendController { - signIn(email: string, password: string): Promise; + signIn(email: string, password: string): Promise; signOut(): Promise; requestEmailForgottenPassword(email: string): Promise; diff --git a/src/lib/components/composites/navigation-bar/NavigationBar.svelte b/src/lib/components/composites/navigation-bar/NavigationBar.svelte index 314d6c44..ca46c1ce 100644 --- a/src/lib/components/composites/navigation-bar/NavigationBar.svelte +++ b/src/lib/components/composites/navigation-bar/NavigationBar.svelte @@ -8,7 +8,7 @@ import type { User } from "$lib/model/backend"; interface Props { - user: User; + user?: User; backRef?: string | undefined; tabs: Tab[]; defaultTabValue: (typeof tabs)[number]["value"]; diff --git a/src/lib/components/composites/navigation-bar/PaperNavigationBar.svelte b/src/lib/components/composites/navigation-bar/PaperNavigationBar.svelte index 58828069..bef2c603 100644 --- a/src/lib/components/composites/navigation-bar/PaperNavigationBar.svelte +++ b/src/lib/components/composites/navigation-bar/PaperNavigationBar.svelte @@ -4,7 +4,7 @@ import type { Paper, PaperSpec, User } from "$lib/model/backend"; interface Props { - user: User; + user?: User; backRef?: string | undefined; paper: Paper | PaperSpec; } diff --git a/src/lib/components/composites/navigation-bar/ProjectNavigationBar.svelte b/src/lib/components/composites/navigation-bar/ProjectNavigationBar.svelte index 98084b44..9261a27a 100644 --- a/src/lib/components/composites/navigation-bar/ProjectNavigationBar.svelte +++ b/src/lib/components/composites/navigation-bar/ProjectNavigationBar.svelte @@ -5,7 +5,7 @@ type TabValue = (typeof tabs)[number]["value"]; interface Props { - user: User; + user?: User; project: Project; defaultTabValue: TabValue; } diff --git a/src/lib/components/composites/navigation-bar/SimpleNavigationBar.svelte b/src/lib/components/composites/navigation-bar/SimpleNavigationBar.svelte index 4bddc897..4e5a585a 100644 --- a/src/lib/components/composites/navigation-bar/SimpleNavigationBar.svelte +++ b/src/lib/components/composites/navigation-bar/SimpleNavigationBar.svelte @@ -4,7 +4,7 @@ import type { User } from "$lib/model/backend"; interface Props { - user: User; + user?: User; backRef?: string | undefined; title: string; tabs: Tab[]; diff --git a/src/lib/components/composites/navigation-bar/UserMenu.svelte b/src/lib/components/composites/navigation-bar/UserMenu.svelte index 06290f89..8c3573b4 100644 --- a/src/lib/components/composites/navigation-bar/UserMenu.svelte +++ b/src/lib/components/composites/navigation-bar/UserMenu.svelte @@ -9,9 +9,10 @@ import type { Icon } from "lucide-svelte"; import type { User } from "$lib/model/backend"; import UserAvatar from "$lib/components/composites/user-avatar/UserAvatar.svelte"; + import { goto } from "$app/navigation"; interface Props { - user: User; + user?: User; } const { user }: Props = $props(); @@ -47,6 +48,11 @@ href: "/settings/account", }, ]; + + function signOut() { + localStorage.removeItem("token"); + goto("/signin"); + } @@ -56,7 +62,11 @@ - {`${user.firstName} ${user.lastName}`} + {#if user} + {`${user.firstName} ${user.lastName}`} + {:else} + Loading User... + {/if} @@ -73,7 +83,7 @@ {/each} - + Sign out ⇧⌘Q diff --git a/src/lib/components/composites/user-avatar/UserAvatar.svelte b/src/lib/components/composites/user-avatar/UserAvatar.svelte index 9d82f36e..1b7afc1c 100644 --- a/src/lib/components/composites/user-avatar/UserAvatar.svelte +++ b/src/lib/components/composites/user-avatar/UserAvatar.svelte @@ -5,14 +5,14 @@ import X from "lucide-svelte/icons/x"; interface Props { - user: User; + user?: User; reviewDecision?: ReviewDecision; } const { user, reviewDecision }: Props = $props(); const getInitial = (text: string) => (text.length > 0 ? text[0].toUpperCase() : ""); - const userInitials = `${getInitial(user.firstName)}${getInitial(user.lastName)}`; + const userInitials = `${getInitial(user?.firstName ?? "")}${getInitial(user?.lastName ?? "")}`;