222 lines
10 KiB
HTML
222 lines
10 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Manage Resources - LabourFlow{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container py-5">
|
|
<div class="row mb-4">
|
|
<div class="col">
|
|
<h1 class="fw-bold text-dark">Manage Resources</h1>
|
|
<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>
|
|
|
|
<!-- 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 -->
|
|
<ul class="nav nav-tabs mb-4" id="resourceTabs" role="tablist">
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link active" id="workers-tab" data-bs-toggle="tab" data-bs-target="#workers" type="button" role="tab">Workers</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link" id="projects-tab" data-bs-toggle="tab" data-bs-target="#projects" type="button" role="tab">Projects</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link" id="teams-tab" data-bs-toggle="tab" data-bs-target="#teams" type="button" role="tab">Teams</button>
|
|
</li>
|
|
</ul>
|
|
|
|
<!-- Tab Content -->
|
|
<div class="tab-content" id="resourceTabsContent">
|
|
|
|
<!-- Workers Tab -->
|
|
<div class="tab-pane fade show active" id="workers" role="tabpanel">
|
|
<div class="card shadow-sm">
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-hover align-middle">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>ID Number</th>
|
|
<th>Teams</th>
|
|
<th class="text-end">Active Status</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for worker in workers %}
|
|
<tr>
|
|
<td><strong>{{ worker.name }}</strong></td>
|
|
<td>{{ worker.id_no }}</td>
|
|
<td>
|
|
{% for team in worker.teams.all %}
|
|
<span class="badge bg-light text-dark border">{{ team.name }}</span>
|
|
{% empty %}
|
|
<span class="text-muted small">No Team</span>
|
|
{% endfor %}
|
|
</td>
|
|
<td class="text-end">
|
|
<div class="form-check form-switch d-flex justify-content-end">
|
|
<input class="form-check-input resource-toggle" type="checkbox" role="switch"
|
|
id="worker-{{ worker.id }}"
|
|
data-model="worker"
|
|
data-id="{{ worker.id }}"
|
|
{% if worker.is_active %}checked{% endif %}>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{% empty %}
|
|
<tr><td colspan="4" class="text-center text-muted py-4">No workers found.</td></tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Projects Tab -->
|
|
<div class="tab-pane fade" id="projects" role="tabpanel">
|
|
<div class="card shadow-sm">
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-hover align-middle">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Description</th>
|
|
<th class="text-end">Active Status</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for project in projects %}
|
|
<tr>
|
|
<td><strong>{{ project.name }}</strong></td>
|
|
<td>{{ project.description|truncatechars:50 }}</td>
|
|
<td class="text-end">
|
|
<div class="form-check form-switch d-flex justify-content-end">
|
|
<input class="form-check-input resource-toggle" type="checkbox" role="switch"
|
|
id="project-{{ project.id }}"
|
|
data-model="project"
|
|
data-id="{{ project.id }}"
|
|
{% if project.is_active %}checked{% endif %}>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{% empty %}
|
|
<tr><td colspan="3" class="text-center text-muted py-4">No projects found.</td></tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Teams Tab -->
|
|
<div class="tab-pane fade" id="teams" role="tabpanel">
|
|
<div class="card shadow-sm">
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-hover align-middle">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Supervisor</th>
|
|
<th>Workers Count</th>
|
|
<th class="text-end">Active Status</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for team in teams %}
|
|
<tr>
|
|
<td><strong>{{ team.name }}</strong></td>
|
|
<td>{{ team.supervisor.username|default:"-" }}</td>
|
|
<td>{{ team.workers.count }}</td>
|
|
<td class="text-end">
|
|
<div class="form-check form-switch d-flex justify-content-end">
|
|
<input class="form-check-input resource-toggle" type="checkbox" role="switch"
|
|
id="team-{{ team.id }}"
|
|
data-model="team"
|
|
data-id="{{ team.id }}"
|
|
{% if team.is_active %}checked{% endif %}>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{% empty %}
|
|
<tr><td colspan="4" class="text-center text-muted py-4">No teams found.</td></tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<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 %}
|