import {
BrowserRouter,
Navigate,
Outlet,
Route,
Routes,
useLocation,
} from "react-router-dom"
import { Header } from "./pages/template/Header.tsx"
import "./style/app.css"
import {
createContext,
lazy,
ReactNode,
Suspense,
useCallback,
useContext,
useEffect,
useMemo,
useState,
} from "react"
import { BASE } from "./Constants.ts"
import { Authentication, Fetcher } from "./app/Fetcher.ts"
import { User } from "./model/User.ts"
import { VisualizerPage } from "./pages/VisualizerPage.tsx"
const HomePage = lazy(() => import("./pages/HomePage.tsx"))
const LoginPage = lazy(() => import("./pages/LoginPage.tsx"))
const RegisterPage = lazy(() => import("./pages/RegisterPage.tsx"))
const NotFoundPage = lazy(() => import("./pages/404.tsx"))
const CreateTeamPage = lazy(() => import("./pages/CreateTeamPage.tsx"))
const TeamPanelPage = lazy(() => import("./pages/TeamPanel.tsx"))
const NewTacticPage = lazy(() => import("./pages/NewTacticPage.tsx"))
const Editor = lazy(() => import("./pages/Editor.tsx"))
const Settings = lazy(() => import("./pages/Settings.tsx"))
const TOKEN_REFRESH_INTERVAL_MS = 60 * 1000
export default function App() {
function suspense(node: ReactNode) {
return (
Loading, please wait...
}>
{node}
)
}
const fetcher = useMemo(() => new Fetcher(getStoredAuthentication()), [])
const [user, setUser] = useState(null)
const handleAuthSuccess = useCallback(
async (auth: Authentication) => {
fetcher.updateAuthentication(auth)
const user = await fetchUser(fetcher)
setUser(user)
storeAuthentication(auth)
},
[fetcher],
)
useEffect(() => {
const interval = setInterval(() => {
fetcher.fetchAPIGet("auth/keep-alive")
}, TOKEN_REFRESH_INTERVAL_MS)
return () => clearInterval(interval)
}, [fetcher])
return (
,
)}
/>
,
)}
/>
)}>
,
)}
/>
,
)}
/>
,
)}
/>
)}
/>
,
)}
/>
)}
/>
,
)}
/>
,
,
)}
/>
,
)}
/>
,
)}
/>
)}
/>
)
}
async function fetchUser(fetcher: Fetcher): Promise {
const response = await fetcher.fetchAPIGet("user")
if (!response.ok) {
throw Error(
"Could not retrieve user information : " + (await response.text()),
)
}
return await response.json()
}
const STORAGE_AUTH_KEY = "token"
function getStoredAuthentication(): Authentication {
const storedUser = localStorage.getItem(STORAGE_AUTH_KEY)
return storedUser == null ? null : JSON.parse(storedUser)
}
function storeAuthentication(auth: Authentication) {
localStorage.setItem(STORAGE_AUTH_KEY, JSON.stringify(auth))
}
interface LoggedInPageProps {
children: ReactNode
}
enum UserFetchingState {
FETCHING,
FETCHED,
ERROR,
}
function LoggedInPage({ children }: LoggedInPageProps) {
const [user, setUser] = useUser()
const fetcher = useAppFetcher()
const [userFetchingState, setUserFetchingState] = useState(
user === null ? UserFetchingState.FETCHING : UserFetchingState.FETCHED,
)
const location = useLocation()
useEffect(() => {
async function initUser() {
try {
const user = await fetchUser(fetcher)
setUser(user)
setUserFetchingState(UserFetchingState.FETCHED)
} catch (e) {
setUserFetchingState(UserFetchingState.ERROR)
}
}
if (userFetchingState === UserFetchingState.FETCHING) initUser()
}, [fetcher, setUser, userFetchingState])
switch (userFetchingState) {
case UserFetchingState.ERROR:
return (
)
case UserFetchingState.FETCHED:
return children
case UserFetchingState.FETCHING:
return Fetching user...
}
}
function AppLayout() {
return (
<>
>
)
}
interface UserContext {
user: User | null
setUser: (user: User | null) => void
}
const SignedInUserContext = createContext(null)
const FetcherContext = createContext(new Fetcher())
export function useAppFetcher() {
return useContext(FetcherContext)
}
export function useUser(): [User | null, (user: User | null) => void] {
const { user, setUser } = useContext(SignedInUserContext)!
return [user, setUser]
}