Skip to content

Commit f31ba33

Browse files
Merge pull request #129 from mithun50/main
Refactor frontend routing to use React Router idiomatically
2 parents a4ff6eb + 9111674 commit f31ba33

File tree

2 files changed

+84
-85
lines changed

2 files changed

+84
-85
lines changed

frontend/src/App.tsx

Lines changed: 36 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import React, { useEffect, useState } from 'react';
2-
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
3-
import { AnimatePresence } from 'framer-motion';
2+
import { BrowserRouter as Router, Routes, Route, Navigate, Outlet } from 'react-router-dom';
43
import { Toaster } from 'react-hot-toast';
54
import Sidebar from './components/layout/Sidebar';
65
import Dashboard from './components/dashboard/Dashboard';
@@ -13,10 +12,10 @@ import SupportPage from './components/pages/SupportPage';
1312
import LandingPage from './components/landing/LandingPage';
1413
import LoginPage from './components/pages/LoginPage';
1514
import ProfilePage from './components/pages/ProfilePage';
15+
import { AnimatePresence } from 'framer-motion';
1616

1717
function App() {
1818
const [isSidebarOpen, setIsSidebarOpen] = useState(true);
19-
const [activePage, setActivePage] = useState('landing'); // Default to landing page
2019
const [repoData, setRepoData] = useState<any>(null); // Store fetched repo stats
2120
const [isAuthenticated, setIsAuthenticated] = useState(false);
2221

@@ -36,34 +35,29 @@ function App() {
3635
const handleLogout = () => {
3736
setIsAuthenticated(false);
3837
localStorage.removeItem('isAuthenticated');
39-
setActivePage('landing');
4038
setRepoData(null);
4139
};
4240

43-
const renderPage = () => {
44-
switch (activePage) {
45-
case 'landing':
46-
return <LandingPage setRepoData={setRepoData} setActivePage={setActivePage} />;
47-
case 'dashboard':
48-
return <Dashboard repoData={repoData} />;
49-
case 'integration':
50-
return <BotIntegrationPage />;
51-
case 'contributors':
52-
return <ContributorsPage repoData={repoData} />;
53-
case 'analytics':
54-
return <AnalyticsPage repoData={repoData} />;
55-
case 'prs':
56-
return <PullRequestsPage repoData={repoData} />;
57-
case 'support':
58-
return <SupportPage />;
59-
case 'settings':
60-
return <SettingsPage />;
61-
case 'profile':
62-
return <ProfilePage />;
63-
default:
64-
return <Dashboard repoData={repoData} />;
65-
}
66-
};
41+
const ProtectedLayout = () => (
42+
<div className="flex">
43+
<Sidebar
44+
isOpen={isSidebarOpen}
45+
setIsOpen={setIsSidebarOpen}
46+
onLogout={handleLogout}
47+
/>
48+
<main
49+
className={`transition-all duration-300 flex-1 ${
50+
isSidebarOpen ? 'ml-64' : 'ml-20'
51+
}`}
52+
>
53+
<div className="p-8">
54+
<AnimatePresence mode="wait">
55+
<Outlet />
56+
</AnimatePresence>
57+
</div>
58+
</main>
59+
</div>
60+
);
6761

6862
return (
6963
<Router>
@@ -81,35 +75,26 @@ function App() {
8175
}
8276
/>
8377
<Route
84-
path="/*"
78+
path="/"
8579
element={
86-
isAuthenticated ? (
87-
<div className="flex">
88-
<Sidebar
89-
isOpen={isSidebarOpen}
90-
setIsOpen={setIsSidebarOpen}
91-
activePage={activePage}
92-
setActivePage={setActivePage}
93-
/>
94-
<main
95-
className={`transition-all duration-300 flex-1 ${
96-
isSidebarOpen ? 'ml-64' : 'ml-20'
97-
}`}
98-
>
99-
<div className="p-8">
100-
<AnimatePresence mode="wait">{renderPage()}</AnimatePresence>
101-
</div>
102-
</main>
103-
</div>
104-
) : (
105-
<Navigate to="/login" replace />
106-
)
80+
isAuthenticated ? <ProtectedLayout /> : <Navigate to="/login" replace />
10781
}
108-
/>
82+
>
83+
<Route index element={<LandingPage setRepoData={setRepoData} />} />
84+
<Route path="dashboard" element={<Dashboard repoData={repoData} />} />
85+
<Route path="integration" element={<BotIntegrationPage />} />
86+
<Route path="contributors" element={<ContributorsPage repoData={repoData} />} />
87+
<Route path="analytics" element={<AnalyticsPage repoData={repoData} />} />
88+
<Route path="prs" element={<PullRequestsPage repoData={repoData} />} />
89+
<Route path="support" element={<SupportPage />} />
90+
<Route path="settings" element={<SettingsPage />} />
91+
<Route path="profile" element={<ProfilePage />} />
92+
</Route>
10993
</Routes>
11094
</div>
11195
</Router>
11296
);
11397
}
11498

11599
export default App;
100+
Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,72 @@
11
import React from 'react';
2+
import { NavLink } from 'react-router-dom';
23
import {
34
LayoutDashboard,
45
Bot,
5-
Github,
6-
MessageSquare,
76
Users,
87
Activity,
98
GitPullRequest,
109
MessageCircleQuestion,
1110
Menu,
1211
Settings,
13-
User
12+
User,
13+
LogOut
1414
} from 'lucide-react';
1515

1616
interface SidebarProps {
1717
isOpen: boolean;
1818
setIsOpen: (isOpen: boolean) => void;
19-
activePage: string;
20-
setActivePage: (page: string) => void;
19+
onLogout: () => void;
2120
}
2221

23-
const Sidebar: React.FC<SidebarProps> = ({ isOpen, setIsOpen, activePage, setActivePage }) => (
24-
<div className={`fixed top-0 left-0 h-full bg-gray-900 text-white transition-all duration-300 ease-in-out ${isOpen ? 'w-64' : 'w-20'}`}>
25-
<div className="p-4 flex items-center justify-between">
26-
<h2 className={`font-bold text-xl ${!isOpen && 'hidden'}`}>Devr.AI</h2>
27-
<button onClick={() => setIsOpen(!isOpen)} className="p-2 hover:bg-gray-800 rounded-lg">
28-
<Menu size={20} />
29-
</button>
22+
const navItems = [
23+
{ icon: <LayoutDashboard size={20} />, label: 'Dashboard', path: '/dashboard' },
24+
{ icon: <Bot size={20} />, label: 'Bot Integration', path: '/integration' },
25+
{ icon: <Users size={20} />, label: 'Contributors', path: '/contributors' },
26+
{ icon: <Activity size={20} />, label: 'Analytics', path: '/analytics' },
27+
{ icon: <GitPullRequest size={20} />, label: 'Pull Requests', path: '/prs' },
28+
{ icon: <MessageCircleQuestion size={20} />, label: 'Support', path: '/support' },
29+
{ icon: <Settings size={20} />, label: 'Settings', path: '/settings' },
30+
{ icon: <User size={20} />, label: 'Profile', path: '/profile' },
31+
];
32+
33+
const Sidebar: React.FC<SidebarProps> = ({ isOpen, setIsOpen, onLogout }) => (
34+
<div className={`fixed top-0 left-0 h-full bg-gray-900 text-white transition-all duration-300 ease-in-out ${isOpen ? 'w-64' : 'w-20'} flex flex-col`}>
35+
<div>
36+
<div className="p-4 flex items-center justify-between">
37+
<h2 className={`font-bold text-xl ${!isOpen && 'hidden'}`}>Devr.AI</h2>
38+
<button onClick={() => setIsOpen(!isOpen)} className="p-2 hover:bg-gray-800 rounded-lg">
39+
<Menu size={20} />
40+
</button>
41+
</div>
42+
43+
<nav className="mt-8">
44+
{navItems.map((item) => (
45+
<NavLink
46+
key={item.path}
47+
to={item.path}
48+
className={({ isActive }) =>
49+
`w-full flex items-center px-4 py-3 text-gray-300 hover:bg-gray-800 hover:text-green-400 transition-colors ${
50+
isActive ? 'bg-gray-800 text-green-400' : ''
51+
}`
52+
}
53+
>
54+
{item.icon}
55+
<span className={`ml-4 ${!isOpen && 'hidden'}`}>{item.label}</span>
56+
</NavLink>
57+
))}
58+
</nav>
3059
</div>
31-
32-
<nav className="mt-8">
33-
{[
34-
{ icon: <LayoutDashboard size={20} />, label: 'Dashboard', id: 'dashboard' },
35-
{ icon: <Bot size={20} />, label: 'Bot Integration', id: 'integration' },
36-
{ icon: <Users size={20} />, label: 'Contributors', id: 'contributors' },
37-
{ icon: <Activity size={20} />, label: 'Analytics', id: 'analytics' },
38-
{ icon: <GitPullRequest size={20} />, label: 'Pull Requests', id: 'prs' },
39-
{ icon: <MessageCircleQuestion size={20} />, label: 'Support', id: 'support' },
40-
{ icon: <Settings size={20} />, label: 'Settings', id: 'settings' },
41-
{ icon: <User size={20} />, label: 'Profile', id: 'profile' },
42-
].map((item) => (
60+
<div className="mt-auto p-4">
4361
<button
44-
key={item.id}
45-
onClick={() => setActivePage(item.id)}
46-
className={`w-full flex items-center px-4 py-3 text-gray-300 hover:bg-gray-800 hover:text-green-400 transition-colors ${
47-
activePage === item.id ? 'bg-gray-800 text-green-400' : ''
48-
}`}
62+
onClick={onLogout}
63+
className={`w-full flex items-center px-4 py-3 text-gray-300 hover:bg-gray-800 hover:text-red-500 transition-colors`}
4964
>
50-
{item.icon}
51-
<span className={`ml-4 ${!isOpen && 'hidden'}`}>{item.label}</span>
65+
<LogOut size={20} />
66+
<span className={`ml-4 ${!isOpen && 'hidden'}`}>Logout</span>
5267
</button>
53-
))}
54-
</nav>
68+
</div>
5569
</div>
5670
);
5771

58-
export default Sidebar;
72+
export default Sidebar;

0 commit comments

Comments
 (0)