feat: Schocken - Admin kann Spiele aus der Liste löschen

This commit is contained in:
2026-07-05 00:51:55 +02:00
parent efda0a1cab
commit cb287585f2

View File

@@ -445,7 +445,7 @@ function NewGameModal({ onClose, onCreate, toast }) {
} }
// ── Spielliste ──────────────────────────────────────────────────────────────── // ── Spielliste ────────────────────────────────────────────────────────────────
function GameList({ games, myId, onSelect, onNew }) { function GameList({ games, myId, onSelect, onNew, onDelete, isAdmin }) {
const active = games.filter(g => g.status !== 'finished'); const active = games.filter(g => g.status !== 'finished');
const finished = games.filter(g => g.status === 'finished'); const finished = games.filter(g => g.status === 'finished');
@@ -456,23 +456,26 @@ function GameList({ games, myId, onSelect, onNew }) {
const GameRow = ({ g }) => { const GameRow = ({ g }) => {
const others = g.players.filter(p=>p.id!==myId).map(p=>p.username).join(', '); const others = g.players.filter(p=>p.id!==myId).map(p=>p.username).join(', ');
return ( return (
<button onClick={()=>onSelect(g.id)} style={{ <div style={{...S.card,padding:'12px 14px',marginBottom:8,display:'flex',alignItems:'center',gap:10,border:'1px solid rgba(255,255,255,0.07)'}}>
...S.card,width:'100%',textAlign:'left',cursor:'pointer', <button onClick={()=>onSelect(g.id)} style={{flex:1,background:'none',border:'none',cursor:'pointer',textAlign:'left',padding:0}}>
padding:'12px 14px',marginBottom:8,display:'flex',alignItems:'center',gap:10,
border:'1px solid rgba(255,255,255,0.07)',
}}>
<div style={{flex:1}}>
<div style={{color:'#fff',fontFamily:'monospace',fontSize:13,marginBottom:3}}> <div style={{color:'#fff',fontFamily:'monospace',fontSize:13,marginBottom:3}}>
🎲 mit <strong>{others}</strong> 🎲 mit <strong>{others}</strong>
</div> </div>
<div style={{color:'rgba(255,255,255,0.35)',fontSize:11,fontFamily:'monospace'}}> <div style={{color:'rgba(255,255,255,0.35)',fontSize:11,fontFamily:'monospace'}}>
{g.players.length} Spieler {g.players.length} Spieler · {statusLabel(g.status)}
</div> </div>
</div> </button>
<span style={{color:g.status==='finished'?'rgba(255,255,255,0.3)':MY_COLOR,fontSize:11,fontFamily:'monospace',flexShrink:0}}> {isAdmin && (
{statusLabel(g.status)} <button onClick={async e => {
</span> e.stopPropagation();
</button> if (!window.confirm('Spiel löschen?')) return;
try {
await apiAs(myId, `/tools/schocken/${g.id}/cancel`, { body:{} });
onDelete(g.id);
} catch(e) { alert(e.message||'Fehler'); }
}} style={{...S.btn('#ff6b9d',true),flexShrink:0}}>🗑</button>
)}
</div>
); );
}; };
@@ -671,7 +674,7 @@ export default function Schocken({ toast }) {
</div> </div>
{!activeId {!activeId
? <GameList games={games} myId={myId} onSelect={setActiveId} onNew={()=>setShowNew(true)}/> ? <GameList games={games} myId={myId} onSelect={setActiveId} onNew={()=>setShowNew(true)} onDelete={id=>setGames(prev=>prev.filter(g=>g.id!==id))} isAdmin={isAdmin}/>
: game && myId : game && myId
? <GameView game={game} myId={myId} onRefresh={loadGame} toast={toast} isAdmin={isAdmin} onSeatChange={id=>{setTestSeat(id);}} /> ? <GameView game={game} myId={myId} onRefresh={loadGame} toast={toast} isAdmin={isAdmin} onSeatChange={id=>{setTestSeat(id);}} />
: <div style={{color:'rgba(255,255,255,0.3)',fontFamily:'monospace',textAlign:'center',paddingTop:40}}>Lade</div> : <div style={{color:'rgba(255,255,255,0.3)',fontFamily:'monospace',textAlign:'center',paddingTop:40}}>Lade</div>