feat: improve assessments filters

This commit is contained in:
2025-08-07 15:33:03 +02:00
parent 666f1a85bf
commit 2a7a4cd595
6 changed files with 674 additions and 47 deletions

View File

@@ -1,9 +1,10 @@
{% extends "base.html" %}
{% from 'components/common/macros.html' import hero_section, filter_section %}
{% from 'components/common/macros.html' import hero_section, simple_filter_section %}
{% from 'components/assessment/assessment_card.html' import assessment_card %}
{% block title %}Évaluations - Gestion Scolaire{% endblock %}
{% block content %}
<div class="space-y-8">
{# Hero Section avec composant réutilisable #}
@@ -30,55 +31,29 @@
gradient_class="from-purple-600 to-blue-600"
) }}
{# Filtres avec composant réutilisable #}
{# Configuration des filtres simplifiés #}
{% set class_options = [{'value': '', 'label': 'Toutes'}] %}
{% for class_group in classes %}
{% set _ = class_options.append({'value': class_group.id|string, 'label': class_group.name}) %}
{% endfor %}
{% set filters = [
{
'id': 'trimester-filter',
'label': 'Trimestre',
'options': [
{'value': '', 'label': 'Tous'},
{'value': '1', 'label': 'Trimestre 1'},
{'value': '2', 'label': 'Trimestre 2'},
{'value': '3', 'label': 'Trimestre 3'}
]
},
{
'id': 'class-filter',
'label': 'Classe',
'options': class_options
},
{
'id': 'correction-filter',
'label': 'Correction',
'options': [
{'value': '', 'label': 'Toutes'},
{'value': 'incomplete', 'label': 'Non terminées'},
{'value': 'complete', 'label': 'Terminées'},
{'value': 'not_started', 'label': 'Non commencées'}
]
},
{
'id': 'sort-filter',
'label': 'Tri',
'options': [
{'value': 'date_desc', 'label': 'Plus récent'},
{'value': 'date_asc', 'label': 'Plus ancien'},
{'value': 'title', 'label': 'Titre A-Z'},
{'value': 'class', 'label': 'Classe'}
]
}
] %}
{% set filters_config = {
'trimester': True,
'correction': True,
'class_options': class_options
} %}
{% call filter_section(filters, {'trimester-filter': current_trimester, 'class-filter': current_class, 'correction-filter': current_correction, 'sort-filter': current_sort}) %}
<div class="flex items-center space-x-4">
<div class="text-sm text-gray-500 font-medium">
{{ assessments|length }} évaluation(s)
</div>
{% call simple_filter_section(
filters_config,
{
'trimester-filter': current_trimester,
'class-filter': current_class,
'correction-filter': current_correction
},
total_items=total_assessments_count,
filtered_items=assessments|length
) %}
<div class="flex flex-col space-y-3">
<div class="md:hidden">
<a href="{{ url_for('assessments.new') }}"
class="w-full bg-gradient-to-r from-purple-500 to-blue-500 hover:from-purple-600 hover:to-blue-600 text-white px-6 py-3 rounded-xl transition-all duration-300 font-semibold shadow-lg hover:shadow-xl transform hover:scale-105 flex items-center justify-center">
@@ -131,6 +106,19 @@
{% endif %}
</div>
{# JavaScript géré par le système centralisé #}
{% endblock %}
{% block scripts %}
<script src="{{ url_for('static', filename='js/simple-filters.js') }}"></script>
<script>
// Configuration spécifique à la page assessments
document.addEventListener('DOMContentLoaded', function() {
// Mettre à jour les compteurs si l'instance existe
if (window.simpleFilters) {
const totalCount = {{ total_assessments_count }};
const filteredCount = {{ assessments|length }};
window.simpleFilters.updateCounts(totalCount, filteredCount);
}
});
</script>
{% endblock %}

View File

@@ -7,6 +7,7 @@
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="{{ url_for('static', filename='css/design-system.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/app.css') }}">
{% block head %}{% endblock %}
<script>
// Configuration Tailwind étendue avec design tokens
tailwind.config = {

View File

@@ -183,7 +183,7 @@
</a>
{% endmacro %}
{# Macro pour filtres standardisés #}
{# Macro pour filtres standardisés - Version classique (conservée pour compatibilité) #}
{% macro filter_section(filters, current_values={}) %}
<div class="filter-section">
<div class="flex flex-col lg:flex-row lg:items-center lg:justify-between space-y-4 lg:space-y-0">
@@ -210,4 +210,86 @@
{% endif %}
</div>
</div>
{% endmacro %}
{# Macro pour filtres simplifiés et discrets #}
{% macro simple_filter_section(filters_config, current_values={}, total_items=0, filtered_items=0) %}
<div class="bg-gray-50 rounded-lg p-4 mb-6 border border-gray-200">
<!-- Filtres compacts en une ligne -->
<div class="flex flex-wrap items-center gap-4 text-sm">
<div class="flex items-center text-gray-600">
<svg class="w-4 h-4 mr-1" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M3 3a1 1 0 011-1h12a1 1 0 011 1v3a1 1 0 01-.293.707L12 11.414V15a1 1 0 01-.293.707l-2 2A1 1 0 018 17v-5.586L3.293 6.707A1 1 0 013 6V3z" clip-rule="evenodd"/>
</svg>
<span id="filtered-count">{{ filtered_items }}</span>/<span class="text-gray-500">{{ total_items }}</span>
</div>
<!-- Filtre Trimestre -->
{% if filters_config.trimester %}
<div class="flex items-center gap-1">
<span class="text-gray-500 text-xs">Trimestre:</span>
<button type="button" data-filter="trimester" data-value=""
class="filter-btn px-2 py-1 text-xs rounded border {% if not current_values.get('trimester-filter') %}bg-blue-600 text-white border-blue-600{% else %}bg-white text-gray-600 border-gray-300 hover:bg-gray-50{% endif %} transition-colors">
Tous
</button>
{% for i in range(1, 4) %}
<button type="button" data-filter="trimester" data-value="{{ i }}"
class="filter-btn px-2 py-1 text-xs rounded border {% if current_values.get('trimester-filter') == i|string %}bg-blue-600 text-white border-blue-600{% else %}bg-white text-gray-600 border-gray-300 hover:bg-gray-50{% endif %} transition-colors">
T{{ i }}
</button>
{% endfor %}
</div>
{% endif %}
<!-- Filtre Classe -->
{% if filters_config.class_options %}
<div class="flex items-center gap-1">
<span class="text-gray-500 text-xs">Classe:</span>
{% for option in filters_config.class_options %}
<button type="button" data-filter="class" data-value="{{ option.value }}"
class="filter-btn px-2 py-1 text-xs rounded border {% if current_values.get('class-filter') == option.value %}bg-blue-600 text-white border-blue-600{% else %}bg-white text-gray-600 border-gray-300 hover:bg-gray-50{% endif %} transition-colors">
{{ option.label }}
</button>
{% endfor %}
</div>
{% endif %}
<!-- Filtre État de correction -->
{% if filters_config.correction %}
<div class="flex items-center gap-1">
<span class="text-gray-500 text-xs">État:</span>
<button type="button" data-filter="correction" data-value=""
class="filter-btn px-2 py-1 text-xs rounded border {% if not current_values.get('correction-filter') %}bg-blue-600 text-white border-blue-600{% else %}bg-white text-gray-600 border-gray-300 hover:bg-gray-50{% endif %} transition-colors">
Toutes
</button>
<button type="button" data-filter="correction" data-value="not_started"
class="filter-btn px-2 py-1 text-xs rounded border {% if current_values.get('correction-filter') == 'not_started' %}bg-red-500 text-white border-red-500{% else %}bg-white text-red-600 border-red-200 hover:bg-red-50{% endif %} transition-colors">
Non commencées
</button>
<button type="button" data-filter="correction" data-value="incomplete"
class="filter-btn px-2 py-1 text-xs rounded border {% if current_values.get('correction-filter') == 'incomplete' %}bg-orange-500 text-white border-orange-500{% else %}bg-white text-orange-600 border-orange-200 hover:bg-orange-50{% endif %} transition-colors">
En cours
</button>
<button type="button" data-filter="correction" data-value="complete"
class="filter-btn px-2 py-1 text-xs rounded border {% if current_values.get('correction-filter') == 'complete' %}bg-green-500 text-white border-green-500{% else %}bg-white text-green-600 border-green-200 hover:bg-green-50{% endif %} transition-colors">
Terminées
</button>
</div>
{% endif %}
</div>
<!-- Reset discret et contenu additionnel -->
<div class="flex items-center justify-between mt-2">
<div id="active-filter-tags" class="flex flex-wrap gap-1">
<!-- Tags générés par JavaScript -->
</div>
<div class="flex items-center gap-2">
<button type="button" id="reset-filters" class="text-xs text-gray-500 hover:text-gray-700 hidden">
Effacer
</button>
{% if caller %}
{{ caller() }}
{% endif %}
</div>
</div>
</div>
{% endmacro %}