183 lines
No EOL
7.8 KiB
HTML
183 lines
No EOL
7.8 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Planning préventif — GMAO{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="py-2 py-md-3">
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<h2 class="mb-0 h5"><i class="bi bi-calendar-check"></i> Planning préventif</h2>
|
|
</div>
|
|
|
|
<!-- Stats rapides -->
|
|
<div class="row g-2 g-md-3 mb-3">
|
|
<div class="col-3">
|
|
<div class="card border-danger text-center h-100">
|
|
<div class="card-body py-2 px-1">
|
|
<h4 class="text-danger mb-0" style="font-size:1.2rem;">{{ stats.overdue }}</h4>
|
|
<small class="text-muted" style="font-size:0.7rem;">En retard</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-3">
|
|
<div class="card border-warning text-center h-100">
|
|
<div class="card-body py-2 px-1">
|
|
<h4 class="text-warning mb-0" style="font-size:1.2rem;">{{ stats.this_week }}</h4>
|
|
<small class="text-muted" style="font-size:0.7rem;">Semaine</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-3">
|
|
<div class="card border-info text-center h-100">
|
|
<div class="card-body py-2 px-1">
|
|
<h4 class="text-info mb-0" style="font-size:1.2rem;">{{ stats.this_month }}</h4>
|
|
<small class="text-muted" style="font-size:0.7rem;">Mois</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-3">
|
|
<div class="card border-secondary text-center h-100">
|
|
<div class="card-body py-2 px-1">
|
|
<h4 class="text-secondary mb-0" style="font-size:1.2rem;">{{ stats.later }}</h4>
|
|
<small class="text-muted" style="font-size:0.7rem;">Plus tard</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Fréquences -->
|
|
<div class="card border-0 shadow-sm mb-3">
|
|
<div class="card-body py-2">
|
|
<div class="d-flex flex-wrap gap-1">
|
|
{% for freq in frequency_counts %}
|
|
<a href="{{ url_for('interventions.index', type='preventif', frequency=freq.days|string) }}"
|
|
class="badge bg-secondary text-decoration-none" style="font-size:0.8rem;">
|
|
{{ freq.label }} <span class="badge bg-light text-dark ms-1">{{ freq.count }}</span>
|
|
</a>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- En retard -->
|
|
{% if overdue %}
|
|
<div class="card border-danger mb-3">
|
|
<div class="card-header bg-danger text-white py-2" style="font-size:0.9rem;">
|
|
<i class="bi bi-exclamation-triangle"></i> En retard ({{ overdue|length }})
|
|
</div>
|
|
<div class="card-body p-0">
|
|
{% for interv in overdue %}
|
|
<a href="{{ url_for('interventions.detail', id=interv.id) }}" class="list-group-item list-group-item-action px-3 py-2 border-bottom">
|
|
<div class="d-flex justify-content-between align-items-start">
|
|
<div style="min-width:0;">
|
|
<strong class="text-truncate d-block">#{{ interv.id }} — {{ interv.title[:60] }}{% if interv.title|length > 60 %}…{% endif %}</strong>
|
|
<small class="text-muted">
|
|
<i class="bi bi-hdd"></i> {{ interv.equipment.name[:30] }}
|
|
{% if interv.frequency_days %}
|
|
· <i class="bi bi-arrow-repeat"></i> {{ frequency_labels.get(interv.frequency_days, interv.frequency_days ~ "j") }}
|
|
{% endif %}
|
|
</small>
|
|
</div>
|
|
<span class="badge bg-danger flex-shrink-0 ms-1" style="font-size:0.7rem;">Retard</span>
|
|
</div>
|
|
</a>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Cette semaine -->
|
|
{% if this_week %}
|
|
<div class="card border-warning mb-3">
|
|
<div class="card-header bg-warning text-dark py-2" style="font-size:0.9rem;">
|
|
<i class="bi bi-calendar-week"></i> Cette semaine ({{ this_week|length }})
|
|
</div>
|
|
<div class="card-body p-0">
|
|
{% for interv in this_week %}
|
|
<a href="{{ url_for('interventions.detail', id=interv.id) }}" class="list-group-item list-group-item-action px-3 py-2 border-bottom">
|
|
<div class="d-flex justify-content-between align-items-start">
|
|
<div style="min-width:0;">
|
|
<strong class="text-truncate d-block">#{{ interv.id }} — {{ interv.title[:60] }}{% if interv.title|length > 60 %}…{% endif %}</strong>
|
|
<small class="text-muted">
|
|
<i class="bi bi-hdd"></i> {{ interv.equipment.name[:30] }}
|
|
{% if interv.frequency_days %}
|
|
· <i class="bi bi-arrow-repeat"></i> {{ frequency_labels.get(interv.frequency_days, interv.frequency_days ~ "j") }}
|
|
{% endif %}
|
|
· <i class="bi bi-calendar"></i> {{ interv.next_due_date.strftime('%d/%m') }}
|
|
</small>
|
|
</div>
|
|
<span class="badge bg-warning text-dark flex-shrink-0 ms-1" style="font-size:0.7rem;">~{{ (interv.next_due_date - now).days }}j</span>
|
|
</div>
|
|
</a>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Ce mois -->
|
|
{% if this_month %}
|
|
<div class="card border-info mb-3">
|
|
<div class="card-header bg-info text-white py-2" style="font-size:0.9rem;">
|
|
<i class="bi bi-calendar-month"></i> Ce mois ({{ this_month|length }})
|
|
</div>
|
|
<div class="card-body p-0">
|
|
{% for interv in this_month %}
|
|
<a href="{{ url_for('interventions.detail', id=interv.id) }}" class="list-group-item list-group-item-action px-3 py-2 border-bottom">
|
|
<div class="d-flex justify-content-between align-items-start">
|
|
<div style="min-width:0;">
|
|
<strong class="text-truncate d-block">#{{ interv.id }} — {{ interv.title[:60] }}{% if interv.title|length > 60 %}…{% endif %}</strong>
|
|
<small class="text-muted">
|
|
<i class="bi bi-hdd"></i> {{ interv.equipment.name[:30] }}
|
|
{% if interv.frequency_days %}
|
|
· <i class="bi bi-arrow-repeat"></i> {{ frequency_labels.get(interv.frequency_days, interv.frequency_days ~ "j") }}
|
|
{% endif %}
|
|
· <i class="bi bi-calendar"></i> {{ interv.next_due_date.strftime('%d/%m') }}
|
|
</small>
|
|
</div>
|
|
<span class="badge bg-info flex-shrink-0 ms-1" style="font-size:0.7rem;">~{{ (interv.next_due_date - now).days }}j</span>
|
|
</div>
|
|
</a>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Plus tard -->
|
|
{% if later %}
|
|
<div class="card border-secondary mb-3">
|
|
<div class="card-header bg-secondary text-white py-2" style="font-size:0.9rem;">
|
|
<i class="bi bi-calendar-plus"></i> Plus tard ({{ later|length }})
|
|
</div>
|
|
<div class="card-body p-0">
|
|
{% for interv in later[:30] %}
|
|
<a href="{{ url_for('interventions.detail', id=interv.id) }}" class="list-group-item list-group-item-action px-3 py-2 border-bottom">
|
|
<div class="d-flex justify-content-between align-items-start">
|
|
<div style="min-width:0;">
|
|
<strong class="text-truncate d-block">#{{ interv.id }} — {{ interv.title[:60] }}{% if interv.title|length > 60 %}…{% endif %}</strong>
|
|
<small class="text-muted">
|
|
<i class="bi bi-hdd"></i> {{ interv.equipment.name[:30] }}
|
|
{% if interv.frequency_days %}
|
|
· <i class="bi bi-arrow-repeat"></i> {{ frequency_labels.get(interv.frequency_days, interv.frequency_days ~ "j") }}
|
|
{% endif %}
|
|
· <i class="bi bi-calendar"></i> {{ interv.next_due_date.strftime('%d/%m/%Y') }}
|
|
</small>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
{% endfor %}
|
|
{% if later|length > 30 %}
|
|
<div class="text-center py-2 text-muted" style="font-size:0.85rem;">
|
|
… et {{ later|length - 30 }} autres
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if not overdue and not this_week and not this_month and not later %}
|
|
<div class="text-center py-5 text-muted">
|
|
<i class="bi bi-check-circle" style="font-size:3rem;"></i>
|
|
<p class="mt-2">Aucune maintenance préventive planifiée</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endblock %} |