Files
fuesse-sexy/public/admin.html
Guido ddcc6ad657 Fix Admin-Spielertabelle: Spalten richtig ausgerichtet + scrollbar
- Chips in inneren <div> statt display:flex direkt auf <td> (sonst fallen die Zellen
  aus dem Spaltenraster -> alles rutschte in die IP-Spalte, Gerät/Browser leer)
- Tabelle horizontal scrollbar (overflow-x) auf schmalen Screens

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 19:03:03 +02:00

140 lines
6.5 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>füsse.sexy — Admin</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='88'>🛠️</text></svg>" />
<style>
:root { --bg:#0f1020; --panel:#1a1b33; --panel2:#232544; --pink:#ff4d8d; --text:#e9e9f5; --muted:#a0a0c0; --ok:#2ecc71; --warn:#ff5a5f; --border:#33345a; }
* { box-sizing: border-box; }
body { margin:0; background:var(--bg); color:var(--text); font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif; }
a { color:var(--pink); }
h1 { color:var(--pink); margin:0; font-size:22px; }
.wrap { max-width:1000px; margin:0 auto; padding:18px; }
input, button, select { font:inherit; }
input[type=password], input[type=text], input[type=number] {
background:var(--panel2); border:1px solid var(--border); color:var(--text);
border-radius:8px; padding:8px 10px; width:100%;
}
button { cursor:pointer; border:none; border-radius:8px; padding:9px 14px; font-weight:600; background:var(--panel2); color:var(--text); border:1px solid var(--border); }
button.primary { background:var(--pink); color:#fff; border:none; }
button.danger { background:#3a1420; color:#ff9bb2; border:1px solid #5a2233; }
button:hover { filter:brightness(1.12); }
.muted { color:var(--muted); font-size:13px; }
.card { background:var(--panel); border:1px solid var(--border); border-radius:14px; padding:16px; margin-bottom:16px; }
/* Login */
#login { max-width:380px; margin:12vh auto; }
#login .row { display:flex; gap:8px; margin-top:10px; }
#login-err { color:var(--warn); min-height:18px; margin-top:8px; font-size:14px; }
/* Panel */
header.top { display:flex; align-items:center; justify-content:space-between; margin-bottom:14px; }
.tabs { display:flex; gap:6px; flex-wrap:wrap; margin-bottom:14px; }
.tabs button.active { background:var(--pink); color:#fff; border:none; }
section.tab { display:none; }
section.tab.active { display:block; }
#players-wrap { overflow-x:auto; }
table { width:100%; border-collapse:collapse; font-size:14px; }
#players-wrap table { min-width:820px; }
th, td { text-align:left; padding:8px 10px; border-bottom:1px solid var(--border); vertical-align:top; }
th { color:var(--muted); font-weight:600; }
.chips { display:flex; flex-wrap:wrap; gap:4px; }
.chip { background:var(--panel2); border:1px solid var(--border); border-radius:999px; padding:2px 8px; font-size:12px; }
/* Settings */
.grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(220px,1fr)); gap:12px; }
.field label { display:block; font-size:13px; color:var(--muted); margin-bottom:4px; }
/* Images */
.gallery { display:grid; grid-template-columns:repeat(auto-fill,minmax(110px,1fr)); gap:10px; }
.thumb { background:var(--panel2); border:1px solid var(--border); border-radius:10px; padding:8px; text-align:center; }
.thumb img { width:100%; height:72px; object-fit:contain; }
.thumb .fn { font-size:11px; color:var(--muted); word-break:break-all; margin:6px 0; }
.uprow { display:flex; gap:8px; align-items:center; margin-top:10px; flex-wrap:wrap; }
.toast { position:fixed; left:50%; bottom:20px; transform:translateX(-50%); background:#000a; border:1px solid var(--border); color:#fff; padding:10px 16px; border-radius:10px; opacity:0; transition:opacity .2s; }
.toast.show { opacity:1; }
.hidden { display:none !important; }
code { background:var(--panel2); padding:1px 5px; border-radius:5px; }
</style>
<div class="wrap">
<!-- Login -->
<div id="login" class="card hidden">
<h1>🛠️ Admin-Login</h1>
<p class="muted">Passwort per CLI: <code>node server/admin.js password</code></p>
<div class="row">
<input id="pw" type="password" placeholder="Passwort" autocomplete="current-password" />
<button id="login-btn" class="primary">Login</button>
</div>
<div id="login-err"></div>
</div>
<!-- Panel -->
<div id="panel" class="hidden">
<header class="top">
<h1>🛠️ füsse.sexy — Admin</h1>
<button id="logout-btn">Logout</button>
</header>
<div class="tabs">
<button data-tab="players" class="active">Spieler</button>
<button data-tab="settings">Einstellungen</button>
<button data-tab="images">Bilder</button>
<button data-tab="board">Rangliste</button>
</div>
<section class="tab active" id="tab-players">
<div class="card">
<p class="muted">Approximative Zuordnung über IP, groben Ort, Gerät & Browser (kein Login vorhanden).</p>
<div id="players-wrap">Lade …</div>
</div>
</section>
<section class="tab" id="tab-settings">
<div class="card">
<p class="muted">Änderungen wirken sofort beim nächsten Spielstart (kein Neustart).</p>
<div id="settings-grid" class="grid"></div>
<div class="uprow">
<button id="cfg-save" class="primary">Speichern</button>
<span id="cfg-status" class="muted"></span>
</div>
</div>
</section>
<section class="tab" id="tab-images">
<div class="card">
<h3>Füße <span class="muted">(die gesuchten Figuren)</span></h3>
<div id="feet-gallery" class="gallery"></div>
<div class="uprow">
<input type="file" id="feet-file" accept=".svg,.png,.webp,.jpg,.jpeg,.gif" />
<button class="primary" data-up="feet">Hochladen</button>
</div>
</div>
<div class="card">
<h3>Deko <span class="muted">(Verwirr-Bilder, nie gesucht)</span></h3>
<div id="props-gallery" class="gallery"></div>
<div class="uprow">
<input type="file" id="props-file" accept=".svg,.png,.webp,.jpg,.jpeg,.gif" />
<button class="primary" data-up="props">Hochladen</button>
</div>
</div>
<p class="muted">💡 Am besten <b>quadratische</b> Bilder: 256×256 oder 512×512 px PNG mit transparentem
Hintergrund (oder SVG mit quadratischem viewBox). Nicht-quadratische werden dank <code>object-fit</code>
nicht verzerrt, sondern nur eingepasst.</p>
</section>
<section class="tab" id="tab-board">
<div class="card">
<h3>Rangliste zurücksetzen</h3>
<div class="uprow">
<button class="danger" data-reset="today">Heute leeren</button>
<button class="danger" data-reset="all">Alles leeren</button>
</div>
</div>
</section>
</div>
</div>
<div id="toast" class="toast"></div>
<script src="/js/admin.js"></script>