Feat: add class page
This commit is contained in:
		
							
								
								
									
										463
									
								
								templates/class_dashboard.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										463
									
								
								templates/class_dashboard.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,463 @@ | ||||
| {% extends "base.html" %} | ||||
| {% from 'components/common/macros.html' import hero_section, action_card, progress_indicator, stat_card %} | ||||
|  | ||||
| {% block title %}{{ class_group.name }} - Dashboard{% endblock %} | ||||
|  | ||||
| {# Override le style du main container pour éviter le clipping des hover effects #} | ||||
| {% block main_class %}w-full px-8 py-8 bg-gray-100{% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
| <div class="class-dashboard" data-class-dashboard data-class-id="{{ class_group.id }}"> | ||||
|     <!-- Live region pour les annonces d'accessibilité --> | ||||
|     <div aria-live="polite" aria-atomic="true" class="live-region" data-live-region></div> | ||||
|      | ||||
|     <!-- Loading overlay --> | ||||
|     <div class="loading-overlay hidden" data-loading-overlay> | ||||
|         <div class="loading-spinner"></div> | ||||
|     </div> | ||||
|      | ||||
|     <!-- Error container --> | ||||
|     <div class="hidden" data-error-container></div> | ||||
|  | ||||
| <div class="max-w-7xl mx-auto"> | ||||
| <div class="space-y-8" style="overflow: visible; padding: 8px; margin: -8px;"> | ||||
|     {# 1. Hero Section avec Contexte de Classe #} | ||||
|     {% 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': class_group.students|length ~ ' élèves' | ||||
|         }, | ||||
|         { | ||||
|             'icon': '<svg class="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z" clip-rule="evenodd"/></svg>', | ||||
|             'text': 'Trimestre ' ~ (selected_trimester or 'Global') | ||||
|         }, | ||||
|         { | ||||
|             'icon': '<svg class="w-4 h-4 mr-2" 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>', | ||||
|             'text': (class_group.assessments|selectattr('grading_progress.status', 'ne', 'completed')|list|length) ~ ' évaluations en attente' | ||||
|         } | ||||
|     ] %} | ||||
|      | ||||
|     {{ hero_section( | ||||
|         title=class_group.name ~ " 🏫", | ||||
|         subtitle="Dashboard de gestion de classe", | ||||
|         meta_info=meta_info, | ||||
|         gradient_class="from-indigo-600 to-purple-600" | ||||
|     ) }} | ||||
|  | ||||
|     {# Breadcrumb de retour #} | ||||
|     <div class="flex items-center text-sm text-gray-600"> | ||||
|         <a href="{{ url_for('classes') }}" 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> | ||||
|             Toutes les classes | ||||
|         </a> | ||||
|     </div> | ||||
|  | ||||
|     {# 2. Actions Principales avec Code Couleur Prioritaire #} | ||||
|     <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6"> | ||||
|         {# Action ROUGE - Corrections en attente (priorité max) #} | ||||
|         {% set pending_assessments = class_group.assessments|selectattr('grading_progress.status', 'ne', 'completed')|list %} | ||||
|         {% if pending_assessments %} | ||||
|             <a href="{{ url_for('grading.assessment_grading', assessment_id=pending_assessments[0].id) }}"  | ||||
|                class="group bg-gradient-to-r from-red-500 to-red-600 text-white rounded-xl p-6 hover:from-red-600 hover:to-red-700 transition-all duration-300 transform hover:scale-[1.02] shadow-lg hover:shadow-xl"> | ||||
|                 <div class="flex items-center"> | ||||
|                     <div class="w-12 h-12 bg-white/20 rounded-xl flex items-center justify-center mr-4 group-hover:bg-white/30 transition-colors"> | ||||
|                         <svg class="w-6 h-6" 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> | ||||
|                         <h3 class="text-lg font-bold mb-1">Terminer corrections</h3> | ||||
|                         <p class="text-sm opacity-90">{{ pending_assessments|length }} évaluation(s) en attente</p> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </a> | ||||
|         {% endif %} | ||||
|  | ||||
|         {# Action VERTE - Nouvelle évaluation #} | ||||
|         <a href="{{ url_for('assessments.new') }}?class_id={{ class_group.id }}"  | ||||
|            class="group bg-gradient-to-r from-green-500 to-green-600 text-white rounded-xl p-6 hover:from-green-600 hover:to-green-700 transition-all duration-300 transform hover:scale-[1.02] shadow-lg hover:shadow-xl"> | ||||
|             <div class="flex items-center"> | ||||
|                 <div class="w-12 h-12 bg-white/20 rounded-xl flex items-center justify-center mr-4 group-hover:bg-white/30 transition-colors"> | ||||
|                     <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-lg font-bold mb-1">Nouvelle évaluation</h3> | ||||
|                     <p class="text-sm opacity-90">Créer pour {{ class_group.name }}</p> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </a> | ||||
|  | ||||
|         {# Action BLEUE - Gérer les élèves #} | ||||
|         <a href="{{ url_for('students') }}?class_id={{ class_group.id }}"  | ||||
|            class="group bg-gradient-to-r from-blue-500 to-blue-600 text-white rounded-xl p-6 hover:from-blue-600 hover:to-blue-700 transition-all duration-300 transform hover:scale-[1.02] shadow-lg hover:shadow-xl"> | ||||
|             <div class="flex items-center"> | ||||
|                 <div class="w-12 h-12 bg-white/20 rounded-xl flex items-center justify-center mr-4 group-hover:bg-white/30 transition-colors"> | ||||
|                     <svg class="w-6 h-6" 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> | ||||
|                 </div> | ||||
|                 <div> | ||||
|                     <h3 class="text-lg font-bold mb-1">Gérer élèves</h3> | ||||
|                     <p class="text-sm opacity-90">{{ class_group.students|length }} élèves inscrits</p> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </a> | ||||
|  | ||||
|         {# Action ORANGE - Voir statistiques #} | ||||
|         <button class="group bg-gradient-to-r from-orange-500 to-orange-600 text-white rounded-xl p-6 hover:from-orange-600 hover:to-orange-700 transition-all duration-300 transform hover:scale-[1.02] shadow-lg hover:shadow-xl"> | ||||
|             <div class="flex items-center"> | ||||
|                 <div class="w-12 h-12 bg-white/20 rounded-xl flex items-center justify-center mr-4 group-hover:bg-white/30 transition-colors"> | ||||
|                     <svg class="w-6 h-6" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                         <path d="M2 11a1 1 0 011-1h2a1 1 0 011 1v5a1 1 0 01-1 1H3a1 1 0 01-1-1v-5zM8 7a1 1 0 011-1h2a1 1 0 011 1v9a1 1 0 01-1 1H9a1 1 0 01-1-1V7zM14 4a1 1 0 011-1h2a1 1 0 011 1v12a1 1 0 01-1 1h-2a1 1 0 01-1-1V4z"/> | ||||
|                     </svg> | ||||
|                 </div> | ||||
|                 <div> | ||||
|                     <h3 class="text-lg font-bold mb-1">Voir statistiques</h3> | ||||
|                     <p class="text-sm opacity-90">Résultats et analyses</p> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </button> | ||||
|     </div> | ||||
|  | ||||
|     {# 3. Dashboard Statistiques par Trimestre #} | ||||
|     <div class="bg-white shadow rounded-xl"> | ||||
|         {# Header de la section #} | ||||
|         <div class="px-6 py-5 border-b border-gray-200 flex justify-between items-center"> | ||||
|             <div class="flex items-center"> | ||||
|                 <h2 class="text-xl font-bold text-gray-900">Statistiques par trimestre</h2> | ||||
|                 <span class="ml-3 bg-blue-100 text-blue-800 text-sm px-3 py-1 rounded-full font-medium"> | ||||
|                     Données temps réel | ||||
|                 </span> | ||||
|             </div> | ||||
|         </div> | ||||
|          | ||||
|         {# Navigation tabs des trimestres #} | ||||
|         <div class="px-6 pt-6"> | ||||
|             <nav class="trimester-tabs" role="tablist" aria-label="Navigation par trimestre"> | ||||
|                 <button data-trimester-tab="1"  | ||||
|                         class="trimester-tab {% if selected_trimester == 1 %}active{% endif %}" | ||||
|                         role="tab" | ||||
|                         aria-selected="{% if selected_trimester == 1 %}true{% else %}false{% endif %}"> | ||||
|                     <div class="flex items-center"> | ||||
|                         <div class="w-3 h-3 rounded-full bg-gradient-to-r from-blue-500 to-blue-600 mr-2"></div> | ||||
|                         Trimestre 1 | ||||
|                     </div> | ||||
|                 </button> | ||||
|                 <button data-trimester-tab="2"  | ||||
|                         class="trimester-tab {% if selected_trimester == 2 %}active{% endif %}" | ||||
|                         role="tab" | ||||
|                         aria-selected="{% if selected_trimester == 2 %}true{% else %}false{% endif %}"> | ||||
|                     <div class="flex items-center"> | ||||
|                         <div class="w-3 h-3 rounded-full bg-gradient-to-r from-green-500 to-green-600 mr-2"></div> | ||||
|                         Trimestre 2 | ||||
|                     </div> | ||||
|                 </button> | ||||
|                 <button data-trimester-tab="3"  | ||||
|                         class="trimester-tab {% if selected_trimester == 3 %}active{% endif %}" | ||||
|                         role="tab" | ||||
|                         aria-selected="{% if selected_trimester == 3 %}true{% else %}false{% endif %}"> | ||||
|                     <div class="flex items-center"> | ||||
|                         <div class="w-3 h-3 rounded-full bg-gradient-to-r from-orange-500 to-orange-600 mr-2"></div> | ||||
|                         Trimestre 3 | ||||
|                     </div> | ||||
|                 </button> | ||||
|                 <button data-trimester-tab="global"  | ||||
|                         class="trimester-tab {% if not selected_trimester %}active{% endif %}" | ||||
|                         role="tab" | ||||
|                         aria-selected="{% if not selected_trimester %}true{% else %}false{% endif %}"> | ||||
|                     <div class="flex items-center"> | ||||
|                         <div class="w-3 h-3 rounded-full bg-gradient-to-r from-purple-500 to-purple-600 mr-2"></div> | ||||
|                         Global | ||||
|                     </div> | ||||
|                 </button> | ||||
|             </nav> | ||||
|         </div> | ||||
|  | ||||
|         {# 4 Cards de statistiques en grid responsive #} | ||||
|         <div class="px-6 pb-6" data-stats-content> | ||||
|             <div class="stats-grid" data-stats-cards> | ||||
|                 {# Card 1 - Domaines #} | ||||
|                 <div class="bg-white rounded-xl shadow-lg p-6" data-stats-card="domains"> | ||||
|                     <div class="flex items-center justify-between mb-4"> | ||||
|                         <h3 class="text-lg font-semibold text-green-900 flex items-center"> | ||||
|                             <svg class="w-5 h-5 text-green-500 mr-2" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                                 <path fill-rule="evenodd" d="M3 4a1 1 0 011-1h12a1 1 0 011 1v2a1 1 0 01-1 1H4a1 1 0 01-1-1V4zm0 4a1 1 0 011-1h12a1 1 0 011 1v2a1 1 0 01-1 1H4a1 1 0 01-1-1V8zm0 4a1 1 0 011-1h12a1 1 0 011 1v2a1 1 0 01-1 1H4a1 1 0 01-1-1v-2z" clip-rule="evenodd"/> | ||||
|                             </svg> | ||||
|                             Domaines | ||||
|                         </h3> | ||||
|                         <div class="w-10 h-10 bg-green-500 rounded-xl flex items-center justify-center"> | ||||
|                             <svg class="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                                 <path fill-rule="evenodd" d="M3 4a1 1 0 011-1h12a1 1 0 011 1v2a1 1 0 01-1 1H4a1 1 0 01-1-1V4zm0 4a1 1 0 011-1h12a1 1 0 011 1v2a1 1 0 01-1 1H4a1 1 0 01-1-1V8zm0 4a1 1 0 011-1h12a1 1 0 011 1v2a1 1 0 01-1 1H4a1 1 0 01-1-1v-2z" clip-rule="evenodd"/> | ||||
|                             </svg> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="space-y-4"> | ||||
|                         <div class="text-center"> | ||||
|                             <div class="text-3xl font-bold text-green-900" data-domains-count>0</div> | ||||
|                             <div class="text-sm text-green-700">domaines évalués</div> | ||||
|                         </div> | ||||
|                         <div class="space-y-2" data-domains-list> | ||||
|                             <!-- Dynamic content populated by JavaScript --> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|  | ||||
|                 {# Card 2 - Compétences #} | ||||
|                 <div class="bg-white rounded-xl shadow-lg p-6" data-stats-card="competences"> | ||||
|                     <div class="flex items-center justify-between mb-4"> | ||||
|                         <h3 class="text-lg font-semibold text-purple-900 flex items-center"> | ||||
|                             <svg class="w-5 h-5 text-purple-500 mr-2" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                                 <path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"/> | ||||
|                             </svg> | ||||
|                             Compétences | ||||
|                         </h3> | ||||
|                         <div class="w-10 h-10 bg-purple-500 rounded-xl flex items-center justify-center"> | ||||
|                             <svg class="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                                 <path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"/> | ||||
|                             </svg> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="space-y-4"> | ||||
|                         <div class="text-center"> | ||||
|                             <div class="text-3xl font-bold text-purple-900" data-competences-count>0</div> | ||||
|                             <div class="text-sm text-purple-700">compétences évaluées</div> | ||||
|                         </div> | ||||
|                         <div class="space-y-2" data-competences-list> | ||||
|                             <!-- Dynamic content populated by JavaScript --> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|  | ||||
|                 {# Card 3 - Résultats #} | ||||
|                 <div class="bg-white rounded-xl shadow-lg p-6" data-stats-card="results"> | ||||
|                     <div class="flex items-center justify-between mb-4"> | ||||
|                         <h3 class="text-lg font-semibold text-orange-900 flex items-center"> | ||||
|                             <svg class="w-5 h-5 text-orange-500 mr-2" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                                 <path d="M2 11a1 1 0 011-1h2a1 1 0 011 1v5a1 1 0 01-1 1H3a1 1 0 01-1-1v-5zM8 7a1 1 0 011-1h2a1 1 0 011 1v9a1 1 0 01-1 1H9a1 1 0 01-1-1V7zM14 4a1 1 0 011-1h2a1 1 0 011 1v12a1 1 0 01-1 1h-2a1 1 0 01-1-1V4z"/> | ||||
|                             </svg> | ||||
|                             Résultats | ||||
|                         </h3> | ||||
|                         <div class="w-10 h-10 bg-orange-500 rounded-xl flex items-center justify-center"> | ||||
|                             <svg class="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                                 <path d="M2 11a1 1 0 011-1h2a1 1 0 011 1v5a1 1 0 01-1 1H3a1 1 0 01-1-1v-5zM8 7a1 1 0 011-1h2a1 1 0 011 1v9a1 1 0 01-1 1H9a1 1 0 01-1-1V7zM14 4a1 1 0 011-1h2a1 1 0 011 1v12a1 1 0 01-1 1h-2a1 1 0 01-1-1V4z"/> | ||||
|                             </svg> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <div class="space-y-4"> | ||||
|                         <div class="text-center"> | ||||
|                             <div class="text-3xl font-bold text-orange-900" data-result="mean">0.0</div> | ||||
|                             <div class="text-sm text-orange-700">moyenne générale</div> | ||||
|                             <div class="text-xs text-orange-600 mt-1" data-result="assessments_count">0 évaluation(s)</div> | ||||
|                         </div> | ||||
|                         <div class="grid grid-cols-2 gap-3 text-sm"> | ||||
|                             <div class="bg-orange-50 rounded-lg p-3 border border-orange-100"> | ||||
|                                 <div class="flex justify-between items-center"> | ||||
|                                     <span class="text-orange-800 font-medium">Min:</span> | ||||
|                                     <span class="text-orange-900 font-bold" data-result="min">0.0</span> | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                             <div class="bg-orange-50 rounded-lg p-3 border border-orange-100"> | ||||
|                                 <div class="flex justify-between items-center"> | ||||
|                                     <span class="text-orange-800 font-medium">Max:</span> | ||||
|                                     <span class="text-orange-900 font-bold" data-result="max">0.0</span> | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                             <div class="bg-orange-50 rounded-lg p-3 border border-orange-100"> | ||||
|                                 <div class="flex justify-between items-center"> | ||||
|                                     <span class="text-orange-800 font-medium">Médiane:</span> | ||||
|                                     <span class="text-orange-900 font-bold" data-result="median">0.0</span> | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                             <div class="bg-orange-50 rounded-lg p-3 border border-orange-100"> | ||||
|                                 <div class="flex justify-between items-center"> | ||||
|                                     <span class="text-orange-800 font-medium">Écart-type:</span> | ||||
|                                     <span class="text-orange-900 font-bold" data-result="std_dev">0.0</span> | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     {# 4. Tableau de Bord Évaluations #} | ||||
|     <div class="bg-white shadow rounded-xl"> | ||||
|         <div class="px-6 py-5 border-b border-gray-200 flex items-center justify-between"> | ||||
|             <div class="flex items-center"> | ||||
|                 <h2 class="text-xl font-bold text-gray-900"> | ||||
|                     Toutes les Évaluations | ||||
|                 </h2> | ||||
|                 <span class="ml-3 bg-blue-100 text-blue-800 text-sm px-3 py-1 rounded-full font-medium"> | ||||
|                     {{ class_group.assessments|length }} évaluations | ||||
|                 </span> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="px-6 py-6"> | ||||
|             {% if class_group.assessments %} | ||||
|                 <div class="space-y-4"> | ||||
|                     {% for assessment in class_group.assessments|sort(attribute='date', reverse=True) %} | ||||
|                         <div class="flex items-center justify-between p-4 bg-white border border-gray-200 rounded-xl shadow-sm hover:shadow-md transition-shadow duration-300 group"> | ||||
|                             <a href="{{ url_for('assessments.detail', id=assessment.id) }}" class="flex items-center space-x-4 flex-1 min-w-0"> | ||||
|                                 <div class="w-10 h-10 bg-gradient-to-br from-blue-500 to-purple-600 rounded-full flex items-center justify-center text-white font-bold text-sm"> | ||||
|                                     {{ assessment.title[0].upper() }} | ||||
|                                 </div> | ||||
|                                 <div class="min-w-0 flex-1"> | ||||
|                                     <h3 class="text-sm font-semibold text-gray-900 group-hover:text-blue-700 transition-colors truncate">{{ assessment.title }}</h3> | ||||
|                                     <div class="flex items-center text-xs text-gray-500 space-x-2"> | ||||
|                                         <span class="flex items-center"> | ||||
|                                             <svg class="w-3 h-3 mr-1" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                                                 <path fill-rule="evenodd" d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z" clip-rule="evenodd"/> | ||||
|                                             </svg> | ||||
|                                             {{ assessment.date.strftime('%d/%m/%Y') }} | ||||
|                                         </span> | ||||
|                                         <span>•</span> | ||||
|                                         <span>Coeff. {{ assessment.coefficient }}</span> | ||||
|                                         <span>•</span> | ||||
|                                         <span>T{{ assessment.trimester }}</span> | ||||
|                                     </div> | ||||
|                                 </div> | ||||
|                             </a> | ||||
|                             <div class="flex items-center space-x-3 flex-shrink-0"> | ||||
|                                 {# Indicateur de progression #} | ||||
|                                 {{ progress_indicator(assessment.grading_progress, clickable=True, assessment_id=assessment.id, compact=True) }} | ||||
|                                  | ||||
|                                 {# Action directe selon statut #} | ||||
|                                 {% if assessment.grading_progress.status == 'completed' %} | ||||
|                                     <a href="{{ url_for('assessments.results', id=assessment.id) }}"  | ||||
|                                        class="text-xs bg-gradient-to-r from-green-500 to-green-600 hover:from-green-600 hover:to-green-700 text-white px-3 py-1.5 rounded-lg transition-all duration-300 font-medium transform hover:scale-[1.02] shadow-lg hover:shadow-xl"> | ||||
|                                         Voir résultats | ||||
|                                     </a> | ||||
|                                 {% else %} | ||||
|                                     <a href="{{ url_for('grading.assessment_grading', assessment_id=assessment.id) }}"  | ||||
|                                        class="text-xs bg-gradient-to-r from-orange-500 to-orange-600 hover:from-orange-600 hover:to-orange-700 text-white px-3 py-1.5 rounded-lg transition-all duration-300 font-medium transform hover:scale-[1.02] shadow-lg hover:shadow-xl"> | ||||
|                                         Noter | ||||
|                                     </a> | ||||
|                                 {% endif %} | ||||
|                                  | ||||
|                                 <a href="{{ url_for('assessments.detail', id=assessment.id) }}" class="text-blue-600 group-hover:text-blue-800 opacity-70 group-hover:opacity-100 transition-all"> | ||||
|                                     <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                                         <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/> | ||||
|                                     </svg> | ||||
|                                 </a> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                     {% endfor %} | ||||
|                 </div> | ||||
|             {% else %} | ||||
|                 <div class="text-center py-12"> | ||||
|                     <div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-4"> | ||||
|                         <svg class="w-8 h-8 text-gray-400" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                             <path d="M9 2a1 1 0 000 2h2a1 1 0 100-2H9z"/> | ||||
|                             <path fill-rule="evenodd" d="M4 5a2 2 0 012-2v1a1 1 0 102 0V3a2 2 0 012 2v6a2 2 0 01-2 2H6a2 2 0 01-2-2V5zm3 2a1 1 0 000 2h2a1 1 0 100-2H7z" clip-rule="evenodd"/> | ||||
|                         </svg> | ||||
|                     </div> | ||||
|                     <h3 class="text-sm font-medium text-gray-900 mb-1"> | ||||
|                         Aucune évaluation pour cette classe | ||||
|                     </h3> | ||||
|                     <p class="text-sm text-gray-500 mb-4">Créez votre première évaluation pour cette classe</p> | ||||
|                     <a href="{{ url_for('assessments.new') }}?class_id={{ class_group.id }}"  | ||||
|                        class="inline-flex items-center text-sm bg-gradient-to-r from-blue-500 to-blue-600 hover:from-blue-600 hover:to-blue-700 text-white px-4 py-2 rounded-lg transition-all duration-300 font-semibold shadow-lg hover:shadow-xl transform hover:scale-[1.02]"> | ||||
|                         <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> | ||||
|                         Créer une évaluation | ||||
|                     </a> | ||||
|                 </div> | ||||
|             {% endif %} | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     {# 5. Aperçu Élèves (simplifié) #} | ||||
|     <div class="bg-white shadow rounded-xl"> | ||||
|         <div class="px-6 py-5 border-b border-gray-200 flex items-center justify-between"> | ||||
|             <div class="flex items-center"> | ||||
|                 <h2 class="text-xl font-bold text-gray-900">Élèves de la classe</h2> | ||||
|                 <span class="ml-3 bg-green-100 text-green-800 text-sm px-3 py-1 rounded-full font-medium"> | ||||
|                     {{ class_group.students|length }} élèves | ||||
|                 </span> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="px-6 py-6"> | ||||
|             {% if class_group.students %} | ||||
|                 <div class="text-center"> | ||||
|                     <div class="flex items-center justify-center space-x-4 text-sm text-gray-600 mb-4"> | ||||
|                         <span class="flex items-center"> | ||||
|                             <svg class="w-4 h-4 mr-1" 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> | ||||
|                             Effectif complet : {{ class_group.students|length }} élèves | ||||
|                         </span> | ||||
|                     </div> | ||||
|                     <a href="{{ url_for('students') }}?class_id={{ class_group.id }}"  | ||||
|                        class="inline-flex items-center text-sm bg-gradient-to-r from-blue-500 to-blue-600 hover:from-blue-600 hover:to-blue-700 text-white px-4 py-2 rounded-lg transition-all duration-300 font-semibold shadow-lg hover:shadow-xl transform hover:scale-[1.02]"> | ||||
|                         <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> | ||||
|                         Voir tous les élèves | ||||
|                     </a> | ||||
|                 </div> | ||||
|             {% else %} | ||||
|                 <div class="text-center py-8"> | ||||
|                     <div class="w-12 h-12 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-4"> | ||||
|                         <svg class="w-6 h-6 text-gray-400" 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> | ||||
|                     </div> | ||||
|                     <h3 class="text-sm font-medium text-gray-900 mb-2">Aucun élève inscrit</h3> | ||||
|                     <p class="text-sm text-gray-500 mb-4">Ajoutez des élèves à cette classe pour commencer les évaluations</p> | ||||
|                     <a href="{{ url_for('students') }}?class_id={{ class_group.id }}"  | ||||
|                        class="inline-flex items-center text-sm bg-gradient-to-r from-green-500 to-green-600 hover:from-green-600 hover:to-green-700 text-white px-4 py-2 rounded-lg transition-all duration-300 font-semibold shadow-lg hover:shadow-xl transform hover:scale-[1.02]"> | ||||
|                         <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> | ||||
|                         Ajouter des élèves | ||||
|                     </a> | ||||
|                 </div> | ||||
|             {% endif %} | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| </div> <!-- Fermeture max-w-7xl --> | ||||
|  | ||||
| </div> <!-- Fermeture class-dashboard --> | ||||
|  | ||||
| {% endblock %} | ||||
|  | ||||
| {% block head %} | ||||
| <script src="{{ url_for('static', filename='js/ClassDashboard.js') }}"></script> | ||||
| <style> | ||||
| /* Fix pour éviter le clipping des hover effects sur cette page */ | ||||
| .class-dashboard { | ||||
|     overflow: visible !important; | ||||
| } | ||||
|  | ||||
| .class-dashboard .grid { | ||||
|     overflow: visible !important; | ||||
| } | ||||
|  | ||||
| .class-dashboard [class*="transform"][class*="hover:scale"] { | ||||
|     transform-origin: center; | ||||
| } | ||||
|  | ||||
| /* Assurer que les conteneurs parents permettent l'overflow */ | ||||
| main { | ||||
|     overflow: visible !important; | ||||
| } | ||||
|  | ||||
| /* Ajout d'un peu d'espace pour les animations */ | ||||
| .class-dashboard .grid > * { | ||||
|     margin: 4px; | ||||
|     position: relative; | ||||
|     z-index: 1; | ||||
| } | ||||
|  | ||||
| .class-dashboard .grid > *:hover { | ||||
|     z-index: 10; | ||||
| } | ||||
| </style> | ||||
| {% endblock %} | ||||
		Reference in New Issue
	
	Block a user