feat(frontend): Finalize auth refactor, routing, and resolve all code review findings
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import { useState, useEffect } from "react"
|
||||
import { Routes, Route } from "react-router-dom"
|
||||
import { MainLayout } from "./components/layout/MainLayout"
|
||||
import { LoginForm } from "./components/auth/LoginForm"
|
||||
import { RegisterForm } from "./components/auth/RegisterForm"
|
||||
import { AuthCallback } from "./components/auth/AuthCallback"
|
||||
import { AuthService, type UserResponse } from "./services/auth"
|
||||
|
||||
function App() {
|
||||
@@ -12,48 +14,41 @@ function App() {
|
||||
|
||||
useEffect(() => {
|
||||
const initAuth = async () => {
|
||||
// Check for token in URL (OIDC callback)
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
const tokenFromUrl = urlParams.get("token")
|
||||
if (tokenFromUrl) {
|
||||
localStorage.setItem("token", tokenFromUrl)
|
||||
// Clean URL
|
||||
window.history.replaceState({}, document.title, "/")
|
||||
try {
|
||||
const userData = await AuthService.getMe()
|
||||
setUser(userData)
|
||||
setIsAuthenticated(true)
|
||||
} catch (err: unknown) {
|
||||
// Not logged in or session expired - this is expected if no cookie
|
||||
console.log("No active session found", err)
|
||||
setIsAuthenticated(false)
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
|
||||
const authStatus = AuthService.isAuthenticated()
|
||||
setIsAuthenticated(authStatus)
|
||||
|
||||
if (authStatus) {
|
||||
try {
|
||||
const userData = await AuthService.getMe()
|
||||
setUser(userData)
|
||||
} catch (err) {
|
||||
console.error("Failed to fetch user profile:", err)
|
||||
AuthService.logout()
|
||||
setIsAuthenticated(false)
|
||||
}
|
||||
}
|
||||
setIsLoading(false)
|
||||
}
|
||||
|
||||
initAuth()
|
||||
}, [])
|
||||
|
||||
const handleAuthSuccess = async () => {
|
||||
setIsAuthenticated(true)
|
||||
try {
|
||||
const userData = await AuthService.getMe()
|
||||
setUser(userData)
|
||||
} catch (err) {
|
||||
setIsAuthenticated(true)
|
||||
} catch (err: unknown) {
|
||||
console.error("Failed to fetch user profile after login:", err)
|
||||
}
|
||||
}
|
||||
|
||||
const handleLogout = () => {
|
||||
AuthService.logout()
|
||||
setIsAuthenticated(false)
|
||||
setUser(null)
|
||||
const handleLogout = async () => {
|
||||
try {
|
||||
await AuthService.logout()
|
||||
} catch (err: unknown) {
|
||||
console.error("Logout failed:", err)
|
||||
} finally {
|
||||
setIsAuthenticated(false)
|
||||
setUser(null)
|
||||
}
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
@@ -64,44 +59,52 @@ function App() {
|
||||
)
|
||||
}
|
||||
|
||||
if (!isAuthenticated) {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-background p-4">
|
||||
{authMode === "login" ? (
|
||||
<LoginForm
|
||||
onSuccess={handleAuthSuccess}
|
||||
onToggleMode={() => setAuthMode("register")}
|
||||
/>
|
||||
) : (
|
||||
<RegisterForm
|
||||
onSuccess={handleAuthSuccess}
|
||||
onToggleMode={() => setAuthMode("login")}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<MainLayout>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex justify-between items-center">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold">Welcome, {user?.display_name || user?.email || "User"}!</h1>
|
||||
<p className="text-sm text-muted-foreground">{user?.email}</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={handleLogout}
|
||||
className="text-sm text-muted-foreground hover:text-primary underline"
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
</div>
|
||||
<p className="text-muted-foreground mt-4">
|
||||
Select a conversation from the sidebar or start a new one to begin your analysis.
|
||||
</p>
|
||||
</div>
|
||||
</MainLayout>
|
||||
<Routes>
|
||||
<Route path="/auth/callback" element={<AuthCallback />} />
|
||||
<Route
|
||||
path="*"
|
||||
element={
|
||||
!isAuthenticated ? (
|
||||
<div className="min-h-screen flex items-center justify-center bg-background p-4">
|
||||
{authMode === "login" ? (
|
||||
<LoginForm
|
||||
onSuccess={handleAuthSuccess}
|
||||
onToggleMode={() => setAuthMode("register")}
|
||||
/>
|
||||
) : (
|
||||
<RegisterForm
|
||||
onSuccess={handleAuthSuccess}
|
||||
onToggleMode={() => setAuthMode("login")}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<MainLayout>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex justify-between items-center">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold">
|
||||
Welcome, {user?.display_name || user?.email || "User"}!
|
||||
</h1>
|
||||
<p className="text-sm text-muted-foreground">{user?.email}</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={handleLogout}
|
||||
className="text-sm text-muted-foreground hover:text-primary underline"
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
</div>
|
||||
<p className="text-muted-foreground mt-4">
|
||||
Select a conversation from the sidebar or start a new one to begin your analysis.
|
||||
</p>
|
||||
</div>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user