diff --git a/core/templates/core/payroll_dashboard.html b/core/templates/core/payroll_dashboard.html
index 2fd00ab..0aa154d 100644
--- a/core/templates/core/payroll_dashboard.html
+++ b/core/templates/core/payroll_dashboard.html
@@ -716,16 +716,32 @@
- {# --- Date range --- #}
-
-
-
+
+
-
-
{# --- Sort state (column-header clicks will set these via JS in Task 9) --- #}
@@ -3668,6 +3684,74 @@ document.addEventListener('DOMContentLoaded', function() {
applyWorkerCrossFilter();
}
+ // === ADJUSTMENTS TAB — Date picker single/range toggle + presets ===
+ // Single mode (default): one visible. On form submit, JS mirrors
+ // the From value into the hidden To so backend gets from==to (exact-day
+ // filter). Range mode: both inputs visible, user picks independently.
+ var dateWrap = document.getElementById('adjDateWrap');
+ if (dateWrap) {
+ var dateFrom = document.getElementById('adjDateFrom');
+ var dateTo = document.getElementById('adjDateTo');
+ var toggleBtn = document.getElementById('adjDateRangeToggle');
+ var dateLabel = document.getElementById('adjDateLabel');
+
+ function applyMode(rangeMode) {
+ dateTo.hidden = !rangeMode;
+ dateLabel.textContent = rangeMode ? 'Date range' : 'Date';
+ // In single mode mirror dateFrom into dateTo so form submit
+ // sends equal values for an exact-day match.
+ if (!rangeMode) dateTo.value = dateFrom.value;
+ }
+ // Start in range mode if URL already has different From and To
+ var urlFrom = dateFrom.value || '';
+ var urlTo = dateTo.value || '';
+ var initialRange = !!urlFrom && !!urlTo && urlFrom !== urlTo;
+ applyMode(initialRange);
+
+ toggleBtn.addEventListener('click', function() {
+ // Toggle: if hidden was the 'To' then we're switching to range
+ applyMode(dateTo.hidden);
+ });
+ // Keep the mirror in sync while in single mode
+ dateFrom.addEventListener('change', function() {
+ if (dateTo.hidden) dateTo.value = dateFrom.value;
+ });
+
+ // Preset quick-buttons
+ function iso(d) { return d.toISOString().slice(0, 10); }
+ document.querySelectorAll('#adjDatePresets [data-preset]').forEach(function(btn) {
+ btn.addEventListener('click', function() {
+ var preset = btn.getAttribute('data-preset');
+ var today = new Date();
+ if (preset === 'today') {
+ dateFrom.value = iso(today);
+ dateTo.value = iso(today);
+ applyMode(false);
+ } else if (preset === 'week') {
+ // ISO-week: Mon -> Sun
+ var dayOffset = (today.getDay() + 6) % 7; // 0 = Monday
+ var weekStart = new Date(today);
+ weekStart.setDate(today.getDate() - dayOffset);
+ var weekEnd = new Date(weekStart);
+ weekEnd.setDate(weekStart.getDate() + 6);
+ dateFrom.value = iso(weekStart);
+ dateTo.value = iso(weekEnd);
+ applyMode(true);
+ } else if (preset === 'month') {
+ var monthStart = new Date(today.getFullYear(), today.getMonth(), 1);
+ var monthEnd = new Date(today.getFullYear(), today.getMonth() + 1, 0);
+ dateFrom.value = iso(monthStart);
+ dateTo.value = iso(monthEnd);
+ applyMode(true);
+ } else if (preset === 'clear') {
+ dateFrom.value = '';
+ dateTo.value = '';
+ applyMode(false);
+ }
+ });
+ });
+ }
+
// --- Direct delete buttons on each unpaid row ---
// Short-circuits the edit modal's usual 2-step delete flow by opening
// #deleteConfirmModal directly with the correct form action + labels.