|
|
@@ -2,8 +2,11 @@
|
|
|
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 mit dynamischen Filtern
|
|
|
$sql = "SELECT sp.*, t.bezeichnung as typ_name, MAX(sc.sterne) as best_sterne,
|
|
|
(SELECT status FROM besitzstatus WHERE spiel_id = sp.id AND spieler_id = :fid) as einzel_status,
|
|
|
(SELECT GROUP_CONCAT(CONCAT(p.name, ': ', b.status) SEPARATOR '||')
|
|
|
@@ -13,15 +16,25 @@ $sql = "SELECT sp.*, t.bezeichnung as typ_name, MAX(sc.sterne) as best_sterne,
|
|
|
LEFT JOIN game_typen t ON sp.typ_id = t.id
|
|
|
LEFT JOIN scores sc ON sp.id = sc.spiel_id " .
|
|
|
($filterPlayerId > 0 ? " AND sc.spieler_id = :pid " : "") . "
|
|
|
- GROUP BY sp.id ORDER BY sp.id DESC";
|
|
|
+ WHERE 1=1 ";
|
|
|
+
|
|
|
+if ($filterTypId > 0) {
|
|
|
+ $sql .= " AND sp.typ_id = :tid ";
|
|
|
+}
|
|
|
+
|
|
|
+$sql .= " GROUP BY sp.id ORDER BY sp.id DESC";
|
|
|
|
|
|
$stmt = $pdo->prepare($sql);
|
|
|
$params = ['fid' => $filterPlayerId];
|
|
|
if ($filterPlayerId > 0) { $params['pid'] = $filterPlayerId; }
|
|
|
+if ($filterTypId > 0) { $params['tid'] = $filterTypId; }
|
|
|
+
|
|
|
$stmt->execute($params);
|
|
|
$inventory = $stmt->fetchAll();
|
|
|
|
|
|
+// Stammdaten für 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();
|
|
|
?>
|
|
|
<!DOCTYPE html>
|
|
|
<html lang="de">
|
|
|
@@ -30,7 +43,7 @@ $spieler = $pdo->query("SELECT * FROM spieler ORDER BY name ASC")->fetchAll();
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
<title>EXIT - Gesamtliste</title>
|
|
|
<style>
|
|
|
- /* THEME VARIABLEN */
|
|
|
+ /* CSS bleibt identisch zu deinem Stand, nur kleine Ergänzung für Form-Layout */
|
|
|
:root {
|
|
|
--bg: #f8f9fa; --card: #ffffff; --text: #333; --border: #ddd;
|
|
|
--header-bg: #2c3e50; --header-text: #ffffff; --row-border: #eee;
|
|
|
@@ -44,57 +57,37 @@ $spieler = $pdo->query("SELECT * FROM spieler ORDER BY name ASC")->fetchAll();
|
|
|
body { font-family: 'Segoe UI', sans-serif; background: var(--bg); margin: 0; padding: 20px; color: var(--text); transition: 0.3s; }
|
|
|
.container { max-width: 1400px; margin: 0 auto; }
|
|
|
.header-area { display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px; }
|
|
|
-
|
|
|
.nav-group { display: flex; align-items: center; gap: 10px; }
|
|
|
+ .back-link { background: var(--accent); color: white !important; text-decoration: none; font-weight: bold; padding: 10px 18px; border-radius: 6px; display: inline-block; }
|
|
|
|
|
|
- .back-link {
|
|
|
- background: var(--accent);
|
|
|
- color: white !important;
|
|
|
- text-decoration: none;
|
|
|
- font-weight: bold;
|
|
|
- padding: 10px 18px;
|
|
|
- border-radius: 6px;
|
|
|
- border: none;
|
|
|
- display: inline-block;
|
|
|
- transition: 0.2s;
|
|
|
- }
|
|
|
- .back-link:hover { opacity: 0.8; transform: translateY(-1px); }
|
|
|
-
|
|
|
- .theme-toggle { background: var(--card); border: 1px solid var(--border); color: var(--text); padding: 8px 12px; border-radius: 20px; cursor: pointer; font-size: 1.1rem; }
|
|
|
-
|
|
|
- .filter-bar { background: var(--card); padding: 15px; border-radius: 12px; box-shadow: 0 4px 15px rgba(0,0,0,0.05); display: flex; gap: 15px; margin-bottom: 20px; align-items: center; border: 1px solid var(--border); }
|
|
|
- select, input { padding: 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--card); color: var(--text); }
|
|
|
- input { flex-grow: 1; }
|
|
|
+ .filter-bar { background: var(--card); padding: 15px; border-radius: 12px; box-shadow: 0 4px 15px rgba(0,0,0,0.05); display: flex; gap: 15px; margin-bottom: 20px; align-items: center; border: 1px solid var(--border); flex-wrap: wrap; }
|
|
|
+ .filter-bar form { display: flex; gap: 10px; flex-grow: 1; align-items: center; }
|
|
|
+
|
|
|
+ select, input { padding: 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--card); color: var(--text); }
|
|
|
+ #searchInput { flex-grow: 1; min-width: 200px; }
|
|
|
|
|
|
table { width: 100%; border-collapse: collapse; background: var(--card); border-radius: 12px; overflow: hidden; box-shadow: 0 4px 20px rgba(0,0,0,0.08); }
|
|
|
- th { background: var(--header-bg); color: var(--header-text); text-align: left; padding: 15px; cursor: pointer; font-size: 0.8em; }
|
|
|
+ th { background: var(--header-bg); color: var(--header-text); text-align: left; padding: 15px; cursor: pointer; font-size: 0.85em; }
|
|
|
td { padding: 12px 15px; border-bottom: 1px solid var(--row-border); }
|
|
|
|
|
|
- .game-thumb { width: 55px; height: 55px; object-fit: cover; border-radius: 8px; border: 1px solid var(--border); cursor: pointer; transition: 0.2s; }
|
|
|
- .game-thumb:hover { transform: scale(1.1); border-color: #e67e22; }
|
|
|
-
|
|
|
+ .game-thumb { width: 55px; height: 55px; object-fit: cover; border-radius: 8px; border: 1px solid var(--border); cursor: pointer; }
|
|
|
.lvl-badge { padding: 4px 10px; border-radius: 20px; color: white; font-size: 11px; font-weight: bold; text-transform: uppercase; }
|
|
|
.lvl-Einsteiger { background: #27ae60; }
|
|
|
.lvl-Fortgeschrittene { background: #2980b9; }
|
|
|
.lvl-Profi { background: #c0392b; }
|
|
|
- .lvl-unknown, .badge-unknown { background: #f39c12; color: white; }
|
|
|
+ .lvl-unknown, .badge-unknown { background: #f39c12; }
|
|
|
|
|
|
.st-badge { padding: 5px 12px; border-radius: 15px; font-size: 11px; font-weight: bold; }
|
|
|
.st-besitzt { background: #d4edda; color: #155724; }
|
|
|
.dark-theme .st-besitzt { background: #1b4332; color: #74c69d; }
|
|
|
- .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); }
|
|
|
.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; }
|
|
|
</style>
|
|
|
- <script>
|
|
|
- if (localStorage.getItem('theme') === 'dark') document.documentElement.classList.add('dark-theme');
|
|
|
- </script>
|
|
|
</head>
|
|
|
<body>
|
|
|
|
|
|
@@ -102,19 +95,29 @@ $spieler = $pdo->query("SELECT * FROM spieler ORDER BY name ASC")->fetchAll();
|
|
|
<div class="header-area">
|
|
|
<h1>📝 Sammlungs-Übersicht</h1>
|
|
|
<div class="nav-group">
|
|
|
- <button onclick="toggleTheme()" class="theme-toggle" id="theme-icon">🌙</button>
|
|
|
+ <button onclick="toggleTheme()" class="theme-toggle" id="theme-icon" style="background:none; border:none; font-size:1.5rem; cursor:pointer;">🌙</button>
|
|
|
<a href="index.php" class="back-link">Dashboard</a>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="filter-bar">
|
|
|
- <form method="GET"><select name="team_filter" onchange="this.form.submit()">
|
|
|
- <option value="0">-- Alle Teams --</option>
|
|
|
- <?php foreach ($spieler as $p): ?>
|
|
|
- <option value="<?= $p['id'] ?>" <?= $filterPlayerId == $p['id'] ? 'selected' : '' ?>><?= htmlspecialchars($p['name']) ?></option>
|
|
|
- <?php endforeach; ?>
|
|
|
- </select></form>
|
|
|
- <input type="text" id="searchInput" placeholder="Suchen..." onkeyup="filterTable()">
|
|
|
+ <form method="GET" id="filterForm">
|
|
|
+ <select name="team_filter" onchange="document.getElementById('filterForm').submit()">
|
|
|
+ <option value="0">-- Alle Teams --</option>
|
|
|
+ <?php foreach ($spieler as $p): ?>
|
|
|
+ <option value="<?= $p['id'] ?>" <?= $filterPlayerId == $p['id'] ? 'selected' : '' ?>><?= htmlspecialchars($p['name']) ?></option>
|
|
|
+ <?php endforeach; ?>
|
|
|
+ </select>
|
|
|
+
|
|
|
+ <select name="typ_filter" onchange="document.getElementById('filterForm').submit()">
|
|
|
+ <option value="0">-- Alle Typen --</option>
|
|
|
+ <?php foreach ($typen as $t): ?>
|
|
|
+ <option value="<?= $t['id'] ?>" <?= $filterTypId == $t['id'] ? 'selected' : '' ?>><?= htmlspecialchars($t['bezeichnung']) ?></option>
|
|
|
+ <?php endforeach; ?>
|
|
|
+ </select>
|
|
|
+ </form>
|
|
|
+
|
|
|
+ <input type="text" id="searchInput" placeholder="Titel, EAN oder Level suchen..." onkeyup="filterTable()">
|
|
|
</div>
|
|
|
|
|
|
<table id="exitTable">
|
|
|
@@ -145,11 +148,7 @@ $spieler = $pdo->query("SELECT * FROM spieler ORDER BY name ASC")->fetchAll();
|
|
|
</td>
|
|
|
<td>
|
|
|
<strong><?= htmlspecialchars($row['titel']) ?></strong><br>
|
|
|
- <?php if($typ == 'Unbekannt'): ?>
|
|
|
- <small class="lvl-badge badge-unknown" style="padding: 1px 6px; font-size: 9px;">UNBEKANNT</small>
|
|
|
- <?php else: ?>
|
|
|
- <small style="opacity: 0.7;"><?= htmlspecialchars($typ) ?></small>
|
|
|
- <?php endif; ?>
|
|
|
+ <small style="opacity: 0.7;"><?= htmlspecialchars($typ) ?></small>
|
|
|
</td>
|
|
|
<td>
|
|
|
<span class="lvl-badge lvl-<?= $lvl ?>">
|
|
|
@@ -184,12 +183,16 @@ $spieler = $pdo->query("SELECT * FROM spieler ORDER BY name ASC")->fetchAll();
|
|
|
<img id="hoverPreview" class="image-preview" src="">
|
|
|
|
|
|
<script>
|
|
|
+ // Theme, Modal und Sortier-Funktionen bleiben wie gehabt...
|
|
|
function toggleTheme() {
|
|
|
const isDark = document.documentElement.classList.toggle('dark-theme');
|
|
|
localStorage.setItem('theme', isDark ? 'dark' : 'light');
|
|
|
document.getElementById('theme-icon').innerText = isDark ? '☀️' : '🌙';
|
|
|
}
|
|
|
- if (localStorage.getItem('theme') === 'dark') document.getElementById('theme-icon').innerText = '☀️';
|
|
|
+ if (localStorage.getItem('theme') === 'dark') {
|
|
|
+ document.documentElement.classList.add('dark-theme');
|
|
|
+ document.getElementById('theme-icon').innerText = '☀️';
|
|
|
+ }
|
|
|
|
|
|
const modal = document.getElementById("imgModal");
|
|
|
const modalImg = document.getElementById("modalContent");
|
|
|
@@ -201,7 +204,10 @@ $spieler = $pdo->query("SELECT * FROM spieler ORDER BY name ASC")->fetchAll();
|
|
|
preview.src = url; preview.style.display = 'block'; updatePos(e);
|
|
|
}
|
|
|
function hidePreview() { preview.style.display = 'none'; }
|
|
|
- function updatePos(e) { preview.style.left = (e.pageX + 20) + 'px'; preview.style.top = (e.pageY - 100) + 'px'; }
|
|
|
+ function updatePos(e) {
|
|
|
+ preview.style.left = (e.pageX + 20) + 'px';
|
|
|
+ preview.style.top = (e.pageY - 100) + 'px';
|
|
|
+ }
|
|
|
document.addEventListener('mousemove', (e) => { if(preview.style.display==='block') updatePos(e); });
|
|
|
|
|
|
function filterTable() {
|
|
|
@@ -213,40 +219,27 @@ $spieler = $pdo->query("SELECT * FROM spieler ORDER BY name ASC")->fetchAll();
|
|
|
function sortTable(n) {
|
|
|
var table = document.getElementById("exitTable");
|
|
|
var rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
|
|
|
- switching = true;
|
|
|
- dir = "asc";
|
|
|
+ switching = true; dir = "asc";
|
|
|
while (switching) {
|
|
|
- switching = false;
|
|
|
- rows = table.rows;
|
|
|
+ switching = false; rows = table.rows;
|
|
|
for (i = 1; i < (rows.length - 1); i++) {
|
|
|
shouldSwitch = false;
|
|
|
x = rows[i].getElementsByTagName("TD")[n];
|
|
|
y = rows[i + 1].getElementsByTagName("TD")[n];
|
|
|
-
|
|
|
let valX = x.innerText.toLowerCase().trim();
|
|
|
let valY = y.innerText.toLowerCase().trim();
|
|
|
-
|
|
|
- // Spezielle Logik für ID (Zahlen)
|
|
|
if (n === 0) {
|
|
|
valX = parseInt(valX.replace('#', '')) || 0;
|
|
|
valY = parseInt(valY.replace('#', '')) || 0;
|
|
|
}
|
|
|
-
|
|
|
- if (dir == "asc") {
|
|
|
- if (valX > valY) { shouldSwitch = true; break; }
|
|
|
- } else if (dir == "desc") {
|
|
|
- if (valX < valY) { shouldSwitch = true; break; }
|
|
|
- }
|
|
|
+ if (dir == "asc") { if (valX > valY) { shouldSwitch = true; break; } }
|
|
|
+ else if (dir == "desc") { if (valX < valY) { shouldSwitch = true; break; } }
|
|
|
}
|
|
|
if (shouldSwitch) {
|
|
|
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
|
|
|
- switching = true;
|
|
|
- switchcount ++;
|
|
|
+ switching = true; switchcount ++;
|
|
|
} else {
|
|
|
- if (switchcount == 0 && dir == "asc") {
|
|
|
- dir = "desc";
|
|
|
- switching = true;
|
|
|
- }
|
|
|
+ if (switchcount == 0 && dir == "asc") { dir = "desc"; switching = true; }
|
|
|
}
|
|
|
}
|
|
|
}
|