Add team filter dropdown to batch pay modal

Client-side filter lets admin narrow batch payment list by team.
Selecting a team hides other workers, unchecks them (so they won't
be paid), and updates the summary total. Select All respects the
filter — only toggles visible rows. Filter resets when switching
between schedule/pay-all modes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Konrad du Plessis 2026-03-24 22:37:48 +02:00
parent 2c3410e7c7
commit 00f16df8b1

View File

@ -2078,6 +2078,7 @@ document.addEventListener('DOMContentLoaded', function() {
// --- Helper: Build a table row for an eligible worker ---
function buildWorkerRow(w, idx) {
var tr = document.createElement('tr');
tr.dataset.team = w.team_name; // Used by team filter
// Checkbox cell
var tdCb = document.createElement('td');
@ -2237,6 +2238,42 @@ document.addEventListener('DOMContentLoaded', function() {
return;
}
// --- Team filter dropdown ---
// Extract unique team names from the eligible workers
var teamNames = [];
data.eligible.forEach(function(w) {
if (teamNames.indexOf(w.team_name) === -1) teamNames.push(w.team_name);
});
teamNames.sort();
var filterRow = document.createElement('div');
filterRow.className = 'd-flex align-items-center gap-2 mb-3';
var filterLabel = document.createElement('label');
filterLabel.className = 'text-muted small mb-0';
filterLabel.textContent = 'Filter by team:';
filterLabel.setAttribute('for', 'batchTeamFilter');
filterRow.appendChild(filterLabel);
var filterSelect = document.createElement('select');
filterSelect.id = 'batchTeamFilter';
filterSelect.className = 'form-select form-select-sm';
filterSelect.style.width = 'auto';
var optAll = document.createElement('option');
optAll.value = '';
optAll.textContent = 'All Teams';
filterSelect.appendChild(optAll);
teamNames.forEach(function(name) {
var opt = document.createElement('option');
opt.value = name;
opt.textContent = name;
filterSelect.appendChild(opt);
});
filterRow.appendChild(filterSelect);
body.appendChild(filterRow);
// --- Summary header ---
var summary = document.createElement('div');
summary.className = 'alert alert-info d-flex justify-content-between align-items-center mb-3';
@ -2292,10 +2329,13 @@ document.addEventListener('DOMContentLoaded', function() {
body.appendChild(table);
// --- Select All checkbox behavior ---
// Only affects VISIBLE rows (respects team filter)
selectAllCb.addEventListener('change', function() {
var cbs = body.querySelectorAll('.batch-worker-cb');
for (var i = 0; i < cbs.length; i++) {
cbs[i].checked = selectAllCb.checked;
var rows = tbody.querySelectorAll('tr');
for (var i = 0; i < rows.length; i++) {
if (rows[i].style.display !== 'none') {
rows[i].querySelector('.batch-worker-cb').checked = selectAllCb.checked;
}
}
updateBatchSummary(data, summary);
});
@ -2304,15 +2344,39 @@ document.addEventListener('DOMContentLoaded', function() {
body.addEventListener('change', function(e) {
if (e.target.classList.contains('batch-worker-cb')) {
updateBatchSummary(data, summary);
var allCbs = body.querySelectorAll('.batch-worker-cb');
// Check if all VISIBLE checkboxes are checked
var allChecked = true;
for (var i = 0; i < allCbs.length; i++) {
if (!allCbs[i].checked) { allChecked = false; break; }
var rows = tbody.querySelectorAll('tr');
for (var i = 0; i < rows.length; i++) {
if (rows[i].style.display !== 'none') {
if (!rows[i].querySelector('.batch-worker-cb').checked) {
allChecked = false; break;
}
}
}
selectAllCb.checked = allChecked;
}
});
// --- Team filter behavior ---
// Shows/hides rows, checks matching workers, unchecks hidden ones
filterSelect.addEventListener('change', function() {
var selectedTeam = filterSelect.value;
var rows = tbody.querySelectorAll('tr');
for (var i = 0; i < rows.length; i++) {
var row = rows[i];
if (!selectedTeam || row.dataset.team === selectedTeam) {
row.style.display = '';
row.querySelector('.batch-worker-cb').checked = true;
} else {
row.style.display = 'none';
row.querySelector('.batch-worker-cb').checked = false;
}
}
selectAllCb.checked = true;
updateBatchSummary(data, summary);
});
// --- Skipped workers (collapsible) ---
if (data.skipped.length > 0) {
body.appendChild(buildSkippedSection(data.skipped));