From 932d17c128b5f2492c1459d89dafeb59427c0d72 Mon Sep 17 00:00:00 2001 From: fds2610-bot Date: Thu, 1 Oct 2026 09:50:08 +0200 Subject: [PATCH] =?UTF-8?q?Fix=20n.n.:=20=E2=80=9E+=20Neu=E2=80=9C=20?= =?UTF-8?q?=C3=B6ffnet=20das=20Formular=20zur=20Neuanlage=20als=20modalen?= =?UTF-8?q?=20Dialog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Elf Listenansichten (Klassen, Buchungsvorlagen, Regelmäßige Buchungen, Erinnerungen, Verträge, Adressen, Sparziele, Kredite, Abgleichregeln, Budgets, Berichtsgruppen) zeigten das Formular unter der Liste. Jetzt öffnet der Knopf „+ Neu“ es als Dialog. Co-Authored-By: Claude Sonnet 5.5 --- Changes.md | 5 + public/static/app.css | 13 +++ public/static/app.js | 14 +++ src/Views/auswertungen/gruppen.php | 6 +- src/Views/banking/regeln.php | 22 ++-- src/Views/planung/budget-verwaltung.php | 42 ++++---- src/Views/termine/erinnerungen.php | 33 +++--- src/Views/termine/index.php | 125 +++++++++++---------- src/Views/vertraege/adressen.php | 97 +++++++++-------- src/Views/vertraege/index.php | 137 +++++++++++++----------- src/Views/vertraege/kredite.php | 99 +++++++++-------- src/Views/vertraege/sparziele.php | 79 +++++++------- src/Views/verwaltung/klassen.php | 26 +++-- src/Views/vorlagen/index.php | 79 +++++++------- tests/e2e/specs/buchungen.spec.js | 3 +- tests/e2e/specs/module.spec.js | 6 +- tests/e2e/specs/neudialog.spec.js | 60 +++++++++++ tests/e2e/specs/planung.spec.js | 1 + tests/e2e/specs/stammdaten.spec.js | 3 +- 19 files changed, 505 insertions(+), 345 deletions(-) create mode 100644 tests/e2e/specs/neudialog.spec.js diff --git a/Changes.md b/Changes.md index c181e87..a261f6b 100644 --- a/Changes.md +++ b/Changes.md @@ -1,5 +1,10 @@ # Änderungen +## „+ Neu“ öffnet das Formular als Dialog (01.10.2026) + +- Das Formular zur Neuanlage stand in elf Ansichten unter der Liste. Jetzt öffnet der Knopf „+ Neu“ es als modalen Dialog (`app.js`, `.neudialog`); nach dem Speichern erscheint die Liste wieder, mit dem neuen Eintrag. Betroffen: Klassen, Buchungsvorlagen, Regelmäßige Buchungen, Erinnerungen, Verträge, Adressen, Sparziele, Kredite, Abgleichregeln, Budgets, Berichtsgruppen. +- E2E: `neudialog.spec.js`; bestehende Specs öffnen den Dialog zuerst. + ## Regelmäßige Buchungen: Klick zum Bearbeiten (01.10.2026) - In „Alle Reihen“ erscheinen alle Felder zunächst als Text und werden erst beim Anklicken zum Eingabefeld (`reihenliste.js`). Ja/Nein-Felder schalten per Klick um, „Speichern“ erscheint erst nach einer Änderung. Konto und Klasse stehen untereinander, die Spalte Name/Buchungstext nimmt den freien Platz. diff --git a/public/static/app.css b/public/static/app.css index 5093ecc..58af625 100644 --- a/public/static/app.css +++ b/public/static/app.css @@ -1289,6 +1289,19 @@ table.splittabelle input.rechts { text-align: right; } „Speichern“ und „Abbrechen“, damit es nicht im Vorbeigehen getroffen wird. */ .splitdialog .knopfleiste .knopf.gefahr { margin-left: auto; } +/* „+ Neu“ in den Listenansichten: Das Formular zur Neuanlage liegt in einem + modalen Dialog, den der Knopf öffnet. Der Dialog trägt den Rahmen, das + Formular darin braucht ihn nicht noch einmal. */ +.neudialog { max-height: 92vh; overflow-y: auto; } + +.neudialog .formular.breit { + max-width: none; + padding: 0; + border: 0; + box-shadow: none; + background: none; +} + /* Die Formatwahl vor Import und Export – als Dialog auf der Verwaltungsseite und als Kachelinhalt auf der Ausweichseite, deshalb zwei Ebenen: der Dialog trägt den Rahmen, .formatwahl die Karten. */ diff --git a/public/static/app.js b/public/static/app.js index 9231e70..9847c97 100644 --- a/public/static/app.js +++ b/public/static/app.js @@ -314,6 +314,20 @@ }); }); + // „+ Neu“ in den Listenansichten: Der Knopf öffnet den Dialog mit dem + // Formular zur Neuanlage. Gespeichert wird per Formularversand; die Ansicht + // lädt danach neu und zeigt die Liste samt neuem Eintrag. + document.querySelectorAll('[data-neudialog]').forEach(function (knopf) { + knopf.addEventListener('click', function () { + const dialog = document.getElementById(knopf.dataset.neudialog); + if (dialog && typeof dialog.showModal === 'function') { + dialog.showModal(); + const feld = dialog.querySelector('input:not([type=hidden]), select, textarea'); + if (feld) { feld.focus(); } + } + }); + }); + // Übermittlungsprotokoll im Zahlungsverkehr: Ein Klick auf den Status holt das // Protokoll der Überweisung in einen modalen Dialog. Ohne oder // fetch bleibt der Status ein Link auf dieselbe Ansicht als eigene Seite. diff --git a/src/Views/auswertungen/gruppen.php b/src/Views/auswertungen/gruppen.php index da55cc3..5122814 100644 --- a/src/Views/auswertungen/gruppen.php +++ b/src/Views/auswertungen/gruppen.php @@ -19,6 +19,7 @@ include __DIR__ . '/../layout/kopf.php';
+ Zur Übersicht
@@ -28,7 +29,7 @@ include __DIR__ . '/../layout/kopf.php'; und rücken unter „Nicht gruppiert“.

-
+

Neue Berichtsgruppe

@@ -39,8 +40,9 @@ include __DIR__ . '/../layout/kopf.php'; +
-
+
$eintrag['gruppe'] !== null); diff --git a/src/Views/banking/regeln.php b/src/Views/banking/regeln.php index 3c33a53..7e373f5 100644 --- a/src/Views/banking/regeln.php +++ b/src/Views/banking/regeln.php @@ -27,6 +27,7 @@ include __DIR__ . '/../layout/kopf.php';

+
-
- +
+ + +
+ + diff --git a/src/Views/planung/budget-verwaltung.php b/src/Views/planung/budget-verwaltung.php index 5222783..add1fd6 100644 --- a/src/Views/planung/budget-verwaltung.php +++ b/src/Views/planung/budget-verwaltung.php @@ -11,6 +11,7 @@ include __DIR__ . '/../layout/kopf.php'; @@ -66,27 +67,28 @@ include __DIR__ . '/../layout/kopf.php'; + +

Neues Budget

+
+ + + + + + + + + + + +
+ + +
+
+
+
-
-

Neues Budget

-
- - - - - - - - - - - -
- -
-
-
-

Budget kopieren

diff --git a/src/Views/termine/erinnerungen.php b/src/Views/termine/erinnerungen.php index d853668..0c6b4e6 100644 --- a/src/Views/termine/erinnerungen.php +++ b/src/Views/termine/erinnerungen.php @@ -22,6 +22,10 @@ include __DIR__ . '/../layout/kopf.php'; kündigen“, „Steuerbescheid prüfen“. Offene Erinnerungen erscheinen im Finanzkalender.

+
+ +
+

Keine Erinnerungen.

@@ -65,22 +69,25 @@ include __DIR__ . '/../layout/kopf.php'; -
- -

Neue Erinnerung

+ + + +

Neue Erinnerung

- - + + - - + + - - + + -
- -
- +
+ + +
+ +
diff --git a/src/Views/termine/index.php b/src/Views/termine/index.php index 6cf3735..9dfc497 100644 --- a/src/Views/termine/index.php +++ b/src/Views/termine/index.php @@ -23,6 +23,10 @@ include __DIR__ . '/../layout/kopf.php'; Erinnerungen
+
+ +
+ 0): ?>
@@ -217,78 +221,81 @@ include __DIR__ . '/../layout/kopf.php'; -
- -

Neue regelmäßige Buchung

+ + + +

Neue regelmäßige Buchung

- - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - -

- Ohne Haken meldet sich die Reihe nur und wartet auf Bestätigung – richtig überall - dort, wo der Betrag schwankt. -

+ +

+ Ohne Haken meldet sich die Reihe nur und wartet auf Bestätigung – richtig überall + dort, wo der Betrag schwankt. +

- + -
- -
- +
+ + +
+ +
diff --git a/src/Views/vertraege/adressen.php b/src/Views/vertraege/adressen.php index 860deee..5dba0e4 100644 --- a/src/Views/vertraege/adressen.php +++ b/src/Views/vertraege/adressen.php @@ -25,6 +25,10 @@ include __DIR__ . '/../layout/kopf.php'; hinausgeht.

+
+ +
+
- - -

Neue Adresse

+ + + +

Neue Adresse

- - + + - - + + - - + + -
-
- - +
+
+ + +
+
+ + +
+
+ + +
-
- - + + + + + + + +
+
+ + +
+
+ + +
-
- - + + + + +
+ +
-
- - - - - - - -
-
- - -
-
- - -
-
- - - - -
- -
- + +
diff --git a/src/Views/vertraege/index.php b/src/Views/vertraege/index.php index 0360ee3..e1e143c 100644 --- a/src/Views/vertraege/index.php +++ b/src/Views/vertraege/index.php @@ -23,6 +23,10 @@ include __DIR__ . '/../layout/kopf.php'; Kredite
+
+ +
+

Kündigungsfristen laufen ab

@@ -131,80 +135,83 @@ include __DIR__ . '/../layout/kopf.php'; -
- -

Neuer Vertrag

+ + + +

Neuer Vertrag

- - + + - - + + - - + + - - + + - - + + - - + + - - + + -
-
- - +
+
+ + +
+
+ + +
+
+ + +
-
- - + + + + + + + + + +
+ +
-
- - -
-
- - - - - - - - - -
- -
- + +
diff --git a/src/Views/vertraege/kredite.php b/src/Views/vertraege/kredite.php index 6f01939..fcd0f45 100644 --- a/src/Views/vertraege/kredite.php +++ b/src/Views/vertraege/kredite.php @@ -21,6 +21,10 @@ include __DIR__ . '/../layout/kopf.php'; Kredite
+
+ +
+ @@ -201,58 +205,61 @@ include __DIR__ . '/../layout/kopf.php'; - - -

Neuer Kredit

-

- Gerechnet wird als Annuitätendarlehen: gleichbleibende Rate, sinkender Zinsanteil. - Der Tilgungsplan entsteht aus diesen Angaben und wird nicht gespeichert. -

+ + + +

Neuer Kredit

+

+ Gerechnet wird als Annuitätendarlehen: gleichbleibende Rate, sinkender Zinsanteil. + Der Tilgungsplan entsteht aus diesen Angaben und wird nicht gespeichert. +

- - + + -
-
- - +
+
+ + +
+
+ + +
+
+ + +
-
- - -
-
- - -
-
-
-
- - +
+
+ + +
+
+ + +
+
+ + +
-
- - -
-
- - -
-
- + -
- -
- +
+ + +
+ +
diff --git a/src/Views/vertraege/sparziele.php b/src/Views/vertraege/sparziele.php index d584c88..3248c75 100644 --- a/src/Views/vertraege/sparziele.php +++ b/src/Views/vertraege/sparziele.php @@ -24,6 +24,10 @@ include __DIR__ . '/../layout/kopf.php'; auf dem Konto lag.

+
+ +
+

Noch kein Sparziel angelegt.

@@ -93,46 +97,49 @@ include __DIR__ . '/../layout/kopf.php'; - - -

Neues Sparziel

+ + + +

Neues Sparziel

- - + + - - -

Der Stand des Ziels ist der Saldo dieses Kontos.

+ + +

Der Stand des Ziels ist der Saldo dieses Kontos.

-
-
- - +
+
+ + +
+
+ + +
+
+ + +
-
- - + + + + + + + +
+ +
-
- - -
-
- - - - - - - -
- -
- + +
diff --git a/src/Views/verwaltung/klassen.php b/src/Views/verwaltung/klassen.php index c2eade7..d26ea2b 100644 --- a/src/Views/verwaltung/klassen.php +++ b/src/Views/verwaltung/klassen.php @@ -9,6 +9,7 @@ include __DIR__ . '/../layout/kopf.php'; ?> @@ -69,19 +70,22 @@ include __DIR__ . '/../layout/kopf.php';
-
- -

Neue Klasse

+ + + +

Neue Klasse

- - + + - - + + -
- -
- +
+ + +
+ +
diff --git a/src/Views/vorlagen/index.php b/src/Views/vorlagen/index.php index 14bd251..2578866 100644 --- a/src/Views/vorlagen/index.php +++ b/src/Views/vorlagen/index.php @@ -27,6 +27,10 @@ include __DIR__ . '/../layout/kopf.php'; die Splitzeilen im gleichen Verhältnis mitgezogen.

+
+ +
+
- - -

Neue Vorlage

+ + + +

Neue Vorlage

- - + + - - + + - - + + - - + + - - + + - - + + - - + + -
- -
- +
+ + +
+ +
diff --git a/tests/e2e/specs/buchungen.spec.js b/tests/e2e/specs/buchungen.spec.js index f879f25..0553a91 100644 --- a/tests/e2e/specs/buchungen.spec.js +++ b/tests/e2e/specs/buchungen.spec.js @@ -54,8 +54,9 @@ test.describe('Buchungen', () => { await page.click('.formular button[type="submit"]') await page.goto('/verwaltung/klassen') + await page.click('#neu-knopf') await page.fill('form[action="/verwaltung/klassen/neu"] #name', KLASSE) - await page.click('form[action="/verwaltung/klassen/neu"] button[type="submit"]') + await page.click('form[action="/verwaltung/klassen/neu"] button.primaer') await page.close() }) diff --git a/tests/e2e/specs/module.spec.js b/tests/e2e/specs/module.spec.js index ff3b5b8..0d32552 100644 --- a/tests/e2e/specs/module.spec.js +++ b/tests/e2e/specs/module.spec.js @@ -201,6 +201,7 @@ test.describe('Module der Phasen 4 bis 7', () => { test('Eine falsche IBAN wird beim Anlegen einer Adresse abgewiesen', async ({ page }) => { await page.goto('/vertraege/adressen') + await page.click('#neu-knopf') await page.fill('#name', 'E2E-Falschtest') await page.fill('#iban', 'DE02120300000000202052') @@ -211,6 +212,7 @@ test.describe('Module der Phasen 4 bis 7', () => { test('Ein Kredit zeigt seinen gerechneten Tilgungsplan', async ({ page }) => { await page.goto('/vertraege/kredite') + await page.click('#neu-knopf') await page.fill('#name', 'E2E-Darlehen') await page.fill('#darlehensbetrag', '100000') @@ -314,10 +316,11 @@ test.describe('Module der Phasen 4 bis 7', () => { test('Regelmäßige Buchungen werden per Klick bearbeitbar', async ({ page }) => { await page.goto('/termine') + await page.click('#neu-knopf') await page.fill('#name', 'E2E-Reihe') await page.fill('#neu_betrag', '-12,50') await page.fill('#neu_buchungstext', 'E2E-Text') - await page.click('form[action="/termine/neu"] button[type="submit"]') + await page.click('form[action="/termine/neu"] button.primaer') const zeile = page.locator('table.reihen tr', { hasText: 'E2E-Reihe' }) await expect(zeile.locator('input[name="betrag"]')).toBeHidden() @@ -398,6 +401,7 @@ test.describe('Module der Phasen 4 bis 7', () => { // Erst eine Adresse anlegen, damit die Auswahl etwas zu bieten hat. await page.goto('/vertraege/adressen') + await page.click('#neu-knopf') await page.fill('#name', empfaenger) await page.fill('#iban', 'DE02120300000000202051') await page.click('button:has-text("Adresse anlegen")') diff --git a/tests/e2e/specs/neudialog.spec.js b/tests/e2e/specs/neudialog.spec.js new file mode 100644 index 0000000..4f706d9 --- /dev/null +++ b/tests/e2e/specs/neudialog.spec.js @@ -0,0 +1,60 @@ +// @ts-check +const { test, expect } = require('@playwright/test') + +const BENUTZER = process.env.E2E_USER || 'e2e' +const PASSWORT = process.env.E2E_PASSWORD || 'e2e-testpasswort' +const MARKE = Date.now().toString().slice(-6) + +// Alle Listenansichten, in denen „+ Neu“ ein modales Formular zur Neuanlage öffnet. +const ANSICHTEN = [ + '/verwaltung/klassen', + '/vorlagen', + '/termine', + '/termine/erinnerungen', + '/vertraege', + '/vertraege/adressen', + '/vertraege/sparziele', + '/vertraege/kredite', + '/banking/regeln', + '/planung/budget/verwaltung', + '/auswertungen/gruppen', +] + +async function anmelden(page) { + await page.goto('/login') + await page.fill('#benutzername', BENUTZER) + await page.fill('#passwort', PASSWORT) + await page.click('button[type="submit"]') + await expect(page).toHaveURL(/\/$/) +} + +test.describe('„+ Neu“ öffnet den Dialog zur Neuanlage', () => { + test.beforeEach(async ({ page }) => { + await anmelden(page) + }) + + for (const pfad of ANSICHTEN) { + test(`${pfad}: Dialog erst nach Klick, Abbrechen schließt ihn`, async ({ page }) => { + await page.goto(pfad) + + await expect(page.locator('#neudialog')).toBeHidden() + await page.click('#neu-knopf') + await expect(page.locator('#neudialog')).toBeVisible() + + await page.locator('#neudialog button', { hasText: 'Abbrechen' }).click() + await expect(page.locator('#neudialog')).toBeHidden() + }) + } + + test('Klasse anlegen: Dialog verschwindet, Eintrag steht in der Liste', async ({ page }) => { + const name = `E2E Dialogklasse ${MARKE}` + + await page.goto('/verwaltung/klassen') + await page.click('#neu-knopf') + await page.fill('#neudialog #name', name) + await page.locator('#neudialog button[type="submit"]', { hasText: 'Klasse anlegen' }).click() + + await expect(page.locator('#neudialog')).toBeHidden() + await expect(page.locator(`input[value="${name}"]`).first()).toBeVisible() + }) +}) diff --git a/tests/e2e/specs/planung.spec.js b/tests/e2e/specs/planung.spec.js index c23c7b3..761450c 100644 --- a/tests/e2e/specs/planung.spec.js +++ b/tests/e2e/specs/planung.spec.js @@ -35,6 +35,7 @@ async function anmelden(page) { */ async function budgetAnlegen(page, name) { await page.goto('/planung/budget/verwaltung') + await page.click('#neu-knopf') await page.fill('#name', name) await page.fill('#jahr', String(JAHR)) await page.click('.formular button:has-text("Budget anlegen")') diff --git a/tests/e2e/specs/stammdaten.spec.js b/tests/e2e/specs/stammdaten.spec.js index b5f4f5e..d4c8bb8 100644 --- a/tests/e2e/specs/stammdaten.spec.js +++ b/tests/e2e/specs/stammdaten.spec.js @@ -163,9 +163,10 @@ test.describe('Stammdaten', () => { const name = `E2E Projekt ${MARKE}` await page.goto('/verwaltung/klassen') + await page.click('#neu-knopf') await page.fill('.formular #name', name) await page.fill('.formular #beschreibung', 'aus dem E2E-Test') - await page.click('.formular button[type="submit"]') + await page.click('.formular button:has-text("Klasse anlegen")') await expect(page.locator('.meldung-erfolg')).toBeVisible()