Browse Source

Neue "Reihen" nun in allen Ansichten verfügbar

erdo 1 month ago
parent
commit
fe225df524
5 changed files with 418 additions and 446 deletions
  1. 162 194
      admin.php
  2. 50 34
      besitz.php
  3. 29 23
      gesamtliste.php
  4. 61 46
      gespielte_spiele.php
  5. 116 149
      index.php

+ 162 - 194
admin.php

@@ -3,76 +3,88 @@ session_start();
 require_once 'config.php'; 
 require_once 'db_config.php'; 
 
-// --- 1. LOGIN / LOGOUT SCHUTZ ---
+// --- 1. LOGIN / LOGOUT ---
 if (isset($_GET['logout'])) { session_destroy(); header("Location: admin.php"); exit; }
 if (isset($_POST['login_auth'])) {
     if ($_POST['pw'] === ADMIN_PASSWORD) { $_SESSION['admin_auth'] = true; }
 }
-$is_admin = (isset($_SESSION['admin_auth']) && $_SESSION['admin_auth'] === true);
-
-if (!$is_admin):
+if (!(isset($_SESSION['admin_auth']) && $_SESSION['admin_auth'] === true)):
 ?>
 <!DOCTYPE html>
 <html lang="de">
-<head>
-    <meta charset="UTF-8">
-    <title>Admin Login</title>
-    <style>
-        body { font-family: sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; background: #f4f7f6; margin: 0; }
-        .login-box { background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); text-align: center; }
-        input { width: 100%; padding: 10px; margin: 10px 0; box-sizing: border-box; border: 1px solid #ddd; border-radius: 4px; }
-        button { width: 100%; padding: 10px; background: #e67e22; color: white; border: none; cursor: pointer; border-radius: 4px; font-weight: bold; }
-    </style>
-</head>
-<body>
-    <div class="login-box">
-        <h2>🔒 Admin Login</h2>
-        <form method="POST"><input type="password" name="pw" placeholder="Passwort" autofocus required><button type="submit" name="login_auth">Einloggen</button></form>
-    </div>
-</body>
+<head><meta charset="UTF-8"><title>Login</title><style>body{font-family:sans-serif;display:flex;justify-content:center;align-items:center;height:100vh;background:#f0f2f5;} .box{background:white;padding:30px;border-radius:8px;box-shadow:0 2px 10px rgba(0,0,0,0.1); text-align:center;}</style></head>
+<body><div class="box"><h2>🔐 Admin Login</h2><form method="POST"><input type="password" name="pw" placeholder="Passwort" autofocus style="width:100%;padding:10px;margin:10px 0;"><button type="submit" name="login_auth" style="width:100%;padding:10px;background:#e67e22;color:white;border:none;cursor:pointer;">Login</button></form></div></body>
 </html>
 <?php exit; endif; ?>
 
 <?php
-// --- 2. VERARBEITUNG DER FORMULARE ---
-$msg = "";
-
-// SPIELE (Add/Update/Delete)
-if (isset($_POST['add_game'])) {
-    $stmt = $pdo->prepare("INSERT INTO spiele (game_reihe_id, titel, game_typ_id, game_level_id, ean, bild_url) VALUES (?,?,?,?,?,?)");
-    $stmt->execute([(int)$_POST['r_id'], $_POST['titel'], (int)$_POST['t_id'], (int)$_POST['l_id'], $_POST['ean'], $_POST['url']]);
-    $msg = "✅ Spiel hinzugefügt!";
+// --- HELPER: STERNE RENDERER ---
+function renderStars($val) {
+    if (!is_numeric($val)) return htmlspecialchars($val);
+    $n = (int)$val; $out = "";
+    for($i=1; $i<=5; $i++) { $out .= ($i <= $n) ? "★" : "☆"; }
+    return "<span style='color:#f1c40f; font-size:1.1em;'>$out</span>";
 }
-if (isset($_POST['upd_game'])) {
-    $stmt = $pdo->prepare("UPDATE spiele SET game_reihe_id=?, titel=?, game_typ_id=?, game_level_id=?, ean=?, bild_url=? WHERE id=?");
-    $stmt->execute([(int)$_POST['r_id'], $_POST['titel'], (int)$_POST['t_id'], (int)$_POST['l_id'], $_POST['ean'], $_POST['url'], (int)$_POST['id']]);
-    $msg = "💾 Änderungen gespeichert!";
+
+// --- 2. SQL AKTIONEN ---
+$msg = ""; $error = "";
+
+// SPIELE SPEICHERN
+if (isset($_POST['save_game'])) {
+    $id = (int)($_POST['id'] ?? 0);
+    $r_id = (int)$_POST['game_reihe_id'];
+    $t_id = ($_POST['game_typ_id'] == '0') ? null : (int)$_POST['game_typ_id'];
+    $l_id = ($_POST['game_level_id'] == '0') ? null : (int)$_POST['game_level_id'];
+    $ean = (!isset($_POST['ean']) || $_POST['ean'] === '') ? null : $_POST['ean'];
+    $url = !empty($_POST['url']) ? $_POST['url'] : 'https://via.placeholder.com/300x180';
+
+    try {
+        if ($id > 0) {
+            $stmt = $pdo->prepare("UPDATE spiele SET game_reihe_id=?, titel=?, game_typ_id=?, game_level_id=?, ean=?, bild_url=? WHERE id=?");
+            $stmt->execute([$r_id, $_POST['titel'], $t_id, $l_id, $ean, $url, $id]);
+            $msg = "Spiel aktualisiert!";
+        } else {
+            $stmt = $pdo->prepare("INSERT INTO spiele (game_reihe_id, titel, game_typ_id, game_level_id, ean, bild_url) VALUES (?,?,?,?,?,?)");
+            $stmt->execute([$r_id, $_POST['titel'], $t_id, $l_id, $ean, $url]);
+            $msg = "Neues Spiel angelegt!";
+        }
+    } catch (PDOException $e) { $error = "Fehler: " . $e->getMessage(); }
 }
 
-// SPIELER
+// STAMMDATEN HINZUFÜGEN (Duplikat-Check)
+if (isset($_POST['add_reihe'])) {
+    $c = $pdo->prepare("SELECT id FROM game_reihe WHERE name=?"); $c->execute([$_POST['name']]);
+    if ($c->fetch()) { $error = "Reihe existiert bereits!"; }
+    else { $pdo->prepare("INSERT INTO game_reihe (name) VALUES (?)")->execute([$_POST['name']]); $msg="Reihe hinzugefügt!"; }
+}
+if (isset($_POST['add_typ'])) {
+    $c = $pdo->prepare("SELECT id FROM game_typ WHERE game_reihe_id=? AND bezeichnung=?"); $c->execute([$_POST['r_id'], $_POST['bez']]);
+    if ($c->fetch()) { $error = "Typ existiert bereits für diese Reihe!"; }
+    else { $pdo->prepare("INSERT INTO game_typ (game_reihe_id, bezeichnung) VALUES (?,?)")->execute([$_POST['r_id'], $_POST['bez']]); $msg="Typ hinzugefügt!"; }
+}
+if (isset($_POST['add_level'])) {
+    $c = $pdo->prepare("SELECT id FROM game_level WHERE game_reihe_id=? AND bezeichnung=?"); $c->execute([$_POST['r_id'], $_POST['bez']]);
+    if ($c->fetch()) { $error = "Level existiert bereits für diese Reihe!"; }
+    else { $pdo->prepare("INSERT INTO game_level (game_reihe_id, bezeichnung) VALUES (?,?)")->execute([$_POST['r_id'], $_POST['bez']]); $msg="Level hinzugefügt!"; }
+}
 if (isset($_POST['add_spieler'])) {
-    $pdo->prepare("INSERT INTO spieler (name) VALUES (?)")->execute([$_POST['name']]);
+    $c = $pdo->prepare("SELECT id FROM spieler WHERE name=?"); $c->execute([$_POST['name']]);
+    if ($c->fetch()) { $error = "Spieler existiert bereits!"; }
+    else { $pdo->prepare("INSERT INTO spieler (name) VALUES (?)")->execute([$_POST['name']]); $msg="Spieler hinzugefügt!"; }
 }
 
-// REIHEN / TYPEN / LEVEL
-if (isset($_POST['add_reihe'])) { $pdo->prepare("INSERT INTO game_reihe (name) VALUES (?)")->execute([$_POST['name']]); }
-if (isset($_POST['add_typ']))   { $pdo->prepare("INSERT INTO game_typ (game_reihe_id, bezeichnung) VALUES (?,?)")->execute([$_POST['r_id'], $_POST['bez']]); }
-if (isset($_POST['add_level'])) { $pdo->prepare("INSERT INTO game_level (game_reihe_id, bezeichnung) VALUES (?,?)")->execute([$_POST['r_id'], $_POST['bez']]); }
-
-// LÖSCHEN (Universal)
-if (isset($_GET['del_table']) && isset($_GET['del_id'])) {
-    $allowed = ['spiele', 'spieler', 'game_reihe', 'game_typ', 'game_level'];
-    if (in_array($_GET['del_table'], $allowed)) {
-        $stmt = $pdo->prepare("DELETE FROM `".$_GET['del_table']."` WHERE id = ?");
-        $stmt->execute([(int)$_GET['del_id']]);
+// LÖSCHEN
+if (isset($_GET['del_t']) && isset($_GET['del_id'])) {
+    if (in_array($_GET['del_t'], ['spiele', 'spieler', 'game_reihe', 'game_typ', 'game_level'])) {
+        $pdo->prepare("DELETE FROM `".$_GET['del_t']."` WHERE id=?")->execute([(int)$_GET['del_id']]);
         header("Location: admin.php"); exit;
     }
 }
 
-// --- 3. DATEN LADEN ---
+// DATEN LADEN
 $reihen  = $pdo->query("SELECT * FROM game_reihe ORDER BY name")->fetchAll();
-$typen   = $pdo->query("SELECT * FROM game_typ ORDER BY bezeichnung")->fetchAll();
-$levels  = $pdo->query("SELECT * FROM game_level ORDER BY bezeichnung")->fetchAll();
+$typen   = $pdo->query("SELECT t.*, r.name as r_name FROM game_typ t JOIN game_reihe r ON t.game_reihe_id = r.id ORDER BY r.name, t.bezeichnung")->fetchAll();
+$levels  = $pdo->query("SELECT l.*, r.name as r_name FROM game_level l JOIN game_reihe r ON l.game_reihe_id = r.id ORDER BY r.name, l.bezeichnung")->fetchAll();
 $spieler = $pdo->query("SELECT * FROM spieler ORDER BY name")->fetchAll();
 $spiele  = $pdo->query("SELECT s.*, r.name as r_name FROM spiele s LEFT JOIN game_reihe r ON s.game_reihe_id = r.id ORDER BY s.id DESC")->fetchAll();
 ?>
@@ -85,172 +97,128 @@ $spiele  = $pdo->query("SELECT s.*, r.name as r_name FROM spiele s LEFT JOIN gam
     <style>
         :root { --accent: #e67e22; --bg: #f4f7f6; --card: #fff; --text: #333; --border: #ddd; }
         .dark-theme { --bg: #1a1a1a; --card: #2d2d2d; --text: #eee; --border: #444; }
-        body { font-family: 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); margin: 0; padding: 20px; transition: 0.3s; }
-        .container { max-width: 1400px; margin: 0 auto; }
-        
-        /* Header & Buttons */
+        body { font-family: 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); margin: 0; padding: 20px; }
         .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
-        .header-btns { display: flex; gap: 10px; align-items: center; }
-        .btn { padding: 8px 15px; border: none; border-radius: 6px; cursor: pointer; color: white; text-decoration: none; font-weight: bold; font-size: 0.9em; transition: 0.2s; }
-        .btn-s { background: #2980b9; } .btn-s:hover { background: #3498db; }
-        .btn-d { background: #c0392b; } .btn-d:hover { background: #e74c3c; }
-        .btn-a { background: #27ae60; } .btn-a:hover { background: #2ecc71; }
-        .btn-nav { background: var(--accent); }
-        #theme-icon { background: none; border: none; font-size: 1.4rem; cursor: pointer; padding: 5px; }
-
-        /* Tabs */
-        .nav-tabs { display: flex; gap: 5px; margin-bottom: 20px; border-bottom: 2px solid var(--border); padding-bottom: 10px; }
-        .t-btn { padding: 10px 20px; border: none; background: transparent; color: var(--text); cursor: pointer; font-weight: bold; border-radius: 6px; }
-        .t-btn.active { background: var(--accent); color: white; }
-        .tab { display: none; background: var(--card); padding: 25px; border-radius: 12px; box-shadow: 0 4px 15px rgba(0,0,0,0.05); border: 1px solid var(--border); }
+        .nav-tabs { display: flex; gap: 10px; margin-bottom: 20px; border-bottom: 2px solid var(--border); }
+        .t-btn { padding: 12px 20px; border: none; background: none; color: var(--text); cursor: pointer; font-weight: bold; }
+        .t-btn.active { border-bottom: 4px solid var(--accent); color: var(--accent); }
+        .tab { display: none; background: var(--card); padding: 20px; border-radius: 12px; border: 1px solid var(--border); }
         .tab.active { display: block; }
-
-        /* Table & Forms */
-        table { width: 100%; border-collapse: collapse; margin-top: 15px; }
-        th { text-align: left; padding: 12px; border-bottom: 2px solid var(--border); background: rgba(0,0,0,0.02); }
-        td { padding: 10px; border-bottom: 1px solid var(--border); }
-        input, select { padding: 9px; border: 1px solid var(--border); border-radius: 6px; background: var(--card); color: var(--text); width: 100%; box-sizing: border-box; }
-        .alert { padding: 15px; background: #d4edda; color: #155724; border-radius: 8px; margin-bottom: 20px; text-align: center; font-weight: bold; }
+        table { width: 100%; border-collapse: collapse; font-size: 0.85em; }
+        th, td { padding: 8px; border-bottom: 1px solid var(--border); text-align: left; }
+        input, select { padding: 6px; border: 1px solid var(--border); border-radius: 4px; background: var(--card); color: var(--text); width: 100%; box-sizing: border-box; }
+        .btn { padding: 6px 10px; border: none; border-radius: 4px; cursor: pointer; color: white; font-weight: bold; }
+        .btn-s { background: #2980b9; } .btn-d { background: #c0392b; } .btn-a { background: #27ae60; }
+        .img-preview { width: 45px; height: 45px; object-fit: cover; border-radius: 4px; }
+        .scroll-area { max-height: 350px; overflow-y: auto; border: 1px solid var(--border); border-radius: 6px; padding: 5px; margin-top: 10px; }
+        .badge { background: #eee; padding: 2px 5px; border-radius: 4px; font-size: 0.75em; color: #666; }
+        .alert { padding: 15px; border-radius: 8px; margin-bottom: 20px; text-align: center; background: #d4edda; color: #155724; }
+        .alert.error { background: #f8d7da; color: #721c24; }
     </style>
 </head>
 <body>
 
-<div class="container">
-    <div class="header">
-        <h1>🛠 Admin Dashboard</h1>
-        <div class="header-btns">
-            <button onclick="toggleTheme()" id="theme-icon">🌙</button>
-            <a href="index.php" class="btn btn-nav">Katalog</a>
-            <a href="admin.php?logout=1" class="btn btn-d">Logout</a>
-        </div>
-    </div>
-
-    <?php if($msg): ?><div class="alert" id="msgbox"><?=$msg?></div><?php endif; ?>
-
-    <div class="nav-tabs">
-        <button class="t-btn active" onclick="openTab(event, 't-spiele')">🎮 Spiele</button>
-        <button class="t-btn" onclick="openTab(event, 't-spieler')">👥 Spieler</button>
-        <button class="t-btn" onclick="openTab(event, 't-config')">⚙️ Stammdaten</button>
-    </div>
+<div class="header">
+    <h1>🛠 Admin Panel</h1>
+    <div><a href="index.php" class="btn btn-s">Katalog</a> <a href="?logout=1" class="btn btn-d">Logout</a></div>
+</div>
 
-    <div id="t-spiele" class="tab active">
-        <h3>Neues Spiel hinzufügen</h3>
-        <form method="POST" style="display:grid; grid-template-columns: 1fr 2fr 1fr 1fr 1fr 2fr auto; gap:10px; align-items: end;">
-            <div><label>Reihe</label><select name="r_id" id="r_new" onchange="filter('new')" required><option value="">Wählen...</option><?php foreach($reihen as $r): ?><option value="<?=$r['id']?>"><?=$r['name']?></option><?php endforeach; ?></select></div>
-            <div><label>Titel</label><input type="text" name="titel" required></div>
-            <div><label>Typ</label><select name="t_id" id="t_new"><option value="0" data-p="0">--</option><?php foreach($typen as $t): ?><option data-p="<?=$t['game_reihe_id']?>" value="<?=$t['id']?>"><?=$t['bezeichnung']?></option><?php endforeach; ?></select></div>
-            <div><label>Level</label><select name="l_id" id="l_new"><option value="0" data-p="0">--</option><?php foreach($levels as $l): ?><option data-p="<?=$l['game_reihe_id']?>" value="<?=$l['id']?>"><?=$l['bezeichnung']?></option><?php endforeach; ?></select></div>
-            <div><label>EAN</label><input type="text" name="ean"></div>
-            <div><label>Bild URL</label><input type="text" name="url"></div>
-            <button type="submit" name="add_game" class="btn btn-a">Hinzufügen</button>
-        </form>
+<?php if($msg): ?><div class="alert"><?=$msg?></div><?php endif; ?>
+<?php if($error): ?><div class="alert error"><?=$error?></div><?php endif; ?>
 
-        <hr style="margin: 30px 0; border: 0; border-top: 1px solid var(--border);">
+<div class="nav-tabs">
+    <button class="t-btn active" onclick="openTab(event, 't-spiele')">🎮 Spiele</button>
+    <button class="t-btn" onclick="openTab(event, 't-spieler')">👥 Spieler</button>
+    <button class="t-btn" onclick="openTab(event, 't-config')">⚙️ Stammdaten</button>
+</div>
 
-        <table>
-            <thead><tr><th>Reihe</th><th>Titel</th><th>Typ</th><th>Level</th><th style="width:100px;">Aktion</th></tr></thead>
-            <?php foreach($spiele as $s): ?>
+<div id="t-spiele" class="tab active">
+    <form method="POST" style="display:grid; grid-template-columns: 1fr 1.5fr 1fr 1fr 1fr 1.5fr auto; gap:5px; margin-bottom:20px; background:#f9f9f9; padding:10px; border-radius:8px; border:1px solid #eee;">
+        <select name="game_reihe_id" id="r_new" onchange="filter('new')" required><option value="">Reihe...</option><?php foreach($reihen as $r): ?><option value="<?=$r['id']?>"><?=$r['name']?></option><?php endforeach; ?></select>
+        <input type="text" name="titel" placeholder="Titel" required>
+        <select name="game_typ_id" id="t_new"><option value="0" data-p="0">Typ...</option><?php foreach($typen as $t): ?><option data-p="<?=$t['game_reihe_id']?>" value="<?=$t['id']?>"><?=$t['bezeichnung']?></option><?php endforeach; ?></select>
+        <select name="game_level_id" id="l_new"><option value="0" data-p="0">Level...</option><?php foreach($levels as $l): ?><option data-p="<?=$l['game_reihe_id']?>" value="<?=$l['id']?>"><?=$l['bezeichnung']?></option><?php endforeach; ?></select>
+        <input type="text" name="ean" placeholder="EAN">
+        <input type="text" name="url" placeholder="Bild-URL">
+        <button type="submit" name="save_game" class="btn btn-a">Neu</button>
+    </form>
+
+    <table>
+        <thead><tr><th>Bild</th><th>Reihe</th><th>Titel</th><th>Typ / Level</th><th>EAN</th><th>Bild-URL</th><th>Aktion</th></tr></thead>
+        <?php foreach($spiele as $s): ?>
+        <tr>
             <form method="POST">
-                <input type="hidden" name="id" value="<?=$s['id']?>">
-                <tr>
-                    <td><select name="r_id" id="r_<?=$s['id']?>" onchange="filter(<?=$s['id']?>)"><?php foreach($reihen as $r): ?><option value="<?=$r['id']?>" <?=$s['game_reihe_id']==$r['id']?'selected':''?>><?=$r['name']?></option><?php endforeach; ?></select></td>
-                    <td><input type="text" name="titel" value="<?=htmlspecialchars($s['titel'])?>"></td>
-                    <td><select name="t_id" id="t_<?=$s['id']?>"><option value="0" data-p="0">--</option><?php foreach($typen as $t): ?><option data-p="<?=$t['game_reihe_id']?>" value="<?=$t['id']?>" <?=$s['game_typ_id']==$t['id']?'selected':''?>><?=$t['bezeichnung']?></option><?php endforeach; ?></select></td>
-                    <td><select name="l_id" id="l_<?=$s['id']?>"><option value="0" data-p="0">--</option><?php foreach($levels as $l): ?><option data-p="<?=$l['game_reihe_id']?>" value="<?=$l['id']?>" <?=$s['game_level_id']==$l['id']?'selected':''?>><?=$l['bezeichnung']?></option><?php endforeach; ?></select></td>
-                    <td>
-                        <div style="display:flex; gap:5px;">
-                            <button type="submit" name="upd_game" class="btn btn-s">💾</button>
-                            <a href="?del_table=spiele&del_id=<?=$s['id']?>" class="btn btn-d" onclick="return confirm('Löschen?')">🗑</a>
-                        </div>
-                    </td>
-                </tr>
+            <input type="hidden" name="id" value="<?=$s['id']?>">
+            <td><img src="<?=htmlspecialchars($s['bild_url'])?>" class="img-preview" onerror="this.src='https://via.placeholder.com/45';"></td>
+            <td><select name="game_reihe_id" id="r_<?=$s['id']?>" onchange="filter(<?=$s['id']?>)"><?php foreach($reihen as $r): ?><option value="<?=$r['id']?>" <?=$s['game_reihe_id']==$r['id']?'selected':''?>><?=$r['name']?></option><?php endforeach; ?></select></td>
+            <td><input type="text" name="titel" value="<?=htmlspecialchars($s['titel'])?>"></td>
+            <td>
+                <select name="game_typ_id" id="t_<?=$s['id']?>" style="margin-bottom:3px;"><option value="0" data-p="0">Typ...</option><?php foreach($typen as $t): ?><option data-p="<?=$t['game_reihe_id']?>" value="<?=$t['id']?>" <?=$s['game_typ_id']==$t['id']?'selected':''?>><?=$t['bezeichnung']?></option><?php endforeach; ?></select>
+                <select name="game_level_id" id="l_<?=$s['id']?>"><option value="0" data-p="0">Lvl...</option><?php foreach($levels as $l): ?><option data-p="<?=$l['game_reihe_id']?>" value="<?=$l['id']?>" <?=$s['game_level_id']==$l['id']?'selected':''?>><?=$l['bezeichnung']?></option><?php endforeach; ?></select>
+                <?php foreach($levels as $lx) if($lx['id'] == $s['game_level_id']) echo "<div style='margin-top:3px'>".renderStars($lx['bezeichnung'])."</div>"; ?>
+            </td>
+            <td><input type="text" name="ean" value="<?=htmlspecialchars($s['ean'])?>"></td>
+            <td><input type="text" name="url" value="<?=htmlspecialchars($s['bild_url'])?>"></td>
+            <td><button type="submit" name="save_game" class="btn btn-s">💾</button> <a href="?del_t=spiele&del_id=<?=$s['id']?>" class="btn btn-d" onclick="return confirm('Löschen?')">🗑</a></td>
             </form>
-            <?php endforeach; ?>
-        </table>
-    </div>
+        </tr>
+        <?php endforeach; ?>
+    </table>
+</div>
 
-    <div id="t-spieler" class="tab">
-        <h3>Spieler Profile</h3>
-        <form method="POST" style="display:flex; gap:10px; margin-bottom:20px;"><input type="text" name="name" placeholder="Name" required style="max-width:300px;"> <button type="submit" name="add_spieler" class="btn btn-a">Spieler anlegen</button></form>
-        <table>
-            <?php foreach($spieler as $sl): ?>
-            <tr><td><?=$sl['name']?></td><td style="text-align:right;"><a href="?del_table=spieler&del_id=<?=$sl['id']?>" class="btn btn-d">Löschen</a></td></tr>
-            <?php endforeach; ?>
-        </table>
-    </div>
+<div id="t-spieler" class="tab">
+    <h3>Spieler Profile</h3>
+    <form method="POST" style="display:flex; gap:10px; margin-bottom:20px;"><input type="text" name="name" placeholder="Name" required><button type="submit" name="add_spieler" class="btn btn-a">Anlegen</button></form>
+    <table><?php foreach($spieler as $sl): ?><tr><td><?=$sl['name']?></td><td style="text-align:right;"><a href="?del_t=spieler&del_id=<?=$sl['id']?>" class="btn btn-d">Löschen</a></td></tr><?php endforeach; ?></table>
+</div>
 
-    <div id="t-config" class="tab">
-        <div style="display:grid; grid-template-columns: 1fr 1fr 1fr; gap:30px;">
-            <div>
-                <h4>Reihen</h4>
-                <form method="POST" style="display:flex; gap:5px; margin-bottom:15px;"><input type="text" name="name" placeholder="Neu..."><button type="submit" name="add_reihe" class="btn btn-a">+</button></form>
-                <div style="max-height:400px; overflow-y:auto;">
-                    <?php foreach($reihen as $r): ?> <div style="display:flex; justify-content:space-between; padding:5px; border-bottom:1px solid var(--border);"><span><?=$r['name']?></span> <a href="?del_table=game_reihe&del_id=<?=$r['id']?>" style="color:red; text-decoration:none;">✕</a></div> <?php endforeach; ?>
-                </div>
-            </div>
-            <div>
-                <h4>Typen (pro Reihe)</h4>
-                <form method="POST">
-                    <select name="r_id" style="margin-bottom:5px;"><?php foreach($reihen as $r): ?><option value="<?=$r['id']?>"><?=$r['name']?></option><?php endforeach; ?></select>
-                    <div style="display:flex; gap:5px;"><input type="text" name="bez" placeholder="Neu..."><button type="submit" name="add_typ" class="btn btn-a">+</button></div>
-                </form>
-                <div style="margin-top:15px; font-size:0.85em;">
-                    <?php foreach($typen as $t): ?> <div style="padding:3px; border-bottom:1px solid #eee;"><?=$t['bezeichnung']?> <small>(ID: <?=$t['game_reihe_id']?>)</small> <a href="?del_table=game_typ&del_id=<?=$t['id']?>" style="color:red; float:right;">✕</a></div> <?php endforeach; ?>
-                </div>
-            </div>
-            <div>
-                <h4>Level (pro Reihe)</h4>
-                <form method="POST">
-                    <select name="r_id" style="margin-bottom:5px;"><?php foreach($reihen as $r): ?><option value="<?=$r['id']?>"><?=$r['name']?></option><?php endforeach; ?></select>
-                    <div style="display:flex; gap:5px;"><input type="text" name="bez" placeholder="Neu..."><button type="submit" name="add_level" class="btn btn-a">+</button></div>
-                </form>
-                <div style="margin-top:15px; font-size:0.85em;">
-                    <?php foreach($levels as $l): ?> <div style="padding:3px; border-bottom:1px solid #eee;"><?=$l['bezeichnung']?> <small>(ID: <?=$l['game_reihe_id']?>)</small> <a href="?del_table=game_level&del_id=<?=$l['id']?>" style="color:red; float:right;">✕</a></div> <?php endforeach; ?>
-                </div>
-            </div>
+<div id="t-config" class="tab">
+    <div style="display:grid; grid-template-columns: 1fr 1fr 1fr; gap:20px;">
+        <div>
+            <h4>1. Reihen</h4>
+            <form method="POST" style="display:flex; gap:5px;"><input type="text" name="name" placeholder="z.B. EXIT" required><button type="submit" name="add_reihe" class="btn btn-a">+</button></form>
+            <div class="scroll-area"><?php foreach($reihen as $r): ?><div style="padding:8px; border-bottom:1px solid #eee;"><span><?=$r['name']?></span> <a href="?del_t=game_reihe&del_id=<?=$r['id']?>" style="float:right; color:red;">✕</a></div><?php endforeach; ?></div>
+        </div>
+        <div>
+            <h4>2. Typen</h4>
+            <form method="POST">
+                <select name="r_id" style="margin-bottom:5px;"><?php foreach($reihen as $r): ?><option value="<?=$r['id']?>"><?=$r['name']?></option><?php endforeach; ?></select>
+                <div style="display:flex; gap:5px;"><input type="text" name="bez" placeholder="z.B. Spiel" required><button type="submit" name="add_typ" class="btn btn-a">+</button></div>
+            </form>
+            <div class="scroll-area"><?php foreach($typen as $t): ?><div style="padding:8px; border-bottom:1px solid #eee;"><span><?=$t['bezeichnung']?> <span class="badge"><?=$t['r_name']?></span></span> <a href="?del_t=game_typ&del_id=<?=$t['id']?>" style="float:right; color:red;">✕</a></div><?php endforeach; ?></div>
+        </div>
+        <div>
+            <h4>3. Level / Sterne</h4>
+            <form method="POST">
+                <select name="r_id" style="margin-bottom:5px;"><?php foreach($reihen as $r): ?><option value="<?=$r['id']?>"><?=$r['name']?></option><?php endforeach; ?></select>
+                <div style="display:flex; gap:5px;"><input type="text" name="bez" placeholder="z.B. 3 oder Profis" required><button type="submit" name="add_level" class="btn btn-a">+</button></div>
+            </form>
+            <div class="scroll-area"><?php foreach($levels as $l): ?><div style="padding:8px; border-bottom:1px solid #eee;"><span><?=renderStars($l['bezeichnung'])?> <span class="badge"><?=$l['r_name']?></span></span> <a href="?del_t=game_level&del_id=<?=$l['id']?>" style="float:right; color:red;">✕</a></div><?php endforeach; ?></div>
         </div>
     </div>
 </div>
 
 <script>
-    function openTab(evt, tabName) {
-        document.querySelectorAll(".tab").forEach(t => t.classList.remove("active"));
-        document.querySelectorAll(".t-btn").forEach(b => b.classList.remove("active"));
-        document.getElementById(tabName).classList.add("active");
-        evt.currentTarget.classList.add("active");
-    }
-
-    function toggleTheme() {
-        const isDark = document.documentElement.classList.toggle('dark-theme');
-        localStorage.setItem('theme', isDark ? 'dark' : 'light');
-        document.getElementById('theme-icon').innerText = isDark ? '☀️' : '🌙';
-    }
-
-    function filter(id) {
-        let reiheSelect = document.getElementById('r_'+id);
-        if(!reiheSelect) return;
-        let val = reiheSelect.value;
-        
-        ['t_'+id, 'l_'+id].forEach(sid => {
-            let s = document.getElementById(sid);
-            if(!s) return;
-            s.querySelectorAll('option').forEach(o => {
-                let p = o.getAttribute('data-p');
-                o.style.display = (p == "0" || p == val) ? "block" : "none";
-            });
-            if(s.options[s.selectedIndex].style.display == "none") s.value = "0";
+function openTab(evt, name) {
+    document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
+    document.querySelectorAll('.t-btn').forEach(b => b.classList.remove('active'));
+    document.getElementById(name).classList.add('active');
+    evt.currentTarget.classList.add('active');
+}
+function filter(id) {
+    let r_val = document.getElementById('r_'+id).value;
+    ['t_'+id, 'l_'+id].forEach(sid => {
+        let sel = document.getElementById(sid); if(!sel) return;
+        sel.querySelectorAll('option').forEach(o => {
+            let p = o.getAttribute('data-p');
+            o.style.display = (p == "0" || p == r_val) ? "block" : "none";
         });
-    }
-
-    document.addEventListener('DOMContentLoaded', () => {
-        if (localStorage.getItem('theme') === 'dark') {
-            document.documentElement.classList.add('dark-theme');
-            document.getElementById('theme-icon').innerText = '☀️';
-        }
-        filter('new');
-        <?php foreach($spiele as $s): ?> filter(<?=$s['id']?>); <?php endforeach; ?>
-        setTimeout(() => { if(document.getElementById('msgbox')) document.getElementById('msgbox').style.display='none'; }, 3000);
+        if(sel.options[sel.selectedIndex].style.display == "none") sel.value = "0";
     });
+}
+document.addEventListener('DOMContentLoaded', () => { 
+    filter('new'); <?php foreach($spiele as $s): ?>filter(<?=$s['id']?>);<?php endforeach; ?> 
+});
 </script>
 </body>
 </html>

+ 50 - 34
besitz.php

@@ -2,57 +2,61 @@
 require_once 'db_config.php';
 
 $msg = "";
+// --- LOGIK: STATUS AKTUALISIEREN ---
 if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_status'])) {
-    $stmt = $pdo->prepare("INSERT INTO besitzstatus (spieler_id, spiel_id, status) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE status = VALUES(status)");
+    $stmt = $pdo->prepare("INSERT INTO besitz_status (spieler_id, spiel_id, status) 
+                           VALUES (?, ?, ?) 
+                           ON DUPLICATE KEY UPDATE status = VALUES(status)");
     $stmt->execute([(int)$_POST['spieler_id'], (int)$_POST['spiel_id'], $_POST['status']]);
     $msg = "Status aktualisiert!";
 }
 
+// --- DATEN LADEN ---
 $spieler = $pdo->query("SELECT * FROM spieler ORDER BY name ASC")->fetchAll();
-$spiele = $pdo->query("SELECT s.*, t.bezeichnung as typ_name FROM spiele s LEFT JOIN game_typen t ON s.typ_id = t.id ORDER BY s.titel ASC")->fetchAll();
+
+// Spiele laden mit korrekten Joins laut deinem Dump
+$sqlSpiele = "SELECT s.*, r.name as reihe_name, t.bezeichnung as typ_name 
+              FROM spiele s 
+              LEFT JOIN game_reihe r ON s.game_reihe_id = r.id 
+              LEFT JOIN game_typ t ON s.game_typ_id = t.id 
+              ORDER BY r.name ASC, s.titel ASC";
+$spiele = $pdo->query($sqlSpiele)->fetchAll();
+
+// Mapping aus der Tabelle MIT Unterstrich
+$statusMapping = [];
+$statusData = $pdo->query("SELECT spieler_id, spiel_id, status FROM besitz_status")->fetchAll();
+foreach ($statusData as $row) {
+    $statusMapping[$row['spiel_id']][$row['spieler_id']] = $row['status'];
+}
 ?>
 <!DOCTYPE html>
 <html lang="de">
 <head>
     <meta charset="UTF-8">
-    <title>EXIT - Bestand</title>
+    <title>EXIT - Bestand & Besitz</title>
     <style>
         :root { --bg: #f4f7f6; --card: #ffffff; --text: #333; --border: #ddd; --accent: #e67e22; }
-        .dark-theme { --bg: #121212cf; --card: #1e1e1e; --text: #e0e0e0; --border: #333; }
+        .dark-theme { --bg: #121212; --card: #1e1e1e; --text: #e0e0e0; --border: #333; }
         body { font-family: 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); padding: 20px; transition: 0.3s; }
         .container { max-width: 1200px; margin: auto; }
+        header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
+        .btn-nav { background: var(--accent); color: white; padding: 10px 15px; border-radius: 6px; text-decoration: none; font-weight: bold; }
         
-        /* DASHBOARD BUTTON DESIGN AUS ADMIN.PHP */
-        .btn-nav { 
-            background: var(--accent); 
-            color: white; 
-            padding: 10px 15px; 
-            border-radius: 6px; 
-            text-decoration: none; 
-            font-weight: bold; 
-            display: inline-block;
-            font-size: 0.9em;
-            transition: 0.2s;
-            border: none;
-            cursor: pointer;
-        }
-        .btn-nav:hover { opacity: 0.8; transform: translateY(-1px); }
-
-        table { width: 100%; border-collapse: collapse; background: var(--card); border: 1px solid var(--border); }
+        table { width: 100%; border-collapse: collapse; background: var(--card); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
         th, td { padding: 12px; border-bottom: 1px solid var(--border); text-align: left; }
+        .reihe-divider { background: rgba(230, 126, 34, 0.1); font-weight: bold; color: var(--accent); }
         
-        /* Status Einfärbung Logik */
-        select { padding: 5px; border-radius: 4px; border: 1px solid var(--border); background: var(--card); color: var(--text); }
-        select[data-status="besitzt"] { background: #d4edda !important; color: #155724 !important; }
-        select[data-status="nicht besitzt"] { background: #f8d7da !important; color: #721c24 !important; }
-        select[data-status="verkauft"] { background: #fff3e0 !important; color: #e67e22 !important; }
+        select { padding: 6px; border-radius: 4px; border: 1px solid var(--border); background: var(--card); color: var(--text); width: 100%; }
+        select[data-status="besitzt"] { background: #27ae60 !important; color: white !important; }
+        select[data-status="verkauft"] { background: #e67e22 !important; color: white !important; }
+        select[data-status="nicht besitzt"] { opacity: 0.5; }
     </style>
 </head>
 <body>
 <div class="container">
-    <header style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
-        <h1>📦 Bestand / Besitz</h1>
-        <div style="display: flex; gap: 15px; align-items: center;">
+    <header>
+        <h1>📦 Bestand & Besitz</h1>
+        <div style="display: flex; gap: 15px;">
             <button onclick="toggleTheme()" id="theme-icon" style="background:none; border:none; cursor:pointer; font-size:1.2rem;">🌙</button>
             <a href="index.php" class="btn-nav">Dashboard</a>
         </div>
@@ -66,13 +70,25 @@ $spiele = $pdo->query("SELECT s.*, t.bezeichnung as typ_name FROM spiele s LEFT
             </tr>
         </thead>
         <tbody>
-            <?php foreach ($spiele as $sp): ?>
+            <?php 
+            $currentReihe = "";
+            foreach ($spiele as $sp): 
+                if ($currentReihe !== $sp['reihe_name']): 
+                    $currentReihe = $sp['reihe_name'];
+            ?>
+                <tr>
+                    <td colspan="<?= count($spieler) + 1 ?>" class="reihe-divider">
+                        <?= htmlspecialchars($currentReihe ?: 'Sonstige') ?>
+                    </td>
+                </tr>
+            <?php endif; ?>
             <tr>
-                <td><strong><?= htmlspecialchars($sp['titel']) ?></strong></td>
+                <td>
+                    <strong><?= htmlspecialchars($sp['titel']) ?></strong><br>
+                    <small style="opacity:0.6"><?= htmlspecialchars($sp['typ_name']) ?></small>
+                </td>
                 <?php foreach ($spieler as $s): 
-                    $st_stmt = $pdo->prepare("SELECT status FROM besitzstatus WHERE spieler_id = ? AND spiel_id = ?");
-                    $st_stmt->execute([$s['id'], $sp['id']]);
-                    $curr = $st_stmt->fetchColumn() ?: 'nicht besitzt';
+                    $curr = $statusMapping[$sp['id']][$s['id']] ?? 'nicht besitzt';
                 ?>
                 <td>
                     <form method="POST">

+ 29 - 23
gesamtliste.php

@@ -1,30 +1,34 @@
 <?php
-require_once 'config.php';
 require_once 'db_config.php';
 
 // Filter-Werte abrufen
 $filterPlayerId = isset($_GET['team_filter']) ? (int)$_GET['team_filter'] : 0;
 $filterTypId = isset($_GET['typ_filter']) ? (int)$_GET['typ_filter'] : 0;
 
-// SQL Query: COUNT(sc.id) hinzugefügt, um "gespielt" ohne Sterne zu erkennen
-$sql = "SELECT sp.*, t.bezeichnung as typ_name, 
+// SQL Query an neue Struktur angepasst
+$sql = "SELECT sp.*, 
+               t.bezeichnung as typ_name, 
+               l.bezeichnung as level_name,
+               r.name as reihe_name,
                MAX(sc.sterne) as best_sterne,
                COUNT(sc.id) as anzahl_scores,
-               (SELECT status FROM besitzstatus WHERE spiel_id = sp.id AND spieler_id = :fid) as einzel_status,
+               (SELECT status FROM besitz_status WHERE spiel_id = sp.id AND spieler_id = :fid) as einzel_status,
                (SELECT GROUP_CONCAT(CONCAT(p.name, ': ', b.status) SEPARATOR '||') 
-                FROM besitzstatus b JOIN spieler p ON b.spieler_id = p.id 
+                FROM besitz_status b JOIN spieler p ON b.spieler_id = p.id 
                 WHERE b.spiel_id = sp.id AND b.status != 'nicht besitzt') as besitz_info
         FROM spiele sp
-        LEFT JOIN game_typen t ON sp.typ_id = t.id
+        LEFT JOIN game_typ t ON sp.game_typ_id = t.id
+        LEFT JOIN game_level l ON sp.game_level_id = l.id
+        LEFT JOIN game_reihe r ON sp.game_reihe_id = r.id
         LEFT JOIN scores sc ON sp.id = sc.spiel_id " . 
         ($filterPlayerId > 0 ? " AND sc.spieler_id = :pid " : "") . "
         WHERE 1=1 ";
 
 if ($filterTypId > 0) {
-    $sql .= " AND sp.typ_id = :tid ";
+    $sql .= " AND sp.game_typ_id = :tid ";
 }
 
-$sql .= " GROUP BY sp.id ORDER BY sp.titel ASC";
+$sql .= " GROUP BY sp.id ORDER BY r.name ASC, sp.titel ASC";
 
 $stmt = $pdo->prepare($sql);
 $params = ['fid' => $filterPlayerId];
@@ -36,7 +40,7 @@ $inventory = $stmt->fetchAll();
 
 // Daten für die Filter-Dropdowns
 $spieler = $pdo->query("SELECT * FROM spieler ORDER BY name ASC")->fetchAll();
-$typen = $pdo->query("SELECT * FROM game_typen ORDER BY bezeichnung ASC")->fetchAll();
+$typen = $pdo->query("SELECT * FROM game_typ ORDER BY bezeichnung ASC")->fetchAll();
 ?>
 <!DOCTYPE html>
 <html lang="de">
@@ -51,7 +55,7 @@ $typen = $pdo->query("SELECT * FROM game_typen ORDER BY bezeichnung ASC")->fetch
             --accent: #e67e22;
         }
         .dark-theme { 
-            --bg: #121212cf; --card: #1e1e1e; --text: #e0e0e0; --border: #333; 
+            --bg: #121212; --card: #1e1e1e; --text: #e0e0e0; --border: #333; 
             --header-bg: #252525; --header-text: #e67e22; --row-border: #2a2a2a;
         }
 
@@ -75,10 +79,11 @@ $typen = $pdo->query("SELECT * FROM game_typen ORDER BY bezeichnung ASC")->fetch
         .game-thumb:hover { transform: scale(1.1); border-color: var(--accent); }
 
         .lvl-badge { padding: 4px 10px; border-radius: 20px; color: white; font-size: 11px; font-weight: bold; text-transform: uppercase; }
+        /* Dynamische Klassen für Level-Farben */
         .lvl-Einsteiger { background: #27ae60; } 
         .lvl-Fortgeschrittene { background: #2980b9; } 
         .lvl-Profi { background: #c0392b; }
-        .lvl-unknown { background: #f39c12; }
+        .lvl-unknown { background: #7f8c8d; }
 
         .st-badge { padding: 5px 12px; border-radius: 15px; font-size: 11px; font-weight: bold; }
         .st-besitzt { background: #d4edda; color: #155724; }
@@ -86,12 +91,12 @@ $typen = $pdo->query("SELECT * FROM game_typen ORDER BY bezeichnung ASC")->fetch
         .st-verkauft { background: #fff3cd; color: #856404; }
         .st-keins { background: #f8d7da; color: #721c24; }
         
-        .team-pill { display: inline-flex; align-items: center; background: var(--bg); padding: 4px 10px; border-radius: 6px; font-size: 12px; margin: 2px; border: 1px solid var(--border); }
+        .team-pill { display: inline-flex; align-items: center; background: var(--bg); padding: 4px 10px; border-radius: 6px; font-size: 11px; margin: 2px; border: 1px solid var(--border); }
         .dot { height: 8px; width: 8px; border-radius: 50%; display: inline-block; margin-right: 6px; }
 
-        #imgModal { display: none; position: fixed; z-index: 10000; left: 0; top: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.9); align-items: center; justify-content: center; cursor: zoom-out; }
+        #imgModal { display: none; position: fixed; z-index: 10000; left: 0; top: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.9); align-items: center; justify-content: center; }
         #modalContent { max-width: 90%; max-height: 90%; border-radius: 10px; }
-        .image-preview { position: absolute; display: none; width: 220px; border: 4px solid white; border-radius: 12px; z-index: 999; box-shadow: 0 15px 35px rgba(0,0,0,0.4); pointer-events: none; }
+        .image-preview { position: absolute; display: none; width: 220px; border: 4px solid white; border-radius: 12px; z-index: 999; pointer-events: none; }
         
         .theme-toggle { background: none; border: none; font-size: 1.5rem; cursor: pointer; }
     </style>
@@ -124,14 +129,14 @@ $typen = $pdo->query("SELECT * FROM game_typen ORDER BY bezeichnung ASC")->fetch
             </select>
         </form>
         
-        <input type="text" id="searchInput" placeholder="Suchen..." onkeyup="filterTable()">
+        <input type="text" id="searchInput" placeholder="Titel oder Reihe suchen..." onkeyup="filterTable()">
     </div>
 
     <table id="exitTable">
         <thead>
             <tr>
-                <th style="width: 70px;">Bild</th>
-                <th onclick="sortTable(1)">Titel ↕</th>
+                <th>Bild</th>
+                <th onclick="sortTable(1)">Spiel / Reihe ↕</th>
                 <th onclick="sortTable(2)">Level ↕</th>
                 <th onclick="sortTable(3)">Bestwert ↕</th>
                 <th>Besitzstatus</th>
@@ -139,8 +144,9 @@ $typen = $pdo->query("SELECT * FROM game_typen ORDER BY bezeichnung ASC")->fetch
         </thead>
         <tbody>
             <?php foreach ($inventory as $row): 
-                $lvl = (empty($row['level']) || strtolower($row['level']) == 'unknown') ? 'unknown' : $row['level'];
-                $typ = (empty($row['typ_name']) || strtolower($row['typ_name']) == 'unknown') ? 'Unbekannt' : $row['typ_name'];
+                $lvlName = $row['level_name'] ?: 'unknown';
+                $typ = $row['typ_name'] ?: 'Standard';
+                $reihe = $row['reihe_name'] ?: 'Sonstige';
             ?>
             <tr>
                 <td>
@@ -153,11 +159,11 @@ $typen = $pdo->query("SELECT * FROM game_typen ORDER BY bezeichnung ASC")->fetch
                 </td>
                 <td>
                     <strong><?= htmlspecialchars($row['titel']) ?></strong><br>
-                    <small style="opacity: 0.7;"><?= htmlspecialchars($typ) ?></small>
+                    <small style="opacity: 0.7;"><?= htmlspecialchars($reihe) ?> (<?= htmlspecialchars($typ) ?>)</small>
                 </td>
                 <td>
-                    <span class="lvl-badge lvl-<?= $lvl ?>">
-                        <?= ($lvl == 'unknown') ? 'Unbekannt' : $lvl ?>
+                    <span class="lvl-badge lvl-<?= htmlspecialchars($lvlName) ?>">
+                        <?= htmlspecialchars($lvlName == 'unknown' ? 'Unbekannt' : $lvlName) ?>
                     </span>
                 </td>
                 <td>
@@ -183,7 +189,7 @@ $typen = $pdo->query("SELECT * FROM game_typen ORDER BY bezeichnung ASC")->fetch
                                 if(count($parts) < 2) continue;
                                 list($tn, $ts) = $parts;
                                 $dot = ($ts == 'besitzt') ? '#27ae60' : '#f39c12';
-                                echo "<span class='team-pill'><span class='dot' style='background:$dot'></span>$tn ($ts)</span>";
+                                echo "<span class='team-pill'><span class='dot' style='background:$dot'></span>$tn</span>";
                             }
                         } else { echo "<small>-</small>"; }
                     endif; ?>

+ 61 - 46
gespielte_spiele.php

@@ -3,33 +3,44 @@ include 'db_config.php';
 
 // --- 1. DATEN LADEN ---
 $allTeams = $pdo->query("SELECT * FROM spieler ORDER BY name ASC")->fetchAll();
-
 $teamFilter = isset($_GET['team_id']) ? (int)$_GET['team_id'] : 0;
 
-$sql = "SELECT sp.*, sc.zeit, sc.hilfe, sc.sterne, s.name as team_name 
+// Neue SQL-Struktur mit Joins für Reihe und Typ
+$sql = "SELECT sp.*, 
+               sc.zeit, sc.hilfe, sc.sterne, 
+               s.name as team_name, 
+               r.name as reihe_name,
+               t.bezeichnung as typ_name
         FROM spiele sp
         JOIN scores sc ON sp.id = sc.spiel_id
-        JOIN spieler s ON sc.spieler_id = s.id";
+        JOIN spieler s ON sc.spieler_id = s.id
+        LEFT JOIN game_reihe r ON sp.game_reihe_id = r.id
+        LEFT JOIN game_typ t ON sp.game_typ_id = t.id";
 
 if ($teamFilter > 0) {
     $sql .= " WHERE s.id = $teamFilter";
 }
 
-$sql .= " ORDER BY sp.titel ASC, sc.zeit ASC"; 
+// Sortierung nach Reihenname, Spieltitel und dann Score-Zeit
+$sql .= " ORDER BY r.name ASC, sp.titel ASC, sc.zeit ASC"; 
 $stmt = $pdo->query($sql);
 $results = $stmt->fetchAll();
 
-// --- 2. GRUPPIERUNG NACH SPIEL ---
-$groupedGames = [];
+// --- 2. GRUPPIERUNG NACH REIHE UND SPIEL ---
+$groupedData = [];
 foreach ($results as $row) {
-    $gameTitle = $row['titel'];
-    if (!isset($groupedGames[$gameTitle])) {
-        $groupedGames[$gameTitle] = [
+    $reihe = !empty($row['reihe_name']) ? $row['reihe_name'] : 'Sonstige';
+    $gameId = $row['id']; // ID als Key nutzen, falls Titel doppelt vorkommen könnten
+    
+    if (!isset($groupedData[$reihe][$gameId])) {
+        $groupedData[$reihe][$gameId] = [
+            'titel' => $row['titel'],
             'bild_url' => $row['bild_url'],
+            'typ_name' => $row['typ_name'],
             'teams' => []
         ];
     }
-    $groupedGames[$gameTitle]['teams'][] = [
+    $groupedData[$reihe][$gameId]['teams'][] = [
         'name' => $row['team_name'],
         'zeit' => (int)$row['zeit'],
         'hilfe' => (int)$row['hilfe'],
@@ -41,14 +52,14 @@ foreach ($results as $row) {
 <html lang="de">
 <head>
     <meta charset="UTF-8">
-    <title>EXIT - Gelöste Abenteuer</title>
+    <title>EXIT Log - Gelöste Abenteuer</title>
     <style>
         :root { 
             --bg: #f4f7f6; --card: #ffffff; --text: #333; --border: #ddd; --accent: #e67e22;
-            --muted: #888;
+            --muted: #888; --reihe-bg: #2c3e50;
         }
         .dark-theme { 
-            --bg: #121212cf; --card: #1e1e1e; --text: #ffffff; --border: #333; --muted: #aaa;
+            --bg: #121212; --card: #1e1e1e; --text: #ffffff; --border: #333; --muted: #aaa;
         }
 
         body { font-family: 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); padding: 20px; transition: 0.3s; }
@@ -57,18 +68,22 @@ foreach ($results as $row) {
         header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 30px; border-bottom: 2px solid var(--accent); padding-bottom: 10px; }
         h1 { color: var(--accent); margin: 0; font-size: 1.8rem; }
         
-        .btn-nav { background: var(--accent); color: white; text-decoration: none; padding: 10px 15px; border-radius: 8px; font-weight: bold; font-size: 0.9em; display: inline-block; border: none; }
+        .btn-nav { background: var(--accent); color: white; text-decoration: none; padding: 10px 15px; border-radius: 8px; font-weight: bold; font-size: 0.9em; display: inline-block; }
         .theme-toggle { background: none; border: none; font-size: 1.5rem; cursor: pointer; padding: 0; line-height: 1; }
 
         .filter-bar { background: var(--card); padding: 15px; border-radius: 12px; border: 1px solid var(--border); margin-bottom: 25px; display: flex; align-items: center; gap: 15px; box-shadow: 0 4px 15px rgba(0,0,0,0.05); }
         select { padding: 8px 15px; border-radius: 6px; border: 1px solid var(--border); background: var(--bg); color: var(--text); cursor: pointer; }
 
+        .reihe-divider { grid-column: 1 / -1; margin: 40px 0 20px; padding: 12px 20px; background: var(--reihe-bg); color: white; border-radius: 8px; font-size: 1.1rem; font-weight: bold; text-transform: uppercase; letter-spacing: 2px; box-shadow: 0 4px 10px rgba(0,0,0,0.1); }
+        .reihe-divider:first-of-type { margin-top: 0; }
+
         .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 25px; }
         .item { background: var(--card); border-radius: 12px; border: 1px solid var(--border); box-shadow: 0 4px 15px rgba(0,0,0,0.1); overflow: hidden; display: flex; flex-direction: column; }
         .item img { width: 100%; height: 200px; object-fit: cover; background: #2a2a2a; border-bottom: 1px solid var(--border); }
         
         .stats { padding: 15px; flex-grow: 1; }
-        .game-title { font-weight: bold; display: block; margin-bottom: 15px; font-size: 1.2em; color: var(--accent); text-align: center; }
+        .game-title { font-weight: bold; display: block; margin-bottom: 5px; font-size: 1.2em; color: var(--accent); text-align: center; line-height: 1.2; }
+        .game-subtitle { display: block; text-align: center; font-size: 0.75em; opacity: 0.6; margin-bottom: 15px; text-transform: uppercase; }
         
         .team-section-label { font-size: 0.7em; color: var(--muted); display: block; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 10px; border-bottom: 1px solid var(--border); padding-bottom: 5px; }
 
@@ -85,11 +100,9 @@ foreach ($results as $row) {
         @media (max-width: 600px) {
             header { flex-direction: column; gap: 15px; text-align: center; }
             .filter-bar { flex-direction: column; align-items: stretch; }
+            .grid { grid-template-columns: 1fr; }
         }
     </style>
-    <script>
-        if (localStorage.getItem('theme') === 'dark') document.documentElement.classList.add('dark-theme');
-    </script>
 </head>
 <body>
 
@@ -117,37 +130,38 @@ foreach ($results as $row) {
     </div>
 
     <div class="grid">
-        <?php foreach ($groupedGames as $title => $data): ?>
-            <div class="item">
-                <img src="<?= htmlspecialchars($data['bild_url']) ?>" onerror="this.src='https://via.placeholder.com/300x200?text=EXIT+Spiel'">
-                <div class="stats">
-                    <span class="game-title"><?= htmlspecialchars($title) ?></span>
-                    
-                    <span class="team-section-label">Gelöst von</span>
-                    
-                    <?php foreach ($data['teams'] as $team): ?>
-                        <div class="team-entry">
-                            <span class="team-name-text">👥 <?= htmlspecialchars($team['name']) ?></span>
-                            
-                            <?php if ($team['zeit'] === 0 && $team['hilfe'] === 0 && $team['sterne'] === 0): ?>
-                                <div class="res-only-solved">✅ Erfolgreich gelöst</div>
-                            <?php else: ?>
-                                <div class="result-row">
-                                    <div class="res-item"><span>Zeit:</span><b><?= $team['zeit'] ?> Min.</b></div>
-                                    <div class="res-item"><span>Hilfe:</span><b><?= $team['hilfe'] ?></b></div>
-                                    <div class="res-item"><b>⭐ <?= $team['sterne'] ?></b></div>
-                                </div>
-                            <?php endif; ?>
-                        </div>
-                    <?php endforeach; ?>
+        <?php foreach ($groupedData as $reiheName => $games): ?>
+            <div class="reihe-divider"><?= htmlspecialchars($reiheName) ?></div>
+            
+            <?php foreach ($games as $gameId => $data): ?>
+                <div class="item">
+                    <img src="<?= htmlspecialchars($data['bild_url']) ?>" onerror="this.src='https://via.placeholder.com/300x200?text=Escape+Spiel'">
+                    <div class="stats">
+                        <span class="game-title"><?= htmlspecialchars($data['titel']) ?></span>
+                        <span class="game-subtitle"><?= htmlspecialchars($data['typ_name'] ?: '') ?></span>
+                        
+                        <span class="team-section-label">Gelöst von</span>
+                        
+                        <?php foreach ($data['teams'] as $team): ?>
+                            <div class="team-entry">
+                                <span class="team-name-text">👥 <?= htmlspecialchars($team['name']) ?></span>
+                                
+                                <?php if ($team['zeit'] === 0 && $team['hilfe'] === 0 && $team['sterne'] === 0): ?>
+                                    <div class="res-only-solved">✅ Erfolgreich gelöst (Archiv)</div>
+                                <?php else: ?>
+                                    <div class="result-row">
+                                        <div class="res-item"><span>Zeit:</span><b><?= $team['zeit'] ?> Min.</b></div>
+                                        <div class="res-item"><span>Hilfe:</span><b><?= $team['hilfe'] ?></b></div>
+                                        <div class="res-item"><b>⭐ <?= $team['sterne'] ?></b></div>
+                                    </div>
+                                <?php endif; ?>
+                            </div>
+                        <?php endforeach; ?>
+                    </div>
                 </div>
-            </div>
+            <?php endforeach; ?>
         <?php endforeach; ?>
     </div>
-
-    <?php if (empty($groupedGames)): ?>
-        <p style="text-align: center; margin-top: 50px; opacity: 0.5;">Hier wurden noch keine Abenteuer gelöst.</p>
-    <?php endif; ?>
 </div>
 
 <script>
@@ -158,6 +172,7 @@ foreach ($results as $row) {
         themeIcon.innerText = isDark ? '☀️' : '🌙';
     }
     if (localStorage.getItem('theme') === 'dark') {
+        document.documentElement.classList.add('dark-theme');
         themeIcon.innerText = '☀️';
     }
 </script>

+ 116 - 149
index.php

@@ -1,7 +1,10 @@
 <?php
 require_once 'db_config.php';
 
-// --- LOGIK: NEUEN SPIELER HINZUFÜGEN ---
+// --- 1. DATEN LADEN (REIHEN FÜR DEN FILTER) ---
+$reihen = $pdo->query("SELECT * FROM game_reihe ORDER BY name ASC")->fetchAll();
+
+// --- 2. LOGIK: NEUEN SPIELER HINZUFÜGEN ---
 if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_player'])) {
     $sql = "INSERT IGNORE INTO spieler (name) VALUES (?)";
     $stmt = $pdo->prepare($sql);
@@ -10,44 +13,47 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_player'])) {
     exit;
 }
 
-// --- LOGIK: SCORE HINZUFÜGEN ---
+// --- 3. LOGIK: SCORE HINZUFÜGEN ---
 if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_score'])) {
     $unbekannt = isset($_POST['ergebnis_unbekannt']);
-    
-    // Wenn unbekannt, werden 0-Werte gespeichert
     $zeit = $unbekannt ? 0 : (int)$_POST['zeit'];
     $hilfe = $unbekannt ? 0 : (int)$_POST['hilfe'];
     $sterne = $unbekannt ? 0 : (int)$_POST['sterne'];
 
     $sql = "INSERT INTO scores (spieler_id, spiel_id, zeit, hilfe, sterne) VALUES (?, ?, ?, ?, ?)";
     $stmt = $pdo->prepare($sql);
-    $stmt->execute([
-        $_POST['spieler_id'], 
-        $_POST['spiel_id'], 
-        $zeit, 
-        $hilfe, 
-        $sterne
-    ]);
+    $stmt->execute([$_POST['spieler_id'], $_POST['spiel_id'], $zeit, $hilfe, $sterne]);
     header("Location: index.php?success=score");
     exit;
 }
 
-// --- DATEN ABFRAGEN ---
-$sqlGames = "SELECT s.*, t.bezeichnung as typ_name 
+// --- 4. DATEN ABFRAGEN (NEUE STRUKTUR MIT JOINS) ---
+$sqlGames = "SELECT s.*, 
+                    r.name as reihe_name, 
+                    t.bezeichnung as typ_name, 
+                    l.bezeichnung as level_name 
              FROM spiele s 
-             LEFT JOIN game_typen t ON s.typ_id = t.id 
-             ORDER BY s.titel ASC";
-$stmtGames = $pdo->query($sqlGames);
-$exitGames = $stmtGames->fetchAll(PDO::FETCH_ASSOC);
+             LEFT JOIN game_reihe r ON s.game_reihe_id = r.id
+             LEFT JOIN game_typ t ON s.game_typ_id = t.id 
+             LEFT JOIN game_level l ON s.game_level_id = l.id
+             ORDER BY r.name ASC, s.titel ASC";
+$exitGames = $pdo->query($sqlGames)->fetchAll(PDO::FETCH_ASSOC);
 
-$stmtAllPlayers = $pdo->query("SELECT * FROM spieler ORDER BY name ASC");
-$playersList = $stmtAllPlayers->fetchAll();
+$playersList = $pdo->query("SELECT * FROM spieler ORDER BY name ASC")->fetchAll();
 
 $sqlScores = "SELECT s.*, p.name as spieler_name 
               FROM scores s 
               JOIN spieler p ON s.spieler_id = p.id 
-              ORDER BY s.sterne DESC, s.zeit ASC";
+              ORDER BY s.id DESC"; 
 $allScores = $pdo->query($sqlScores)->fetchAll();
+
+// Hilfsfunktion Sterne (Zahlen zu ★)
+function getStarRating($val) {
+    if (!is_numeric($val)) return htmlspecialchars($val);
+    $n = (int)$val; $out = "";
+    for($i=1; $i<=5; $i++) { $out .= ($i <= $n) ? "★" : "☆"; }
+    return $out;
+}
 ?>
 
 <!DOCTYPE html>
@@ -63,118 +69,59 @@ $allScores = $pdo->query($sqlScores)->fetchAll();
             --input-bg: #fff; --footer-bg: #f1f1f1; --success: #27ae60;
         }
         .dark-theme { 
-            --bg: #121212cf; --card: #1e1e1e; --text: #e0e0e0; --border: #333;
+            --bg: #121212; --card: #1e1e1e; --text: #e0e0e0; --border: #333;
             --input-bg: #2a2a2a; --footer-bg: #1a1a1a;
         }
 
         body { font-family: 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); margin: 0; padding-bottom: 120px; transition: 0.3s; }
         .container { max-width: 1200px; margin: auto; padding: 20px; }
         
-        .alert { 
-            background: var(--success); color: white; padding: 15px; border-radius: 8px; 
-            margin-bottom: 20px; text-align: center; font-weight: bold;
-            animation: fadeOut 1s forwards; animation-delay: 3s;
-        }
-        @keyframes fadeOut { from {opacity: 1;} to {opacity: 0; visibility: hidden;} }
+        .alert { background: var(--success); color: white; padding: 15px; border-radius: 8px; margin-bottom: 20px; text-align: center; font-weight: bold; }
 
         header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px; border-bottom: 1px solid var(--border); padding-bottom: 15px; }
         h1 { color: var(--accent); margin: 0; font-size: 1.6em; }
 
-        .theme-toggle { background: var(--card); border: 1px solid var(--border); color: var(--text); width: 42px; height: 34px; border-radius: 10px; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: 0.3s; }
-
-        .swiper-outer-wrapper {
-            position: relative;
-            width: 100%;
-            padding: 0 50px; 
-            box-sizing: border-box;
-            margin-bottom: 40px;
-        }
+        .theme-toggle { background: var(--card); border: 1px solid var(--border); color: var(--text); width: 42px; height: 34px; border-radius: 10px; cursor: pointer; display: flex; align-items: center; justify-content: center; }
 
-        .swiper { width: 100%; padding-top: 10px; }
-        .swiper-slide { width: 320px; height: auto; }
-        .swiper-pagination-progressbar { background: var(--border) !important; height: 4px !important; top: 0 !important; }
-        .swiper-pagination-progressbar-fill { background: var(--accent) !important; }
+        .swiper-outer-wrapper { position: relative; width: 100%; padding: 0 40px; box-sizing: border-box; margin-bottom: 40px; }
+        .swiper-slide { width: 300px; height: auto; }
         
-        .swiper-button-next, .swiper-button-prev { 
-            color: var(--text); 
-            background: none;   
-            width: auto;        
-            height: auto;       
-            box-shadow: none;   
-            border: none;       
-            position: absolute;
-            top: 50%;
-            transform: translateY(-50%);
-            z-index: 10;
-            opacity: 0.5;       
-            transition: all 0.3s ease;
-        }
-
-        .swiper-button-next:hover, .swiper-button-prev:hover {
-            color: var(--accent);
-            opacity: 1;
-            transform: translateY(-50%) scale(1.1);
-        }
-
-        .swiper-button-prev { left: 10px; }
-        .swiper-button-next { right: 10px; }
-
-        .swiper-button-next:after, .swiper-button-prev:after { 
-            font-size: 40px;    
-            font-weight: bold; 
-        }
-
-        @media (max-width: 768px) {
-            .swiper-outer-wrapper { padding: 0 10px; }
-            .swiper-button-next, .swiper-button-prev { display: none; }
-        }
-
-        .card { background: var(--card); border-radius: 12px; border: 1px solid var(--border); overflow: hidden; height: 100%; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
-        .card img { width: 100%; height: 180px; object-fit: cover; opacity: 0.9; }
-        .content { padding: 15px; }
+        .card { background: var(--card); border-radius: 12px; border: 1px solid var(--border); overflow: hidden; height: 100%; box-shadow: 0 4px 15px rgba(0,0,0,0.1); display: flex; flex-direction: column; }
+        .card img { width: 100%; height: 160px; object-fit: cover; }
+        .content { padding: 15px; flex-grow: 1; }
         
-        h2 { color: var(--accent); margin-top: 0; font-size: 1.1em; }
-        .stats { width: 100%; border-collapse: collapse; font-size: 0.85em; }
+        h2 { color: var(--accent); margin: 0 0 5px 0; font-size: 1.1em; }
+        .reihe-label { font-size: 0.75em; opacity: 0.7; text-transform: uppercase; display: block; margin-bottom: 2px; }
+
+        .stats { width: 100%; border-collapse: collapse; font-size: 0.85em; margin-top: 10px; }
         .stats td { padding: 6px 0; border-bottom: 1px solid var(--border); }
         
-        .badge { padding: 4px 8px; border-radius: 4px; font-size: 0.7em; font-weight: bold; text-transform: uppercase; color: white; display: inline-block; margin-bottom: 5px; }
-        .level-Einsteiger { background: #27ae60; } 
-        .level-Profi { background: #c0392b; } 
-        .level-Fortgeschrittene { background: #2980b9; }
-        .level-unknown { background: #f39c12; }
+        .badge { padding: 3px 7px; border-radius: 4px; font-size: 0.65em; font-weight: bold; text-transform: uppercase; color: white; display: inline-block; margin-bottom: 5px; margin-right: 3px; }
+        .level-badge { background: #7f8c8d; }
+        .type-badge { background: transparent; border: 1px solid var(--accent); color: var(--accent); }
 
         .bottom-section { display: grid; grid-template-columns: 1fr 2fr; gap: 20px; margin-top: 20px; }
-        @media (max-width: 768px) { .bottom-section { grid-template-columns: 1fr; } }
+        @media (max-width: 768px) { .bottom-section { grid-template-columns: 1fr; } .swiper-outer-wrapper { padding: 0 10px; } }
 
         .form-section, .info-section { background: var(--card); padding: 20px; border-radius: 12px; border: 1px solid var(--border); }
-        .highlight-border { border-color: var(--accent); }
+        .highlight-border { border-color: var(--accent); border-width: 2px; }
         
-        .info-section a { color: var(--accent); text-decoration: none; display: block; padding: 10px; border: 1px dashed var(--border); border-radius: 8px; text-align: center; transition: 0.2s; }
-        .info-section a:hover { background: var(--bg); border-color: var(--accent); }
-
-        input, select { width: 100%; padding: 10px; background: var(--input-bg); border: 1px solid var(--border); color: var(--text); border-radius: 5px; margin-bottom: 10px; box-sizing: border-box; }
+        input, select { width: 100%; padding: 10px; background: var(--input-bg); border: 1px solid var(--border); color: var(--text); border-radius: 5px; margin-bottom: 10px; }
         button { background: var(--accent); color: white; border: none; padding: 12px; border-radius: 5px; cursor: pointer; font-weight: bold; width: 100%; }
 
-        .footer-nav { position: fixed; bottom: 0; left: 0; width: 100%; background: var(--footer-bg); border-top: 2px solid var(--accent); padding: 15px 0; display: flex; justify-content: center; gap: 20px; z-index: 1000; flex-wrap: wrap; }
-        .footer-nav a { color: var(--accent); text-decoration: none; font-weight: bold; font-size: 0.8em; padding: 5px 10px; border: 1px solid transparent; transition: 0.3s; }
-        .footer-nav a:hover { border-color: var(--accent); border-radius: 5px; }
-        
-        #playerModal { display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: var(--card); padding: 30px; border-radius: 12px; border: 1px solid var(--accent); z-index: 2000; color: var(--text); box-shadow: 0 0 50px rgba(0,0,0,0.5); }
+        .footer-nav { position: fixed; bottom: 0; left: 0; width: 100%; background: var(--footer-bg); border-top: 2px solid var(--accent); padding: 15px 0; display: flex; justify-content: center; gap: 20px; z-index: 1000; }
+        .footer-nav a { color: var(--accent); text-decoration: none; font-weight: bold; font-size: 0.85em; }
+
+        #playerModal { display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: var(--card); padding: 30px; border-radius: 12px; border: 1px solid var(--accent); z-index: 2000; }
         .overlay { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); z-index: 1500; }
-        
-        .unknown-box { margin-bottom: 15px; display: flex; align-items: center; gap: 8px; font-size: 0.9em; }
-        .unknown-box input { width: auto; margin: 0; cursor: pointer; }
     </style>
-    <script>
-        if (localStorage.getItem('theme') === 'dark') document.documentElement.classList.add('dark-theme');
-    </script>
 </head>
 <body>
 
 <div class="container">
     <?php if (isset($_GET['success'])): ?>
         <div class="alert" id="success-alert">
-            <?= $_GET['success'] === 'score' ? '✅ Score erfolgreich gespeichert!' : '👤 Neuer Spieler angelegt!' ?>
+            <?= $_GET['success'] === 'score' ? '✅ Score gespeichert!' : '👤 Spieler angelegt!' ?>
         </div>
     <?php endif; ?>
 
@@ -185,17 +132,17 @@ $allScores = $pdo->query($sqlScores)->fetchAll();
 
     <div class="swiper-outer-wrapper">
         <div class="swiper mySwiper">
-            <div class="swiper-pagination"></div>
             <div class="swiper-wrapper">
-                <?php foreach ($exitGames as $game): 
-                    $lvl_class = (empty($game['level']) || strtolower($game['level']) == 'unknown') ? 'unknown' : $game['level'];
-                ?>
+                <?php foreach ($exitGames as $game): ?>
                     <div class="swiper-slide">
                         <div class="card">
-                            <img src="<?= htmlspecialchars($game['bild_url']) ?>" alt="Cover" onerror="this.src='https://via.placeholder.com/320x180?text=Kein+Bild'">
+                            <img src="<?= htmlspecialchars($game['bild_url']) ?>" onerror="this.src='https://via.placeholder.com/300x160?text=Kein+Cover'">
                             <div class="content">
-                                <span class="badge level-<?= $lvl_class ?>"><?= htmlspecialchars($game['level'] ?: 'Unbekannt') ?></span>
+                                <span class="reihe-label"><?= htmlspecialchars($game['reihe_name']) ?></span>
                                 <h2><?= htmlspecialchars($game['titel']) ?></h2>
+                                <span class="badge type-badge"><?= htmlspecialchars($game['typ_name'] ?: 'Basis') ?></span>
+                                <span class="badge level-badge"><?= getStarRating($game['level_name'] ?: '---') ?></span>
+
                                 <table class="stats">
                                     <?php 
                                     $found = false;
@@ -203,11 +150,11 @@ $allScores = $pdo->query($sqlScores)->fetchAll();
                                         if ($entry['spiel_id'] == $game['id']): $found = true; ?>
                                         <tr>
                                             <td><strong><?= htmlspecialchars($entry['spieler_name']) ?></strong></td>
-                                            <td><?= $entry['zeit'] > 0 ? $entry['zeit']."'" : '?' ?></td>
-                                            <td style="color:#f1c40f"><?= $entry['sterne'] > 0 ? $entry['sterne']."★" : "gespielt" ?></td>
+                                            <td><?= $entry['zeit'] > 0 ? $entry['zeit']." Min" : '?' ?></td>
+                                            <td style="color:#f1c40f; text-align:right;"><?= $entry['sterne'] > 0 ? $entry['sterne']."★" : "" ?></td>
                                         </tr>
                                     <?php endif; endforeach; 
-                                    if (!$found) echo "<tr><td colspan='3' style='opacity:0.5'>Noch keine Scores.</td></tr>";
+                                    if (!$found) echo "<tr><td colspan='3' style='opacity:0.4'>Noch ungelöst...</td></tr>";
                                     ?>
                                 </table>
                             </div>
@@ -215,31 +162,36 @@ $allScores = $pdo->query($sqlScores)->fetchAll();
                     </div>
                 <?php endforeach; ?>
             </div>
+            <div class="swiper-pagination"></div>
         </div>
-        <div class="swiper-button-prev"></div>
-        <div class="swiper-button-next"></div>
     </div>
 
     <div class="bottom-section">
         <div class="info-section">
             <h2>📜 Archiv</h2>
-            <p style="font-size: 0.8em; opacity: 0.6; margin-bottom: 15px;">Bereits gelöste Abenteuer einsehen.</p>
-            <a href="gespielte_spiele.php">📂 Übersicht gespielte Spiele</a>
+            <p style="font-size: 0.8em; opacity: 0.6;">Alle Spielergebnisse einsehen.</p>
+            <a href="gespielte_spiele.php" style="color: var(--accent); font-weight:bold; text-decoration:none;">📂 Zur Übersicht</a>
         </div>
 
         <div class="form-section highlight-border">
-            <h2>🎯 Ergebnis eintragen</h2>
-            <form method="POST" action="index.php">
-                <select name="spiel_id" required>
+            <h2>🎯 Score eintragen</h2>
+            <form method="POST">
+                <select id="filter_reihe" onchange="filterGamesByReihe()">
+                    <option value="">-- Alle Reihen --</option>
+                    <?php foreach ($reihen as $r): ?>
+                        <option value="<?= $r['id'] ?>"><?= htmlspecialchars($r['name']) ?></option>
+                    <?php endforeach; ?>
+                </select>
+
+                <select name="spiel_id" id="spiel_select" required>
                     <option value="">-- Spiel wählen --</option>
-                    <?php foreach ($exitGames as $game): 
-                        $display_typ = $game['typ_name'] ?: 'Unbekannt';
-                    ?>
-                        <option value="<?= $game['id'] ?>">
-                            <?= htmlspecialchars($game['titel']) ?> (<?= htmlspecialchars($display_typ) ?>)
+                    <?php foreach ($exitGames as $game): ?>
+                        <option value="<?= $game['id'] ?>" data-reihe="<?= $game['game_reihe_id'] ?>">
+                            <?= htmlspecialchars($game['reihe_name']) ?>: <?= htmlspecialchars($game['titel']) ?>
                         </option>
                     <?php endforeach; ?>
                 </select>
+
                 <select name="spieler_id" required>
                     <option value="">-- Wer hat gespielt? --</option>
                     <?php foreach ($playersList as $p): ?>
@@ -247,9 +199,9 @@ $allScores = $pdo->query($sqlScores)->fetchAll();
                     <?php endforeach; ?>
                 </select>
                 
-                <div class="unknown-box">
-                    <input type="checkbox" name="ergebnis_unbekannt" id="ergebnis_unbekannt" onchange="toggleInputs()">
-                    <label for="ergebnis_unbekannt">Ergebnisse unbekannt</label>
+                <div style="display: flex; align-items: center; gap: 8px; margin-bottom:10px; font-size:0.9em;">
+                    <input type="checkbox" name="ergebnis_unbekannt" id="ergebnis_unbekannt" onchange="toggleInputs()" style="width:auto; margin:0;">
+                    <label for="ergebnis_unbekannt">Ergebnis unbekannt (nur Archivierung)</label>
                 </div>
 
                 <div id="input-fields" style="display: flex; gap: 10px;">
@@ -266,34 +218,52 @@ $allScores = $pdo->query($sqlScores)->fetchAll();
 <div class="footer-nav">
     <a href="javascript:void(0)" onclick="toggleModal()">👤 NEUER SPIELER</a>
     <a href="besitz.php">📦 BESTAND</a> 
-    <a href="gesamtliste.php">📝 GESAMTÜBERSICHT</a>
+    <a href="gesamtliste.php">📝 LISTE</a>
     <a href="admin.php">🛠 ADMIN</a>
 </div>
 
 <div class="overlay" id="overlay" onclick="toggleModal()"></div>
 <div id="playerModal">
-    <h2>👤 Team/Spieler anlegen</h2>
-    <form method="POST" action="index.php">
+    <h2 style="color:var(--accent); margin-top:0;">👤 Team/Spieler</h2>
+    <form method="POST">
         <input type="text" name="neuer_spieler_name" placeholder="Name" required>
         <button type="submit" name="add_player">Anlegen</button>
-        <button type="button" onclick="toggleModal()" style="background: #666; margin-top: 10px;">Abbrechen</button>
+        <button type="button" onclick="toggleModal()" style="background: #666; margin-top: 8px;">Abbrechen</button>
     </form>
 </div>
 
 <script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>
 <script>
-    const themeIcon = document.getElementById('theme-icon');
     function toggleTheme() {
         const isDark = document.documentElement.classList.toggle('dark-theme');
         localStorage.setItem('theme', isDark ? 'dark' : 'light');
-        themeIcon.innerText = isDark ? '☀️' : '🌙';
+        document.getElementById('theme-icon').innerText = isDark ? '☀️' : '🌙';
+    }
+    if (localStorage.getItem('theme') === 'dark') {
+        document.documentElement.classList.add('dark-theme');
+        document.getElementById('theme-icon').innerText = '☀️';
+    }
+
+    function filterGamesByReihe() {
+        const reihenId = document.getElementById('filter_reihe').value;
+        const select = document.getElementById('spiel_select');
+        const options = select.querySelectorAll('option');
+
+        options.forEach(opt => {
+            const rId = opt.getAttribute('data-reihe');
+            if (reihenId === "" || rId === reihenId || !rId) {
+                opt.style.display = "block";
+            } else {
+                opt.style.display = "none";
+            }
+        });
+        select.value = ""; 
     }
-    if (localStorage.getItem('theme') === 'dark') themeIcon.innerText = '☀️';
 
     function toggleInputs() {
         const check = document.getElementById('ergebnis_unbekannt');
-        const fields = ['zeit', 'sterne', 'hilfe'];
-        fields.forEach(id => {
+        const ids = ['zeit', 'sterne', 'hilfe'];
+        ids.forEach(id => {
             const el = document.getElementById(id);
             el.disabled = check.checked;
             if (check.checked) el.value = '';
@@ -302,20 +272,6 @@ $allScores = $pdo->query($sqlScores)->fetchAll();
         document.getElementById('input-fields').style.opacity = check.checked ? '0.5' : '1';
     }
 
-    new Swiper(".mySwiper", {
-        slidesPerView: "auto", 
-        spaceBetween: 20, 
-        grabCursor: true, 
-        pagination: { 
-            el: ".swiper-pagination", 
-            type: "progressbar" 
-        },
-        navigation: {
-            nextEl: ".swiper-button-next",
-            prevEl: ".swiper-button-prev",
-        },
-    });
-
     function toggleModal() {
         const m = document.getElementById('playerModal');
         const o = document.getElementById('overlay');
@@ -323,6 +279,17 @@ $allScores = $pdo->query($sqlScores)->fetchAll();
         m.style.display = vis ? 'none' : 'block';
         o.style.display = vis ? 'none' : 'block';
     }
+
+    new Swiper(".mySwiper", {
+        slidesPerView: "auto", 
+        spaceBetween: 20, 
+        pagination: { el: ".swiper-pagination", type: "progressbar" },
+    });
+
+    setTimeout(() => { 
+        const a = document.getElementById('success-alert');
+        if(a) a.style.display = 'none';
+    }, 3000);
 </script>
 </body>
 </html>