Add dedicated home page with game list and welcome screen, replacing auto-selection behavior
Implemented HomePage component with centered welcome message, create/join button, and list of user's games with name/code display. Modified App.jsx to show HomePage when no game is selected instead of auto-selecting first game. Added `goHome` handler to reset all game state and return to home screen. Added home button (🏠) to GamePickerCard header next to help button with bilingual tooltip. Removed automatic
This commit is contained in:
+22
-2
@@ -27,6 +27,7 @@ import NewGameModal from "./components/NewGameModal";
|
||||
import StatsModal from "./components/StatsModal";
|
||||
import AdminSettingsModal from "./components/AdminSettingsModal";
|
||||
import InvitePage from "./components/InvitePage";
|
||||
import HomePage from "./components/HomePage";
|
||||
import { useLanguage } from "./i18n";
|
||||
|
||||
export default function App() {
|
||||
@@ -134,7 +135,7 @@ export default function App() {
|
||||
const gs = await api("/games");
|
||||
setGames(gs);
|
||||
|
||||
if (gs[0] && !gameId) setGameId(gs[0].id);
|
||||
// Always open on the start page; the user explicitly chooses a game.
|
||||
};
|
||||
|
||||
const reloadSheet = async () => {
|
||||
@@ -528,7 +529,7 @@ export default function App() {
|
||||
await api(`/games/${gameId}`, { method: "DELETE" });
|
||||
const nextGames = await api("/games");
|
||||
setGames(nextGames);
|
||||
setGameId(nextGames[0]?.id || null);
|
||||
setGameId(null);
|
||||
setSheet(null);
|
||||
setGameMeta(null);
|
||||
setMembers([]);
|
||||
@@ -539,6 +540,20 @@ export default function App() {
|
||||
showSnack(language === "en" ? "Game cancelled." : "Spiel abgebrochen.");
|
||||
};
|
||||
|
||||
const goHome = () => {
|
||||
setGameId(null);
|
||||
setSheet(null);
|
||||
setGameMeta(null);
|
||||
setMembers([]);
|
||||
setGameChips([]);
|
||||
setWinnerUserId("");
|
||||
setChipOpen(false);
|
||||
setChipEntry(null);
|
||||
setCelebrateOpen(false);
|
||||
setCelebrateName("");
|
||||
setStartCelebrateOpen(false);
|
||||
};
|
||||
|
||||
// ===== Winner =====
|
||||
const saveWinner = async () => {
|
||||
if (!gameId) return;
|
||||
@@ -735,6 +750,9 @@ export default function App() {
|
||||
<AdminSettingsModal open={adminSettingsOpen} onClose={() => setAdminSettingsOpen(false)} />
|
||||
)}
|
||||
|
||||
{!gameId ? (
|
||||
<HomePage games={games} onOpenNewGame={() => setNewGameOpen(true)} onOpenGame={setGameId} />
|
||||
) : <>
|
||||
<GamePickerCard
|
||||
games={games}
|
||||
gameId={gameId}
|
||||
@@ -750,6 +768,7 @@ export default function App() {
|
||||
chipCount={gameChips.length}
|
||||
onStartGame={startGame}
|
||||
onCancelGame={cancelGame}
|
||||
onGoHome={goHome}
|
||||
/>
|
||||
|
||||
{gameStarted && (
|
||||
@@ -760,6 +779,7 @@ export default function App() {
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>}
|
||||
|
||||
<HelpModal open={helpOpen} onClose={() => setHelpOpen(false)} />
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ export default function GamePickerCard({
|
||||
chipCount = 0,
|
||||
onStartGame,
|
||||
onCancelGame,
|
||||
onGoHome,
|
||||
}) {
|
||||
const { language, t } = useLanguage();
|
||||
const cur = games.find((x) => x.id === gameId);
|
||||
@@ -102,8 +103,11 @@ export default function GamePickerCard({
|
||||
))}
|
||||
</select>
|
||||
|
||||
<button onClick={onOpenHelp} style={styles.helpBtn} title={t("help")}>
|
||||
{t("help")}
|
||||
<button onClick={onGoHome} style={styles.helpBtn} title={language === "en" ? "Home" : "Startseite"} aria-label={language === "en" ? "Home" : "Startseite"}>
|
||||
🏠
|
||||
</button>
|
||||
<button onClick={onOpenHelp} style={styles.helpBtn} title={t("help")} aria-label={t("help")}>
|
||||
❔
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import React from "react";
|
||||
import { styles } from "../styles/styles";
|
||||
import { stylesTokens } from "../styles/theme";
|
||||
import { useLanguage } from "../i18n";
|
||||
|
||||
export default function HomePage({ games = [], onOpenNewGame, onOpenGame }) {
|
||||
const { language, t } = useLanguage();
|
||||
return (
|
||||
<main className="hp-home-page" style={{ marginTop: 14, display: "grid", gap: 14 }}>
|
||||
<div style={styles.card}>
|
||||
<div style={{ padding: "26px 20px 22px", textAlign: "center" }}>
|
||||
<div style={{ fontSize: 34, color: stylesTokens.textGold }}>✦</div>
|
||||
<h1 style={{ margin: "8px 0 0", color: stylesTokens.textGold, fontSize: 24 }}>{language === "en" ? "Welcome to Notizbogen" : "Willkommen beim Notizbogen"}</h1>
|
||||
<p style={{ margin: "9px auto 0", maxWidth: 430, color: stylesTokens.textDim, lineHeight: 1.5 }}>{language === "en" ? "Create a new investigation or join an existing game to get started." : "Erstelle eine neue Ermittlung oder tritt einem bestehenden Spiel bei, um zu beginnen."}</p>
|
||||
<button onClick={onOpenNewGame} style={{ ...styles.primaryBtn, marginTop: 18 }}>{language === "en" ? "✦ Create or join game" : "✦ Spiel erstellen oder beitreten"}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{games.length > 0 && <div style={styles.card}>
|
||||
<div style={styles.sectionHeader}>{language === "en" ? "Your games" : "Deine Spiele"}</div>
|
||||
<div style={{ display: "grid", gap: 8, padding: 12 }}>
|
||||
{games.map((game) => <button key={game.id} onClick={() => onOpenGame(game.id)} style={{ ...styles.secondaryBtn, display: "flex", justifyContent: "space-between", alignItems: "center", textAlign: "left" }}>
|
||||
<span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{game.name}</span><span style={{ color: stylesTokens.textGold, marginLeft: 10 }}>{game.code}</span>
|
||||
</button>)}
|
||||
</div>
|
||||
</div>}
|
||||
</main>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user