From ab3e61ba33b89b3ab1ed574c1b17758956cf4f35 Mon Sep 17 00:00:00 2001 From: javaisbetterthanpython Date: Sun, 7 Jun 2026 22:50:23 -0400 Subject: [PATCH 1/3] Fix blank rounds, re-jumble, and court-count handling. Regenerate no longer drops the current round until generation succeeds, failed rounds clear the generating flag, sit-outs respect court capacity, and round navigation stays in sync after new rounds. Co-authored-by: Cursor --- pages/rounds.tsx | 33 ++++++++++++++++-------- src/CourtsModal.tsx | 10 ++++++-- src/matching/heuristics.ts | 51 +++++++++++++++++++++++++++----------- src/useShuffler.tsx | 46 +++++++++++++++++++++++++--------- 4 files changed, 101 insertions(+), 39 deletions(-) diff --git a/pages/rounds.tsx b/pages/rounds.tsx index 8319f14..89b84f9 100644 --- a/pages/rounds.tsx +++ b/pages/rounds.tsx @@ -35,17 +35,28 @@ export default function Rounds() { const [courtsModal, setCourtsModal] = useState(false); const [roundIndex, setRoundIndex] = useState(0); + const prevRoundCount = React.useRef(state.rounds.length); - // Handle rounds loading into state. + // Jump to latest round when a new round is appended (not when regenerating). useEffect(() => { - if (state.rounds.length && roundIndex === 0) { - setRoundIndex(Math.max(state.rounds.length - 1, 0)); + if (state.rounds.length > prevRoundCount.current) { + setRoundIndex(state.rounds.length - 1); window.scrollTo(0, 0); + } else if (roundIndex >= state.rounds.length && state.rounds.length > 0) { + setRoundIndex(state.rounds.length - 1); + } + prevRoundCount.current = state.rounds.length; + }, [state.rounds.length, roundIndex]); + + useEffect(() => { + if (state.rounds.length && roundIndex === 0 && prevRoundCount.current <= 1) { + setRoundIndex(Math.max(state.rounds.length - 1, 0)); } - }, [state.rounds]); + }, [state.rounds.length, roundIndex]); + const displayIndex = Math.max( 0, - Math.min(roundIndex, state.rounds.length - 1) + Math.min(roundIndex, Math.max(state.rounds.length - 1, 0)) ); const round = state.rounds[displayIndex]; const volunteers = state.volunteerSitoutsByRound[displayIndex]; @@ -84,7 +95,6 @@ export default function Rounds() { fixedPairs, regenerate, }); - if (!regenerate && roundIndex) setRoundIndex((index) => index + 1); setPlayersModal(false); }} /> @@ -96,7 +106,6 @@ export default function Rounds() { regenerate, courts, }); - if (!regenerate && roundIndex) setRoundIndex((index) => index + 1); setCourtsModal(false); }} /> @@ -138,6 +147,9 @@ export default function Rounds() { )} + {state.generating && !round ? ( +

Jumbling the next round…

+ ) : null}
{/* Sitting out */}{" "}
@@ -224,16 +236,17 @@ export default function Rounds() {
diff --git a/src/CourtsModal.tsx b/src/CourtsModal.tsx index 4ae8935..b9e2aae 100644 --- a/src/CourtsModal.tsx +++ b/src/CourtsModal.tsx @@ -66,13 +66,19 @@ export function CourtsModal({ Cancel