fix(fees): naprawiono klik w kwadrat miesiąca (konflikt cudzysłowów w onclick)
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions

Błąd: onclick="fn({{ name|tojson }})" — Jinja tojson generuje wartość
z cudzysłowami, które łamały atrybut HTML (zewnętrzne też cudzysłowy).
Efekt: klik w kwadrat nie robił nic.

Naprawa: przejście na data-* atrybuty + DOMContentLoaded event listener
z document.querySelectorAll. Zero escapingu, zero konfliktów.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maciej Pienczyn 2026-04-14 19:29:06 +02:00
parent f274d59ae6
commit 5893645c46

View File

@ -497,14 +497,30 @@
<span class="month-cell clickable {% if is_premium %}paid-premium{% else %}{{ fee.status }}{% endif %}" <span class="month-cell clickable {% if is_premium %}paid-premium{% else %}{{ fee.status }}{% endif %}"
title="{{ fee.status }}: wpłacono {{ fee.amount_paid|int }} z {{ fee.amount|int }} zł{% if underpaid %} ⚠ stawka powinna wynosić {{ expected }} zł{% endif %}{% if is_premium %} (stawka pełna 300 zł){% endif %} · Kliknij, aby edytować płatność" title="{{ fee.status }}: wpłacono {{ fee.amount_paid|int }} z {{ fee.amount|int }} zł{% if underpaid %} ⚠ stawka powinna wynosić {{ expected }} zł{% endif %}{% if is_premium %} (stawka pełna 300 zł){% endif %} · Kliknij, aby edytować płatność"
style="position:relative;cursor:pointer;{% if underpaid %}outline:2px solid var(--error);outline-offset:-2px;{% endif %}" style="position:relative;cursor:pointer;{% if underpaid %}outline:2px solid var(--error);outline-offset:-2px;{% endif %}"
onclick="openPaymentModalSmart({{ cf.company.id }}, {{ cf.company.name|tojson }}, {{ year }}, {{ m }}, {{ fee.id }}, {{ fee.amount|int }}, {{ expected }}, {{ 'true' if fee.status == 'paid' else 'false' }}, {{ fee.amount_paid|int if fee.amount_paid else 0 }})"> data-company-id="{{ cf.company.id }}"
data-company-name="{{ cf.company.name }}"
data-year="{{ year }}"
data-month="{{ m }}"
data-fee-id="{{ fee.id }}"
data-amount="{{ fee.amount|int }}"
data-expected="{{ expected }}"
data-is-paid="{{ 'true' if fee.status == 'paid' else 'false' }}"
data-amount-paid="{{ fee.amount_paid|int if fee.amount_paid else 0 }}">
{{ m }}{% if fee.status == 'partial' %}<span class="partial-badge">{{ fee.amount_paid|int }}</span>{% endif %}{% if underpaid %}<span style="position:absolute;top:-6px;right:-6px;background:var(--error);color:white;font-size:8px;font-weight:700;width:14px;height:14px;border-radius:50%;display:flex;align-items:center;justify-content:center;line-height:1;">!</span>{% endif %} {{ m }}{% if fee.status == 'partial' %}<span class="partial-badge">{{ fee.amount_paid|int }}</span>{% endif %}{% if underpaid %}<span style="position:absolute;top:-6px;right:-6px;background:var(--error);color:white;font-size:8px;font-weight:700;width:14px;height:14px;border-radius:50%;display:flex;align-items:center;justify-content:center;line-height:1;">!</span>{% endif %}
</span> </span>
{% else %} {% else %}
<span class="month-cell empty clickable" <span class="month-cell empty clickable"
title="Brak wpłaty za miesiąc {{ m }} (stawka {{ expected }} zł) · Kliknij, aby zarejestrować wpłatę" title="Brak wpłaty za miesiąc {{ m }} (stawka {{ expected }} zł) · Kliknij, aby zarejestrować wpłatę"
style="cursor:pointer;" style="cursor:pointer;"
onclick="openPaymentModalSmart({{ cf.company.id }}, {{ cf.company.name|tojson }}, {{ year }}, {{ m }}, null, {{ expected }}, {{ expected }}, false, 0)"> data-company-id="{{ cf.company.id }}"
data-company-name="{{ cf.company.name }}"
data-year="{{ year }}"
data-month="{{ m }}"
data-fee-id=""
data-amount="{{ expected }}"
data-expected="{{ expected }}"
data-is-paid="false"
data-amount-paid="0">
{{ m }} {{ m }}
</span> </span>
{% endif %} {% endif %}
@ -770,6 +786,28 @@ async function generateFees() {
document.getElementById('paymentModal').classList.remove('active'); document.getElementById('paymentModal').classList.remove('active');
} }
// Event delegation — wszystkie klikalne kwadraciki miesięcy w widoku rocznym
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.month-cell.clickable').forEach(function(cell) {
cell.addEventListener('click', function(ev) {
ev.preventDefault();
var d = cell.dataset;
var feeId = d.feeId ? parseInt(d.feeId) : null;
openPaymentModalSmart(
parseInt(d.companyId),
d.companyName,
parseInt(d.year),
parseInt(d.month),
feeId,
parseFloat(d.amount),
parseFloat(d.expected),
d.isPaid === 'true',
parseFloat(d.amountPaid || 0)
);
});
});
});
document.getElementById('paymentForm').addEventListener('submit', async function(e) { document.getElementById('paymentForm').addEventListener('submit', async function(e) {
e.preventDefault(); e.preventDefault();