gesamtliste.php 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. <?php
  2. require_once 'db_config.php';
  3. $filterPlayerId = isset($_GET['team_filter']) ? (int)$_GET['team_filter'] : 0;
  4. // SQL-Abfrage: :fid wird für den Einzel-Status genutzt, :pid für den globalen Filter
  5. $sql = "SELECT sp.*, t.bezeichnung as typ_name, MAX(sc.sterne) as best_sterne,
  6. (SELECT status FROM besitzstatus WHERE spiel_id = sp.id AND spieler_id = :fid) as einzel_status,
  7. (SELECT GROUP_CONCAT(CONCAT(p.name, ': ', b.status) SEPARATOR '||')
  8. FROM besitzstatus b JOIN spieler p ON b.spieler_id = p.id
  9. WHERE b.spiel_id = sp.id AND b.status != 'nicht besitzt') as besitz_info
  10. FROM spiele sp
  11. LEFT JOIN game_typen t ON sp.typ_id = t.id
  12. LEFT JOIN scores sc ON sp.id = sc.spiel_id " .
  13. ($filterPlayerId > 0 ? " AND sc.spieler_id = :pid " : "") . "
  14. GROUP BY sp.id ORDER BY sp.id DESC";
  15. $stmt = $pdo->prepare($sql);
  16. // Parameter-Array vorbereiten
  17. $params = ['fid' => $filterPlayerId]; // :fid wird immer benötigt für die Subquery
  18. if ($filterPlayerId > 0) {
  19. $params['pid'] = $filterPlayerId; // :pid nur hinzufügen, wenn der Filter aktiv ist
  20. }
  21. $stmt->execute($params);
  22. $inventory = $stmt->fetchAll();
  23. $spieler = $pdo->query("SELECT * FROM spieler ORDER BY id ASC")->fetchAll();
  24. ?>
  25. <!DOCTYPE html>
  26. <html lang="de">
  27. <head>
  28. <meta charset="UTF-8">
  29. <title>EXIT Gesamtliste</title>
  30. <style>
  31. body { font-family: 'Segoe UI', sans-serif; background: #f8f9fa; padding: 20px; }
  32. .container { max-width: 1400px; margin: 0 auto; }
  33. table { width: 100%; border-collapse: collapse; background: white; border-radius: 10px; overflow: hidden; box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
  34. th, td { padding: 12px 15px; text-align: left; border-bottom: 1px solid #eee; }
  35. th { background: #e67e22; color: white; cursor: pointer; font-size: 0.8em; text-transform: uppercase; }
  36. .game-thumb { width: 50px; height: 50px; object-fit: cover; border-radius: 8px; }
  37. .lvl-badge { padding: 4px 8px; border-radius: 4px; color: white; font-size: 0.7em; font-weight: bold; }
  38. .lvl-Einsteiger { background: #27ae60; } .lvl-Fortgeschrittene { background: #2980b9; } .lvl-Profi { background: #c0392b; }
  39. .st-badge { padding: 4px 8px; border-radius: 12px; font-size: 0.7em; font-weight: bold; display: inline-block; }
  40. .st-besitzt { background: #d4edda; color: #155724; }
  41. .st-verkauft { background: #fff3cd; color: #856404; }
  42. .st-keins { background: #f8d7da; color: #721c24; }
  43. .team-pill { display: inline-block; background: #eee; padding: 2px 6px; border-radius: 4px; font-size: 0.8em; margin: 2px; border: 1px solid #ddd; }
  44. </style>
  45. </head>
  46. <body>
  47. <div class="container">
  48. <div style="display:flex; justify-content: space-between; align-items:center; margin-bottom:20px;">
  49. <h1>📝 Sammlungs-Übersicht</h1>
  50. <a href="index.php" style="color:#e67e22; font-weight:bold; text-decoration:none;">← Dashboard</a>
  51. </div>
  52. <div style="background:white; padding:15px; border-radius:10px; margin-bottom:20px; display:flex; gap:15px;">
  53. <form method="GET">
  54. <select name="team_filter" onchange="this.form.submit()" style="padding:10px; border-radius:5px;">
  55. <option value="0">-- Alle Teams --</option>
  56. <?php foreach ($spieler as $p): ?>
  57. <option value="<?= $p['id'] ?>" <?= $filterPlayerId == $p['id'] ? 'selected' : '' ?>><?= htmlspecialchars($p['name']) ?></option>
  58. <?php endforeach; ?>
  59. </select>
  60. </form>
  61. <input type="text" id="searchInput" placeholder="Suchen..." onkeyup="filterTable()" style="flex-grow:1; padding:10px; border:1px solid #ddd; border-radius:5px;">
  62. </div>
  63. <table id="exitTable">
  64. <thead>
  65. <tr>
  66. <th onclick="sortTable(0)">ID</th>
  67. <th>Bild</th>
  68. <th onclick="sortTable(2)">Titel</th>
  69. <th>Level</th>
  70. <th>Bestwert</th>
  71. <th>Besitzstatus</th>
  72. </tr>
  73. </thead>
  74. <tbody>
  75. <?php foreach ($inventory as $row): ?>
  76. <tr>
  77. <td>#<?= $row['id'] ?></td>
  78. <td><img src="<?= $row['bild_url'] ?>" class="game-thumb" onerror="this.src='https://via.placeholder.com/50?text=?'"></td>
  79. <td><strong><?= htmlspecialchars($row['titel']) ?></strong><br><small style="color:#666;"><?= htmlspecialchars($row['typ_name'] ?? 'Unbekannt') ?></small></td>
  80. <td><span class="lvl-badge lvl-<?= $row['level'] ?>"><?= $row['level'] ?></span></td>
  81. <td><?= $row['best_sterne'] ? "<b style='color:#e67e22'>{$row['best_sterne']} ★</b>" : "-" ?></td>
  82. <td>
  83. <?php if ($filterPlayerId > 0):
  84. $st = $row['einzel_status'] ?: 'nicht besitzt';
  85. $class = ($st == 'besitzt') ? 'st-besitzt' : (($st == 'verkauft') ? 'st-verkauft' : 'st-keins');
  86. ?>
  87. <span class="st-badge <?= $class ?>"><?= strtoupper($st) ?></span>
  88. <?php else: ?>
  89. <?php
  90. if ($row['besitz_info']) {
  91. $teams = explode('||', $row['besitz_info']);
  92. foreach ($teams as $t) {
  93. $parts = explode(': ', $t);
  94. if(count($parts) < 2) continue;
  95. $tname = $parts[0]; $tstat = $parts[1];
  96. $color = ($tstat == 'besitzt') ? '#27ae60' : '#f39c12';
  97. echo "<span class='team-pill'><b style='color:$color'>●</b> " . htmlspecialchars($tname) . " (" . htmlspecialchars($tstat) . ")</span>";
  98. }
  99. } else { echo "<small style='color:#ccc'>Kein Team besitzt es</small>"; }
  100. ?>
  101. <?php endif; ?>
  102. </td>
  103. </tr>
  104. <?php endforeach; ?>
  105. </tbody>
  106. </table>
  107. </div>
  108. <script>
  109. function filterTable() {
  110. let input = document.getElementById("searchInput"),
  111. filter = input.value.toUpperCase(),
  112. tr = document.getElementById("exitTable").getElementsByTagName("tr");
  113. for (let i = 1; i < tr.length; i++) {
  114. tr[i].style.display = tr[i].innerText.toUpperCase().includes(filter) ? "" : "none";
  115. }
  116. }
  117. function sortTable(n) {
  118. var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
  119. table = document.getElementById("exitTable");
  120. switching = true; dir = "asc";
  121. while (switching) {
  122. switching = false; rows = table.rows;
  123. for (i = 1; i < (rows.length - 1); i++) {
  124. shouldSwitch = false;
  125. x = rows[i].getElementsByTagName("TD")[n];
  126. y = rows[i + 1].getElementsByTagName("TD")[n];
  127. var valX = x.innerText.toLowerCase().replace('#', '');
  128. var valY = y.innerText.toLowerCase().replace('#', '');
  129. if (n === 0) { valX = parseInt(valX); valY = parseInt(valY); }
  130. if (dir == "asc") { if (valX > valY) { shouldSwitch = true; break; }
  131. } else { if (valX < valY) { shouldSwitch = true; break; } }
  132. }
  133. if (shouldSwitch) {
  134. rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
  135. switching = true; switchcount ++;
  136. } else {
  137. if (switchcount == 0 && dir == "asc") { dir = "desc"; switching = true; }
  138. }
  139. }
  140. }
  141. </script>
  142. </body>
  143. </html>