194 lines
11 KiB
HTML
194 lines
11 KiB
HTML
{% load i18n static inspections_tags %}
|
|
|
|
{# Inspections et contrôles liés à l'asset #}
|
|
<div class="card mb-3" id="asset-inspections-card">
|
|
<div class="card-header bg-light d-flex align-items-center justify-content-between">
|
|
<h5 class="mb-0 fs-6 fw-bold">
|
|
<i class="bi bi-patch-check me-2 text-primary"></i>{% translate "Inspections et contrôles terrain" %}
|
|
{% if inspections %}
|
|
<span class="badge bg-secondary rounded-pill ms-1">{{ total_count }}</span>
|
|
{% endif %}
|
|
</h5>
|
|
{% if can_inspect %}
|
|
<button type="button"
|
|
class="btn btn-outline-primary btn-sm btn-trigger-asset-inspection"
|
|
data-bs-toggle="modal"
|
|
data-bs-target="#quickInspectionModal"
|
|
data-content-type-id="{{ asset_ct_id }}"
|
|
data-object-id="{{ asset_pk }}"
|
|
data-target-code="{{ asset.code|default:asset.pk }}"
|
|
data-target-name="{{ asset.name_fr|default:asset.name_nl|default:asset }}"
|
|
data-target-type="{{ asset.category.name_fr|default:'Asset' }}"
|
|
data-target-status="{{ asset.get_status_display|default:asset.inspection_status|default:'-' }}">
|
|
<i class="bi bi-plus-lg me-1"></i>{% translate "Nouvelle inspection" %}
|
|
</button>
|
|
{% endif %}
|
|
</div>
|
|
<div class="card-body p-0">
|
|
{% if inspections %}
|
|
<div class="table-responsive">
|
|
<table class="table table-hover table-sm mb-0 align-middle">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th style="width: 15%;" class="ps-3">{% translate "Date & Heure" %}</th>
|
|
<th style="width: 18%;">{% translate "Statut du contrôle" %}</th>
|
|
<th style="width: 15%;">{% translate "Nature" %}</th>
|
|
<th style="width: 20%;">{% translate "Inspecteur" %}</th>
|
|
<th style="width: 22%;">{% translate "Remarques" %}</th>
|
|
<th style="width: 10%;" class="pe-3 text-end">{% translate "Action" %}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for insp in inspections %}
|
|
<tr>
|
|
<td class="ps-3 fw-semibold">
|
|
{{ insp.inspection_date|date:"d/m/Y H:i" }}
|
|
</td>
|
|
<td>
|
|
<span class="badge {{ insp.status_badge_class }}">
|
|
<i class="bi {{ insp.status_icon }} me-1"></i>{{ insp.get_result_status_display }}
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<span class="badge bg-light text-dark border">{{ insp.get_nature_display }}</span>
|
|
</td>
|
|
<td>
|
|
<i class="bi bi-person me-1 text-muted"></i>{{ insp.inspector.get_full_name|default:insp.inspector.username|default:"-" }}
|
|
</td>
|
|
<td>
|
|
<span class="small text-muted text-truncate d-inline-block" style="max-width: 220px;" title="{{ insp.details_summary }}">
|
|
{{ insp.details_summary }}
|
|
</span>
|
|
</td>
|
|
<td class="pe-3 text-end">
|
|
<button type="button" class="btn btn-xs btn-outline-primary px-2 py-1 rounded" data-bs-toggle="modal" data-bs-target="#assetInspectionDetailModal{{ insp.id }}">
|
|
<i class="bi bi-eye me-1"></i>{% translate "Détail" %}
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% else %}
|
|
<div class="p-3 text-center text-muted small">
|
|
<i class="bi bi-info-circle fs-5 d-block mb-1 text-secondary"></i>
|
|
{% translate "Aucune inspection ni vérification enregistrée pour cet équipement." %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
{% for insp in inspections %}
|
|
<!-- Modale de détail de l'inspection pour l'asset -->
|
|
<div class="modal fade" id="assetInspectionDetailModal{{ insp.id }}" tabindex="-1" aria-labelledby="assetInspectionDetailModalLabel{{ insp.id }}" aria-hidden="true">
|
|
<div class="modal-dialog modal-lg modal-dialog-centered">
|
|
<div class="modal-content border-0 shadow">
|
|
<div class="modal-header bg-light py-2.5">
|
|
<h5 class="modal-title fs-6 fw-bold" id="assetInspectionDetailModalLabel{{ insp.id }}">
|
|
<i class="bi bi-patch-check me-2 text-primary"></i>{% translate "Détail du contrôle" %} - {{ insp.inspection_date|date:"d/m/Y H:i" }}
|
|
</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body p-3">
|
|
<ul class="list-group list-group-flush mb-3">
|
|
<li class="list-group-item d-flex justify-content-between align-items-center px-0">
|
|
<span class="text-muted"><i class="bi bi-geo-alt me-1"></i>{% translate "Équipement cible" %}</span>
|
|
<span class="fw-bold text-end ms-2">{{ insp.target_display }}</span>
|
|
</li>
|
|
<li class="list-group-item d-flex justify-content-between align-items-center px-0">
|
|
<span class="text-muted"><i class="bi bi-calendar-event me-1"></i>{% translate "Date & Heure" %}</span>
|
|
<span class="fw-semibold">{{ insp.inspection_date|date:"d/m/Y H:i" }}</span>
|
|
</li>
|
|
<li class="list-group-item d-flex justify-content-between align-items-center px-0">
|
|
<span class="text-muted"><i class="bi bi-shield-check me-1"></i>{% translate "Résultat du contrôle" %}</span>
|
|
<span class="badge {{ insp.status_badge_class }}"><i class="bi {{ insp.status_icon }} me-1"></i>{{ insp.get_result_status_display }}</span>
|
|
</li>
|
|
<li class="list-group-item d-flex justify-content-between align-items-center px-0">
|
|
<span class="text-muted"><i class="bi bi-eye me-1"></i>{% translate "Nature" %}</span>
|
|
<span class="badge bg-light text-dark border">{{ insp.get_nature_display }}</span>
|
|
</li>
|
|
<li class="list-group-item d-flex justify-content-between align-items-center px-0">
|
|
<span class="text-muted"><i class="bi bi-person me-1"></i>{% translate "Inspecteur" %}</span>
|
|
<span class="fw-semibold">{{ insp.inspector.get_full_name|default:insp.inspector.username|default:"-" }}</span>
|
|
</li>
|
|
|
|
{% get_inspection_detail_template insp as detail_template %}
|
|
{% if detail_template %}
|
|
{% include detail_template with insp=insp %}
|
|
{% endif %}
|
|
</ul>
|
|
|
|
{% if insp.notes %}
|
|
<div class="mb-3">
|
|
<label class="form-label text-muted small fw-semibold"><i class="bi bi-journal-text me-1"></i>{% translate "Remarques / Observations" %}:</label>
|
|
<div class="p-2 bg-light rounded border text-secondary small">
|
|
{{ insp.notes|linebreaksbr }}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if insp.documents.all %}
|
|
<div>
|
|
<label class="form-label text-muted small fw-semibold mb-2"><i class="bi bi-camera me-1"></i>{% translate "Photos & Documents joints" %} ({{ insp.documents.count }}):</label>
|
|
<div class="d-flex flex-wrap gap-2">
|
|
{% for doc in insp.documents.all %}
|
|
<a href="{{ doc.file_url }}" target="_blank" class="d-inline-block border rounded p-1 bg-light">
|
|
<img data-src="{{ doc.file_url }}" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1 1'%3E%3C/svg%3E" loading="lazy" alt="Photo" class="rounded" style="width: 75px; height: 75px; object-fit: cover;">
|
|
</a>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="modal-footer py-2 bg-light">
|
|
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">{% translate "Fermer" %}</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
|
|
{% if can_inspect %}
|
|
{% include "inspections/components/inspection_form_modal.html" %}
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const triggerBtns = document.querySelectorAll('.btn-trigger-asset-inspection');
|
|
triggerBtns.forEach(btn => {
|
|
btn.addEventListener('click', function() {
|
|
const ctId = this.getAttribute('data-content-type-id');
|
|
const objId = this.getAttribute('data-object-id');
|
|
const code = this.getAttribute('data-target-code');
|
|
const name = this.getAttribute('data-target-name');
|
|
const type = this.getAttribute('data-target-type');
|
|
const status = this.getAttribute('data-target-status');
|
|
|
|
const modalCtInput = document.getElementById('insp_content_type_id');
|
|
const modalObjInput = document.getElementById('insp_object_id');
|
|
const modalTypeCode = document.getElementById('insp_target_code');
|
|
const modalTypeName = document.getElementById('insp_target_name');
|
|
const modalTypeBadge = document.getElementById('insp_target_type');
|
|
const modalStatusBadge = document.getElementById('insp_target_status');
|
|
|
|
if (modalCtInput) modalCtInput.value = ctId;
|
|
if (modalObjInput) modalObjInput.value = objId;
|
|
if (modalTypeCode) modalTypeCode.textContent = code;
|
|
if (modalTypeName) modalTypeName.textContent = name;
|
|
if (modalTypeBadge) modalTypeBadge.textContent = type;
|
|
if (modalStatusBadge) modalStatusBadge.textContent = status;
|
|
});
|
|
});
|
|
|
|
const form = document.getElementById('quickInspectionForm');
|
|
if (form && !form.dataset.reloadHandlerAttached) {
|
|
form.dataset.reloadHandlerAttached = 'true';
|
|
form.addEventListener('submit', function() {
|
|
setTimeout(function() {
|
|
window.location.reload();
|
|
}, 600);
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
{% endif %}
|