feat(frontend): Finalize auth refactor, routing, and resolve all code review findings

This commit is contained in:
Yunxiao Xu
2026-02-12 00:11:08 -08:00
parent 7fe020f26c
commit 2545f6df13
17 changed files with 335 additions and 216 deletions

View File

@@ -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>
)
}