Finanzmanager/src/Views/vertraege/kredite.php
fds2610-bot d1db40fa55 Fix #126: Taschenrechner an den Betragsfeldern
Jedes Zahlenfeld (inputmode="decimal") zeigt rechts ein Rechnersymbol.
Klick darauf oder Alt+R öffnet einen Taschenrechner mit Grundrechenarten
und Klammern, komplett per Tastatur bedienbar: Ziffern, + - * / ( ),
Backspace, Entf, Pfeiltasten, C löscht alles, = setzt das Ergebnis ein,
Enter überträgt ins Feld, Escape schließt und fokussiert das Feld. Das
Ergebnis steht nach jedem Tastendruck unter der Rechnung.

Das Symbol ist ein Hintergrundbild (kein Wrapper-Element, kein Eingriff in
die Layouts); gerechnet wird mit eigenem Parser statt eval. In modalen
Dialogen wandert der Rechner mit hinein. Stück/Kurs übernehmen 6,
Zinssätze 3 Nachkommastellen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:22:18 +02:00

265 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
use Finanzmanager\Models\Kredit;
use Finanzmanager\View;
/**
* @var list<array<string,mixed>> $kredite
* @var array<string,mixed>|null $kredit
* @var array<string,mixed>|null $plan
* @var list<array<string,mixed>> $konten
* @var string $csrfToken
*/
include __DIR__ . '/../layout/kopf.php';
?>
<div class="tableiste">
<a href="/vertraege" class="tab">Verträge</a>
<a href="/vertraege/adressen" class="tab">Adressen</a>
<a href="/vertraege/sparziele" class="tab">Sparziele</a>
<span class="tab aktiv" title="Annuitätendarlehen mit gleichbleibender Rate: Der Zinsanteil sinkt, die Tilgung wächst. Der Tilgungsplan wird aus Betrag, Zins, Rate und Beginn gerechnet, nicht gespeichert.">Kredite</span>
</div>
<div class="seitenaktionen">
<button type="button" class="knopf primaer" id="neu-knopf" data-neudialog="neudialog">+ Neu</button>
</div>
<?php if ($kredite !== []): ?>
<table class="liste zahlen">
<thead>
<tr>
<th>Kredit</th><th class="rechts">Darlehen</th><th class="rechts">Zins</th>
<th class="rechts">Rate</th><th>Rhythmus</th><th class="rechts">Restschuld heute</th>
<th class="rechts">Aktion</th>
</tr>
</thead>
<tbody>
<?php foreach ($kredite as $eintrag): ?>
<tr<?= (int)$eintrag['aktiv'] === 1 ? '' : ' class="inaktiv"' ?>>
<td>
<a href="/vertraege/kredite?kredit=<?= (int)$eintrag['id'] ?>">
<?= View::h($eintrag['name']) ?>
</a>
</td>
<td class="rechts"><?= View::betrag($eintrag['darlehensbetrag']) ?></td>
<td class="rechts"><?= View::h(number_format((float)$eintrag['zinssatz'], 2, ',', '.')) ?> %</td>
<td class="rechts"><?= View::betrag($eintrag['rate']) ?></td>
<td><?= View::h(Kredit::RHYTHMUS_NAMEN[$eintrag['rhythmus']] ?? $eintrag['rhythmus']) ?></td>
<td class="rechts"><?= View::betrag($eintrag['restschuld']) ?></td>
<td class="rechts">
<form method="post" action="/vertraege/kredite/<?= (int)$eintrag['id'] ?>/loeschen"
class="inline" data-bestaetigen="Kredit „<?= View::h($eintrag['name']) ?>“ löschen?">
<input type="hidden" name="csrf_token" value="<?= View::h($csrfToken) ?>">
<button type="submit" class="knopf klein gefahr">Löschen</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
<?php if ($kredit !== null && $plan !== null): ?>
<h3>Tilgungsplan: <?= View::h($kredit['name']) ?></h3>
<?php if (!$plan['tilgt']): ?>
<p class="meldung meldung-fehler" role="status">
Die Rate deckt nicht einmal die Zinsen der ersten Periode – so würde die
Restschuld wachsen statt zu sinken. Bitte Rate oder Zinssatz prüfen.
</p>
<?php else: ?>
<div class="kennzahlenleiste">
<div class="kennzahlkachel">
<span class="kennzahltitel">Laufzeit</span>
<span class="kennzahl"><?= (int)round($plan['laufzeit_monate'] / 12) ?> J.</span>
<span class="nebentext"><?= (int)$plan['laufzeit_monate'] ?> Monate</span>
</div>
<div class="kennzahlkachel">
<span class="kennzahltitel">Letzte Rate</span>
<span class="kennzahl klein"><?= View::h(View::datum($plan['letzte_rate_am'])) ?></span>
</div>
<div class="kennzahlkachel">
<span class="kennzahltitel">Zinsen gesamt</span>
<span class="kennzahl negativ"><?= View::betrag($plan['zinsen']) ?></span>
</div>
<?php if ($plan['restschuld_zinsbindung'] !== null): ?>
<div class="kennzahlkachel">
<span class="kennzahltitel">Rest bei Zinsbindungsende</span>
<span class="kennzahl"><?= View::betrag($plan['restschuld_zinsbindung']) ?></span>
</div>
<?php endif; ?>
</div>
<?php
// Bei langen Laufzeiten sind alle Raten zu viel; gezeigt werden die
// nächsten zwei Jahre und das Ende.
$zeilen = $plan['zeilen'];
$gekuerzt = count($zeilen) > 30;
$anzeige = $gekuerzt
? array_merge(array_slice($zeilen, 0, 24), array_slice($zeilen, -3))
: $zeilen;
?>
<table class="liste zahlen">
<thead>
<tr>
<th class="rechts">Nr.</th><th>Fällig</th><th class="rechts">Zahlung</th>
<th class="rechts">Zinsen</th><th class="rechts">Tilgung</th><th class="rechts">Restschuld</th>
</tr>
</thead>
<tbody>
<?php $vorige = 0; ?>
<?php foreach ($anzeige as $zeile): ?>
<?php if ($gekuerzt && $zeile['nummer'] > $vorige + 1): ?>
<tr class="luecke">
<td colspan="6" class="nebentext">
… <?= (int)($zeile['nummer'] - $vorige - 1) ?> weitere Raten …
</td>
</tr>
<?php endif; ?>
<tr>
<td class="rechts"><?= (int)$zeile['nummer'] ?></td>
<td><?= View::h(View::datum($zeile['datum'])) ?></td>
<td class="rechts"><?= View::betrag($zeile['zahlung']) ?></td>
<td class="rechts"><?= View::betrag($zeile['zinsen']) ?></td>
<td class="rechts"><?= View::betrag($zeile['tilgung']) ?></td>
<td class="rechts"><?= View::betrag($zeile['restschuld']) ?></td>
</tr>
<?php $vorige = (int)$zeile['nummer']; ?>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
<form method="post" action="/vertraege/kredite/<?= (int)$kredit['id'] ?>" class="formular breit">
<input type="hidden" name="csrf_token" value="<?= View::h($csrfToken) ?>">
<h3>Kredit bearbeiten</h3>
<label for="b_name">Name</label>
<input type="text" id="b_name" name="name" value="<?= View::h($kredit['name']) ?>" required>
<div class="feldpaar">
<div>
<label for="b_betrag">Darlehensbetrag</label>
<input type="text" id="b_betrag" name="darlehensbetrag" inputmode="decimal"
value="<?= View::h(number_format((float)$kredit['darlehensbetrag'], 2, ',', '')) ?>">
</div>
<div>
<label for="b_zins">Zinssatz (%)</label>
<input type="text" id="b_zins" name="zinssatz" inputmode="decimal" data-nachkommastellen="3"
value="<?= View::h(number_format((float)$kredit['zinssatz'], 3, ',', '')) ?>">
</div>
<div>
<label for="b_rate">Rate</label>
<input type="text" id="b_rate" name="rate" inputmode="decimal"
value="<?= View::h(number_format((float)$kredit['rate'], 2, ',', '')) ?>">
</div>
</div>
<div class="feldpaar">
<div>
<label for="b_rhythmus">Rhythmus</label>
<select id="b_rhythmus" name="rhythmus">
<?php foreach (Kredit::RHYTHMUS_NAMEN as $schluessel => $name): ?>
<option value="<?= View::h($schluessel) ?>"
<?= $kredit['rhythmus'] === $schluessel ? 'selected' : '' ?>>
<?= View::h($name) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div>
<label for="b_beginn">Beginn</label>
<input type="date" id="b_beginn" name="beginn" value="<?= View::h((string)$kredit['beginn']) ?>">
</div>
<div>
<label for="b_bindung">Zinsbindung bis</label>
<input type="date" id="b_bindung" name="zinsbindung_bis"
value="<?= View::h((string)($kredit['zinsbindung_bis'] ?? '')) ?>">
</div>
</div>
<label for="b_sonder">Jährliche Sondertilgung <span class="optional">(im Dezember)</span></label>
<input type="text" id="b_sonder" name="sondertilgung" inputmode="decimal"
value="<?= View::h(number_format((float)$kredit['sondertilgung'], 2, ',', '')) ?>">
<label for="b_konto">Konto</label>
<select id="b_konto" name="konto_id">
<option value="">– keines –</option>
<?php foreach ($konten as $konto): ?>
<option value="<?= (int)$konto['id'] ?>"
<?= (int)$kredit['konto_id'] === (int)$konto['id'] ? 'selected' : '' ?>>
<?= View::h($konto['name']) ?>
</option>
<?php endforeach; ?>
</select>
<label class="ankreuzfeld">
<input type="checkbox" name="aktiv" value="1" <?= (int)$kredit['aktiv'] === 1 ? 'checked' : '' ?>>
aktiv
</label>
<div class="knopfleiste">
<button type="submit" class="knopf primaer">Speichern</button>
</div>
</form>
<?php endif; ?>
<dialog id="neudialog" class="splitdialog neudialog">
<form method="post" action="/vertraege/kredite/neu" class="formular breit">
<input type="hidden" name="csrf_token" value="<?= View::h($csrfToken) ?>">
<h2>Neuer Kredit</h2>
<p class="feldhinweis">
Gerechnet wird als Annuitätendarlehen: gleichbleibende Rate, sinkender Zinsanteil.
Der Tilgungsplan entsteht aus diesen Angaben und wird nicht gespeichert.
</p>
<label for="name">Name</label>
<input type="text" id="name" name="name" required placeholder="z. B. Baufinanzierung">
<div class="feldpaar">
<div>
<label for="darlehensbetrag">Darlehensbetrag</label>
<input type="text" id="darlehensbetrag" name="darlehensbetrag" inputmode="decimal" required>
</div>
<div>
<label for="zinssatz">Zinssatz (%)</label>
<input type="text" id="zinssatz" name="zinssatz" inputmode="decimal" data-nachkommastellen="3" required>
</div>
<div>
<label for="rate">Rate</label>
<input type="text" id="rate" name="rate" inputmode="decimal" required>
</div>
</div>
<div class="feldpaar">
<div>
<label for="rhythmus">Rhythmus</label>
<select id="rhythmus" name="rhythmus">
<?php foreach (Kredit::RHYTHMUS_NAMEN as $schluessel => $name): ?>
<option value="<?= View::h($schluessel) ?>"><?= View::h($name) ?></option>
<?php endforeach; ?>
</select>
</div>
<div>
<label for="beginn">Beginn</label>
<input type="date" id="beginn" name="beginn" value="<?= View::h(date('Y-m-d')) ?>" required>
</div>
<div>
<label for="zinsbindung_bis">Zinsbindung bis</label>
<input type="date" id="zinsbindung_bis" name="zinsbindung_bis">
</div>
</div>
<label class="ankreuzfeld">
<input type="checkbox" name="aktiv" value="1" checked> aktiv
</label>
<div class="knopfleiste">
<button type="submit" class="knopf primaer">Kredit anlegen</button>
<button type="submit" class="knopf" formmethod="dialog" formnovalidate>Abbrechen</button>
</div>
</form>
</dialog>
<?php include __DIR__ . '/../layout/fuss.php'; ?>