TypeScript 61.9%
HTML 37.2%
SQL 0.7%
1'use client';23import Link from 'next/link';4import { usePathname } from 'next/navigation';5import { cn } from '@/lib/format';67export interface AccountNavItem {8 href: string;9 label: string;10 badge?: number;11}1213export const ACCOUNT_NAV: Array<{ label: string; items: AccountNavItem[] }> = [14 {15 label: 'My RareIndex',16 items: [17 { href: '/collections', label: 'Collections' },18 { href: '/my-index', label: 'My Index' },19 { href: '/watchlist', label: 'Watchlist' },20 { href: '/targets', label: 'Price targets' },21 { href: '/deals', label: 'Deal Radar' },22 { href: '/saved', label: 'Saved searches' },23 ],24 },25 {26 label: 'Signals',27 items: [28 { href: '/alerts', label: 'Alerts' },29 { href: '/notifications', label: 'Inbox' },30 ],31 },32 {33 label: 'Account',34 items: [35 { href: '/account/settings', label: 'Profile' },36 { href: '/account/security', label: 'Security' },37 { href: '/account/notifications', label: 'Notifications' },38 { href: '/account/api-keys', label: 'API keys' },39 { href: '/account/data', label: 'Data & privacy' },40 ],41 },42];4344export function AccountNav({ unread, handle }: { unread: number; handle: string | null }) {45 const pathname = usePathname();46 return (47 <nav aria-label="Account" className="text-[13px]">48 {/* mobile: horizontal scroll */}49 <div className="-mx-4 flex gap-1 overflow-x-auto px-4 pb-2 scrollbar-none lg:hidden">50 {ACCOUNT_NAV.flatMap((g) => g.items).map((i) => {51 const active = pathname === i.href || pathname.startsWith(`${i.href}/`);52 return (53 <Link key={i.href} href={i.href} className={cn('shrink-0 rounded-full border px-3 py-1.5', active ? 'border-fg bg-accent text-accent-fg' : 'border-border text-muted')}>54 {i.label}55 {i.href === '/notifications' && unread > 0 ? <span className="ml-1.5 rounded-full bg-alert px-1.5 text-[10px] font-semibold text-white">{unread}</span> : null}56 </Link>57 );58 })}59 </div>60 {/* desktop: sidebar */}61 <div className="hidden lg:block">62 {ACCOUNT_NAV.map((g) => (63 <div key={g.label} className="mb-4">64 <p className="mb-1 px-2 text-[10px] font-semibold uppercase tracking-wider text-subtle">{g.label}</p>65 <ul className="space-y-0.5">66 {g.items.map((i) => {67 const active = pathname === i.href || pathname.startsWith(`${i.href}/`);68 return (69 <li key={i.href}>70 <Link href={i.href} className={cn('flex items-center justify-between rounded-md px-2 py-1.5', active ? 'bg-inset font-medium text-fg' : 'text-muted hover:bg-inset hover:text-fg')}>71 {i.label}72 {i.href === '/notifications' && unread > 0 ? <span className="rounded-full bg-alert px-1.5 text-[10px] font-semibold text-white">{unread}</span> : null}73 </Link>74 </li>75 );76 })}77 </ul>78 </div>79 ))}80 {handle ? (81 <Link href={`/u/${handle}`} className="block rounded-md border border-dashed border-border px-2 py-1.5 text-xs text-muted hover:text-fg">82 Public profile → /u/{handle}83 </Link>84 ) : (85 <Link href="/account/settings#handle" className="block rounded-md border border-dashed border-border px-2 py-1.5 text-xs text-muted hover:text-fg">86 Claim a public handle →87 </Link>88 )}89 </div>90 </nav>91 );92}93