Quelltext des aktuellen Standes
(function () {
'use strict';
var amountEl = document.getElementById('cost_amount');
var netEl = document.getElementById('cost_amount_net');
var intvlEl = document.getElementById('cost_interval');
var taxEl = document.getElementById('tax_rate');
var firstPayEl = document.getElementById('first_payment_date');
var previewCard = document.getElementById('costPreviewCard');
var mGross = document.getElementById('prev-monthly-gross');
var mNet = document.getElementById('prev-monthly-net');
var yGross = document.getElementById('prev-yearly-gross');
var yNet = document.getElementById('prev-yearly-net');
var dueBox = document.getElementById('prev-next-payment');
var dueText = document.getElementById('prev-next-payment-text');
if (!amountEl) return;
function fmt(v) {
return v.toLocaleString('de-DE', {minimumFractionDigits: 2, maximumFractionDigits: 2}) + '\u202f\u20AC';
}
function nextPayDate(firstDate, interval) {
if (!firstDate) return null;
var today = new Date(); today.setHours(0, 0, 0, 0);
var d = new Date(firstDate);
if (isNaN(d.getTime())) return null;
if (d >= today) return d;
var step = interval === 'quarterly' ? 3 : interval === 'yearly' ? 12 : 1;
while (d < today) { d.setMonth(d.getMonth() + step); }
return d;
}
function update() {
var raw = amountEl.value;
var amount = parseFloat(raw);
if (!raw || isNaN(amount) || amount <= 0) {
previewCard.style.display = 'none';
return;
}
previewCard.style.display = '';
var intvl = intvlEl.value;
var taxRaw = parseFloat(taxEl.value);
var hasTax = taxEl.value !== '' && !isNaN(taxRaw) && taxRaw > 0;
var isOneTime = intvl === 'one_time';
var monthly = isOneTime ? 0
: intvl === 'monthly' ? amount
: intvl === 'quarterly' ? amount / 3
: amount / 12;
var yearly = isOneTime ? 0 : monthly * 12;
if (isOneTime) {
mGross.textContent = <?= json_encode($this->t('(einmalig)'), JSON_UNESCAPED_UNICODE) ?>;
yGross.textContent = <?= json_encode($this->t('(einmalig)'), JSON_UNESCAPED_UNICODE) ?>;
mNet.textContent = hasTax ? fmt(amount / (1 + taxRaw / 100)) + <?= json_encode(' ' . $this->t('netto'), JSON_UNESCAPED_UNICODE) ?> : <?= json_encode($this->t('(keine MwSt)'), JSON_UNESCAPED_UNICODE) ?>;
yNet.textContent = '–';
if (firstPayEl.value) {
dueBox.style.display = 'flex';
dueText.textContent = new Date(firstPayEl.value).toLocaleDateString('de-DE', {day: '2-digit', month: '2-digit', year: 'numeric'});
} else {
dueBox.style.display = 'none';
}
return;
}
mGross.textContent = fmt(monthly);
yGross.textContent = fmt(yearly);
if (hasTax) {
var factor = 1 + taxRaw / 100;
mNet.textContent = fmt(monthly / factor);
yNet.textContent = fmt(yearly / factor);
} else {
mNet.textContent = <?= json_encode($this->t('(keine MwSt)'), JSON_UNESCAPED_UNICODE) ?>;
yNet.textContent = <?= json_encode($this->t('(keine MwSt)'), JSON_UNESCAPED_UNICODE) ?>;
}
var next = nextPayDate(firstPayEl.value, intvl);
if (next) {
dueBox.style.display = 'flex';
dueText.textContent = next.toLocaleDateString('de-DE', {day: '2-digit', month: '2-digit', year: 'numeric'});
} else {
dueBox.style.display = 'none';
}
}
// Brutto und Netto über den MwSt-Satz synchron halten: Eingabe in einem
// Feld berechnet das andere; ohne MwSt-Satz gilt Netto = Brutto.
// Gespeichert wird weiterhin nur der Brutto-Betrag.
function taxFactor() {
var rate = parseFloat(taxEl.value);
return isNaN(rate) || rate < 0 ? 1 : 1 + rate / 100;
}
function syncFromNet() {
if (!netEl) return;
var nv = parseFloat(netEl.value);
amountEl.value = isNaN(nv) ? '' : (nv * taxFactor()).toFixed(2);
}
function syncFromGross() {
if (!netEl) return;
var gv = parseFloat(amountEl.value);
netEl.value = isNaN(gv) ? '' : (gv / taxFactor()).toFixed(2);
}
if (netEl) {
netEl.addEventListener('input', function () { syncFromNet(); update(); });
amountEl.addEventListener('input', syncFromGross);
taxEl.addEventListener('input', function () {
// Beim Wechsel des Steuersatzes gewinnt das zuletzt „führende" Feld:
// Brutto, wenn befüllt, sonst Netto.
if (amountEl.value !== '') { syncFromGross(); } else { syncFromNet(); }
});
}
[amountEl, intvlEl, taxEl, firstPayEl].forEach(function (el) {
el.addEventListener('input', update);
el.addEventListener('change', update);
});
update();
}());