FSCash/html/dashboard.php
fds2610-bot cd9477dc7c Dashboard: Summenzeile unterhalb der gefilterten Liste ergänzen
Fügt eine optisch abgesetzte Summenzeile unter der Dashboard-Tabelle
hinzu, die die Beträge der aktuell sichtbaren (per Spaltenfilter
gefilterten) Einträge summiert und live aktualisiert.

Schließt #6

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 12:22:26 +02:00

280 lines
9.2 KiB
PHP

<?php
require 'config.php';
require_once 'lib/fscash.php';
error_log('Session user_id: ' . (isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 'nicht gesetzt'));
// 1. Session-Prüfung (nur für geschützte Seiten)
if (!isset($_SESSION['user_id'])) {
header('Location: index.php');
exit;
}
// Ab hier: Nur für angemeldete Benutzer
error_log($_SESSION['user_id']);
// Rollen des angemeldeten Benutzers ermitteln
$roles = fscash_user_roles((int)$_SESSION['user_id'], $admin_ids, $aktien_ids);
if ($roles['is_admin']) {
$is_admin = "true";
}
if ($roles['is_aktien']) {
$is_aktien = "true";
}
// Aktuelles Jahr und Monat ermitteln, ggf. aus GET-Parametern
$year = isset($_GET['year']) ? (int)$_GET['year'] : (int)date('Y');
$month = isset($_GET['month']) ? (int)$_GET['month'] : (int)date('m');
// Monats- und Jahresgrenzen prüfen und anpassen
['month' => $month, 'year' => $year] = fscash_normalize_month_year($month, $year);
// Daten abrufen
$sql="WITH user_names AS (
SELECT
p.id,
b_single.username AS zahler,
GROUP_CONCAT(b_array.username) AS personen
FROM
entries p
LEFT JOIN users b_single ON p.user_id = b_single.id
JOIN JSON_TABLE(p.person, '$[*]' COLUMNS(id INT PATH '$')) AS jt
LEFT JOIN users b_array ON jt.id = b_array.id
GROUP BY
p.id, b_single.username
)
SELECT
e.*,
un.zahler,
un.personen,
c.name AS kategorie,
pm.name AS zahlweise
FROM
entries e
JOIN user_names un ON e.id = un.id
LEFT JOIN categories c ON e.category = c.category_id
LEFT JOIN payment_methods pm ON e.payment_method = pm.payment_method_id
WHERE
EXTRACT(YEAR FROM e.date) = :year
AND EXTRACT(MONTH FROM e.date) = :month
ORDER BY
e.date DESC, id desc;
";
$stmt = $pdo->prepare($sql);
$stmt->execute([
'year' => $year,
'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;
}
}
// Vorauswahl der Filter aus GET-Parametern (z. B. Link aus einem Report)
$presetZahler = isset($_GET['zahler']) ? $_GET['zahler'] : '';
$presetKategorie = isset($_GET['kategorie']) ? $_GET['kategorie'] : '';
$presetKategorien = isset($_GET['kategorien']) && is_array($_GET['kategorien']) ? $_GET['kategorien'] : [];
$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">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=0.8">
<title>FSCash - Dashboard</title>
<link rel="stylesheet" href="assets/css/style.css">
</head>
<body>
<div class="container">
<!-- Navigation -->
<nav class="nav">
<button class="hamburger">☰</button>
<ul class="nav-list">
<li><a href="dashboard.php">Start</a></li>
<?php if ($is_aktien === "true") echo '<li><a href="aktien.php">Aktien</a></li>'; ?>
<?php if ($is_admin === "true") echo '<li><a href="register.php">Neue User</a></li>'; ?>
<li><a href="rep-month.php">Report Monat</a></li>
<li><a href="rep-person.php">Report Personen</a></li>
<li><a href="menu5.php" style="display: none;">Menüpunkt 5</a></li>
</ul>
<!-- Container für die rechten Buttons -->
<div class="nav-right">
<a href="?year=<?= $year ?>&month=<?= $month - 1 ?>" class="nav-button"> &lt; </a>
<a href="?year=<?= $year ?>&month=<?= $month + 1 ?>" class="nav-button"> &gt; </a>
<a href="logout.php" class="logout">Logout</a>
</div>
</nav>
<h2><?= strftime('%B %Y', mktime(0, 0, 0, $month, 1, $year)) ?></h2>
<!-- Tabelle -->
<table>
<thead>
<tr>
<th>Datum</th>
<th class="hide-on-mobile">Zahler</th>
<th class="hide-on-mobile">Person</th>
<th class="hide-on-mobile">Kategorie</th>
<th>Zahlweise</th>
<th>Betreff</th>
<th>Betrag</th>
<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) ?>" <?= $wert === $presetZahler ? 'selected' : '' ?>><?= 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) ?>" <?= $wert === $presetKategorie ? 'selected' : '' ?>><?= 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 id="entries-body">
<?php foreach ($entries as $entry): ?>
<tr>
<td><?= htmlspecialchars($entry['date']) ?></td>
<td class="hide-on-mobile"><?= htmlspecialchars($entry['zahler'] ?? '') ?></td>
<td class="hide-on-mobile"><?= htmlspecialchars($entry['personen'] ?? '') ?></td>
<td class="hide-on-mobile"><?= htmlspecialchars($entry['kategorie'] ?? '') ?></td>
<td><?= htmlspecialchars($entry['zahlweise'] ?? '') ?></td>
<td><?= htmlspecialchars($entry['subject']) ?></td>
<td class="align-right" data-amount="<?= htmlspecialchars($entry['amount']) ?>"><?= htmlspecialchars( number_format($entry['amount'], 2, ',', '.')) ?></td>
<td class="hide-on-mobile"><?= htmlspecialchars($entry['note']) ?></td>
<td class="hide-on-mobile">
<a href="edit_entry.php?id=<?= $entry['id'] ?>">
<img class="pencil" src="/assets/img/pencil.png" width="20px" />
</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot>
<tr class="sum-row">
<td>Summe</td>
<td class="hide-on-mobile"></td>
<td class="hide-on-mobile"></td>
<td class="hide-on-mobile"></td>
<td></td>
<td></td>
<td class="align-right" id="sum-value">0,00</td>
<td class="hide-on-mobile"></td>
<td></td>
</tr>
</tfoot>
</table>
<!-- Neu-Button -->
<a href="new_entry.php" class="btn-xr">+</a>
</div>
<script>
// Hamburger-Menü-Funktion
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');
const sumValue = document.getElementById('sum-value');
// Mehrfach-Kategorie-Vorauswahl, z. B. per Link aus dem Personenreport (Kategorie-Select kann nur einen Wert anzeigen)
const presetKategorien = <?= json_encode(array_map('strtolower', $presetKategorien)) ?>;
function applyFilters() {
const activeFilters = Array.from(filters)
.map(f => ({ col: parseInt(f.dataset.col, 10), value: f.value.trim().toLowerCase() }))
.filter(f => f.value !== '');
let sum = 0;
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);
}) && (presetKategorien.length === 0 || (cells[3] && presetKategorien.includes(cells[3].textContent.trim().toLowerCase())));
row.style.display = visible ? '' : 'none';
if (visible) {
const amountCell = cells[6];
if (amountCell) {
sum += parseFloat(amountCell.dataset.amount) || 0;
}
}
});
if (sumValue) {
sumValue.textContent = sum.toLocaleString('de-DE', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
}
filters.forEach(f => {
f.addEventListener('input', applyFilters);
f.addEventListener('change', applyFilters);
});
applyFilters();
})();
</script>
</body>
</html>