Add gameday TeamSnap loading state

This commit is contained in:
Codex
2026-04-23 12:34:12 -05:00
parent a26a611d3b
commit d6630e1879
2 changed files with 62 additions and 11 deletions

View File

@@ -60,6 +60,8 @@ export function GamedayPage() {
const [playerFilterMenuOpen, setPlayerFilterMenuOpen] = useState(false);
const playerFilterMenuRef = useRef<HTMLDivElement | null>(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 (
<section className="page-grid gameday-page">
<div className="panel gameday-loading-panel" role="status" aria-live="polite">
<div className="gameday-loading-spinner spinner-border text-primary" aria-hidden="true" />
<div className="gameday-loading-copy">
<span className="gameday-loading-label">Waiting for TeamSnap</span>
<strong>Loading gameday data</strong>
<span className="muted">Teams, games, roster data, and lineup details are being fetched.</span>
</div>
</div>
</section>
);
}
return (
<section className="page-grid gameday-page">
{isPlaybackPlaying && nowPlaying ? (

View File

@@ -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;