feat: ajout de la pagination et des filtres dans le store d'activités, mise à jour des composants pour gérer l'affichage des jobs, et amélioration de la gestion des états des jobs. Intégration d'une nouvelle composante de pagination pour une navigation optimisée.

This commit is contained in:
ext.jeremy.guillot@maxicoffee.domains
2025-07-13 13:22:42 +02:00
parent b456f9304d
commit b4bfa48d00
6 changed files with 382 additions and 41 deletions

View File

@@ -0,0 +1,202 @@
<template>
<div v-if="totalPages > 1" class="flex items-center justify-between px-4 py-3 bg-white border-t border-gray-200">
<!-- Informations de pagination -->
<div class="flex items-center text-sm text-gray-700">
<span>
Affichage de
<span class="font-medium">{{ startItem }}</span>
à
<span class="font-medium">{{ endItem }}</span>
sur
<span class="font-medium">{{ total }}</span>
résultats
</span>
</div>
<!-- Contrôles de pagination -->
<div class="flex items-center space-x-2">
<!-- Bouton précédent -->
<button
@click="goToPage(currentPage - 1)"
:disabled="!hasPreviousPage"
:class="[
'relative inline-flex items-center px-2 py-2 text-sm font-medium rounded-md',
hasPreviousPage
? 'text-gray-500 bg-white border border-gray-300 hover:bg-gray-50'
: 'text-gray-300 bg-gray-100 border border-gray-200 cursor-not-allowed'
]">
<span class="sr-only">Précédent</span>
<ChevronLeftIcon class="h-5 w-5" />
</button>
<!-- Numéros de page -->
<div class="hidden md:flex space-x-1">
<!-- Première page -->
<button
v-if="showFirstPage"
@click="goToPage(1)"
:class="[
'relative inline-flex items-center px-3 py-2 text-sm font-medium rounded-md',
currentPage === 1
? 'z-10 bg-indigo-50 border-indigo-500 text-indigo-600'
: 'bg-white border-gray-300 text-gray-500 hover:bg-gray-50'
]">
1
</button>
<!-- Points de suspension gauche -->
<span v-if="showLeftDots" class="relative inline-flex items-center px-3 py-2 text-sm font-medium text-gray-700">
...
</span>
<!-- Pages visibles -->
<button
v-for="page in visiblePages"
:key="page"
@click="goToPage(page)"
:class="[
'relative inline-flex items-center px-3 py-2 text-sm font-medium rounded-md',
currentPage === page
? 'z-10 bg-indigo-50 border-indigo-500 text-indigo-600'
: 'bg-white border-gray-300 text-gray-500 hover:bg-gray-50'
]">
{{ page }}
</button>
<!-- Points de suspension droite -->
<span v-if="showRightDots" class="relative inline-flex items-center px-3 py-2 text-sm font-medium text-gray-700">
...
</span>
<!-- Dernière page -->
<button
v-if="showLastPage"
@click="goToPage(totalPages)"
:class="[
'relative inline-flex items-center px-3 py-2 text-sm font-medium rounded-md',
currentPage === totalPages
? 'z-10 bg-indigo-50 border-indigo-500 text-indigo-600'
: 'bg-white border-gray-300 text-gray-500 hover:bg-gray-50'
]">
{{ totalPages }}
</button>
</div>
<!-- Pagination mobile -->
<div class="md:hidden flex items-center space-x-2">
<span class="text-sm text-gray-700">
{{ currentPage }} / {{ totalPages }}
</span>
</div>
<!-- Bouton suivant -->
<button
@click="goToPage(currentPage + 1)"
:disabled="!hasNextPage"
:class="[
'relative inline-flex items-center px-2 py-2 text-sm font-medium rounded-md',
hasNextPage
? 'text-gray-500 bg-white border border-gray-300 hover:bg-gray-50'
: 'text-gray-300 bg-gray-100 border border-gray-200 cursor-not-allowed'
]">
<span class="sr-only">Suivant</span>
<ChevronRightIcon class="h-5 w-5" />
</button>
</div>
</div>
</template>
<script setup>
import { ChevronLeftIcon, ChevronRightIcon } from '@heroicons/vue/24/outline';
import { computed } from 'vue';
const props = defineProps({
currentPage: {
type: Number,
required: true
},
totalPages: {
type: Number,
required: true
},
total: {
type: Number,
required: true
},
limit: {
type: Number,
required: true
},
hasNextPage: {
type: Boolean,
default: false
},
hasPreviousPage: {
type: Boolean,
default: false
}
});
const emit = defineEmits(['page-change']);
// Calculs pour l'affichage des informations
const startItem = computed(() => {
return Math.max(1, (props.currentPage - 1) * props.limit + 1);
});
const endItem = computed(() => {
return Math.min(props.total, props.currentPage * props.limit);
});
// Logique pour afficher les numéros de page
const visiblePages = computed(() => {
const pages = [];
const maxVisible = 5; // Nombre maximum de pages visibles
const half = Math.floor(maxVisible / 2);
let start = Math.max(1, props.currentPage - half);
let end = Math.min(props.totalPages, start + maxVisible - 1);
// Ajuster le début si on est près de la fin
if (end - start + 1 < maxVisible) {
start = Math.max(1, end - maxVisible + 1);
}
// Ne pas inclure la première et dernière page dans visiblePages
// si elles sont déjà affichées séparément
const actualStart = start === 1 && props.totalPages > maxVisible ? 2 : start;
const actualEnd = end === props.totalPages && props.totalPages > maxVisible ? props.totalPages - 1 : end;
for (let i = actualStart; i <= actualEnd; i++) {
if (i !== 1 && i !== props.totalPages) {
pages.push(i);
} else if (props.totalPages <= maxVisible) {
pages.push(i);
}
}
return pages;
});
const showFirstPage = computed(() => {
return props.totalPages > 5 && props.currentPage > 3;
});
const showLastPage = computed(() => {
return props.totalPages > 5 && props.currentPage < props.totalPages - 2;
});
const showLeftDots = computed(() => {
return props.totalPages > 5 && props.currentPage > 4;
});
const showRightDots = computed(() => {
return props.totalPages > 5 && props.currentPage < props.totalPages - 3;
});
const goToPage = (page) => {
if (page >= 1 && page <= props.totalPages && page !== props.currentPage) {
emit('page-change', page);
}
};
</script>