diff --git a/README.md b/README.md index 311b88c..264b642 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/html/assets/css/style.css b/html/assets/css/style.css index a40dabc..bced8d3 100644 --- a/html/assets/css/style.css +++ b/html/assets/css/style.css @@ -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; diff --git a/html/dashboard.php b/html/dashboard.php index 88b6d09..592388d 100644 --- a/html/dashboard.php +++ b/html/dashboard.php @@ -191,7 +191,7 @@ sort($filterZahlweise, SORT_STRING | SORT_FLAG_CASE); - + @@ -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.')); + }); + }); +})(); diff --git a/html/toggle_abgeglichen.php b/html/toggle_abgeglichen.php new file mode 100644 index 0000000..a246c2e --- /dev/null +++ b/html/toggle_abgeglichen.php @@ -0,0 +1,52 @@ + 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() + ]); +} diff --git a/migrations/0001_add_abgeglichen.sql b/migrations/0001_add_abgeglichen.sql new file mode 100644 index 0000000..0c0e012 --- /dev/null +++ b/migrations/0001_add_abgeglichen.sql @@ -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;