Spaltenfilter im Dashboard hinzugefügt, Docker-Dateien in .gitignore aufgenommen

Jede Tabellenspalte im Dashboard bekommt eine eigene Filterzeile (Text- oder
Dropdown-Filter je nach Spalte), die die sichtbaren Einträge clientseitig
per JS einschränkt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
fds2610-bot 2026-07-23 15:30:16 +02:00
parent 97c7fd73e0
commit d63b3d86d2
3 changed files with 127 additions and 1 deletions

2
.gitignore vendored
View file

@ -4,4 +4,6 @@ info.php
config.php
*.old
html/.Trash-1000
Dockerfile
docker-compose.yml

View file

@ -326,6 +326,31 @@ tr:hover {
display: inline-block;
}
/* Spaltenfilter im Tabellenkopf */
tr.filter-row th {
background: white;
padding: 6px 8px;
text-transform: none;
letter-spacing: normal;
font-weight: normal;
}
.column-filter {
width: 100%;
box-sizing: border-box;
padding: 6px 8px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 0.85em;
color: #333;
background: white;
}
.column-filter:focus {
outline: none;
border-color: var(--primary-color);
}
/* Button */
.btn-xr {

View file

@ -70,6 +70,39 @@ $stmt->execute([
'month' => $month
]);
$entries = $stmt->fetchAll();
// Eindeutige Werte für die Filter-Dropdowns ermitteln
$filterZahler = [];
$filterPersonen = [];
$filterKategorie = [];
$filterZahlweise = [];
foreach ($entries as $entry) {
if (!empty($entry['zahler'])) {
$filterZahler[$entry['zahler']] = true;
}
if (!empty($entry['personen'])) {
foreach (explode(',', $entry['personen']) as $person) {
$person = trim($person);
if ($person !== '') {
$filterPersonen[$person] = true;
}
}
}
if (!empty($entry['kategorie'])) {
$filterKategorie[$entry['kategorie']] = true;
}
if (!empty($entry['zahlweise'])) {
$filterZahlweise[$entry['zahlweise']] = true;
}
}
$filterZahler = array_keys($filterZahler);
$filterPersonen = array_keys($filterPersonen);
$filterKategorie = array_keys($filterKategorie);
$filterZahlweise = array_keys($filterZahlweise);
sort($filterZahler, SORT_STRING | SORT_FLAG_CASE);
sort($filterPersonen, SORT_STRING | SORT_FLAG_CASE);
sort($filterKategorie, SORT_STRING | SORT_FLAG_CASE);
sort($filterZahlweise, SORT_STRING | SORT_FLAG_CASE);
?>
<!DOCTYPE html>
<html lang="de">
@ -116,8 +149,47 @@ $entries = $stmt->fetchAll();
<th class="hide-on-mobile">Hinweis</th>
<th>&nbsp;</th>
</tr>
<tr class="filter-row">
<th><input type="text" class="column-filter" data-col="0" placeholder="Filter…"></th>
<th class="hide-on-mobile">
<select class="column-filter" data-col="1">
<option value="">Alle</option>
<?php foreach ($filterZahler as $wert): ?>
<option value="<?= htmlspecialchars($wert) ?>"><?= htmlspecialchars($wert) ?></option>
<?php endforeach; ?>
</select>
</th>
<th class="hide-on-mobile">
<select class="column-filter" data-col="2">
<option value="">Alle</option>
<?php foreach ($filterPersonen as $wert): ?>
<option value="<?= htmlspecialchars($wert) ?>"><?= htmlspecialchars($wert) ?></option>
<?php endforeach; ?>
</select>
</th>
<th class="hide-on-mobile">
<select class="column-filter" data-col="3">
<option value="">Alle</option>
<?php foreach ($filterKategorie as $wert): ?>
<option value="<?= htmlspecialchars($wert) ?>"><?= htmlspecialchars($wert) ?></option>
<?php endforeach; ?>
</select>
</th>
<th>
<select class="column-filter" data-col="4">
<option value="">Alle</option>
<?php foreach ($filterZahlweise as $wert): ?>
<option value="<?= htmlspecialchars($wert) ?>"><?= htmlspecialchars($wert) ?></option>
<?php endforeach; ?>
</select>
</th>
<th><input type="text" class="column-filter" data-col="5" placeholder="Filter…"></th>
<th><input type="text" class="column-filter" data-col="6" placeholder="Filter…"></th>
<th class="hide-on-mobile"><input type="text" class="column-filter" data-col="7" placeholder="Filter…"></th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
<tbody id="entries-body">
<?php foreach ($entries as $entry): ?>
<tr>
<td><?= htmlspecialchars($entry['date']) ?></td>
@ -147,6 +219,33 @@ $entries = $stmt->fetchAll();
document.querySelector('.hamburger').addEventListener('click', function() {
document.querySelector('.nav-list').classList.toggle('show');
});
// Spaltenfilter für die Tabelle
(function() {
const filters = document.querySelectorAll('.column-filter');
const rows = document.querySelectorAll('#entries-body tr');
function applyFilters() {
const activeFilters = Array.from(filters)
.map(f => ({ col: parseInt(f.dataset.col, 10), value: f.value.trim().toLowerCase() }))
.filter(f => f.value !== '');
rows.forEach(row => {
const cells = row.children;
const visible = activeFilters.every(f => {
const cell = cells[f.col];
if (!cell) return true;
return cell.textContent.trim().toLowerCase().includes(f.value);
});
row.style.display = visible ? '' : 'none';
});
}
filters.forEach(f => {
f.addEventListener('input', applyFilters);
f.addEventListener('change', applyFilters);
});
})();
</script>
</body>
</html>