feat: add temporal student gestion
This commit is contained in:
		
							
								
								
									
										608
									
								
								templates/class_students.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										608
									
								
								templates/class_students.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,608 @@ | ||||
| {% extends "base.html" %} | ||||
| {% from 'components/common/macros.html' import hero_section %} | ||||
|  | ||||
| {% block title %}Élèves de {{ class_group.name }} - Gestion Scolaire{% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
| <div class="space-y-6"> | ||||
|     {# Hero Section avec Statistiques des Élèves #} | ||||
|     {% set meta_info = [ | ||||
|         { | ||||
|             'icon': '<svg class="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 20 20"><path d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z"/></svg>', | ||||
|             'text': stats.total_current ~ ' élèves actuels' | ||||
|         }, | ||||
|         { | ||||
|             'icon': '<svg class="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" clip-rule="evenodd"/></svg>', | ||||
|             'text': stats.recent_arrivals ~ ' arrivées (30j)' | ||||
|         }, | ||||
|         { | ||||
|             'icon': '<svg class="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z" clip-rule="evenodd"/></svg>', | ||||
|             'text': stats.recent_departures ~ ' départs (30j)' | ||||
|         } | ||||
|     ] %} | ||||
|  | ||||
|     {% set primary_action = { | ||||
|         'url': 'javascript:openEnrollModal()', | ||||
|         'text': 'Inscrire un élève', | ||||
|         'icon': '<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" clip-rule="evenodd"/></svg>' | ||||
|     } %} | ||||
|  | ||||
|     {{ hero_section( | ||||
|         title=class_group.name ~ " 👥", | ||||
|         subtitle="Gestion des élèves", | ||||
|         meta_info=meta_info, | ||||
|         primary_action=primary_action, | ||||
|         gradient_class="from-blue-500 to-blue-600" | ||||
|     ) }} | ||||
|  | ||||
|     {# Breadcrumb Navigation #} | ||||
|     <div class="flex items-center text-sm text-gray-600"> | ||||
|         <a href="{{ url_for('classes.dashboard', id=class_group.id) }}"  | ||||
|            class="hover:text-blue-600 transition-colors flex items-center"> | ||||
|             <svg class="w-4 h-4 mr-1" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                 <path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd"/> | ||||
|             </svg> | ||||
|             Retour au dashboard | ||||
|         </a> | ||||
|     </div> | ||||
|  | ||||
|     {# Statistiques d'effectifs #} | ||||
|     <div class="grid grid-cols-1 md:grid-cols-3 gap-6"> | ||||
|         <div class="bg-gradient-to-r from-blue-500 to-blue-600 text-white rounded-xl p-6"> | ||||
|             <div class="flex items-center"> | ||||
|                 <div class="w-12 h-12 bg-white/20 rounded-xl flex items-center justify-center mr-4"> | ||||
|                     <svg class="w-6 h-6" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                         <path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/> | ||||
|                     </svg> | ||||
|                 </div> | ||||
|                 <div> | ||||
|                     <h3 class="text-2xl font-bold">{{ stats.total_current }}</h3> | ||||
|                     <p class="text-sm opacity-90">Élèves actuels</p> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|          | ||||
|         <div class="bg-gradient-to-r from-green-500 to-green-600 text-white rounded-xl p-6"> | ||||
|             <div class="flex items-center"> | ||||
|                 <div class="w-12 h-12 bg-white/20 rounded-xl flex items-center justify-center mr-4"> | ||||
|                     <svg class="w-6 h-6" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                         <path fill-rule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" clip-rule="evenodd"/> | ||||
|                     </svg> | ||||
|                 </div> | ||||
|                 <div> | ||||
|                     <h3 class="text-2xl font-bold">{{ stats.recent_arrivals }}</h3> | ||||
|                     <p class="text-sm opacity-90">Arrivées (30j)</p> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|          | ||||
|         <div class="bg-gradient-to-r from-orange-500 to-orange-600 text-white rounded-xl p-6"> | ||||
|             <div class="flex items-center"> | ||||
|                 <div class="w-12 h-12 bg-white/20 rounded-xl flex items-center justify-center mr-4"> | ||||
|                     <svg class="w-6 h-6" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                         <path fill-rule="evenodd" d="M3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z" clip-rule="evenodd"/> | ||||
|                     </svg> | ||||
|                 </div> | ||||
|                 <div> | ||||
|                     <h3 class="text-2xl font-bold">{{ stats.recent_departures }}</h3> | ||||
|                     <p class="text-sm opacity-90">Départs (30j)</p> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     {# Liste des élèves actuels #} | ||||
|     <div class="bg-white shadow rounded-lg"> | ||||
|         <div class="px-6 py-4 border-b border-gray-200"> | ||||
|             <h2 class="text-xl font-semibold text-gray-900 flex items-center"> | ||||
|                 <svg class="w-6 h-6 mr-2 text-blue-600" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                     <path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/> | ||||
|                 </svg> | ||||
|                 Élèves actuellement inscrits ({{ current_students|length }}) | ||||
|             </h2> | ||||
|         </div> | ||||
|          | ||||
|         {% if current_students %} | ||||
|             <div class="divide-y divide-gray-200"> | ||||
|                 {% for student in current_students %} | ||||
|                     {% set enrollment = student.get_current_enrollment() %} | ||||
|                     <div class="px-6 py-4 flex items-center justify-between hover:bg-gray-50"> | ||||
|                         <div class="flex items-center"> | ||||
|                             <div class="w-10 h-10 bg-blue-100 rounded-full flex items-center justify-center mr-4"> | ||||
|                                 <span class="text-sm font-medium text-blue-600">{{ student.first_name[0] }}{{ student.last_name[0] }}</span> | ||||
|                             </div> | ||||
|                             <div> | ||||
|                                 <div class="text-lg font-medium text-gray-900">{{ student.first_name }} {{ student.last_name }}</div> | ||||
|                                 <div class="text-sm text-gray-500"> | ||||
|                                     {% if enrollment %} | ||||
|                                         Inscrit depuis le {{ enrollment.enrollment_date.strftime('%d/%m/%Y') }} | ||||
|                                         {% if enrollment.enrollment_reason %} | ||||
|                                             ({{ enrollment.enrollment_reason }}) | ||||
|                                         {% endif %} | ||||
|                                     {% endif %} | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                          | ||||
|                         <div class="flex space-x-2"> | ||||
|                             <button onclick="transferStudent({{ student.id }}, '{{ student.first_name }} {{ student.last_name }}')"  | ||||
|                                     class="bg-blue-100 hover:bg-blue-200 text-blue-700 px-3 py-1 rounded text-sm transition-colors"> | ||||
|                                 Transférer | ||||
|                             </button> | ||||
|                             <button onclick="departureStudent({{ student.id }}, '{{ student.first_name }} {{ student.last_name }}')"  | ||||
|                                     class="bg-orange-100 hover:bg-orange-200 text-orange-700 px-3 py-1 rounded text-sm transition-colors"> | ||||
|                                 Départ | ||||
|                             </button> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 {% endfor %} | ||||
|             </div> | ||||
|         {% else %} | ||||
|             <div class="px-6 py-8 text-center text-gray-500"> | ||||
|                 <svg class="w-12 h-12 mx-auto mb-4 text-gray-300" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                     <path d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z"/> | ||||
|                 </svg> | ||||
|                 <p>Aucun élève inscrit dans cette classe</p> | ||||
|             </div> | ||||
|         {% endif %} | ||||
|     </div> | ||||
|  | ||||
|     {# Historique des mouvements #} | ||||
|     {% if class_movements %} | ||||
|         <div class="bg-white shadow rounded-lg"> | ||||
|             <div class="px-6 py-4 border-b border-gray-200"> | ||||
|                 <h2 class="text-xl font-semibold text-gray-900 flex items-center"> | ||||
|                     <svg class="w-6 h-6 mr-2 text-gray-600" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                         <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clip-rule="evenodd"/> | ||||
|                     </svg> | ||||
|                     Historique des mouvements (6 derniers mois) | ||||
|                 </h2> | ||||
|             </div> | ||||
|              | ||||
|             <div class="divide-y divide-gray-200"> | ||||
|                 {% for student, enrollments in class_movements %} | ||||
|                     <div class="px-6 py-4"> | ||||
|                         <div class="flex items-center justify-between mb-2"> | ||||
|                             <span class="font-medium text-gray-900">{{ student.first_name }} {{ student.last_name }}</span> | ||||
|                         </div> | ||||
|                          | ||||
|                         <div class="space-y-1"> | ||||
|                             {% for enrollment in enrollments %} | ||||
|                                 <div class="flex items-center justify-between text-sm"> | ||||
|                                     <div class="flex items-center"> | ||||
|                                         {% if enrollment.departure_date %} | ||||
|                                             <span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-orange-100 text-orange-800 mr-2"> | ||||
|                                                 Départ | ||||
|                                             </span> | ||||
|                                             <span class="text-gray-600"> | ||||
|                                                 Du {{ enrollment.enrollment_date.strftime('%d/%m/%Y') }} au {{ enrollment.departure_date.strftime('%d/%m/%Y') }} | ||||
|                                                 {% if enrollment.departure_reason %} | ||||
|                                                     - {{ enrollment.departure_reason }} | ||||
|                                                 {% endif %} | ||||
|                                             </span> | ||||
|                                         {% else %} | ||||
|                                             <span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-green-100 text-green-800 mr-2"> | ||||
|                                                 Arrivée | ||||
|                                             </span> | ||||
|                                             <span class="text-gray-600"> | ||||
|                                                 Depuis le {{ enrollment.enrollment_date.strftime('%d/%m/%Y') }} | ||||
|                                                 {% if enrollment.enrollment_reason %} | ||||
|                                                     - {{ enrollment.enrollment_reason }} | ||||
|                                                 {% endif %} | ||||
|                                             </span> | ||||
|                                         {% endif %} | ||||
|                                     </div> | ||||
|                                      | ||||
|                                     {% if enrollment.departure_date %} | ||||
|                                         <button onclick="cancelDeparture({{ enrollment.id }}, '{{ student.first_name }} {{ student.last_name }}')" | ||||
|                                                 class="bg-green-100 hover:bg-green-200 text-green-700 px-2 py-1 rounded text-xs transition-colors"> | ||||
|                                             Annuler le départ | ||||
|                                         </button> | ||||
|                                     {% endif %} | ||||
|                                 </div> | ||||
|                             {% endfor %} | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 {% endfor %} | ||||
|             </div> | ||||
|         </div> | ||||
|     {% endif %} | ||||
| </div> | ||||
|  | ||||
| {# Modal d'inscription d'élève #} | ||||
| <div id="enrollModal" class="fixed inset-0 bg-gray-600 bg-opacity-50 hidden items-center justify-center z-50"> | ||||
|     <div class="bg-white rounded-lg p-6 max-w-md w-full mx-4"> | ||||
|         <div class="flex items-center justify-between mb-4"> | ||||
|             <h3 class="text-lg font-semibold">Inscrire un élève dans {{ class_group.name }}</h3> | ||||
|             <button type="button" onclick="closeEnrollModal()"  | ||||
|                     class="text-gray-400 hover:text-gray-600 transition-colors"> | ||||
|                 <svg class="w-6 h-6" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                     <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"/> | ||||
|                 </svg> | ||||
|             </button> | ||||
|         </div> | ||||
|          | ||||
|         {# Tabs pour choisir le mode #} | ||||
|         <div class="flex mb-4 border-b border-gray-200"> | ||||
|             <button type="button" id="newStudentTab"  | ||||
|                     class="px-4 py-2 text-sm font-medium text-blue-600 border-b-2 border-blue-600" | ||||
|                     onclick="switchEnrollMode('new')"> | ||||
|                 Nouvel élève | ||||
|             </button> | ||||
|             <button type="button" id="existingStudentTab"  | ||||
|                     class="px-4 py-2 text-sm font-medium text-gray-500 border-b-2 border-transparent" | ||||
|                     onclick="switchEnrollMode('existing')"> | ||||
|                 Élève existant | ||||
|             </button> | ||||
|         </div> | ||||
|          | ||||
|         <form id="enrollForm" method="post" action="{{ url_for('classes.enroll_student') }}"> | ||||
|             <input type="hidden" name="class_id" value="{{ class_group.id }}"> | ||||
|             <input type="hidden" name="mode" id="enrollMode" value="new"> | ||||
|              | ||||
|             {# Mode élève existant #} | ||||
|             <div id="existingStudentFields" class="hidden"> | ||||
|                 <div class="mb-4"> | ||||
|                     <label for="student_id" class="block text-sm font-medium text-gray-700 mb-2">Élève</label> | ||||
|                     <select name="student_id" id="student_id" | ||||
|                             class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"> | ||||
|                         <option value="">Sélectionner un élève</option> | ||||
|                         {% for student in available_students %} | ||||
|                             <option value="{{ student.id }}"> | ||||
|                                 {{ student.first_name }} {{ student.last_name }} | ||||
|                                 {% set current_class = student.get_current_class() %} | ||||
|                                 {% if current_class %} | ||||
|                                     (actuellement en {{ current_class.name }}) | ||||
|                                 {% else %} | ||||
|                                     (non inscrit) | ||||
|                                 {% endif %} | ||||
|                             </option> | ||||
|                         {% endfor %} | ||||
|                     </select> | ||||
|                 </div> | ||||
|             </div> | ||||
|              | ||||
|             {# Mode nouvel élève #} | ||||
|             <div id="newStudentFields"> | ||||
|                 <div class="grid grid-cols-2 gap-4 mb-4"> | ||||
|                     <div> | ||||
|                         <label for="new_first_name" class="block text-sm font-medium text-gray-700 mb-2">Prénom</label> | ||||
|                         <input type="text" name="new_first_name" id="new_first_name"  | ||||
|                                class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"> | ||||
|                     </div> | ||||
|                     <div> | ||||
|                         <label for="new_last_name" class="block text-sm font-medium text-gray-700 mb-2">Nom</label> | ||||
|                         <input type="text" name="new_last_name" id="new_last_name"  | ||||
|                                class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="mb-4"> | ||||
|                     <label for="new_email" class="block text-sm font-medium text-gray-700 mb-2">Email (optionnel)</label> | ||||
|                     <input type="email" name="new_email" id="new_email"  | ||||
|                            class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"> | ||||
|                 </div> | ||||
|             </div> | ||||
|              | ||||
|             <div class="mb-4"> | ||||
|                 <label for="enrollment_date" class="block text-sm font-medium text-gray-700 mb-2">Date d'inscription</label> | ||||
|                 <input type="date" name="enrollment_date" id="enrollment_date" required | ||||
|                        class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"> | ||||
|             </div> | ||||
|              | ||||
|             <div class="mb-6"> | ||||
|                 <label for="enrollment_reason" class="block text-sm font-medium text-gray-700 mb-2">Motif (optionnel)</label> | ||||
|                 <input type="text" name="enrollment_reason" id="enrollment_reason"  | ||||
|                        placeholder="Ex: Nouvelle inscription, Transfert d'établissement..." | ||||
|                        class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"> | ||||
|             </div> | ||||
|              | ||||
|             <div class="flex justify-end space-x-3"> | ||||
|                 <button type="button" onclick="closeEnrollModal()"  | ||||
|                         class="px-4 py-2 text-gray-600 hover:text-gray-800 transition-colors"> | ||||
|                     Annuler | ||||
|                 </button> | ||||
|                 <button type="submit"  | ||||
|                         class="bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-md transition-colors"> | ||||
|                     Inscrire | ||||
|                 </button> | ||||
|             </div> | ||||
|         </form> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| {# Modal de transfert #} | ||||
| <div id="transferModal" class="fixed inset-0 bg-gray-600 bg-opacity-50 hidden items-center justify-center z-50"> | ||||
|     <div class="bg-white rounded-lg p-6 max-w-md w-full mx-4"> | ||||
|         <div class="flex items-center justify-between mb-4"> | ||||
|             <h3 class="text-lg font-semibold">Transférer <span id="transferStudentName"></span></h3> | ||||
|             <button type="button" onclick="closeTransferModal()"  | ||||
|                     class="text-gray-400 hover:text-gray-600 transition-colors"> | ||||
|                 <svg class="w-6 h-6" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                     <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"/> | ||||
|                 </svg> | ||||
|             </button> | ||||
|         </div> | ||||
|          | ||||
|         <form id="transferForm" method="post" action="{{ url_for('classes.transfer_student') }}"> | ||||
|             <input type="hidden" name="student_id" id="transferStudentId"> | ||||
|              | ||||
|             <div class="mb-4"> | ||||
|                 <label for="new_class_id" class="block text-sm font-medium text-gray-700 mb-2">Nouvelle classe</label> | ||||
|                 <select name="new_class_id" id="new_class_id" required  | ||||
|                         class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"> | ||||
|                     <option value="">Sélectionner une classe</option> | ||||
|                     {% for class in other_classes %} | ||||
|                         <option value="{{ class.id }}">{{ class.name }}</option> | ||||
|                     {% endfor %} | ||||
|                 </select> | ||||
|             </div> | ||||
|              | ||||
|             <div class="mb-4"> | ||||
|                 <label for="transfer_date" class="block text-sm font-medium text-gray-700 mb-2">Date de transfert</label> | ||||
|                 <input type="date" name="transfer_date" id="transfer_date" required | ||||
|                        class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"> | ||||
|             </div> | ||||
|              | ||||
|             <div class="mb-6"> | ||||
|                 <label for="transfer_reason" class="block text-sm font-medium text-gray-700 mb-2">Motif (optionnel)</label> | ||||
|                 <input type="text" name="transfer_reason" id="transfer_reason"  | ||||
|                        placeholder="Ex: Changement de niveau, Réorientation..." | ||||
|                        class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"> | ||||
|             </div> | ||||
|              | ||||
|             <div class="flex justify-end space-x-3"> | ||||
|                 <button type="button" onclick="closeTransferModal()"  | ||||
|                         class="px-4 py-2 text-gray-600 hover:text-gray-800 transition-colors"> | ||||
|                     Annuler | ||||
|                 </button> | ||||
|                 <button type="submit"  | ||||
|                         class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-md transition-colors"> | ||||
|                     Transférer | ||||
|                 </button> | ||||
|             </div> | ||||
|         </form> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| {# Modal de départ #} | ||||
| <div id="departureModal" class="fixed inset-0 bg-gray-600 bg-opacity-50 hidden items-center justify-center z-50"> | ||||
|     <div class="bg-white rounded-lg p-6 max-w-md w-full mx-4"> | ||||
|         <div class="flex items-center justify-between mb-4"> | ||||
|             <h3 class="text-lg font-semibold">Marquer le départ de <span id="departureStudentName"></span></h3> | ||||
|             <button type="button" onclick="closeDepartureModal()"  | ||||
|                     class="text-gray-400 hover:text-gray-600 transition-colors"> | ||||
|                 <svg class="w-6 h-6" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                     <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"/> | ||||
|                 </svg> | ||||
|             </button> | ||||
|         </div> | ||||
|          | ||||
|         <form id="departureForm" method="post" action="{{ url_for('classes.student_departure') }}"> | ||||
|             <input type="hidden" name="student_id" id="departureStudentId"> | ||||
|              | ||||
|             <div class="mb-4"> | ||||
|                 <label for="departure_date" class="block text-sm font-medium text-gray-700 mb-2">Date de départ</label> | ||||
|                 <input type="date" name="departure_date" id="departure_date" required | ||||
|                        class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"> | ||||
|             </div> | ||||
|              | ||||
|             <div class="mb-6"> | ||||
|                 <label for="departure_reason" class="block text-sm font-medium text-gray-700 mb-2">Motif (optionnel)</label> | ||||
|                 <input type="text" name="departure_reason" id="departure_reason"  | ||||
|                        placeholder="Ex: Fin de scolarité, Déménagement, Changement d'établissement..." | ||||
|                        class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"> | ||||
|             </div> | ||||
|              | ||||
|             <div class="flex justify-end space-x-3"> | ||||
|                 <button type="button" onclick="closeDepartureModal()"  | ||||
|                         class="px-4 py-2 text-gray-600 hover:text-gray-800 transition-colors"> | ||||
|                     Annuler | ||||
|                 </button> | ||||
|                 <button type="submit"  | ||||
|                         class="bg-orange-600 hover:bg-orange-700 text-white px-4 py-2 rounded-md transition-colors"> | ||||
|                     Confirmer le départ | ||||
|                 </button> | ||||
|             </div> | ||||
|         </form> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| {# Modal de confirmation d'annulation de départ #} | ||||
| <div id="cancelDepartureModal" class="fixed inset-0 bg-gray-600 bg-opacity-50 hidden items-center justify-center z-50"> | ||||
|     <div class="bg-white rounded-lg p-6 max-w-md w-full mx-4"> | ||||
|         <div class="flex items-center justify-between mb-4"> | ||||
|             <h3 class="text-lg font-semibold">Annuler le départ de <span id="cancelDepartureStudentName"></span></h3> | ||||
|             <button type="button" onclick="closeCancelDepartureModal()"  | ||||
|                     class="text-gray-400 hover:text-gray-600 transition-colors"> | ||||
|                 <svg class="w-6 h-6" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                     <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"/> | ||||
|                 </svg> | ||||
|             </button> | ||||
|         </div> | ||||
|          | ||||
|         <div class="mb-6"> | ||||
|             <div class="bg-yellow-50 border border-yellow-200 rounded-lg p-4"> | ||||
|                 <div class="flex"> | ||||
|                     <div class="flex-shrink-0"> | ||||
|                         <svg class="h-5 w-5 text-yellow-400" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                             <path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd"/> | ||||
|                         </svg> | ||||
|                     </div> | ||||
|                     <div class="ml-3"> | ||||
|                         <h4 class="text-sm font-medium text-yellow-800">Attention</h4> | ||||
|                         <p class="text-sm text-yellow-700 mt-1"> | ||||
|                             Cette action va réintégrer l'élève dans la classe et supprimer la date de départ.  | ||||
|                             L'élève redeviendra éligible pour les futures évaluations de cette classe. | ||||
|                         </p> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|          | ||||
|         <form id="cancelDepartureForm" method="post" action="{{ url_for('classes.cancel_departure') }}"> | ||||
|             <input type="hidden" name="enrollment_id" id="cancelDepartureEnrollmentId"> | ||||
|              | ||||
|             <div class="flex justify-end space-x-3"> | ||||
|                 <button type="button" onclick="closeCancelDepartureModal()"  | ||||
|                         class="px-4 py-2 text-gray-600 hover:text-gray-800 transition-colors"> | ||||
|                     Annuler | ||||
|                 </button> | ||||
|                 <button type="submit"  | ||||
|                         class="bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-md transition-colors"> | ||||
|                     Confirmer l'annulation | ||||
|                 </button> | ||||
|             </div> | ||||
|         </form> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| <script> | ||||
| // Initialiser la date d'aujourd'hui dans les champs de date | ||||
| document.addEventListener('DOMContentLoaded', function() { | ||||
|     const today = new Date().toISOString().split('T')[0]; | ||||
|     document.getElementById('enrollment_date').value = today; | ||||
|     document.getElementById('transfer_date').value = today; | ||||
|     document.getElementById('departure_date').value = today; | ||||
|      | ||||
|     // Vérifier s'il y a eu un rechargement après inscription | ||||
|     const urlParams = new URLSearchParams(window.location.search); | ||||
|     if (urlParams.has('reload')) { | ||||
|         // Supprimer le paramètre de l'URL pour éviter le rechargement en boucle | ||||
|         const newUrl = window.location.pathname; | ||||
|         window.history.replaceState({}, document.title, newUrl); | ||||
|          | ||||
|         // Faire défiler vers le haut pour voir le message de succès | ||||
|         window.scrollTo(0, 0); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| // Gestion des modals d'inscription | ||||
| function openEnrollModal() { | ||||
|     document.getElementById('enrollModal').classList.remove('hidden'); | ||||
|     document.getElementById('enrollModal').classList.add('flex'); | ||||
|     // Réinitialiser au mode "nouvel élève" par défaut | ||||
|     switchEnrollMode('new'); | ||||
| } | ||||
|  | ||||
| function closeEnrollModal() { | ||||
|     document.getElementById('enrollModal').classList.add('hidden'); | ||||
|     document.getElementById('enrollModal').classList.remove('flex'); | ||||
|     // Réinitialiser le formulaire | ||||
|     document.getElementById('enrollForm').reset(); | ||||
|     const today = new Date().toISOString().split('T')[0]; | ||||
|     document.getElementById('enrollment_date').value = today; | ||||
| } | ||||
|  | ||||
| // Gestion du changement de mode d'inscription | ||||
| function switchEnrollMode(mode) { | ||||
|     const existingTab = document.getElementById('existingStudentTab'); | ||||
|     const newTab = document.getElementById('newStudentTab'); | ||||
|     const existingFields = document.getElementById('existingStudentFields'); | ||||
|     const newFields = document.getElementById('newStudentFields'); | ||||
|     const modeInput = document.getElementById('enrollMode'); | ||||
|      | ||||
|     if (mode === 'existing') { | ||||
|         // Activer l'onglet "Élève existant" | ||||
|         existingTab.classList.add('text-blue-600', 'border-blue-600'); | ||||
|         existingTab.classList.remove('text-gray-500', 'border-transparent'); | ||||
|         newTab.classList.add('text-gray-500', 'border-transparent'); | ||||
|         newTab.classList.remove('text-blue-600', 'border-blue-600'); | ||||
|          | ||||
|         // Afficher les champs correspondants | ||||
|         existingFields.classList.remove('hidden'); | ||||
|         newFields.classList.add('hidden'); | ||||
|          | ||||
|         // Mettre à jour le mode | ||||
|         modeInput.value = 'existing'; | ||||
|          | ||||
|         // Rendre student_id requis | ||||
|         document.getElementById('student_id').required = true; | ||||
|         document.getElementById('new_first_name').required = false; | ||||
|         document.getElementById('new_last_name').required = false; | ||||
|     } else { | ||||
|         // Activer l'onglet "Nouvel élève" | ||||
|         newTab.classList.add('text-blue-600', 'border-blue-600'); | ||||
|         newTab.classList.remove('text-gray-500', 'border-transparent'); | ||||
|         existingTab.classList.add('text-gray-500', 'border-transparent'); | ||||
|         existingTab.classList.remove('text-blue-600', 'border-blue-600'); | ||||
|          | ||||
|         // Afficher les champs correspondants | ||||
|         newFields.classList.remove('hidden'); | ||||
|         existingFields.classList.add('hidden'); | ||||
|          | ||||
|         // Mettre à jour le mode | ||||
|         modeInput.value = 'new'; | ||||
|          | ||||
|         // Rendre les champs du nouvel élève requis | ||||
|         document.getElementById('student_id').required = false; | ||||
|         document.getElementById('new_first_name').required = true; | ||||
|         document.getElementById('new_last_name').required = true; | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Gestion des modals de transfert | ||||
| function transferStudent(studentId, studentName) { | ||||
|     document.getElementById('transferStudentId').value = studentId; | ||||
|     document.getElementById('transferStudentName').textContent = studentName; | ||||
|     document.getElementById('transferModal').classList.remove('hidden'); | ||||
|     document.getElementById('transferModal').classList.add('flex'); | ||||
| } | ||||
|  | ||||
| function closeTransferModal() { | ||||
|     document.getElementById('transferModal').classList.add('hidden'); | ||||
|     document.getElementById('transferModal').classList.remove('flex'); | ||||
| } | ||||
|  | ||||
| // Gestion des modals de départ | ||||
| function departureStudent(studentId, studentName) { | ||||
|     document.getElementById('departureStudentId').value = studentId; | ||||
|     document.getElementById('departureStudentName').textContent = studentName; | ||||
|     document.getElementById('departureModal').classList.remove('hidden'); | ||||
|     document.getElementById('departureModal').classList.add('flex'); | ||||
| } | ||||
|  | ||||
| function closeDepartureModal() { | ||||
|     document.getElementById('departureModal').classList.add('hidden'); | ||||
|     document.getElementById('departureModal').classList.remove('flex'); | ||||
| } | ||||
|  | ||||
| // Gestion des modals d'annulation de départ | ||||
| function cancelDeparture(enrollmentId, studentName) { | ||||
|     document.getElementById('cancelDepartureEnrollmentId').value = enrollmentId; | ||||
|     document.getElementById('cancelDepartureStudentName').textContent = studentName; | ||||
|     document.getElementById('cancelDepartureModal').classList.remove('hidden'); | ||||
|     document.getElementById('cancelDepartureModal').classList.add('flex'); | ||||
| } | ||||
|  | ||||
| function closeCancelDepartureModal() { | ||||
|     document.getElementById('cancelDepartureModal').classList.add('hidden'); | ||||
|     document.getElementById('cancelDepartureModal').classList.remove('flex'); | ||||
| } | ||||
|  | ||||
| // Fermer les modals en cliquant à l'extérieur | ||||
| document.addEventListener('click', function(event) { | ||||
|     const modals = ['enrollModal', 'transferModal', 'departureModal', 'cancelDepartureModal']; | ||||
|     modals.forEach(modalId => { | ||||
|         const modal = document.getElementById(modalId); | ||||
|         if (event.target === modal) { | ||||
|             modal.classList.add('hidden'); | ||||
|             modal.classList.remove('flex'); | ||||
|         } | ||||
|     }); | ||||
| }); | ||||
|  | ||||
| // Fermer les modals avec la touche Échap | ||||
| document.addEventListener('keydown', function(event) { | ||||
|     if (event.key === 'Escape') { | ||||
|         const modals = ['enrollModal', 'transferModal', 'departureModal', 'cancelDepartureModal']; | ||||
|         modals.forEach(modalId => { | ||||
|             const modal = document.getElementById(modalId); | ||||
|             if (modal && !modal.classList.contains('hidden')) { | ||||
|                 modal.classList.add('hidden'); | ||||
|                 modal.classList.remove('flex'); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| }); | ||||
| </script> | ||||
| {% endblock %} | ||||
		Reference in New Issue
	
	Block a user