Files
3d-pricing/templates/mobile.html
T
2026-07-07 08:58:12 +02:00

219 lines
8.7 KiB
HTML

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<title>3D Pricing — Mobile</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; padding-bottom: 2rem; }
.topbar {
background: #1a1d23; color: #fff; padding: .75rem 1rem;
display: flex; align-items: center; justify-content: space-between;
position: sticky; top: 0; z-index: 100;
}
.topbar .brand { font-weight: 700; font-size: 1.1rem; }
.topbar .brand span { color: #ff6b35; }
.section-title {
font-size: .7rem; font-weight: 700; text-transform: uppercase;
letter-spacing: .08em; color: #6b7280; padding: 1rem 1rem .4rem;
}
.slot-card {
background: #fff; border-radius: 10px; padding: .9rem 1rem;
margin: .4rem .75rem; box-shadow: 0 1px 4px rgba(0,0,0,.06);
}
.slot-card .job-name { font-weight: 600; font-size: .95rem; }
.slot-card .meta { font-size: .78rem; color: #6b7280; }
.slot-card .time { font-size: .82rem; color: #374151; }
.tab-bar {
display: flex; background: #fff; border-bottom: 2px solid #f0f0f0;
position: sticky; top: 53px; z-index: 99;
}
.tab-bar button {
flex: 1; border: none; background: none; padding: .7rem .5rem;
font-size: .8rem; color: #6b7280; font-weight: 600;
border-bottom: 2px solid transparent; margin-bottom: -2px;
transition: color .15s, border-color .15s;
}
.tab-bar button.active { color: #ff6b35; border-bottom-color: #ff6b35; }
.tab-pane { display: none; }
.tab-pane.active { display: block; }
.form-card { background: #fff; border-radius: 10px; margin: .75rem; padding: 1rem; box-shadow: 0 1px 4px rgba(0,0,0,.06); }
.btn-primary-orange { background: #ff6b35; color: #fff; border: none; border-radius: 8px; }
.btn-primary-orange:hover { background: #e85d2d; color: #fff; }
</style>
</head>
<body>
<div class="topbar">
<div class="brand"><i class="bi bi-layers-half me-1"></i>3D<span>Pricing</span></div>
<a href="/" class="btn btn-sm btn-outline-light btn-sm">
<i class="bi bi-grid me-1"></i>Bureau
</a>
</div>
<!-- Tabs -->
<div class="tab-bar">
<button class="active" onclick="showTab('planning', this)">
<i class="bi bi-calendar3 d-block mb-1"></i>Planning
</button>
<button onclick="showTab('block', this)">
<i class="bi bi-calendar-x d-block mb-1"></i>Indispo
</button>
<button onclick="showTab('shift', this)">
<i class="bi bi-arrow-left-right d-block mb-1"></i>Décaler
</button>
<button onclick="showTab('fail', this)">
<i class="bi bi-exclamation-triangle d-block mb-1"></i>Échec
</button>
</div>
{% with messages = get_flashed_messages(with_categories=true) %}
{% for cat, msg in messages %}
<div class="alert alert-{{ cat }} mx-3 mt-2 mb-0 py-2 small">{{ msg }}</div>
{% endfor %}
{% endwith %}
<!-- ── Tab : Planning ─────────────────────────────────── -->
<div class="tab-pane active" id="tab-planning">
<div class="section-title">Prochaines impressions</div>
{% if upcoming %}
{% for s in upcoming %}
<div class="slot-card">
<div class="d-flex justify-content-between align-items-start">
<div>
<div class="job-name">{{ s.job_name }}</div>
<div class="meta">
<i class="bi bi-printer me-1"></i>{{ s.printer_name }}
{% if s.client_name %} · {{ s.client_name }}{% endif %}
</div>
<div class="time mt-1">
<i class="bi bi-clock me-1"></i>
{{ s.planned_start[:16].replace('T',' ') }} →
{{ s.planned_end[11:16] }}
</div>
</div>
<span class="badge {% if s.status=='done' %}bg-success{% elif s.status=='failed' %}bg-danger{% else %}bg-secondary{% endif %}">
{{ s.status }}
</span>
</div>
</div>
{% endfor %}
{% else %}
<div class="text-center text-muted py-5">
<i class="bi bi-calendar-check fs-1 d-block mb-2"></i>
Aucune impression planifiée.
</div>
{% endif %}
</div>
<!-- ── Tab : Indisponibilité ──────────────────────────── -->
<div class="tab-pane" id="tab-block">
<div class="section-title">Ajouter une indisponibilité</div>
<div class="form-card">
<form method="POST">
<input type="hidden" name="action" value="block">
<div class="mb-3">
<label class="form-label fw-semibold">Date</label>
<input type="date" name="date" class="form-control" value="{{ today }}" required>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">Type</label>
<select name="type" class="form-select">
<option value="off">🔴 Jour off (toutes machines)</option>
<option value="maintenance">🔧 Maintenance</option>
<option value="other">📌 Autre</option>
</select>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">Machine (optionnel)</label>
<select name="printer_id" class="form-select">
<option value="">Toutes les machines</option>
{% for p in printers %}
<option value="{{ p.id }}">{{ p.name }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">Note</label>
<input type="text" name="notes" class="form-control" placeholder="Raison…">
</div>
<button type="submit" class="btn btn-primary-orange w-100">
<i class="bi bi-calendar-plus me-1"></i>Ajouter
</button>
</form>
</div>
</div>
<!-- ── Tab : Décaler ──────────────────────────────────── -->
<div class="tab-pane" id="tab-shift">
<div class="section-title">Décaler un créneau</div>
<div class="form-card">
<form method="POST">
<input type="hidden" name="action" value="shift">
<div class="mb-3">
<label class="form-label fw-semibold">Créneau à décaler</label>
<select name="slot_id" class="form-select" required>
<option value="">Choisir…</option>
{% for s in upcoming %}
<option value="{{ s.id }}">
{{ s.job_name }} — {{ s.planned_start[:16].replace('T',' ') }} [{{ s.printer_name }}]
</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">Nouveau début</label>
<input type="datetime-local" name="new_start" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary-orange w-100">
<i class="bi bi-arrow-left-right me-1"></i>Décaler
</button>
</form>
</div>
</div>
<!-- ── Tab : Échec ────────────────────────────────────── -->
<div class="tab-pane" id="tab-fail">
<div class="section-title">Signaler un échec d'impression</div>
<div class="form-card">
<form method="POST">
<input type="hidden" name="action" value="fail">
<div class="mb-3">
<label class="form-label fw-semibold">Créneau concerné</label>
<select name="slot_id" class="form-select" required>
<option value="">Choisir…</option>
{% for s in upcoming %}
<option value="{{ s.id }}">
{{ s.job_name }} — {{ s.planned_start[:16].replace('T',' ') }} [{{ s.printer_name }}]
</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">Description du problème</label>
<textarea name="failure_note" class="form-control" rows="3"
placeholder="Détachement, sous-extrusion, bourrage…"></textarea>
</div>
<button type="submit" class="btn btn-danger w-100">
<i class="bi bi-exclamation-triangle me-1"></i>Signaler l'échec
</button>
</form>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
function showTab(name, btn) {
document.querySelectorAll('.tab-pane').forEach(p => p.classList.remove('active'));
document.querySelectorAll('.tab-bar button').forEach(b => b.classList.remove('active'));
document.getElementById('tab-' + name).classList.add('active');
btn.classList.add('active');
}
</script>
</body>
</html>