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] }