From d6630e187917d94b431ad0d6d5cd4a9e579e6458 Mon Sep 17 00:00:00 2001 From: Codex Date: Thu, 23 Apr 2026 12:34:12 -0500 Subject: [PATCH] Add gameday TeamSnap loading state --- frontend/src/pages/GamedayPage.tsx | 44 ++++++++++++++++++++++-------- frontend/src/styles.css | 29 ++++++++++++++++++++ 2 files changed, 62 insertions(+), 11 deletions(-) diff --git a/frontend/src/pages/GamedayPage.tsx b/frontend/src/pages/GamedayPage.tsx index 3e56796..731c2f7 100644 --- a/frontend/src/pages/GamedayPage.tsx +++ b/frontend/src/pages/GamedayPage.tsx @@ -60,6 +60,8 @@ export function GamedayPage() { const [playerFilterMenuOpen, setPlayerFilterMenuOpen] = useState(false); const playerFilterMenuRef = useRef(null); const teamId = walkup.selectedTeamId; + const resolvedSelectedGameId = + selectedGameId || searchParams.get("gameId") || (walkup.nextGame ? String(walkup.nextGame.id) : ""); const { activeKey: playingClipKey, activeDetails: nowPlaying, @@ -111,25 +113,25 @@ export function GamedayPage() { }, [playerFilterMenuOpen]); const assignmentsQuery = useQuery({ - queryKey: ["assignments", selectedGameId], - queryFn: () => api.listAssignments(selectedGameId), - enabled: Boolean(selectedGameId), + queryKey: ["assignments", resolvedSelectedGameId], + queryFn: () => api.listAssignments(resolvedSelectedGameId), + enabled: Boolean(resolvedSelectedGameId), retry: 0, }); - const preparedGame = selectedGameId ? loadPreparedGame(selectedGameId) : null; + const preparedGame = resolvedSelectedGameId ? loadPreparedGame(resolvedSelectedGameId) : null; const assignmentList = assignmentsQuery.data ?? preparedGame?.assignments ?? []; const eventLineupQuery = useQuery({ - queryKey: ["teamsnap", "eventLineup", teamId, selectedGameId], - queryFn: () => teamsnapClient.loadEventLineupData(teamId, selectedGameId), - enabled: Boolean(teamId && selectedGameId), + queryKey: ["teamsnap", "eventLineup", teamId, resolvedSelectedGameId], + queryFn: () => teamsnapClient.loadEventLineupData(teamId, resolvedSelectedGameId), + enabled: Boolean(teamId && resolvedSelectedGameId), }); const availabilityQuery = useQuery({ - queryKey: ["teamsnap", "availabilities", teamId, selectedGameId], - queryFn: () => teamsnapClient.loadAvailabilities(teamId, selectedGameId), - enabled: Boolean(teamId && selectedGameId), + queryKey: ["teamsnap", "availabilities", teamId, resolvedSelectedGameId], + queryFn: () => teamsnapClient.loadAvailabilities(teamId, resolvedSelectedGameId), + enabled: Boolean(teamId && resolvedSelectedGameId), }); const orderedMembers = useMemo( @@ -147,7 +149,12 @@ export function GamedayPage() { ? orderedMembers : orderedMembers.filter((member) => (playerFilter === "players" ? isPlayerMember(member) : !isPlayerMember(member))); - const selectedGame = walkup.games.find((game) => String(game.id) === selectedGameId) ?? null; + const selectedGame = walkup.games.find((game) => String(game.id) === resolvedSelectedGameId) ?? null; + const isLoadingTeamSnapData = + walkup.teamsQuery.isLoading || + walkup.membersQuery.isLoading || + walkup.eventsQuery.isLoading || + (Boolean(teamId && resolvedSelectedGameId) && (eventLineupQuery.isLoading || availabilityQuery.isLoading)); function selectGame(gameId: string) { setSelectedGameId(gameId); @@ -168,6 +175,21 @@ export function GamedayPage() { ); } + if (isLoadingTeamSnapData) { + return ( +
+
+ +
+ ); + } + return (
{isPlaybackPlaying && nowPlaying ? ( diff --git a/frontend/src/styles.css b/frontend/src/styles.css index dfe46be..02d706e 100644 --- a/frontend/src/styles.css +++ b/frontend/src/styles.css @@ -279,6 +279,35 @@ select { margin-top: 0; } +.gameday-loading-panel { + min-height: min(42vh, 24rem); + display: grid; + place-items: center; + gap: 1rem; + text-align: center; + padding: 2rem 1.5rem; +} + +.gameday-loading-spinner { + width: 3rem; + height: 3rem; + border-width: 0.28rem; +} + +.gameday-loading-copy { + display: grid; + gap: 0.35rem; + max-width: 24rem; +} + +.gameday-loading-label { + color: var(--accent); + font-size: 0.82rem; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; +} + .stack { display: grid; gap: 0.75rem;