diff --git a/main/templates/course_detail.html b/main/templates/course_detail.html
index 0c55cd8..b634a2d 100644
--- a/main/templates/course_detail.html
+++ b/main/templates/course_detail.html
@@ -195,9 +195,12 @@ $(document).ready(function() {
// Keep the current ordering so we can restore it
var storedOrder = table.order();
+ // Expose grouping state to the global scope so exports can read it
+ window.courseGroupBy = groupBy;
$('#btnGroup').on('click', function(){
groupBy = !groupBy;
+ window.courseGroupBy = groupBy;
$(this).text(groupBy ? 'Désactiver le groupement' : 'Grouper par coureur');
if (groupBy) {
// Sort by Nom (col 1) then Prénom (col 2) to make grouping contiguous
@@ -213,6 +216,27 @@ $(document).ready(function() {
function getVisibleRows() {
var dt = $('#arriveesTable').DataTable();
var rows = dt.rows({search: 'applied'}).data().toArray();
+ // If grouping is active, inject group-header marker rows into the exported data
+ try {
+ if (window.courseGroupBy) {
+ var output = [];
+ var lastKey = null;
+ for (var i = 0; i < rows.length; i++) {
+ var name = rows[i][1] || '';
+ var prenom = rows[i][2] || '';
+ var key = name + '|' + prenom;
+ if (key !== lastKey) {
+ // marker row: first cell '__GROUP__', second cell holds the group label
+ output.push(['__GROUP__', name + ' ' + prenom, '', '', '']);
+ lastKey = key;
+ }
+ output.push(rows[i]);
+ }
+ return JSON.stringify(output);
+ }
+ } catch (e) {
+ // fallback to default rows if anything goes wrong
+ }
return JSON.stringify(rows);
}
diff --git a/main/views.py b/main/views.py
index bfff531..3b3fddd 100644
--- a/main/views.py
+++ b/main/views.py
@@ -134,7 +134,7 @@ def export_csv(request, course_id):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = f'attachment; filename="course_{course_id}_resultats.csv"'
writer = csv.writer(response)
- writer.writerow(['Rang', 'Nom', 'Classe', 'Temps'])
+ writer.writerow(['Rang', 'Nom', 'Prénom', 'Classe', 'Temps'])
import json
rows_json = request.POST.get('rows')
@@ -172,13 +172,14 @@ def export_pdf(request, course_id):
p.setFont("Helvetica-Bold", 16)
p.drawString(50, y, f"Résultats - {course.nom} ({course.date})")
- # En-tête du tableau
+ # En-tête du tableau (colonnes: premier, Nom, Prénom, Classe, Temps)
y -= 40
p.setFont("Helvetica", 12)
p.drawString(50, y, first_col_label)
p.drawString(100, y, "Nom")
- p.drawString(300, y, "Classe")
- p.drawString(400, y, "Temps")
+ p.drawString(220, y, "Prénom")
+ p.drawString(340, y, "Classe")
+ p.drawString(460, y, "Temps")
y -= 20
# Contenu : soit les lignes filtrées envoyées en POST, soit toutes les arrivées en base
@@ -188,10 +189,24 @@ def export_pdf(request, course_id):
try:
rows = json.loads(rows_json)
for row in rows:
- p.drawString(50, y, str(row[0]))
- p.drawString(100, y, str(row[1]))
- p.drawString(300, y, str(row[2]))
- p.drawString(400, y, str(row[3]))
+ # If we receive a group marker row (injected client-side when grouping), render it as a header
+ if isinstance(row, list) and len(row) > 0 and row[0] == '__GROUP__':
+ # Render group header spanning the table width
+ p.setFont("Helvetica-Bold", 12)
+ p.drawString(50, y, str(row[1]))
+ p.setFont("Helvetica", 12)
+ else:
+ # Standard row: expected format [first, nom, prenom, classe, temps]
+ first = row[0] if len(row) > 0 else ''
+ nom = row[1] if len(row) > 1 else ''
+ prenom = row[2] if len(row) > 2 else ''
+ classe = row[3] if len(row) > 3 else ''
+ temps_val = row[4] if len(row) > 4 else ''
+ p.drawString(50, y, str(first))
+ p.drawString(100, y, str(nom))
+ p.drawString(220, y, str(prenom))
+ p.drawString(340, y, str(classe))
+ p.drawString(460, y, str(temps_val))
y -= 20
# Nouvelle page si nécessaire
if y < 50:
@@ -206,8 +221,9 @@ def export_pdf(request, course_id):
first_value = a.tour if course.type == 'multi' else a.rang
p.drawString(50, y, str(first_value))
p.drawString(100, y, a.coureur.nom)
- p.drawString(300, y, a.coureur.classe)
- p.drawString(400, y, str(a.temps))
+ p.drawString(220, y, a.coureur.prenom)
+ p.drawString(340, y, a.coureur.classe)
+ p.drawString(460, y, str(a.temps))
y -= 20
# Nouvelle page si nécessaire
if y < 50: