loko/loko/assets/templates/assets/components/asset_interventions.html

263 lines
15 KiB
HTML

{% load i18n %}
{# Interventions liées à l'asset #}
<div class="card mb-3" id="asset-interventions-card">
<div class="card-header bg-light d-flex align-items-center justify-content-between">
<h5 class="mb-0">
<i class="bi bi-wrench-adjustable me-2"></i>{% translate "Interventions liées" %}
{% if interventions %}
<span class="badge bg-secondary rounded-pill ms-1">{{ interventions|length }}</span>
{% endif %}
</h5>
{% if can_add_intervention %}
<button type="button" class="btn btn-outline-primary btn-sm" data-bs-toggle="modal" data-bs-target="#createInterventionForAssetModal">
<i class="bi bi-plus-lg me-1"></i>{% translate "Créer une intervention" %}
</button>
{% endif %}
</div>
<div class="card-body p-0">
{% if interventions %}
<div class="table-responsive">
<table class="table table-hover table-sm mb-0 align-middle">
<thead class="table-light">
<tr>
<th style="width: 12%;" class="ps-3">{% translate "Code" %}</th>
<th style="width: 25%;">{% translate "Titre" %}</th>
<th style="width: 18%;">{% translate "Symptôme" %}</th>
<th style="width: 15%;">{% translate "Statut" %}</th>
<th style="width: 10%;">{% translate "Priorité" %}</th>
<th style="width: 12%;">{% translate "Attribué à" %}</th>
<th style="width: 8%;" class="pe-3">{% translate "Date" %}</th>
</tr>
</thead>
<tbody>
{% for intervention in interventions %}
<tr>
<td class="ps-3">
<a href="{% url 'interventions:intervention_detail' intervention.id %}" class="fw-bold text-decoration-none">
{{ intervention.code }}
</a>
</td>
<td>
<a href="{% url 'interventions:intervention_detail' intervention.id %}" class="text-reset text-decoration-none">
{{ intervention.title }}
</a>
{% if intervention.maintain_type == 'corrective' %}
<span class="badge bg-danger ms-1" title="{% translate 'Maintenance corrective' %}">{% translate "Corrective" %}</span>
{% elif intervention.maintain_type == 'preventive' %}
<span class="badge bg-warning text-dark ms-1" title="{% translate 'Maintenance préventive' %}">{% translate "Préventive" %}</span>
{% elif intervention.maintain_type == 'ameliorative' %}
<span class="badge bg-success ms-1" title="{% translate 'Maintenance améliorative' %}">{% translate "Améliorative" %}</span>
{% endif %}
</td>
<td>
{% if intervention.symptom %}
{{ intervention.symptom.get_name }}
{% else %}
<span class="text-muted">-</span>
{% endif %}
</td>
<td>
<span class="badge" style="background-color: {{ intervention.status_color_hex }}; color: {{ intervention.status_text_color_hex }};">
{{ intervention.get_status_display }}
</span>
</td>
<td>
{% if intervention.priority == '1' %}
<span class="badge bg-danger">{{ intervention.get_priority_display }}</span>
{% elif intervention.priority == '2' %}
<span class="badge bg-warning text-dark">{{ intervention.get_priority_display }}</span>
{% elif intervention.priority == '3' %}
<span class="badge bg-secondary">{{ intervention.get_priority_display }}</span>
{% elif intervention.priority == '4' %}
<span class="badge bg-light text-dark border">{{ intervention.get_priority_display }}</span>
{% else %}
<span class="badge bg-secondary">{{ intervention.get_priority_display|default:"-" }}</span>
{% endif %}
</td>
<td>
{% if intervention.assigned_team %}
<span class="small">{{ intervention.assigned_team.name }}</span>
{% elif intervention.assigned_provider %}
<span class="small">{{ intervention.assigned_provider.name }}</span>
{% else %}
<span class="text-muted small">-</span>
{% endif %}
</td>
<td class="pe-3">
<small class="text-muted">{{ intervention.creation_time|date:"d/m/Y" }}</small>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="p-3 text-muted">
<i class="bi bi-info-circle me-1"></i>{% translate "Aucune intervention liée à cet asset." %}
</div>
{% endif %}
</div>
</div>
{% if can_add_intervention %}
<!-- Modal de création d'une intervention depuis l'asset -->
<div class="modal fade" id="createInterventionForAssetModal" tabindex="-1" aria-labelledby="createInterventionForAssetModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header bg-light">
<h5 class="modal-title" id="createInterventionForAssetModalLabel">
<i class="bi bi-wrench-adjustable me-2"></i>{% translate "Nouvelle intervention" %}
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{% translate 'Fermer' %}"></button>
</div>
<form id="createInterventionForAssetForm" action="{% url 'assets:create_intervention_for_asset' asset_model asset.id %}" method="post">
{% csrf_token %}
<div class="modal-body">
<div id="createInterventionAlert" class="alert alert-danger d-none mb-3"></div>
<div class="mb-3">
<label class="form-label fw-semibold required">{% translate "Titre" %}</label>
<input type="text" name="title" class="form-control" placeholder="{% translate "Titre de l'intervention" %}" required>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">{% translate "Symptôme" %}</label>
<select name="symptom_id" id="asset_intervention_symptom_select" class="form-select">
<option value="">{% translate "-- Sélectionner un symptôme --" %}</option>
{% for s in symptoms %}
<option value="{{ s.id }}" data-name="{{ s.get_name }}" data-priority="{{ s.priority|default:'3' }}">{{ s.get_name }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label class="form-label fw-semibold d-block">{% translate "Type de maintenance" %}</label>
<div class="btn-group w-100" role="group" aria-label="{% translate 'Type de maintenance' %}">
<input type="radio" class="btn-check" name="maintain_type" id="maintain_type_corrective" value="corrective" checked>
<label class="btn btn-outline-danger d-flex align-items-center justify-content-center gap-1 py-2" for="maintain_type_corrective">
<i class="bi bi-wrench"></i>
<span>{% translate "Corrective" %}</span>
</label>
<input type="radio" class="btn-check" name="maintain_type" id="maintain_type_preventive" value="preventive">
<label class="btn btn-outline-warning text-dark d-flex align-items-center justify-content-center gap-1 py-2" for="maintain_type_preventive">
<i class="bi bi-shield-check"></i>
<span>{% translate "Préventive" %}</span>
</label>
<input type="radio" class="btn-check" name="maintain_type" id="maintain_type_ameliorative" value="ameliorative">
<label class="btn btn-outline-success d-flex align-items-center justify-content-center gap-1 py-2" for="maintain_type_ameliorative">
<i class="bi bi-arrow-up-circle"></i>
<span>{% translate "Améliorative" %}</span>
</label>
</div>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">{% translate "Priorité" %}</label>
<select name="priority" id="asset_intervention_priority_select" class="form-select">
<option value="1">{% translate "Urgent" %}</option>
<option value="2">{% translate "Élevé" %}</option>
<option value="3" selected>{% translate "Normal" %}</option>
<option value="4">{% translate "Bas" %}</option>
</select>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">{% translate "Description / Remarques" %}</label>
<textarea name="init_description" class="form-control" rows="3" placeholder="{% translate 'Détails ou remarques initiales...' %}"></textarea>
</div>
</div>
<div class="modal-footer bg-light">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{% translate "Annuler" %}</button>
<button type="submit" class="btn btn-primary" id="submitCreateInterventionBtn">
<span class="spinner-border spinner-border-sm me-1 d-none" id="submitCreateInterventionSpinner" role="status"></span>
<i class="bi bi-check-circle me-1" id="submitCreateInterventionIcon"></i>{% translate "Créer" %}
</button>
</div>
</form>
</div>
</div>
</div>
<script>
(function() {
const form = document.getElementById('createInterventionForAssetForm');
if (!form) return;
const symptomSelect = document.getElementById('asset_intervention_symptom_select');
const titleInput = form.querySelector('input[name="title"]');
const prioritySelect = document.getElementById('asset_intervention_priority_select');
let lastAutoTitle = '';
if (symptomSelect && titleInput) {
symptomSelect.addEventListener('change', function() {
const selectedOpt = symptomSelect.options[symptomSelect.selectedIndex];
if (selectedOpt && selectedOpt.value) {
const symName = selectedOpt.getAttribute('data-name') || selectedOpt.text.trim();
const symPriority = selectedOpt.getAttribute('data-priority');
if (!titleInput.value || titleInput.value === lastAutoTitle) {
titleInput.value = symName;
lastAutoTitle = symName;
}
if (symPriority && prioritySelect) {
prioritySelect.value = symPriority;
}
}
});
titleInput.addEventListener('input', function() {
if (titleInput.value !== lastAutoTitle) {
lastAutoTitle = '';
}
});
}
form.addEventListener('submit', function(e) {
e.preventDefault();
const alertDiv = document.getElementById('createInterventionAlert');
const submitBtn = document.getElementById('submitCreateInterventionBtn');
const spinner = document.getElementById('submitCreateInterventionSpinner');
const icon = document.getElementById('submitCreateInterventionIcon');
alertDiv.classList.add('d-none');
alertDiv.textContent = '';
submitBtn.disabled = true;
if (spinner) spinner.classList.remove('d-none');
if (icon) icon.classList.add('d-none');
const formData = new FormData(form);
fetch(form.action, {
method: 'POST',
body: formData,
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(data => {
if (data.success && data.redirect_url) {
window.location.href = data.redirect_url;
} else {
alertDiv.textContent = data.error || '{% translate "Une erreur est survenue." %}';
alertDiv.classList.remove('d-none');
submitBtn.disabled = false;
if (spinner) spinner.classList.add('d-none');
if (icon) icon.classList.remove('d-none');
}
})
.catch(err => {
alertDiv.textContent = '{% translate "Erreur réseau lors de la création." %}';
alertDiv.classList.remove('d-none');
submitBtn.disabled = false;
if (spinner) spinner.classList.add('d-none');
if (icon) icon.classList.remove('d-none');
});
});
})();
</script>
{% endif %}