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" 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 storedAuth = useMemo(() => getStoredAuthentication(), []) const fetcher = useMemo(() => new Fetcher(storedAuth), [storedAuth]) 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") console.log("KEPT 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) => void } const SignedInUserContext = createContext(null) const FetcherContext = createContext(new Fetcher()) export function useAppFetcher() { return useContext(FetcherContext) } export function useUser(): [User | null, (user: User) => void] { const { user, setUser } = useContext(SignedInUserContext)! return [user, setUser] }