diff --git a/.beans/nuzlocke-tracker-h205--auth-aware-navigation-menu.md b/.beans/nuzlocke-tracker-h205--auth-aware-navigation-menu.md index 6ef95d5..6047ba8 100644 --- a/.beans/nuzlocke-tracker-h205--auth-aware-navigation-menu.md +++ b/.beans/nuzlocke-tracker-h205--auth-aware-navigation-menu.md @@ -1,11 +1,11 @@ --- # nuzlocke-tracker-h205 title: Auth-aware navigation menu -status: todo +status: completed type: task priority: normal created_at: 2026-03-21T10:06:20Z -updated_at: 2026-03-21T10:06:24Z +updated_at: 2026-03-21T10:22:08Z parent: nuzlocke-tracker-ce4o blocked_by: - nuzlocke-tracker-5svj @@ -15,13 +15,24 @@ Update the Layout component to show different nav links based on auth state and ## Checklist -- [ ] Replace static \`navLinks\` array with dynamic links based on \`useAuth()\` state -- [ ] **Logged out**: Home, Runs, Genlockes, Stats (no New Run, no Admin) -- [ ] **Logged in (non-admin)**: New Run, My Runs, Genlockes, Stats -- [ ] **Logged in (admin)**: New Run, My Runs, Genlockes, Stats, Admin -- [ ] Update both desktop and mobile nav (they share the same \`navLinks\` array, so this should be automatic) -- [ ] Verify menu updates reactively on login/logout +- [x] Replace static \`navLinks\` array with dynamic links based on \`useAuth()\` state +- [x] **Logged out**: Home, Runs, Genlockes, Stats (no New Run, no Admin) +- [x] **Logged in (non-admin)**: New Run, My Runs, Genlockes, Stats +- [x] **Logged in (admin)**: New Run, My Runs, Genlockes, Stats, Admin +- [x] Update both desktop and mobile nav (they share the same \`navLinks\` array, so this should be automatic) +- [x] Verify menu updates reactively on login/logout ## Files to change - \`frontend/src/components/Layout.tsx\` — make \`navLinks\` dynamic based on auth state + +## Summary of Changes + +- Removed static `navLinks` array from module scope +- Added dynamic `navLinks` computation inside `Layout` component using `useMemo` +- Navigation now depends on `user` and `isAdmin` from `useAuth()`: + - Logged out: Home, Runs, Genlockes, Stats + - Logged in (non-admin): New Run, My Runs, Genlockes, Stats + - Logged in (admin): New Run, My Runs, Genlockes, Stats, Admin +- Updated `isActive` function to handle Home route (`/`) correctly +- Both desktop and mobile nav automatically use the same dynamic `navLinks` array diff --git a/frontend/src/components/Layout.tsx b/frontend/src/components/Layout.tsx index 689fc76..0671323 100644 --- a/frontend/src/components/Layout.tsx +++ b/frontend/src/components/Layout.tsx @@ -1,16 +1,8 @@ -import { useState } from 'react' +import { useState, useMemo } from 'react' import { Link, Outlet, useLocation } from 'react-router-dom' import { useTheme } from '../hooks/useTheme' import { useAuth } from '../contexts/AuthContext' -const navLinks = [ - { to: '/runs/new', label: 'New Run' }, - { to: '/runs', label: 'My Runs' }, - { to: '/genlockes', label: 'Genlockes' }, - { to: '/stats', label: 'Stats' }, - { to: '/admin', label: 'Admin' }, -] - function NavLink({ to, active, @@ -136,9 +128,34 @@ function UserMenu({ onAction }: { onAction?: () => void }) { export function Layout() { const [menuOpen, setMenuOpen] = useState(false) const location = useLocation() + const { user, isAdmin } = useAuth() + + const navLinks = useMemo(() => { + if (!user) { + // Logged out: Home, Runs, Genlockes, Stats + return [ + { to: '/', label: 'Home' }, + { to: '/runs', label: 'Runs' }, + { to: '/genlockes', label: 'Genlockes' }, + { to: '/stats', label: 'Stats' }, + ] + } + // Logged in: New Run, My Runs, Genlockes, Stats + const links = [ + { to: '/runs/new', label: 'New Run' }, + { to: '/runs', label: 'My Runs' }, + { to: '/genlockes', label: 'Genlockes' }, + { to: '/stats', label: 'Stats' }, + ] + // Admin gets Admin link + if (isAdmin) { + links.push({ to: '/admin', label: 'Admin' }) + } + return links + }, [user, isAdmin]) function isActive(to: string) { - if (to === '/runs/new') return location.pathname === '/runs/new' + if (to === '/' || to === '/runs/new') return location.pathname === to return location.pathname.startsWith(to) }