Add gameday TeamSnap loading state
This commit is contained in:
@@ -60,6 +60,8 @@ export function GamedayPage() {
|
|||||||
const [playerFilterMenuOpen, setPlayerFilterMenuOpen] = useState(false);
|
const [playerFilterMenuOpen, setPlayerFilterMenuOpen] = useState(false);
|
||||||
const playerFilterMenuRef = useRef<HTMLDivElement | null>(null);
|
const playerFilterMenuRef = useRef<HTMLDivElement | null>(null);
|
||||||
const teamId = walkup.selectedTeamId;
|
const teamId = walkup.selectedTeamId;
|
||||||
|
const resolvedSelectedGameId =
|
||||||
|
selectedGameId || searchParams.get("gameId") || (walkup.nextGame ? String(walkup.nextGame.id) : "");
|
||||||
const {
|
const {
|
||||||
activeKey: playingClipKey,
|
activeKey: playingClipKey,
|
||||||
activeDetails: nowPlaying,
|
activeDetails: nowPlaying,
|
||||||
@@ -111,25 +113,25 @@ export function GamedayPage() {
|
|||||||
}, [playerFilterMenuOpen]);
|
}, [playerFilterMenuOpen]);
|
||||||
|
|
||||||
const assignmentsQuery = useQuery({
|
const assignmentsQuery = useQuery({
|
||||||
queryKey: ["assignments", selectedGameId],
|
queryKey: ["assignments", resolvedSelectedGameId],
|
||||||
queryFn: () => api.listAssignments(selectedGameId),
|
queryFn: () => api.listAssignments(resolvedSelectedGameId),
|
||||||
enabled: Boolean(selectedGameId),
|
enabled: Boolean(resolvedSelectedGameId),
|
||||||
retry: 0,
|
retry: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
const preparedGame = selectedGameId ? loadPreparedGame(selectedGameId) : null;
|
const preparedGame = resolvedSelectedGameId ? loadPreparedGame(resolvedSelectedGameId) : null;
|
||||||
const assignmentList = assignmentsQuery.data ?? preparedGame?.assignments ?? [];
|
const assignmentList = assignmentsQuery.data ?? preparedGame?.assignments ?? [];
|
||||||
|
|
||||||
const eventLineupQuery = useQuery({
|
const eventLineupQuery = useQuery({
|
||||||
queryKey: ["teamsnap", "eventLineup", teamId, selectedGameId],
|
queryKey: ["teamsnap", "eventLineup", teamId, resolvedSelectedGameId],
|
||||||
queryFn: () => teamsnapClient.loadEventLineupData(teamId, selectedGameId),
|
queryFn: () => teamsnapClient.loadEventLineupData(teamId, resolvedSelectedGameId),
|
||||||
enabled: Boolean(teamId && selectedGameId),
|
enabled: Boolean(teamId && resolvedSelectedGameId),
|
||||||
});
|
});
|
||||||
|
|
||||||
const availabilityQuery = useQuery({
|
const availabilityQuery = useQuery({
|
||||||
queryKey: ["teamsnap", "availabilities", teamId, selectedGameId],
|
queryKey: ["teamsnap", "availabilities", teamId, resolvedSelectedGameId],
|
||||||
queryFn: () => teamsnapClient.loadAvailabilities(teamId, selectedGameId),
|
queryFn: () => teamsnapClient.loadAvailabilities(teamId, resolvedSelectedGameId),
|
||||||
enabled: Boolean(teamId && selectedGameId),
|
enabled: Boolean(teamId && resolvedSelectedGameId),
|
||||||
});
|
});
|
||||||
|
|
||||||
const orderedMembers = useMemo(
|
const orderedMembers = useMemo(
|
||||||
@@ -147,7 +149,12 @@ export function GamedayPage() {
|
|||||||
? orderedMembers
|
? orderedMembers
|
||||||
: orderedMembers.filter((member) => (playerFilter === "players" ? isPlayerMember(member) : !isPlayerMember(member)));
|
: 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) {
|
function selectGame(gameId: string) {
|
||||||
setSelectedGameId(gameId);
|
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 (
|
return (
|
||||||
<section className="page-grid gameday-page">
|
<section className="page-grid gameday-page">
|
||||||
{isPlaybackPlaying && nowPlaying ? (
|
{isPlaybackPlaying && nowPlaying ? (
|
||||||
|
|||||||
@@ -279,6 +279,35 @@ select {
|
|||||||
margin-top: 0;
|
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 {
|
.stack {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
|
|||||||
Reference in New Issue
Block a user