Prevent winner selection from being overwritten by polling updates using dirty flag

Added `winnerSelectionDirtyRef` to track when user has manually changed winner selection. Modified `loadGameMeta` to skip updating `winnerUserId` state when dirty flag is set, preventing polling from overwriting user's unsaved selection. Introduced `selectWinner` helper that sets dirty flag on manual selection and clears flag after successful save. Reset dirty flag in all state cleanup handlers (goHome, logout, le
This commit is contained in:
2026-08-02 11:38:08 +02:00
parent ea08016ea5
commit d672648a05
+16 -2
View File
@@ -60,6 +60,7 @@ export default function App() {
// Winner selection (host only)
const [winnerUserId, setWinnerUserId] = useState("");
const winnerSelectionDirtyRef = useRef(false);
// Modals
const [helpOpen, setHelpOpen] = useState(false);
@@ -149,7 +150,9 @@ export default function App() {
const meta = await api(`/games/${gameId}`);
setGameMeta(meta);
setWinnerUserId(meta?.winner_user_id || "");
if (!winnerSelectionDirtyRef.current) {
setWinnerUserId(meta?.winner_user_id || "");
}
const chips = meta?.started ? await api(`/games/${gameId}/chips`) : [];
setGameChips(chips || []);
@@ -226,6 +229,7 @@ export default function App() {
lastWinnerIdRef.current = null;
gameStartBaselineRef.current = false;
lastGameStartedRef.current = false;
winnerSelectionDirtyRef.current = false;
setCelebrateOpen(false);
setCelebrateName("");
setStartCelebrateOpen(false);
@@ -370,6 +374,7 @@ export default function App() {
setMembers([]);
setGameChips([]);
setWinnerUserId("");
winnerSelectionDirtyRef.current = false;
// reset winner celebration on logout
winnerBaselineRef.current = false;
@@ -478,6 +483,7 @@ export default function App() {
setMembers([]);
setGameChips([]);
setWinnerUserId("");
winnerSelectionDirtyRef.current = false;
setPulseId(null);
// auch Chip-Modal-State resetten
@@ -535,6 +541,7 @@ export default function App() {
setMembers([]);
setGameChips([]);
setWinnerUserId("");
winnerSelectionDirtyRef.current = false;
setChipOpen(false);
setChipEntry(null);
showSnack(language === "en" ? "Game cancelled." : "Spiel abgebrochen.");
@@ -547,6 +554,7 @@ export default function App() {
setMembers([]);
setGameChips([]);
setWinnerUserId("");
winnerSelectionDirtyRef.current = false;
setChipOpen(false);
setChipEntry(null);
setCelebrateOpen(false);
@@ -561,9 +569,15 @@ export default function App() {
method: "PATCH",
body: JSON.stringify({ winner_user_id: winnerUserId || null }),
});
winnerSelectionDirtyRef.current = false;
await loadGameMeta();
};
const selectWinner = (value) => {
winnerSelectionDirtyRef.current = true;
setWinnerUserId(value);
};
// ===== Sheet actions =====
const cycleStatus = async (entry) => {
if (gameMeta?.winner_user_id) return;
@@ -806,7 +820,7 @@ export default function App() {
isHost={isHost}
members={members}
winnerUserId={winnerUserId}
setWinnerUserId={setWinnerUserId}
setWinnerUserId={selectWinner}
onSave={saveWinner}
/>
)}