import { Component, useEffect, useState, type ErrorInfo, type ReactElement, type ReactNode } from "react"; import { NavLink, Navigate, Route, Routes, useLocation } from "react-router-dom"; import { WalkupProvider, useWalkupContext } from "./hooks/useWalkupContext"; import { useSession } from "./hooks/useSession"; import { DashboardPage } from "./pages/DashboardPage"; import { GamePage } from "./pages/GamePage"; import { LibraryPage } from "./pages/LibraryPage"; import { OperatorPage } from "./pages/OperatorPage"; import { ProfilePage } from "./pages/ProfilePage"; import { AdminPage } from "./pages/AdminPage"; import { SignInPage } from "./pages/SignInPage"; import { formatTeamLabel } from "./lib/teamsnapHelpers"; function getRouteDestinationLabel(pathname: string) { switch (pathname) { case "/": return "your dashboard"; case "/library": return "walkup clips"; case "/games": return "game clips"; case "/operator": return "the operator console"; default: return "this page"; } } function ProtectedRoute({ children }: { children: ReactElement }) { const location = useLocation(); const { data, isLoading } = useSession(); if (isLoading) { return (
Loading session...
); } if (!data?.authenticated) { return ; } return children; } function HomeRoute() { const walkup = useWalkupContext(); if (walkup.sessionQuery.isLoading) { return (
Loading session...
); } if (!walkup.sessionQuery.data?.authenticated) { return ; } return ( ); } function SignInRoute() { const walkup = useWalkupContext(); if (walkup.sessionQuery.isLoading) { return (
Loading session...
); } if (walkup.sessionQuery.data?.authenticated) { return ; } return ; } function TeamSelectionRoute({ children }: { children: ReactElement }) { return children; } function TeamSelectionModal() { const location = useLocation(); const walkup = useWalkupContext(); if (!walkup.isTeamSnap || !walkup.teamsQuery.isFetched || walkup.hasSelectedTeam) { return null; } return (

Step 2 of 2

Pick the team you want to use.

You are signed in with TeamSnap. Choose a team to continue to {getRouteDestinationLabel(location.pathname)}.

Available teams

{walkup.teamsQuery.isLoading ? (
Loading teams...
) : (
{walkup.teamsQuery.data?.map((team) => { const teamId = String(team.id); const selected = teamId === walkup.selectedTeamId; return ( ); })} {!walkup.teamsQuery.data?.length ? (
No teams were returned for this account.
) : null}
)}

What happens next

1. Sign in with TeamSnap.
2. Choose the team you want to manage.
3. Continue into the dashboard, walkup clips, or game tools.
); } class AppErrorBoundary extends Component<{ children: ReactNode }, { errorMessage: string | null }> { state = { errorMessage: null }; static getDerivedStateFromError(error: unknown) { return { errorMessage: error instanceof Error ? error.message : "Unexpected render error", }; } componentDidCatch(error: unknown, errorInfo: ErrorInfo) { console.error("Walkup render error", error, errorInfo); } render() { if (this.state.errorMessage) { return (

App Error

{this.state.errorMessage}
); } return this.props.children; } } function ShellLayout() { const [navOpen, setNavOpen] = useState(false); const walkup = useWalkupContext(); const location = useLocation(); const showNavbar = walkup.sessionQuery.data?.authenticated === true; const showTeamSelectionModal = walkup.isTeamSnap && walkup.teamsQuery.isFetched && !walkup.hasSelectedTeam; const shellClassName = showNavbar ? "shell is-authenticated" : "shell is-authless"; useEffect(() => { setNavOpen(false); }, [location.pathname]); useEffect(() => { if (!showTeamSelectionModal) { return; } const previousOverflow = document.body.style.overflow; document.body.style.overflow = "hidden"; return () => { document.body.style.overflow = previousOverflow; }; }, [showTeamSelectionModal]); return (
{showNavbar ? (
Baseball audio ops Walkup
) : null}
} /> } /> } /> } /> } /> } /> } />
{showTeamSelectionModal ? : null}
); } export default function App() { return ( ); }