This commit is contained in:
Flatlogic Bot 2026-02-03 21:54:23 +00:00
parent c6cc41cce3
commit 091645a299
4 changed files with 107 additions and 58 deletions

View File

@ -43,7 +43,10 @@
</div> </div>
<div class="mb-4"> <div class="mb-4">
<label class="form-label fw-bold d-block mb-3">Select Labourers</label> <div class="d-flex justify-content-between align-items-center mb-3">
<label class="form-label fw-bold mb-0">Select Labourers</label>
<a href="{% url 'manage_resources' %}" class="small text-decoration-none text-primary">Manage Resources</a>
</div>
<div class="row"> <div class="row">
{% for checkbox in form.workers %} {% for checkbox in form.workers %}
<div class="col-md-6 col-lg-4 mb-2"> <div class="col-md-6 col-lg-4 mb-2">

View File

@ -7,10 +7,22 @@
<div class="row mb-4"> <div class="row mb-4">
<div class="col"> <div class="col">
<h1 class="fw-bold text-dark">Manage Resources</h1> <h1 class="fw-bold text-dark">Manage Resources</h1>
<p class="text-muted">Toggle the active status of workers, projects, and teams. Inactive items will be hidden from selection forms.</p> <p class="text-muted">Quickly toggle the active status of workers, projects, and teams. Inactive items will be hidden from selection forms.</p>
</div> </div>
</div> </div>
<!-- Feedback Toast -->
<div class="position-fixed bottom-0 end-0 p-3" style="z-index: 11">
<div id="liveToast" class="toast align-items-center text-white bg-success border-0" role="alert" aria-live="assertive" aria-atomic="true">
<div class="d-flex">
<div class="toast-body" id="toastMessage">
Status updated successfully.
</div>
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
</div>
</div>
<!-- Tabs --> <!-- Tabs -->
<ul class="nav nav-tabs mb-4" id="resourceTabs" role="tablist"> <ul class="nav nav-tabs mb-4" id="resourceTabs" role="tablist">
<li class="nav-item" role="presentation"> <li class="nav-item" role="presentation">
@ -37,8 +49,7 @@
<tr> <tr>
<th>Name</th> <th>Name</th>
<th>ID Number</th> <th>ID Number</th>
<th>Status</th> <th class="text-end">Active Status</th>
<th class="text-end">Action</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -46,26 +57,18 @@
<tr> <tr>
<td>{{ worker.name }}</td> <td>{{ worker.name }}</td>
<td>{{ worker.id_no }}</td> <td>{{ worker.id_no }}</td>
<td>
{% if worker.is_active %}
<span class="badge bg-success">Active</span>
{% else %}
<span class="badge bg-secondary">Inactive</span>
{% endif %}
</td>
<td class="text-end"> <td class="text-end">
<form method="post" action="{% url 'toggle_resource_status' 'worker' worker.id %}"> <div class="form-check form-switch d-flex justify-content-end">
{% csrf_token %} <input class="form-check-input resource-toggle" type="checkbox" role="switch"
{% if worker.is_active %} id="worker-{{ worker.id }}"
<button type="submit" class="btn btn-sm btn-outline-danger">Deactivate</button> data-model="worker"
{% else %} data-id="{{ worker.id }}"
<button type="submit" class="btn btn-sm btn-outline-success">Activate</button> {% if worker.is_active %}checked{% endif %}>
{% endif %} </div>
</form>
</td> </td>
</tr> </tr>
{% empty %} {% empty %}
<tr><td colspan="4" class="text-center text-muted py-4">No workers found.</td></tr> <tr><td colspan="3" class="text-center text-muted py-4">No workers found.</td></tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
@ -84,8 +87,7 @@
<tr> <tr>
<th>Name</th> <th>Name</th>
<th>Description</th> <th>Description</th>
<th>Status</th> <th class="text-end">Active Status</th>
<th class="text-end">Action</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -93,26 +95,18 @@
<tr> <tr>
<td>{{ project.name }}</td> <td>{{ project.name }}</td>
<td>{{ project.description|truncatechars:50 }}</td> <td>{{ project.description|truncatechars:50 }}</td>
<td>
{% if project.is_active %}
<span class="badge bg-success">Active</span>
{% else %}
<span class="badge bg-secondary">Inactive</span>
{% endif %}
</td>
<td class="text-end"> <td class="text-end">
<form method="post" action="{% url 'toggle_resource_status' 'project' project.id %}"> <div class="form-check form-switch d-flex justify-content-end">
{% csrf_token %} <input class="form-check-input resource-toggle" type="checkbox" role="switch"
{% if project.is_active %} id="project-{{ project.id }}"
<button type="submit" class="btn btn-sm btn-outline-danger">Deactivate</button> data-model="project"
{% else %} data-id="{{ project.id }}"
<button type="submit" class="btn btn-sm btn-outline-success">Activate</button> {% if project.is_active %}checked{% endif %}>
{% endif %} </div>
</form>
</td> </td>
</tr> </tr>
{% empty %} {% empty %}
<tr><td colspan="4" class="text-center text-muted py-4">No projects found.</td></tr> <tr><td colspan="3" class="text-center text-muted py-4">No projects found.</td></tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
@ -132,8 +126,7 @@
<th>Name</th> <th>Name</th>
<th>Supervisor</th> <th>Supervisor</th>
<th>Workers Count</th> <th>Workers Count</th>
<th>Status</th> <th class="text-end">Active Status</th>
<th class="text-end">Action</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -142,26 +135,18 @@
<td>{{ team.name }}</td> <td>{{ team.name }}</td>
<td>{{ team.supervisor.username|default:"-" }}</td> <td>{{ team.supervisor.username|default:"-" }}</td>
<td>{{ team.workers.count }}</td> <td>{{ team.workers.count }}</td>
<td>
{% if team.is_active %}
<span class="badge bg-success">Active</span>
{% else %}
<span class="badge bg-secondary">Inactive</span>
{% endif %}
</td>
<td class="text-end"> <td class="text-end">
<form method="post" action="{% url 'toggle_resource_status' 'team' team.id %}"> <div class="form-check form-switch d-flex justify-content-end">
{% csrf_token %} <input class="form-check-input resource-toggle" type="checkbox" role="switch"
{% if team.is_active %} id="team-{{ team.id }}"
<button type="submit" class="btn btn-sm btn-outline-danger">Deactivate</button> data-model="team"
{% else %} data-id="{{ team.id }}"
<button type="submit" class="btn btn-sm btn-outline-success">Activate</button> {% if team.is_active %}checked{% endif %}>
{% endif %} </div>
</form>
</td> </td>
</tr> </tr>
{% empty %} {% empty %}
<tr><td colspan="5" class="text-center text-muted py-4">No teams found.</td></tr> <tr><td colspan="4" class="text-center text-muted py-4">No teams found.</td></tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
@ -172,4 +157,57 @@
</div> </div>
</div> </div>
{% endblock %}
<script>
document.addEventListener('DOMContentLoaded', function() {
const toggles = document.querySelectorAll('.resource-toggle');
const toastEl = document.getElementById('liveToast');
const toast = new bootstrap.Toast(toastEl);
const toastMessage = document.getElementById('toastMessage');
toggles.forEach(toggle => {
toggle.addEventListener('change', function() {
const model = this.dataset.model;
const id = this.dataset.id;
const isChecked = this.checked;
const url = `/manage-resources/toggle/${model}/${id}/`;
fetch(url, {
method: 'POST',
headers: {
'X-CSRFToken': '{{ csrf_token }}',
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => {
if (response.ok) {
return response.json();
}
throw new Error('Network response was not ok.');
})
.then(data => {
if (data.success) {
toastMessage.textContent = data.message;
toastEl.classList.remove('bg-danger');
toastEl.classList.add('bg-success');
toast.show();
} else {
// Revert switch if failed
this.checked = !isChecked;
alert('Failed to update status.');
}
})
.catch(error => {
console.error('Error:', error);
// Revert switch on error
this.checked = !isChecked;
toastMessage.textContent = "Error updating status.";
toastEl.classList.remove('bg-success');
toastEl.classList.add('bg-danger');
toast.show();
});
});
});
});
</script>
{% endblock %}

View File

@ -8,6 +8,7 @@ from django.db.models import Sum, Q
from django.core.mail import send_mail from django.core.mail import send_mail
from django.conf import settings from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.http import JsonResponse
from .models import Worker, Project, Team, WorkLog, PayrollRecord from .models import Worker, Project, Team, WorkLog, PayrollRecord
from .forms import WorkLogForm from .forms import WorkLogForm
from datetime import timedelta from datetime import timedelta
@ -178,6 +179,13 @@ def toggle_resource_status(request, model_type, pk):
obj.is_active = not obj.is_active obj.is_active = not obj.is_active
obj.save() obj.save()
if request.headers.get('x-requested-with') == 'XMLHttpRequest':
return JsonResponse({
'success': True,
'is_active': obj.is_active,
'message': f"{obj.name} is now {'Active' if obj.is_active else 'Inactive'}."
})
return redirect('manage_resources') return redirect('manage_resources')
def payroll_dashboard(request): def payroll_dashboard(request):
@ -294,4 +302,4 @@ def payslip_detail(request, pk):
'record': record, 'record': record,
'logs': logs, 'logs': logs,
} }
return render(request, 'core/payslip.html', context) return render(request, 'core/payslip.html', context)