diff --git a/README.md b/README.md index 0877aac..7665f9f 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ A small multiplayer web app that acts as a digital note sheet for a Harry Potter - Multiple games per user - Join games using a short join code - Host-controlled game start with automatic player chips +- Pre-game lobby with live player list, host status, and start confirmation - Player chips are generated from the first name initial and first two surname letters, e.g. `SNE` for Sascha Nesterovic - Automatic player list with host indication - Personal note sheet for each player and game diff --git a/frontend/src/components/GamePickerCard.jsx b/frontend/src/components/GamePickerCard.jsx index c2b7e20..6a253ba 100644 --- a/frontend/src/components/GamePickerCard.jsx +++ b/frontend/src/components/GamePickerCard.jsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useState } from "react"; import { styles } from "../styles/styles"; import { stylesTokens } from "../styles/theme"; @@ -16,6 +16,8 @@ export default function GamePickerCard({ onStartGame, }) { const cur = games.find((x) => x.id === gameId); + const [starting, setStarting] = useState(false); + const [startError, setStartError] = useState(""); const renderMemberName = (m) => { const base = ((m.display_name || "").trim() || (m.email || "").trim() || "—"); @@ -46,6 +48,21 @@ export default function GamePickerCard({ whiteSpace: "nowrap", }); + const handleStartGame = async () => { + if (!onStartGame || starting || members.length < 2) return; + if (!window.confirm("Spiel jetzt starten? Danach können keine weiteren Spieler beitreten.")) return; + + setStarting(true); + setStartError(""); + try { + await onStartGame(); + } catch (e) { + setStartError(e?.message || "Das Spiel konnte nicht gestartet werden."); + } finally { + setStarting(false); + } + }; + return (
@@ -89,26 +106,82 @@ export default function GamePickerCard({
)} -
- {!started ? ( - isHost ? ( - - ) : ( -
- Warte auf den Host, der das Spiel startet. + {!started ? ( +
+
+
+
+ Lobby +
+
+ {isHost ? "Du bist der Host dieses Spiels." : "Du bist der Lobby beigetreten."} +
+
+
+
{members.length}
+
Spieler
- ) - ) : ( -
- ✓ Spiel läuft · {chipCount} Spieler-Chips erstellt
- )} -
+ +
+ {members.length > 0 ? members.map((m, index) => { + const isMe = String(me?.id) === String(m.id); + const isMemberHost = String(hostUserId) === String(m.id); + const name = ((m.display_name || "").trim() || (m.email || "").trim() || "Spieler"); + return ( +
+ {index + 1} + + {name}{isMe ? " (du)" : ""} + + {isMemberHost && 👑} +
+ ); + }) : ( +
+ Warte auf Spieler … +
+ )} +
+ + {isHost ? ( + <> + +
+ {members.length < 2 ? "Mindestens 2 Spieler werden benötigt." : "Beim Start werden die Spieler-Chips erstellt."} +
+ + ) : ( +
+ Warte, bis der Host das Spiel startet. +
+ )} + + {startError &&
{startError}
} +
+ ) : ( +
+ ✓ Spiel läuft · {chipCount} Spieler-Chips erstellt +
+ )} {/* Spieler */} - {members?.length > 0 && ( + {started && members?.length > 0 && (