From ad20d1f4c9a1f3f0e12814ebaa62ccd1415d121c Mon Sep 17 00:00:00 2001 From: tristan Date: Mon, 1 Jun 2026 09:54:54 +0000 Subject: [PATCH] =?UTF-8?q?[ERP-73]=20Paginer=20toutes=20les=20listes=20c?= =?UTF-8?q?=C3=B4t=C3=A9=20front=20+=20composable=20de=20liste=20pagin?= =?UTF-8?q?=C3=A9e=20r=C3=A9utilisable=20(#30)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Contexte Ticket Lesstime : #73 (id 492) — volet front de la pagination (groupe Transversal). Dépend du back ERP-72 (déjà mergé sur develop). Pas de spec docs/specs ; référence = description #73 + .claude/rules/frontend.md. ## Implémentation - Composable réutilisable `usePaginatedList` (`frontend/shared/composables/`) générique, branché directement sur `MalioDataTable` (props page/perPage/totalItems + events update:page/update:per-page). - Force `Accept: application/ld+json` (sans Accept, API Platform renvoie un tableau plat sans pagination). - Migration des pages admin existantes (M0 catégories, Sites, Utilisateurs, Rôles) vers le composable. - Refactor de `useCategoriesAdmin` : ne porte plus la liste paginée (déplacée vers `usePaginatedList` dans la page) et concentre son rôle sur le référentiel `CategoryType` (chargé en une fois via `?pagination=false`, échappatoire prévue par `pagination_client_enabled: true` côté back). - Cas limites couverts : liste vide (pas de contrôle pagination affiché), page hors borne après filtre (retombe sur la dernière page valide), items/page 10/25/50, reset filtres/tri, swallow erreur réseau. - Pattern « liste paginée » documenté dans `.claude/rules/frontend.md` (section dédiée + exemple). ## Décision URL Le ticket suggérait « idéalement page/tri/filtre dans l'URL » — arbitré explicitement par Tristan en faveur de la règle ABSOLUE n°6 du CLAUDE.md (state local uniquement, jamais persisté dans l'URL). Aucun reflet URL implémenté ; comportement homogène entre toutes les listes migrées. ## Tests - `make nuxt-test` : 101/101 OK (22 nouveaux tests sur `usePaginatedList`, 6 anciens tests `useCategoriesAdmin.fetchAll` retirés en cohérence avec la refacto). - Vérification manuelle dans le navigateur (`make dev-nuxt`) : Sites, Utilisateurs, Rôles, Catégories affichent le sélecteur `Lignes : 10` et les boutons Prev/Next ; audit-log (non migré, composable spécifique) intact avec ses 3 pages. - Aucun test E2E ajouté (règle d'or projet). - Pre-commit hook : ESLint + PHPUnit 322/322 OK. ## Hors périmètre - `audit-log.vue` non migré : composable `useAuditLog` spécifique (cache partagé page/timeline, filtres complexes, persistance URL préexistante). Refactor risqué et net-zéro pour ERP-73. - M1 répertoire clients : pas encore livré sur develop (seules les specs sont mergées via #23). Le futur écran consommera `usePaginatedList` dès sa création. Reviewed-on: https://gitea.malio.fr/MALIO-DEV/Starseed/pulls/30 Co-authored-by: tristan Co-committed-by: tristan --- .claude/rules/frontend.md | 47 ++ .../__tests__/useCategoriesAdmin.spec.ts | 153 ++----- .../catalog/composables/useCategoriesAdmin.ts | 103 ++--- .../catalog/pages/admin/categories.vue | 39 +- frontend/modules/core/pages/admin/roles.vue | 41 +- frontend/modules/core/pages/admin/users.vue | 41 +- frontend/modules/sites/pages/admin/sites.vue | 43 +- .../__tests__/usePaginatedList.test.ts | 412 ++++++++++++++++++ .../shared/composables/usePaginatedList.ts | 364 ++++++++++++++++ 9 files changed, 971 insertions(+), 272 deletions(-) create mode 100644 frontend/shared/composables/__tests__/usePaginatedList.test.ts create mode 100644 frontend/shared/composables/usePaginatedList.ts diff --git a/.claude/rules/frontend.md b/.claude/rules/frontend.md index 6c34164..fec9242 100644 --- a/.claude/rules/frontend.md +++ b/.claude/rules/frontend.md @@ -53,6 +53,53 @@ Tout affichage LISTE tabulaire (donnees metier paginees, CRUD admin) doit passer **Exception** : tableaux purement presentationnels non paginables (diff field/old/new, grille de comparaison, matrice RBAC d'admin, etc.) peuvent rester en `` HTML brut. +## Listes paginees (standard) — usePaginatedList obligatoire + +**Toute liste qui consomme une `GetCollection` API doit passer par `usePaginatedList`** (`frontend/shared/composables/usePaginatedList.ts`). Le composable est le pendant front de la regle ABSOLUE n°13 (« toute collection est paginee cote back ») : il consomme l'envelope Hydra (`member` / `totalItems` / `view`) et expose un etat reactif a brancher directement sur `MalioDataTable`. + +Pattern de reference : + +```ts +const { + items, + totalItems, + currentPage, + itemsPerPage, + itemsPerPageOptions, + fetch: loadList, + goToPage, + setItemsPerPage, +} = usePaginatedList({ url: '/my-resources' }) + +onMounted(loadList) +``` + +```vue + +``` + +Garanties offertes par le composable : +- Force `Accept: application/ld+json` → API Platform 4 renvoie bien `member` / `totalItems` (sans Accept, retour tableau plat sans pagination). +- Defaut 10 items/page, choix client 10 / 25 / 50, aligne sur le defaut serveur. +- Mutation `setFilters` / `setSort` / `setItemsPerPage` → retombe systematiquement en page 1. +- Cas limite « page hors borne apres filtre » : retombe automatiquement sur la derniere page valide (`tests/usePaginatedList.test.ts`). +- Etat 100 % local (refs internes a l'instance) — **jamais reflete dans l'URL**, conformement a la regle « Etat des tableaux — pas de persistance URL » ci-dessous. + +A NE PAS faire : +- Charger une collection complete via `?itemsPerPage=999` pour bypasser la pagination. Le seul cas legitime de retour complet est l'alimentation d'un `