140 lines
5.8 KiB
HTML
140 lines
5.8 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="fr">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Suivi commande — {{ job.name }}</title>
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css" rel="stylesheet">
|
|
<style>
|
|
body { background: #f4f6f9; }
|
|
.topbar { background: #1a1d23; color: #fff; padding: 1rem 1.5rem; }
|
|
.topbar .brand { font-weight: 800; font-size: 1.2rem; }
|
|
.topbar .brand span { color: #ff6b35; }
|
|
.card { border: none; border-radius: 10px; box-shadow: 0 1px 4px rgba(0,0,0,.06); }
|
|
.stat-val { font-size: 1.5rem; font-weight: 700; }
|
|
.timeline { position: relative; padding-left: 2rem; }
|
|
.timeline::before { content: ''; position: absolute; left: .6rem; top: 0; bottom: 0;
|
|
width: 2px; background: #dee2e6; }
|
|
.timeline-item { position: relative; margin-bottom: 1.2rem; }
|
|
.timeline-item::before { content: ''; position: absolute; left: -1.55rem; top: .3rem;
|
|
width: 12px; height: 12px; border-radius: 50%; border: 2px solid #fff;
|
|
box-shadow: 0 0 0 2px #dee2e6; background: #6b7280; }
|
|
.timeline-item.done::before { background: #22c55e; box-shadow: 0 0 0 2px #22c55e; }
|
|
.timeline-item.failed::before { background: #ef4444; box-shadow: 0 0 0 2px #ef4444; }
|
|
.timeline-item.planned::before{ background: #3b82f6; box-shadow: 0 0 0 2px #3b82f6; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="topbar d-flex align-items-center justify-content-between">
|
|
<div class="brand"><i class="bi bi-layers-half me-1"></i>3D<span>Pricing</span></div>
|
|
<small class="text-secondary">Suivi de commande</small>
|
|
</div>
|
|
|
|
<div class="container py-4" style="max-width:720px">
|
|
|
|
<!-- En-tête commande -->
|
|
<div class="card mb-4">
|
|
<div class="card-body">
|
|
<h4 class="fw-bold mb-1">{{ job.name }}</h4>
|
|
{% if job.client_name %}
|
|
<div class="text-muted small mb-3"><i class="bi bi-building me-1"></i>{{ job.client_name }}</div>
|
|
{% endif %}
|
|
|
|
<div class="row g-3">
|
|
<div class="col-6 col-md-3 text-center">
|
|
{% set status_map = {'planned':'En cours','done':'Terminé','failed':'Échec','cancelled':'Annulé'} %}
|
|
{% set slot_statuses = slots | map(attribute='status') | list %}
|
|
{% if 'done' in slot_statuses %}
|
|
<span class="badge bg-success fs-6 px-3 py-2">✅ Terminé</span>
|
|
{% elif 'failed' in slot_statuses %}
|
|
<span class="badge bg-danger fs-6 px-3 py-2">❌ Incident</span>
|
|
{% elif slots %}
|
|
<span class="badge bg-primary fs-6 px-3 py-2">🖨️ En cours</span>
|
|
{% else %}
|
|
<span class="badge bg-secondary fs-6 px-3 py-2">📋 Planifié</span>
|
|
{% endif %}
|
|
</div>
|
|
<div class="col-6 col-md-3 text-center">
|
|
<div class="text-muted small">Pièces commandées</div>
|
|
<div class="stat-val">{{ job.order_qty or 1 }}</div>
|
|
</div>
|
|
<div class="col-6 col-md-3 text-center">
|
|
<div class="text-muted small">Matière</div>
|
|
<div class="fw-semibold">
|
|
{% if job.material_name %}
|
|
{% if job.material_color %}
|
|
<span style="display:inline-block;width:12px;height:12px;border-radius:50%;
|
|
background:{{ job.material_color | css_color }};border:1px solid #ccc;
|
|
vertical-align:middle;margin-right:4px"></span>
|
|
{% endif %}
|
|
{{ job.material_name }}
|
|
{% else %}—{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-6 col-md-3 text-center">
|
|
<div class="text-muted small">Créé le</div>
|
|
<div class="fw-semibold">{{ job.created_at[:10] }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% if job.description %}
|
|
<hr class="my-3">
|
|
<p class="text-muted small mb-0"><i class="bi bi-info-circle me-1"></i>{{ job.description }}</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Timeline créneaux -->
|
|
{% if slots %}
|
|
<div class="card mb-4">
|
|
<div class="card-body">
|
|
<h6 class="fw-bold mb-3"><i class="bi bi-printer me-2"></i>Suivi d'impression</h6>
|
|
<div class="timeline">
|
|
{% for s in slots %}
|
|
<div class="timeline-item {{ s.status }}">
|
|
<div class="d-flex justify-content-between align-items-start">
|
|
<div>
|
|
<div class="fw-semibold">{{ s.printer_name }}</div>
|
|
<div class="small text-muted">
|
|
{{ s.planned_start[:16].replace('T', ' ') }} →
|
|
{{ s.planned_end[11:16] }}
|
|
</div>
|
|
{% if s.failure_note %}
|
|
<div class="small text-danger mt-1">
|
|
<i class="bi bi-exclamation-triangle me-1"></i>{{ s.failure_note }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<span class="badge
|
|
{% if s.status == 'done' %}bg-success
|
|
{% elif s.status == 'failed' %}bg-danger
|
|
{% elif s.status == 'planned' %}bg-primary
|
|
{% else %}bg-secondary{% endif %} ms-2">
|
|
{{ {'done':'Terminé','failed':'Échec','planned':'Planifié','cancelled':'Annulé'}.get(s.status, s.status) }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% else %}
|
|
<div class="card mb-4">
|
|
<div class="card-body text-center text-muted py-4">
|
|
<i class="bi bi-calendar-plus fs-2 d-block mb-2"></i>
|
|
Impression non encore planifiée.
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="text-center text-muted small">
|
|
<i class="bi bi-shield-lock me-1"></i>
|
|
Cette page est partagée uniquement pour le suivi de votre commande.
|
|
Les informations de tarification ne sont pas visibles.
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|