Add quick 'Adjust' button to pending payments table rows
Each worker row now has an Adjust button (slider icon) that opens the Add Adjustment modal with that worker pre-checked and their most recent project pre-selected. Header Add Adjustment button resets the modal to a clean state (no workers pre-checked). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c3bbffe9c0
commit
cfed13c9f5
@ -308,6 +308,12 @@
|
|||||||
data-worker-name="{{ wd.worker.name }}">
|
data-worker-name="{{ wd.worker.name }}">
|
||||||
<i class="fas fa-eye"></i>
|
<i class="fas fa-eye"></i>
|
||||||
</button>
|
</button>
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-secondary quick-adjust-btn"
|
||||||
|
data-worker-id="{{ wd.worker.id }}"
|
||||||
|
data-worker-project="{{ wd.last_project_id|default:'' }}"
|
||||||
|
title="Add adjustment for {{ wd.worker.name }}">
|
||||||
|
<i class="fas fa-sliders-h"></i>
|
||||||
|
</button>
|
||||||
<form method="POST" action="{% url 'process_payment' wd.worker.id %}"
|
<form method="POST" action="{% url 'process_payment' wd.worker.id %}"
|
||||||
class="d-inline pay-form">
|
class="d-inline pay-form">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
@ -1389,6 +1395,59 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// === QUICK ADJUST BUTTON ===
|
||||||
|
// Opens the Add Adjustment modal with one worker pre-checked
|
||||||
|
// and their most recent project pre-selected.
|
||||||
|
var _quickAdjustOpen = false; // Flag to distinguish quick-adjust from header button
|
||||||
|
document.querySelectorAll('.quick-adjust-btn').forEach(function(btn) {
|
||||||
|
btn.addEventListener('click', function() {
|
||||||
|
_quickAdjustOpen = true;
|
||||||
|
var workerId = this.dataset.workerId;
|
||||||
|
var projectId = this.dataset.workerProject;
|
||||||
|
|
||||||
|
// Uncheck all workers, then check only the target worker
|
||||||
|
addAdjWorkerCheckboxes.forEach(function(cb) {
|
||||||
|
cb.checked = (cb.value === workerId);
|
||||||
|
});
|
||||||
|
updateWorkerCount();
|
||||||
|
|
||||||
|
// Pre-select the worker's most recent project (if available)
|
||||||
|
if (projectId && addAdjProject) {
|
||||||
|
addAdjProject.value = projectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset type to default (Bonus) and trigger field visibility update
|
||||||
|
if (addAdjType) {
|
||||||
|
addAdjType.value = 'Bonus';
|
||||||
|
toggleProjectField();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the modal
|
||||||
|
var modal = new bootstrap.Modal(document.getElementById('addAdjustmentModal'));
|
||||||
|
modal.show();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// When the modal is opened from the HEADER button (not quick-adjust),
|
||||||
|
// clear any pre-selected workers and project from a previous quick-adjust.
|
||||||
|
var addAdjModal = document.getElementById('addAdjustmentModal');
|
||||||
|
if (addAdjModal) {
|
||||||
|
addAdjModal.addEventListener('show.bs.modal', function() {
|
||||||
|
if (_quickAdjustOpen) {
|
||||||
|
_quickAdjustOpen = false;
|
||||||
|
return; // Quick-adjust already set the values
|
||||||
|
}
|
||||||
|
// Reset: uncheck all workers, clear project, reset type
|
||||||
|
addAdjWorkerCheckboxes.forEach(function(cb) { cb.checked = false; });
|
||||||
|
updateWorkerCount();
|
||||||
|
if (addAdjProject) addAdjProject.value = '';
|
||||||
|
if (addAdjType) {
|
||||||
|
addAdjType.value = 'Bonus';
|
||||||
|
toggleProjectField();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Form validation: ensure at least one worker is selected before submit.
|
// Form validation: ensure at least one worker is selected before submit.
|
||||||
// Without this, the form would submit and silently create 0 adjustments.
|
// Without this, the form would submit and silently create 0 adjustments.
|
||||||
var addAdjForm = document.querySelector('#addAdjustmentModal form');
|
var addAdjForm = document.querySelector('#addAdjustmentModal form');
|
||||||
|
|||||||
@ -921,6 +921,9 @@ def payroll_dashboard(request):
|
|||||||
|
|
||||||
has_loan = Loan.objects.filter(worker=worker, active=True).exists()
|
has_loan = Loan.objects.filter(worker=worker, active=True).exists()
|
||||||
|
|
||||||
|
# Most recent project — used by the "Adjust" button to pre-select project
|
||||||
|
last_project_id = unpaid_logs[-1].project_id if unpaid_logs else None
|
||||||
|
|
||||||
workers_data.append({
|
workers_data.append({
|
||||||
'worker': worker,
|
'worker': worker,
|
||||||
'unpaid_count': log_count,
|
'unpaid_count': log_count,
|
||||||
@ -935,6 +938,7 @@ def payroll_dashboard(request):
|
|||||||
'is_overdue': is_overdue,
|
'is_overdue': is_overdue,
|
||||||
'has_loan': has_loan,
|
'has_loan': has_loan,
|
||||||
'earliest_unpaid': earliest_unpaid,
|
'earliest_unpaid': earliest_unpaid,
|
||||||
|
'last_project_id': last_project_id,
|
||||||
})
|
})
|
||||||
outstanding_total += max(total_payable, Decimal('0.00'))
|
outstanding_total += max(total_payable, Decimal('0.00'))
|
||||||
unpaid_wages_total += log_amount
|
unpaid_wages_total += log_amount
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user