You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
127 lines
6.1 KiB
127 lines
6.1 KiB
{% extends 'base.html' %} |
|
{% block content %} |
|
{% load static %} |
|
{% load temps_format %} |
|
<div class="container-fluid mt-4"> |
|
<h1 class="h3 mb-4 text-gray-800">Course : {{ course.nom }} ({{ course.date }})</h1> |
|
<div class="row"> |
|
<div class="col-lg-8 mx-auto"> |
|
<div class="card shadow mb-4"> |
|
<div class="card-header py-3"> |
|
<h6 class="m-0 font-weight-bold text-primary">Gestion de la course</h6> |
|
</div> |
|
<div class="card-body"> |
|
<form method="post"> |
|
{% csrf_token %} |
|
{% if not is_started %} |
|
<button type="submit" name="start" class="btn btn-success">Départ |
|
<i class="fa-solid fa-play"></i> |
|
</button> |
|
{% elif not is_finished %} |
|
<button type="button" id="btnFinish" class="btn btn-danger">Fin course |
|
<i class="fa-solid fa-stop"></i> |
|
</button> |
|
<!-- Modal confirmation fin de course --> |
|
<div class="modal fade" id="finishModal" tabindex="-1" role="dialog" aria-labelledby="finishModalLabel" aria-hidden="true"> |
|
<div class="modal-dialog" role="document"> |
|
<div class="modal-content"> |
|
<div class="modal-header"> |
|
<h5 class="modal-title" id="finishModalLabel">Confirmer la fin de la course</h5> |
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> |
|
<span aria-hidden="true">×</span> |
|
</button> |
|
</div> |
|
<div class="modal-body"> |
|
Êtes-vous sûr de vouloir terminer la course ? Cette action est irréversible. |
|
</div> |
|
<div class="modal-footer"> |
|
<form method="post" style="margin:0;"> |
|
{% csrf_token %} |
|
<button type="submit" name="finish" class="btn btn-danger">Valider la fin</button> |
|
</form> |
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Annuler</button> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
{% else %} |
|
<span class="badge badge-secondary">Course terminée</span> |
|
{% endif %} |
|
</form> |
|
</div> |
|
</div> |
|
<div class="card shadow mb-4"> |
|
<div class="card-header py-3 d-flex justify-content-between align-items-center"> |
|
<h6 class="m-0 font-weight-bold text-primary">Arrivées</h6> |
|
<div> |
|
<a href="{% url 'export_csv' course.id %}" class="btn btn-success mb-2"> |
|
<i class="fas fa-file-csv" title="Exporter en CSV"></i> |
|
</a> |
|
<a href="{% url 'export_pdf' course.id %}" class="btn btn-danger mb-2"> |
|
<i class="fas fa-file-pdf" title="Exporter en PDF"></i> |
|
</a> |
|
</div> |
|
</div> |
|
<div class="card-body"> |
|
<table class="table table-striped" id="arriveesTable"> |
|
<thead> |
|
<tr> |
|
<th>Rang</th> |
|
<th>Nom</th> |
|
<th>Classe</th> |
|
<th>Temps</th> |
|
</tr> |
|
</thead> |
|
<tbody> |
|
{% for a in arrivees %} |
|
<tr> |
|
<td>{{ a.rang }}</td> |
|
<td>{{ a.coureur.nom }}</td> |
|
<td>{{ a.coureur.classe }}</td> |
|
<td>{% if a.temps %}{{ a.temps|seconds_to_hms }}{% endif %}</td> |
|
</tr> |
|
{% empty %} |
|
<tr><td colspan="4">Aucun coureur arrivé.</td></tr> |
|
{% endfor %} |
|
</tbody> |
|
</table> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
{% endblock %} |
|
{% block extra_js %} |
|
<!-- DataTables JS & CSS --> |
|
<link rel="stylesheet" href="{% static 'bootstrap/dataTables.bootstrap4.min.css' %}"> |
|
<script src="{% static 'jquery/jquery.dataTables.min.js' %}"></script> |
|
<script src="{% static 'bootstrap/dataTables.bootstrap4.min.js' %}"></script> |
|
<script src="{% static 'jquery/datatables.fr.js' %}"></script> |
|
<script> |
|
const courseId = "{{ course.id }}"; |
|
const wsScheme = window.location.protocol === "https:" ? "wss" : "ws"; |
|
const wsUrl = `${wsScheme}://${window.location.host}/ws/course/${courseId}/`; |
|
const socket = new WebSocket(wsUrl); |
|
|
|
socket.onmessage = function(e) { |
|
// Recharge juste le tbody via AJAX |
|
fetch(window.location.href, { headers: { 'X-Requested-With': 'XMLHttpRequest' } }) |
|
.then(response => response.text()) |
|
.then(html => { |
|
const table = document.getElementById('arriveesTable').getElementsByTagName('tbody')[0]; |
|
table.innerHTML = html; |
|
$('#arriveesTable').DataTable(); |
|
}); |
|
}; |
|
|
|
// Modal confirmation fin de course |
|
document.getElementById('btnFinish').onclick = function() { |
|
$('#finishModal').modal('show'); |
|
}; |
|
|
|
// Initialisation DataTables au chargement |
|
$(document).ready(function() { |
|
$('#arriveesTable').DataTable(); |
|
}); |
|
</script> |
|
{% endblock %} |