Fix work log payroll modal: dead IIFE + missing aria-labelledby

Two issues caught by code quality review on commit 2e60124:

1. C1 (critical): the <script> at line ~398 runs during HTML parsing,
   BEFORE the modal markup at line ~627 has been parsed. getElementById
   returned null, the `if (!modalEl) return;` guard silently exited the
   IIFE, and the delegated click listener was never attached — so the
   modal was completely dormant. Wrapped the IIFE body in a
   DOMContentLoaded handler so the DOM is fully parsed before lookups.

2. I1 (a11y): added aria-labelledby on the modal root + a matching id on
   the modal-title h5 so screen readers announce the title correctly
   (Bootstrap 5 a11y convention).

No behavioural changes to the JS logic itself — only the wrapping and
two aria attributes on the markup.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Konrad du Plessis 2026-04-22 16:30:10 +02:00
parent 2e60124b9f
commit 8e1f634f8f

View File

@ -396,7 +396,7 @@
{# Builds the modal body from JSON via createElement + textContent. #}
{% if user.is_authenticated and user.is_staff or user.is_superuser %}
<script>
(function() {
document.addEventListener('DOMContentLoaded', function() {
var modalEl = document.getElementById('workLogPayrollModal');
if (!modalEl) return;
var bodyEl = document.getElementById('workLogPayrollBody');
@ -614,7 +614,7 @@
ev.preventDefault();
openForLog(target.getAttribute('data-log-id'));
});
})();
});
</script>
{% endif %}
@ -624,11 +624,11 @@
{# Hidden by default. Any element with data-log-id anywhere in the app #}
{# triggers this modal. Fetches JSON and builds the DOM safely. #}
{% if user.is_authenticated and user.is_staff or user.is_superuser %}
<div class="modal fade" id="workLogPayrollModal" tabindex="-1" aria-hidden="true">
<div class="modal fade" id="workLogPayrollModal" tabindex="-1" aria-labelledby="workLogPayrollModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="fas fa-calendar-day me-2"></i>Work Log Payroll</h5>
<h5 class="modal-title" id="workLogPayrollModalLabel"><i class="fas fa-calendar-day me-2"></i>Work Log Payroll</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body" id="workLogPayrollBody">