diff --git a/apps/presi/apps/web/src/lib/api/client.ts b/apps/presi/apps/web/src/lib/api/client.ts index 0ba545b41..457796f7d 100644 --- a/apps/presi/apps/web/src/lib/api/client.ts +++ b/apps/presi/apps/web/src/lib/api/client.ts @@ -14,9 +14,15 @@ const BASE_URL = PUBLIC_BACKEND_URL || 'http://localhost:3008'; const API_URL = `${BASE_URL}/api`; const AUTH_URL = PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001'; +// Storage keys must match @manacore/shared-auth +const STORAGE_KEYS = { + APP_TOKEN: '@auth/appToken', + REFRESH_TOKEN: '@auth/refreshToken', +}; + function getToken(): string | null { if (!browser) return null; - return localStorage.getItem('accessToken'); + return localStorage.getItem(STORAGE_KEYS.APP_TOKEN); } async function fetchWithAuth(url: string, options: RequestInit = {}): Promise { @@ -49,8 +55,8 @@ async function fetchWithAuth(url: string, options: RequestInit = {}): Promise { if (!browser) return false; - const refreshToken = localStorage.getItem('refreshToken'); - if (!refreshToken) return false; + const storedRefreshToken = localStorage.getItem(STORAGE_KEYS.REFRESH_TOKEN); + if (!storedRefreshToken) return false; try { - const response = await fetch(`${AUTH_URL}/auth/refresh`, { + const response = await fetch(`${AUTH_URL}/api/v1/auth/refresh`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ refreshToken }), + body: JSON.stringify({ refreshToken: storedRefreshToken }), }); if (response.ok) { const data = await response.json(); - localStorage.setItem('accessToken', data.accessToken); + localStorage.setItem(STORAGE_KEYS.APP_TOKEN, data.accessToken); if (data.refreshToken) { - localStorage.setItem('refreshToken', data.refreshToken); + localStorage.setItem(STORAGE_KEYS.REFRESH_TOKEN, data.refreshToken); } return true; } @@ -86,10 +92,10 @@ async function refreshToken(): Promise { return false; } -// Auth API +// Auth API (legacy - prefer using @manacore/shared-auth via auth store) export const authApi = { async login(email: string, password: string) { - const response = await fetch(`${AUTH_URL}/auth/login`, { + const response = await fetch(`${AUTH_URL}/api/v1/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }), @@ -102,14 +108,14 @@ export const authApi = { const data = await response.json(); if (browser) { - localStorage.setItem('accessToken', data.accessToken); - localStorage.setItem('refreshToken', data.refreshToken); + localStorage.setItem(STORAGE_KEYS.APP_TOKEN, data.accessToken); + localStorage.setItem(STORAGE_KEYS.REFRESH_TOKEN, data.refreshToken); } return data; }, async register(email: string, password: string) { - const response = await fetch(`${AUTH_URL}/auth/register`, { + const response = await fetch(`${AUTH_URL}/api/v1/auth/register`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }), @@ -122,22 +128,22 @@ export const authApi = { const data = await response.json(); if (browser) { - localStorage.setItem('accessToken', data.accessToken); - localStorage.setItem('refreshToken', data.refreshToken); + localStorage.setItem(STORAGE_KEYS.APP_TOKEN, data.accessToken); + localStorage.setItem(STORAGE_KEYS.REFRESH_TOKEN, data.refreshToken); } return data; }, logout() { if (browser) { - localStorage.removeItem('accessToken'); - localStorage.removeItem('refreshToken'); + localStorage.removeItem(STORAGE_KEYS.APP_TOKEN); + localStorage.removeItem(STORAGE_KEYS.REFRESH_TOKEN); } }, isAuthenticated(): boolean { if (!browser) return false; - return !!localStorage.getItem('accessToken'); + return !!localStorage.getItem(STORAGE_KEYS.APP_TOKEN); }, }; diff --git a/apps/presi/apps/web/src/routes/+layout.svelte b/apps/presi/apps/web/src/routes/+layout.svelte index b0de65340..233f31b14 100644 --- a/apps/presi/apps/web/src/routes/+layout.svelte +++ b/apps/presi/apps/web/src/routes/+layout.svelte @@ -62,7 +62,10 @@ // Navigation items for Presi // Profile, Mana, and Settings are in the user dropdown via profileHref, manaHref, settingsHref - const navItems: PillNavItem[] = [{ href: '/', label: 'Decks', icon: 'document' }]; + const navItems: PillNavItem[] = [ + { href: '/', label: 'Decks', icon: 'document' }, + { href: '/feedback', label: 'Feedback', icon: 'chat' }, + ]; // Public routes that don't require auth const publicRoutes = ['/login', '/register', '/forgot-password']; diff --git a/scripts/generate-env.mjs b/scripts/generate-env.mjs index 84b6348f2..148a8a2da 100644 --- a/scripts/generate-env.mjs +++ b/scripts/generate-env.mjs @@ -328,6 +328,7 @@ const APP_CONFIGS = [ PORT: (env) => env.PRESI_BACKEND_PORT || '3008', DATABASE_URL: (env) => env.PRESI_DATABASE_URL, MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL, + JWT_PUBLIC_KEY: (env) => env.JWT_PUBLIC_KEY, CORS_ORIGINS: (env) => env.CORS_ORIGINS, }, },