forked from AOSSIE-Org/Devr.AI
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathApp.tsx
More file actions
201 lines (181 loc) · 5.95 KB
/
Copy pathApp.tsx
File metadata and controls
201 lines (181 loc) · 5.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
import React, { useEffect, useState } from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate, Outlet } from 'react-router-dom';
import { AnimatePresence } from 'framer-motion';
import toast, { Toaster } from 'react-hot-toast';
import Sidebar from './components/layout/Sidebar';
import Dashboard from './components/dashboard/Dashboard';
import BotIntegrationPage from './components/integration/BotIntegrationPage';
import ContributorsPage from './components/contributors/ContributorsPage';
import PullRequestsPage from './components/pages/PullRequestsPage';
import SettingsPage from './components/pages/SettingsPage';
import AnalyticsPage from './components/pages/AnalyticsPage';
import SupportPage from './components/pages/SupportPage';
import LandingPage from './components/landing/LandingPage';
import LoginPage from './components/pages/LoginPage';
import ProfilePage from './components/pages/ProfilePage';
import SignUpPage from './components/pages/SignUpPage';
import { supabase } from './lib/supabaseClient';
import ForgotPasswordPage from './components/pages/ForgotPasswordPage';
import ResetPasswordPage from './components/pages/ResetPasswordPage';
import { useLocation } from 'react-router-dom';
// Define proper TypeScript interfaces
interface RepositoryData {
id: string;
name: string;
full_name: string;
description?: string;
html_url: string;
stargazers_count: number;
forks_count: number;
language?: string;
created_at: string;
updated_at: string;
owner: {
login: string;
avatar_url: string;
};
}
function App() {
const [isSidebarOpen, setIsSidebarOpen] = useState(true);
const [repoData, setRepoData] = useState<RepositoryData | null>(null);
const [isAuthenticated, setIsAuthenticated] = useState(false);
// Auto login if user has already logged in
useEffect(() => {
supabase.auth.getSession().then(({ data, error }) => {
if (error) {
toast.error('User Login Failed');
console.error('Error checking session:', error);
return;
}
setIsAuthenticated(!!data.session);
});
const { data: subscription } = supabase.auth.onAuthStateChange(
(event, session) => {
switch (event) {
case "SIGNED_IN":
setIsAuthenticated(true);
toast.success("Signed in!");
break;
case "SIGNED_OUT":
setIsAuthenticated(false);
setRepoData(null);
toast.success("Signed out!");
break;
case "PASSWORD_RECOVERY":
toast("Check your email to reset your password.");
break;
case "TOKEN_REFRESHED":
// Session refreshed silently
break;
case "USER_UPDATED":
// User profile updated
break;
}
}
);
return () => {
subscription.subscription.unsubscribe();
};
}, []);
const handleLogin = () => {
setIsAuthenticated(true);
};
const handleLogout = async () => {
const { error } = await supabase.auth.signOut();
if (error) {
toast.error('Logout failed');
console.error('Error during logout:', error);
return;
}
toast.success('Signed out!');
setIsAuthenticated(false);
setRepoData(null);
};
const ProtectedLayout = () => {
const location = useLocation();
const landingAllowedRoutes = [
'/dashboard',
'/contributors',
'/analytics',
'/prs',
];
const shouldShowLanding =
!repoData && landingAllowedRoutes.includes(location.pathname);
return (
<div className="flex">
<Sidebar
isOpen={isSidebarOpen}
setIsOpen={setIsSidebarOpen}
onLogout={handleLogout}
/>
<main
className={`transition-all duration-300 flex-1 ${isSidebarOpen ? 'ml-64' : 'ml-20'
}`}
>
<div className="p-8">
{/* Conditional Landing Page */}
{shouldShowLanding && (
<LandingPage setRepoData={setRepoData} />
)}
<AnimatePresence mode="wait">
<Outlet />
</AnimatePresence>
</div>
</main>
</div>
);
};
return (
<Router>
<div className="min-h-screen bg-gray-950 text-white">
<Toaster position="top-right" />
<Routes>
<Route
path="/login"
element={
isAuthenticated ? (
<Navigate to="/" replace />
) : (
<LoginPage onLogin={handleLogin} />
)
}
/>
<Route
path="/forgot-password"
element={
isAuthenticated ? (
<Navigate to="/" replace />
) : (
<ForgotPasswordPage />
)
}
/>
<Route path="/reset-password" element={<ResetPasswordPage />} />
<Route
path="/signup"
element={
isAuthenticated ? <Navigate to="/" replace /> : <SignUpPage />
}
/>
<Route
path="/"
element={
isAuthenticated ? <ProtectedLayout /> : <Navigate to="/login" replace />
}
>
<Route index element={<LandingPage setRepoData={setRepoData} />} />
<Route path="dashboard" element={<Dashboard repoData={repoData} />} />
<Route path="integration" element={<BotIntegrationPage />} />
<Route path="contributors" element={<ContributorsPage repoData={repoData} />} />
<Route path="analytics" element={<AnalyticsPage repoData={repoData} />} />
<Route path="prs" element={<PullRequestsPage repoData={repoData} />} />
<Route path="support" element={<SupportPage />} />
<Route path="settings" element={<SettingsPage />} />
<Route path="profile" element={<ProfilePage />} />
</Route>
</Routes>
</div>
</Router>
);
}
export default App;