Skip to content

Commit 9f335e9

Browse files
authored
Merge pull request #231 from DevanshuNEU/feat/settings-page
feat(settings): Add Settings Page with UX improvements
2 parents d1db8c3 + b4127d0 commit 9f335e9

4 files changed

Lines changed: 383 additions & 82 deletions

File tree

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1+
import { Routes, Route, Navigate } from 'react-router-dom'
12
import { DashboardLayout } from './dashboard/DashboardLayout'
23
import { DashboardHome } from './dashboard/DashboardHome'
4+
import { SettingsPage } from '../pages/SettingsPage'
35

46
export function Dashboard() {
57
return (
68
<DashboardLayout>
7-
<DashboardHome />
9+
<Routes>
10+
<Route index element={<DashboardHome />} />
11+
<Route path="settings" element={<SettingsPage />} />
12+
<Route path="*" element={<Navigate to="/dashboard" replace />} />
13+
</Routes>
814
</DashboardLayout>
915
)
1016
}

frontend/src/components/dashboard/Sidebar.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { Link, useLocation } from 'react-router-dom'
22
import {
33
FolderGit2,
4-
Search,
5-
Settings,
64
BookOpen,
75
ChevronLeft,
86
ChevronRight,
@@ -26,12 +24,10 @@ interface NavItem {
2624

2725
const mainNavItems: NavItem[] = [
2826
{ name: 'Repositories', href: '/dashboard', icon: <FolderGit2 className="w-5 h-5" /> },
29-
{ name: 'Global Search', href: '/dashboard/search', icon: <Search className="w-5 h-5" /> },
3027
]
3128

3229
const bottomNavItems: NavItem[] = [
3330
{ name: 'Documentation', href: '/docs', icon: <BookOpen className="w-5 h-5" />, external: true },
34-
{ name: 'Settings', href: '/dashboard/settings', icon: <Settings className="w-5 h-5" /> },
3531
]
3632

3733
export function Sidebar({ collapsed, onToggle, mobileOpen, onMobileClose }: SidebarProps) {

frontend/src/components/dashboard/TopNav.tsx

Lines changed: 50 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
import { Link } from 'react-router-dom'
22
import { useAuth } from '../../contexts/AuthContext'
3-
import { useState } from 'react'
4-
import {
5-
Menu,
6-
Search,
7-
Github,
8-
Sun,
9-
Moon,
10-
LogOut,
11-
Settings,
12-
BookOpen,
13-
ExternalLink
14-
} from 'lucide-react'
3+
import { Menu, Search, Github, Sun, Moon, LogOut, Settings, BookOpen, ExternalLink } from 'lucide-react'
154
import { useTheme } from 'next-themes'
165
import { Button } from '@/components/ui/button'
6+
import {
7+
DropdownMenu,
8+
DropdownMenuContent,
9+
DropdownMenuItem,
10+
DropdownMenuLabel,
11+
DropdownMenuSeparator,
12+
DropdownMenuTrigger,
13+
} from '@/components/ui/dropdown-menu'
1714

1815
interface TopNavProps {
1916
onToggleSidebar: () => void
@@ -24,7 +21,6 @@ interface TopNavProps {
2421
export function TopNav({ onToggleSidebar, sidebarCollapsed, onOpenCommandPalette }: TopNavProps) {
2522
const { session, signOut } = useAuth()
2623
const { theme, setTheme } = useTheme()
27-
const [showUserMenu, setShowUserMenu] = useState(false)
2824

2925
const userEmail = session?.user?.email || 'User'
3026
const userInitial = userEmail.charAt(0).toUpperCase()
@@ -55,7 +51,7 @@ export function TopNav({ onToggleSidebar, sidebarCollapsed, onOpenCommandPalette
5551
</div>
5652

5753
{/* Center - Command Palette Trigger */}
58-
<button
54+
<button
5955
className="hidden sm:flex items-center gap-2 px-3 py-1.5 bg-muted border border-border rounded-lg text-muted-foreground hover:text-foreground hover:bg-muted/80 transition-all max-w-xs"
6056
onClick={onOpenCommandPalette}
6157
>
@@ -84,72 +80,49 @@ export function TopNav({ onToggleSidebar, sidebarCollapsed, onOpenCommandPalette
8480
className="text-muted-foreground hover:text-foreground"
8581
aria-label={theme === 'dark' ? 'Switch to light mode' : 'Switch to dark mode'}
8682
>
87-
{theme === 'dark' ? (
88-
<Sun className="w-5 h-5" />
89-
) : (
90-
<Moon className="w-5 h-5" />
91-
)}
83+
{theme === 'dark' ? <Sun className="w-5 h-5" /> : <Moon className="w-5 h-5" />}
9284
</Button>
9385

94-
{/* User Menu */}
95-
<div className="relative">
96-
<button
97-
onClick={() => setShowUserMenu(!showUserMenu)}
98-
className="flex items-center gap-2 p-1 rounded-lg hover:bg-muted transition-colors"
99-
>
100-
<div className="w-8 h-8 rounded-full bg-gradient-to-br from-primary to-purple-600 flex items-center justify-center">
101-
<span className="text-primary-foreground text-sm font-medium">{userInitial}</span>
102-
</div>
103-
</button>
104-
105-
{showUserMenu && (
106-
<>
107-
<div
108-
className="fixed inset-0 z-40"
109-
onClick={() => setShowUserMenu(false)}
110-
/>
111-
<div className="absolute right-0 top-full mt-2 w-56 bg-card border border-border rounded-xl shadow-lg z-50 py-2">
112-
<div className="px-4 py-2 border-b border-border">
113-
<p className="text-sm text-foreground font-medium truncate">{userEmail}</p>
114-
<p className="text-xs text-muted-foreground">Free Plan</p>
115-
</div>
116-
<div className="py-1">
117-
<Link
118-
to="/dashboard/settings"
119-
className="flex items-center gap-2 px-4 py-2 text-sm text-muted-foreground hover:text-foreground hover:bg-muted transition-colors"
120-
onClick={() => setShowUserMenu(false)}
121-
>
122-
<Settings className="w-4 h-4" />
123-
Settings
124-
</Link>
125-
<a
126-
href="/docs"
127-
target="_blank"
128-
rel="noopener noreferrer"
129-
className="flex items-center gap-2 px-4 py-2 text-sm text-muted-foreground hover:text-foreground hover:bg-muted transition-colors"
130-
onClick={() => setShowUserMenu(false)}
131-
>
132-
<BookOpen className="w-4 h-4" />
133-
Documentation
134-
<ExternalLink className="w-3 h-3 ml-auto opacity-50" />
135-
</a>
136-
</div>
137-
<div className="border-t border-border py-1">
138-
<button
139-
onClick={() => {
140-
signOut()
141-
setShowUserMenu(false)
142-
}}
143-
className="flex items-center gap-2 w-full text-left px-4 py-2 text-sm text-destructive hover:bg-muted transition-colors"
144-
>
145-
<LogOut className="w-4 h-4" />
146-
Sign out
147-
</button>
148-
</div>
86+
{/* User Menu - using shadcn DropdownMenu for proper click-outside handling */}
87+
<DropdownMenu>
88+
<DropdownMenuTrigger asChild>
89+
<button className="flex items-center gap-2 p-1 rounded-lg hover:bg-muted transition-colors focus:outline-none">
90+
<div className="w-8 h-8 rounded-full bg-gradient-to-br from-primary to-purple-600 flex items-center justify-center">
91+
<span className="text-primary-foreground text-sm font-medium">{userInitial}</span>
92+
</div>
93+
</button>
94+
</DropdownMenuTrigger>
95+
<DropdownMenuContent align="end" className="w-56">
96+
<DropdownMenuLabel className="font-normal">
97+
<div className="flex flex-col space-y-1">
98+
<p className="text-sm font-medium truncate">{userEmail}</p>
99+
<p className="text-xs text-muted-foreground">Free Plan</p>
149100
</div>
150-
</>
151-
)}
152-
</div>
101+
</DropdownMenuLabel>
102+
<DropdownMenuSeparator />
103+
<DropdownMenuItem asChild>
104+
<Link to="/dashboard/settings" className="cursor-pointer">
105+
<Settings className="mr-2 h-4 w-4" />
106+
Settings
107+
</Link>
108+
</DropdownMenuItem>
109+
<DropdownMenuItem asChild>
110+
<a href="/docs" target="_blank" rel="noopener noreferrer" className="cursor-pointer">
111+
<BookOpen className="mr-2 h-4 w-4" />
112+
Documentation
113+
<ExternalLink className="ml-auto h-3 w-3 opacity-50" />
114+
</a>
115+
</DropdownMenuItem>
116+
<DropdownMenuSeparator />
117+
<DropdownMenuItem
118+
onClick={() => signOut()}
119+
className="text-destructive focus:text-destructive cursor-pointer"
120+
>
121+
<LogOut className="mr-2 h-4 w-4" />
122+
Sign out
123+
</DropdownMenuItem>
124+
</DropdownMenuContent>
125+
</DropdownMenu>
153126
</div>
154127
</div>
155128
</nav>

0 commit comments

Comments
 (0)