Feature: abgeglichen-Feld pro Buchungszeile (Issue #8)

Buchungszeilen bekommen ein neues, boolesches Feld "abgeglichen"
(Standard: false). Ein Klick auf eine Zeile im Dashboard schaltet den
Wert per AJAX sofort um; abgeglichene Zeilen werden grün hinterlegt.
This commit is contained in:
fds2610-bot 2026-07-26 12:33:23 +02:00
parent 878e26ff46
commit 91adeac26c
5 changed files with 96 additions and 1 deletions

View file

@ -8,6 +8,10 @@ Dokumentiere Ausgaben on-the-go als Webapp
- [ ] Zusammenfassen von mehreren Einträgen zu einer Aktie
- [ ] Prüfen ob APIKEYS leer sind und ggfs die Aktualisierung ausblenden
## V.2.4
- [X] Buchungszeilen im Dashboard haben ein zusätzliches Feld "abgeglichen" (Standard: nicht abgeglichen). Ein Klick auf die Zeile schaltet den Wert um und speichert ihn sofort in der DB. Abgeglichene Zeilen werden mit grünem Hintergrund dargestellt.
## V.2.3
- [X] Listen mit Spaltenfiltern (Dashboard) zeigen unterhalb eine optisch abgesetzte Summenzeile, die die Beträge der aktuell sichtbaren (gefilterten) Einträge in der Spalte "Betrag" aufsummiert.

View file

@ -326,6 +326,15 @@ tr:hover {
display: inline-block;
}
/* Abgeglichene Buchungszeilen */
tr.entry-row {
cursor: pointer;
}
tr.entry-row.abgeglichen td {
background-color: #d4edda;
}
/* Spaltenfilter im Tabellenkopf */
tr.filter-row th {
background: white;

View file

@ -191,7 +191,7 @@ sort($filterZahlweise, SORT_STRING | SORT_FLAG_CASE);
</thead>
<tbody id="entries-body">
<?php foreach ($entries as $entry): ?>
<tr>
<tr class="entry-row<?= !empty($entry['abgeglichen']) ? ' abgeglichen' : '' ?>" data-id="<?= $entry['id'] ?>">
<td><?= htmlspecialchars($entry['date']) ?></td>
<td class="hide-on-mobile"><?= htmlspecialchars($entry['zahler'] ?? '') ?></td>
<td class="hide-on-mobile"><?= htmlspecialchars($entry['personen'] ?? '') ?></td>
@ -275,6 +275,33 @@ document.querySelector('.hamburger').addEventListener('click', function() {
applyFilters();
})();
// Abgeglichen-Status per Klick auf die Buchungszeile umschalten
(function() {
document.querySelectorAll('#entries-body tr.entry-row').forEach(function(row) {
row.addEventListener('click', function(e) {
if (e.target.closest('a')) return; // Klick auf Bearbeiten-Link nicht abfangen
const id = row.dataset.id;
if (!id) return;
fetch('toggle_abgeglichen.php', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ id: id })
})
.then(res => res.json())
.then(data => {
if (data.success) {
row.classList.toggle('abgeglichen', data.abgeglichen);
} else {
alert('Fehler: ' + data.message);
}
})
.catch(() => alert('Fehler beim Speichern.'));
});
});
})();
</script>
</body>
</html>

View file

@ -0,0 +1,52 @@
<?php
require 'config.php';
header('Content-Type: application/json');
if (!isset($_SESSION['user_id'])) {
http_response_code(401);
echo json_encode([
'success' => false,
'message' => 'Nicht angemeldet.'
]);
exit;
}
// JSON-Input einlesen
$data = json_decode(file_get_contents('php://input'), true);
$id = $data['id'] ?? null;
// Input validieren
if (!is_numeric($id)) {
echo json_encode([
'success' => false,
'message' => 'Ungültige Eingabedaten.'
]);
exit;
}
try {
$stmt = $pdo->prepare("UPDATE entries SET abgeglichen = NOT abgeglichen WHERE id = :id");
$stmt->execute(['id' => (int)$id]);
if ($stmt->rowCount() === 0) {
echo json_encode([
'success' => false,
'message' => 'Eintrag nicht gefunden.'
]);
exit;
}
$stmtRead = $pdo->prepare("SELECT abgeglichen FROM entries WHERE id = :id");
$stmtRead->execute(['id' => (int)$id]);
$abgeglichen = (bool)$stmtRead->fetchColumn();
echo json_encode([
'success' => true,
'abgeglichen' => $abgeglichen
]);
} catch (PDOException $e) {
echo json_encode([
'success' => false,
'message' => 'Datenbankfehler: ' . $e->getMessage()
]);
}

View file

@ -0,0 +1,3 @@
-- Feature: zusätzliches Feld "abgeglichen" pro Buchungszeile (Issue #8).
-- Neue Buchungszeilen sind per DEFAULT nicht abgeglichen (false).
ALTER TABLE entries ADD COLUMN IF NOT EXISTS abgeglichen TINYINT(1) NOT NULL DEFAULT 0;