Silos/frontend/src/App.tsx

135 lines
4.1 KiB
TypeScript

import { Routes, Route, Navigate, useSearchParams, useNavigate } from 'react-router-dom'
import { useEffect, useState } from 'react'
import LandingPage from './pages/LandingPage'
import LoginPage from './pages/LoginPage'
import DashboardPage from './pages/DashboardPage'
import ShedPage from './pages/workspace/ShedPage'
import SiloPage from './pages/workspace/SiloPage'
import SketchPage from './pages/workspace/SketchPage'
import SteadPage from './pages/workspace/SteadPage'
import SteadCreatePage from './pages/workspace/SteadCreatePage'
import ForbiddenPage from './pages/ForbiddenPage'
import ProtectedRoute from './components/ProtectedRoute'
import AccountPage from './pages/AccountPage'
import WorkspaceAdminPage from './pages/WorkspaceAdminPage'
import InvitationPage from './pages/InvitationPage'
import { authApi, saveAuth } from './lib/api'
function GoogleCallback() {
const [params] = useSearchParams()
const navigate = useNavigate()
const [error, setError] = useState<string | null>(null)
useEffect(() => {
const accessToken = params.get('access_token')
const refreshToken = params.get('refresh_token')
if (!accessToken || !refreshToken) {
setError('Google sign-in did not return valid session credentials.')
return
}
localStorage.setItem('silos_access_token', accessToken)
localStorage.setItem('silos_refresh_token', refreshToken)
void authApi.me().then((user) => {
saveAuth({ access_token: accessToken, refresh_token: refreshToken, token_type: 'bearer', user })
navigate('/dashboard', { replace: true })
}).catch(() => {
localStorage.removeItem('silos_access_token')
localStorage.removeItem('silos_refresh_token')
setError('Google sign-in could not be completed.')
})
}, [navigate, params])
if (error) return <main className="flex min-h-screen items-center justify-center bg-silos-cream p-6"><div className="rounded-2xl bg-white p-6 text-center shadow"><p className="text-sm text-red-700">{error}</p><button type="button" onClick={() => navigate('/login')} className="mt-4 rounded-lg bg-silos-brown px-4 py-2 text-sm text-white">Return to login</button></div></main>
return <Navigate to="/dashboard" replace />
}
export default function App() {
return (
<Routes>
<Route path="/" element={<LandingPage />} />
<Route path="/login" element={<LoginPage />} />
<Route
path="/dashboard"
element={
<ProtectedRoute>
<DashboardPage />
</ProtectedRoute>
}
/>
<Route
path="/settings"
element={
<ProtectedRoute>
<AccountPage />
</ProtectedRoute>
}
/>
<Route
path="/profile"
element={
<ProtectedRoute>
<AccountPage />
</ProtectedRoute>
}
/>
<Route
path="/settings/workspaces"
element={
<ProtectedRoute>
<WorkspaceAdminPage />
</ProtectedRoute>
}
/>
<Route path="/invite/:token" element={<InvitationPage />} />
<Route path="/auth/google/callback" element={<GoogleCallback />} />
<Route
path="/forbidden"
element={
<ProtectedRoute>
<ForbiddenPage />
</ProtectedRoute>
}
/>
<Route
path="/workspace/shed/:id"
element={
<ProtectedRoute>
<ShedPage />
</ProtectedRoute>
}
/>
<Route
path="/workspace/silo/:id"
element={
<ProtectedRoute>
<SiloPage />
</ProtectedRoute>
}
/>
<Route
path="/workspace/sketch/:id"
element={
<ProtectedRoute>
<SketchPage />
</ProtectedRoute>
}
/>
<Route
path="/workspace/stead/new"
element={
<ProtectedRoute>
<SteadCreatePage />
</ProtectedRoute>
}
/>
<Route
path="/workspace/stead/:id"
element={
<ProtectedRoute>
<SteadPage />
</ProtectedRoute>
}
/>
</Routes>
)
}