diff --git a/assets/vue/app/domain/activity/application/store/activityStore.js b/assets/vue/app/domain/activity/application/store/activityStore.js index aaef161..2a422d5 100644 --- a/assets/vue/app/domain/activity/application/store/activityStore.js +++ b/assets/vue/app/domain/activity/application/store/activityStore.js @@ -8,8 +8,16 @@ export const useActivityStore = defineStore('activity', { jobs: [], loading: false, error: null, + // Pagination + currentPage: 1, + totalPages: 0, + total: 0, + limit: 20, + hasNextPage: false, + hasPreviousPage: false, + // Filtres filter: { - status: ['pending', 'in_progress', 'failed'], + status: ['pending', 'in_progress'], // Par défaut, ne montrer que les actifs sortBy: 'createdAt', sortOrder: 'DESC' } @@ -20,28 +28,57 @@ export const useActivityStore = defineStore('activity', { completedJobs: state => state.jobs.filter(job => job.isCompleted()), failedJobs: state => state.jobs.filter(job => job.hasError()), isLoading: state => state.loading, - hasError: state => !!state.error + hasError: state => !!state.error, + // Getters pour la pagination + paginationInfo: state => ({ + currentPage: state.currentPage, + totalPages: state.totalPages, + total: state.total, + limit: state.limit, + hasNextPage: state.hasNextPage, + hasPreviousPage: state.hasPreviousPage + }) }, actions: { /** * Charge la liste des jobs selon les filtres actuels + * @param {number} page - Numéro de page optionnel */ - async loadJobs() { + async loadJobs(page = null) { this.loading = true; this.error = null; try { const options = { - page: 1, // Page fixée à 1 - limit: 100, // Limite augmentée pour récupérer plus de jobs + page: page || this.currentPage, + limit: this.limit, sortBy: this.filter.sortBy, sortOrder: this.filter.sortOrder, status: this.filter.status }; const jobCollection = await jobRepository.getJobs(options); + + // Mettre à jour les données this.jobs = jobCollection.items; + this.currentPage = jobCollection.page; + this.total = jobCollection.total; + this.hasNextPage = jobCollection.hasNextPage; + this.hasPreviousPage = jobCollection.hasPreviousPage; + + // Calculer le nombre total de pages + this.totalPages = Math.ceil(this.total / this.limit); + + console.log('Store updated with:', { + jobs: this.jobs.length, + currentPage: this.currentPage, + total: this.total, + limit: this.limit, + totalPages: this.totalPages, + hasNextPage: this.hasNextPage, + hasPreviousPage: this.hasPreviousPage + }); } catch (error) { this.error = error.message; console.error('Error loading jobs:', error); @@ -50,13 +87,35 @@ export const useActivityStore = defineStore('activity', { } }, + /** + * Va à une page spécifique + * @param {number} page + */ + async goToPage(page) { + if (page >= 1 && page <= this.totalPages && page !== this.currentPage) { + this.currentPage = page; + await this.loadJobs(page); + } + }, + /** * Met à jour les filtres et recharge la liste * @param {Object} filter */ async updateFilter(filter) { this.filter = { ...this.filter, ...filter }; - await this.loadJobs(); + this.currentPage = 1; // Retourner à la première page lors du changement de filtre + await this.loadJobs(1); + }, + + /** + * Met à jour la limite par page + * @param {number} limit + */ + async updateLimit(limit) { + this.limit = limit; + this.currentPage = 1; // Retourner à la première page + await this.loadJobs(1); }, /** @@ -71,6 +130,8 @@ export const useActivityStore = defineStore('activity', { await jobRepository.deleteJob(id); // Supprimer le job de la liste locale this.jobs = this.jobs.filter(job => job.id !== id); + // Recharger la page courante pour avoir les bons totaux + await this.loadJobs(this.currentPage); } catch (error) { this.error = error.message; console.error('Error deleting job:', error); @@ -90,7 +151,7 @@ export const useActivityStore = defineStore('activity', { try { const deleted = await jobRepository.deleteJobs(criteria); // Recharger la liste après suppression - await this.loadJobs(); + await this.loadJobs(this.currentPage); return deleted; } catch (error) { this.error = error.message; diff --git a/assets/vue/app/domain/activity/domain/entities/job.js b/assets/vue/app/domain/activity/domain/entities/job.js index 56eec2e..f26a8a8 100644 --- a/assets/vue/app/domain/activity/domain/entities/job.js +++ b/assets/vue/app/domain/activity/domain/entities/job.js @@ -26,15 +26,15 @@ export class Job { } isActive() { - return ['PENDING', 'IN_PROGRESS'].includes(this.status); + return ['pending', 'in_progress'].includes(this.status); } hasError() { - return this.status === 'ERROR'; + return this.status === 'failed'; } isCompleted() { - return this.status === 'COMPLETED'; + return this.status === 'completed'; } } diff --git a/assets/vue/app/domain/activity/infrastructure/api/ApiJobRepository.js b/assets/vue/app/domain/activity/infrastructure/api/ApiJobRepository.js index d5f9a01..1b73960 100644 --- a/assets/vue/app/domain/activity/infrastructure/api/ApiJobRepository.js +++ b/assets/vue/app/domain/activity/infrastructure/api/ApiJobRepository.js @@ -23,6 +23,8 @@ export class ApiJobRepository extends JobRepositoryInterface { url += `&status=${status.join(',')}`; } + console.log('Fetching jobs from URL:', url); + const response = await fetch(url); if (!response.ok) { @@ -30,14 +32,53 @@ export class ApiJobRepository extends JobRepositoryInterface { } const data = await response.json(); + console.log('API Response:', data); + + // Gérer différents formats de réponse API + let jobs, total, currentPage, limit_returned, hasNext, hasPrev; + + if (Array.isArray(data)) { + // Si l'API retourne directement un tableau + jobs = data; + total = data.length; + currentPage = page; + limit_returned = limit; + hasNext = false; + hasPrev = false; + } else if (data.items || data.data) { + // Si l'API retourne un objet avec les données dans items ou data + jobs = data.items || data.data || []; + total = data.total || data.totalCount || jobs.length; + currentPage = data.page || data.currentPage || page; + limit_returned = data.limit || data.perPage || limit; + hasNext = data.hasNextPage || data.hasNext || (currentPage * limit_returned < total); + hasPrev = data.hasPreviousPage || data.hasPrev || currentPage > 1; + } else { + // Format par défaut + jobs = data || []; + total = data.total || 0; + currentPage = data.page || 1; + limit_returned = data.limit || limit; + hasNext = !!data.hasNextPage; + hasPrev = !!data.hasPreviousPage; + } + + console.log('Processed data:', { + jobs: jobs.length, + total, + currentPage, + limit_returned, + hasNext, + hasPrev + }); return new JobCollection( - data || [], - data.total || 0, - data.page || 1, - data.limit || limit, - !!data.hasNextPage, - !!data.hasPreviousPage + jobs, + total, + currentPage, + limit_returned, + hasNext, + hasPrev ); } catch (error) { console.error('API Error:', error); diff --git a/assets/vue/app/domain/activity/presentation/components/JobItem.vue b/assets/vue/app/domain/activity/presentation/components/JobItem.vue index 8054088..faada3f 100644 --- a/assets/vue/app/domain/activity/presentation/components/JobItem.vue +++ b/assets/vue/app/domain/activity/presentation/components/JobItem.vue @@ -2,10 +2,10 @@ @@ -32,7 +32,7 @@ -
+
-
+
@@ -50,7 +50,7 @@ 100%
-
+
@@ -79,8 +79,8 @@