Add current members list display in NewGameModal

Introduced a UI element in NewGameModal to display the list of current members when available. Also used React Portal to render the bottom snack for joins directly in the document body. These updates enhance UI clarity and user feedback during game interactions.
This commit is contained in:
2026-02-06 14:46:36 +01:00
parent 7b7b23f52d
commit 85805531c2
2 changed files with 72 additions and 26 deletions

View File

@@ -1,4 +1,5 @@
import React, { useEffect, useRef, useState } from "react"; import React, { useEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { api } from "./api/client"; import { api } from "./api/client";
import { cycleTag } from "./utils/cycleTag"; import { cycleTag } from "./utils/cycleTag";
@@ -581,6 +582,7 @@ export default function App() {
currentCode={gameMeta?.code || ""} currentCode={gameMeta?.code || ""}
gameFinished={!!gameMeta?.winner_user_id} gameFinished={!!gameMeta?.winner_user_id}
hasGame={!!gameId} hasGame={!!gameId}
currentMembers={members}
/> />
<ChipModal <ChipModal
@@ -599,32 +601,34 @@ export default function App() {
/> />
{/* Bottom snack for joins */} {/* Bottom snack for joins */}
{snack && ( {snack &&
<div createPortal(
style={{ <div
position: "fixed", style={{
left: "50%", position: "fixed",
bottom: 14, left: "50%",
transform: "translateX(-50%)", bottom: 14,
maxWidth: "92vw", transform: "translateX(-50%)",
padding: "10px 12px", maxWidth: "92vw",
borderRadius: 14, padding: "10px 12px",
border: `1px solid ${stylesTokens.panelBorder}`, borderRadius: 14,
background: stylesTokens.panelBg, border: `1px solid ${stylesTokens.panelBorder}`,
color: stylesTokens.textMain, background: stylesTokens.panelBg,
boxShadow: "0 12px 30px rgba(0,0,0,0.35)", color: stylesTokens.textMain,
backdropFilter: "blur(6px)", boxShadow: "0 12px 30px rgba(0,0,0,0.35)",
fontWeight: 900, backdropFilter: "blur(6px)",
fontSize: 13, fontWeight: 900,
textAlign: "center", fontSize: 13,
zIndex: 2147483647, textAlign: "center",
pointerEvents: "none", zIndex: 2147483647,
animation: "fadeIn 120ms ease-out", pointerEvents: "none",
}} }}
> >
{snack} {snack}
</div> </div>,
)} document.body
)
}
</div> </div>
); );
} }

View File

@@ -12,6 +12,7 @@ export default function NewGameModal({
currentCode = "", currentCode = "",
gameFinished = false, gameFinished = false,
hasGame = false, hasGame = false,
currentMembers = [],
}) { }) {
// modes: running | choice | create | join // modes: running | choice | create | join
const [mode, setMode] = useState("choice"); const [mode, setMode] = useState("choice");
@@ -168,6 +169,47 @@ export default function NewGameModal({
</> </>
)} )}
{currentMembers?.length > 0 && (
<div
style={{
marginTop: 10,
padding: 10,
borderRadius: 14,
border: `1px solid ${stylesTokens.panelBorder}`,
background: stylesTokens.panelBg,
display: "grid",
gap: 8,
}}
>
<div style={{ fontSize: 12, opacity: 0.8, color: stylesTokens.textDim }}>
Aktuelle Spieler ({currentMembers.length})
</div>
<div style={{ display: "flex", flexWrap: "wrap", gap: 8 }}>
{currentMembers.map((m) => {
const name = ((m.display_name || "").trim() || (m.email || "").trim() || "—");
return (
<div
key={m.id}
style={{
padding: "6px 10px",
borderRadius: 999,
border: `1px solid rgba(233,216,166,0.18)`,
background: "rgba(10,10,12,0.35)",
color: stylesTokens.textMain,
fontSize: 13,
fontWeight: 900,
}}
>
{name}
</div>
);
})}
</div>
</div>
)}
{/* ✅ CHOICE: nur wenn Spiel beendet oder kein Spiel selected */} {/* ✅ CHOICE: nur wenn Spiel beendet oder kein Spiel selected */}
{mode === "choice" && ( {mode === "choice" && (
<> <>