feat: durées en minutes + feedback visuel du retraitement

- Filtre format_duration : affiche les temps en min/s au lieu de secondes brutes
- Bouton reprocess : spinner animé, compteur temps réel, confirmation immédiate

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
dom
2026-02-11 17:18:03 +01:00
parent 9d07894c6f
commit 86a26b9f8c
5 changed files with 72 additions and 17 deletions

View File

@@ -14,7 +14,7 @@
{% endif %}
<div class="group-title" style="margin-top:1.5rem;">Actions</div>
<button id="reprocess-btn" style="width:100%;padding:0.6rem;background:#3b82f6;color:white;border:none;border-radius:0.375rem;cursor:pointer;font-size:0.875rem;font-weight:600;margin-bottom:0.5rem;">Relancer l'étude</button>
<div id="reprocess-status" style="font-size:0.75rem;padding:0.25rem;"></div>
<div id="reprocess-status" style="font-size:0.75rem;padding:0.25rem;min-height:1.5rem;"></div>
{% endblock %}
{% block content %}
@@ -33,7 +33,7 @@
{% if dossier.processing_time_s is not none %}
<div class="info-item">
<label>Temps de traitement</label>
<span>{{ dossier.processing_time_s }}s</span>
<span>{{ dossier.processing_time_s|format_duration }}</span>
</div>
{% endif %}
</div>
@@ -286,29 +286,41 @@ document.getElementById('reprocess-btn').addEventListener('click', async () => {
const status = document.getElementById('reprocess-status');
btn.disabled = true;
btn.textContent = 'Traitement en cours...';
status.textContent = '';
status.style.color = '#3b82f6';
btn.style.background = '#64748b';
btn.innerHTML = '<span style="display:inline-flex;align-items:center;gap:0.4rem;"><span class="spinner"></span> Traitement en cours...</span>';
status.innerHTML = '<span style="color:#3b82f6;">Demande envoyée, traitement lancé. Veuillez patienter...</span>';
const startTime = Date.now();
const timer = setInterval(() => {
const elapsed = Math.floor((Date.now() - startTime) / 1000);
const min = Math.floor(elapsed / 60);
const sec = elapsed % 60;
const timeStr = min > 0 ? min + 'min ' + String(sec).padStart(2, '0') + 's' : sec + 's';
status.innerHTML = '<span style="color:#3b82f6;">Traitement en cours... ' + timeStr + '</span>';
}, 1000);
try {
const response = await fetch('/reprocess/{{ filepath }}', { method: 'POST' });
clearInterval(timer);
const data = await response.json();
if (data.ok) {
status.textContent = data.message;
status.style.color = '#16a34a';
setTimeout(() => location.reload(), 1500);
status.innerHTML = '<span style="color:#16a34a;font-weight:600;">Traitement terminé. Rechargement...</span>';
btn.style.background = '#16a34a';
btn.innerHTML = 'Terminé';
setTimeout(() => location.reload(), 1000);
} else {
status.textContent = (data.error || 'Erreur');
status.style.color = '#dc2626';
status.innerHTML = '<span style="color:#dc2626;">' + (data.error || 'Erreur') + '</span>';
btn.disabled = false;
btn.textContent = 'Relancer l\'étude';
btn.style.background = '#3b82f6';
btn.innerHTML = 'Relancer l\'étude';
}
} catch (err) {
status.textContent = 'Erreur réseau';
status.style.color = '#dc2626';
clearInterval(timer);
status.innerHTML = '<span style="color:#dc2626;">Erreur réseau</span>';
btn.disabled = false;
btn.textContent = 'Relancer l\'étude';
btn.style.background = '#3b82f6';
btn.innerHTML = 'Relancer l\'étude';
}
});
</script>