Enhance winner management with localStorage updates

Refactored winner storage logic by introducing `clearWinnerLS` and replacing outdated functions with `getWinnerLS` and `setWinnerLS`. Added a `WinnerBadge` component to display the winner's status and updated game lifecycle handling to ensure proper winner reset and management.
This commit is contained in:
2026-02-06 10:02:11 +01:00
parent 7024a681da
commit 74de7bf4dd
3 changed files with 88 additions and 23 deletions

View File

@@ -4,7 +4,8 @@ import React, { useEffect, useState } from "react";
import { api } from "./api/client"; import { api } from "./api/client";
import { cycleTag } from "./utils/cycleTag"; import { cycleTag } from "./utils/cycleTag";
import { getChipLS, setChipLS, clearChipLS } from "./utils/chipStorage"; import { getChipLS, setChipLS, clearChipLS } from "./utils/chipStorage";
import { getWinner, setWinner as saveWinnerLS } from "./utils/winnerStorage";
import { getWinnerLS, setWinnerLS, clearWinnerLS } from "./utils/winnerStorage";
import { useHpGlobalStyles } from "./styles/hooks/useHpGlobalStyles"; import { useHpGlobalStyles } from "./styles/hooks/useHpGlobalStyles";
import { styles } from "./styles/styles"; import { styles } from "./styles/styles";
@@ -21,6 +22,7 @@ import GamePickerCard from "./components/GamePickerCard";
import SheetSection from "./components/SheetSection"; import SheetSection from "./components/SheetSection";
import DesignModal from "./components/DesignModal"; import DesignModal from "./components/DesignModal";
import WinnerCard from "./components/WinnerCard"; import WinnerCard from "./components/WinnerCard";
import WinnerBadge from "./components/WinnerBadge";
export default function App() { export default function App() {
useHpGlobalStyles(); useHpGlobalStyles();
@@ -80,6 +82,8 @@ export default function App() {
setSheet(sh); setSheet(sh);
}; };
// ===== Effects =====
// Dropdown outside click // Dropdown outside click
useEffect(() => { useEffect(() => {
const onDown = (e) => { const onDown = (e) => {
@@ -102,15 +106,19 @@ export default function App() {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
// load sheet when game changes // load sheet + winner when game changes
useEffect(() => { useEffect(() => {
(async () => { (async () => {
if (!gameId) return; if (!gameId) return;
try { try {
await reloadSheet(); await reloadSheet();
} catch {} } catch {
// Winner pro Game aus LS laden // ignore
setWinnerName(getWinner(gameId)); }
// Sieger pro Game aus localStorage laden
setWinnerName(getWinnerLS(gameId));
})(); })();
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [gameId]); }, [gameId]);
@@ -188,15 +196,29 @@ export default function App() {
method: "POST", method: "POST",
body: JSON.stringify({ name: "Spiel " + new Date().toLocaleString() }), body: JSON.stringify({ name: "Spiel " + new Date().toLocaleString() }),
}); });
const gs = await api("/games"); const gs = await api("/games");
setGames(gs); setGames(gs);
setGameId(g.id); setGameId(g.id);
// Neues Spiel -> Sieger leer
clearWinnerLS(g.id);
setWinnerName("");
}; };
// ===== Winner actions ===== // ===== Winner actions =====
const saveWinner = () => { const saveWinner = () => {
if (!gameId) return; if (!gameId) return;
saveWinnerLS(gameId, winnerName.trim()); const v = (winnerName || "").trim();
if (!v) {
clearWinnerLS(gameId);
setWinnerName("");
return;
}
setWinnerLS(gameId, v);
setWinnerName(v);
}; };
// ===== Sheet actions ===== // ===== Sheet actions =====
@@ -338,6 +360,9 @@ export default function App() {
<HelpModal open={helpOpen} onClose={() => setHelpOpen(false)} /> <HelpModal open={helpOpen} onClose={() => setHelpOpen(false)} />
{/* Sieger Badge: nur wenn gesetzt */}
<WinnerBadge winner={(winnerName || "").trim()} />
<div style={{ marginTop: 14, display: "grid", gap: 14 }}> <div style={{ marginTop: 14, display: "grid", gap: 14 }}>
{sections.map((sec) => ( {sections.map((sec) => (
<SheetSection <SheetSection
@@ -380,7 +405,11 @@ export default function App() {
}} }}
/> />
<ChipModal chipOpen={chipOpen} closeChipModalToDash={closeChipModalToDash} chooseChip={chooseChip} /> <ChipModal
chipOpen={chipOpen}
closeChipModalToDash={closeChipModalToDash}
chooseChip={chooseChip}
/>
</div> </div>
); );
} }

View File

@@ -0,0 +1,28 @@
// frontend/src/utils/winnerStorage.js
function winnerKey(gameId) {
return `winner:${gameId}`;
}
export function getWinnerLS(gameId) {
if (!gameId) return "";
try {
return localStorage.getItem(winnerKey(gameId)) || "";
} catch {
return "";
}
}
export function setWinnerLS(gameId, name) {
if (!gameId) return;
try {
localStorage.setItem(winnerKey(gameId), (name || "").trim());
} catch {}
}
export function clearWinnerLS(gameId) {
if (!gameId) return;
try {
localStorage.removeItem(winnerKey(gameId));
} catch {}
}

View File

@@ -1,20 +1,28 @@
// frontend/src/utils/winnerStorage.js
function winnerKey(gameId) { function winnerKey(gameId) {
return `winner:${gameId}`; return `winner:${gameId}`;
} }
export function getWinner(gameId) { export function getWinnerLS(gameId) {
if (!gameId) return ""; if (!gameId) return "";
try { try {
return localStorage.getItem(winnerKey(gameId)) || ""; return localStorage.getItem(winnerKey(gameId)) || "";
} catch { } catch {
return ""; return "";
}
} }
}
export function setWinner(gameId, name) { export function setWinnerLS(gameId, name) {
if (!gameId) return; if (!gameId) return;
try { try {
localStorage.setItem(winnerKey(gameId), name || ""); localStorage.setItem(winnerKey(gameId), (name || "").trim());
} catch {} } catch {}
} }
export function clearWinnerLS(gameId) {
if (!gameId) return;
try {
localStorage.removeItem(winnerKey(gameId));
} catch {}
}