- useCategoriesAdmin : extract `HYDRA_NO_PAGINATION = 999` to a named
constant (was duplicated between fetchAll and fetchTypes) + comment
the post-M0 server-pagination debt.
- useCategoryForm + useApi + shared/utils/api : drop the local copy of
`extractErrorMessage` in useCategoryForm (it was duplicating the one
in useApi), and centralize Hydra error / violation extraction in
`shared/utils/api.ts` via two new helpers :
- extractApiErrorMessage(data) : tries hydra:description, detail,
description, message, error, title, hydra:title — used by both
useApi.onResponseError and useCategoryForm.handleApiError.
- extractApiViolations(data) : returns the ApiPlatform 422
violations as a typed array (handles `violations` and
`hydra:violations`), letting each caller map them onto its own
fields. useCategoryForm now uses this helper instead of an
inline loop, ready for the next form drawer to reuse.
handleApiError keeps a manual fallback toast on non-409/422 errors :
the native useApi toast is disabled by design (`toast: false`) to allow
fine-grained 409/422 mapping, so the catch-all branch must re-emit one
or a 500 would be silent.
No behavior change — 43/43 Vitest tests still pass.
Extrait la logique fetch/CRUD inline de la page categories (ERP-49) vers
deux composables dedies, conformement au pattern Starseed :
- useCategoriesAdmin : singleton state (categories + types + loading +
error). Pre-chargement des types au mount de la page (au lieu du
fetch par ouverture du drawer). Reset au logout via
onAuthSessionCleared + appel explicite dans logout.vue.
- useCategoryForm : state local par form (pas singleton). Valide
cote client en miroir des RG back (RG-1.02 / RG-1.04 / RG-1.05),
mappe les erreurs 409 (doublon RG-1.07) et 422 (violations API
Platform) sur les bons champs. submitCreate / submitUpdate /
submitDelete renvoient la ressource ou null pour decoupler la
decision de fermeture du drawer.
La page et le drawer deviennent purement presentationnels. Aucune
regression UX : meme validations, memes toasts, meme pattern
view -> edit du drawer (via isDirty expose par useCategoryForm).
## Contexte
Ticket Lesstime : [#49](https://lesstime.malio.fr/tasks/460) — premier ticket front du M0 (Gestion des catégories).
Suit la chaîne back ERP-43..48 mergée sur develop.
## Contenu first draft (Claude Code)
- Page Nuxt `/admin/categories` (`MalioDataTable` + bouton `+ Ajouter`)
- Composant `<CategoryDrawer>` : modes création / consultation / édition, transition auto view → edit à la première modification, validation client miroir RG-1.02 (name requis) / RG-1.04 (longueur 2-120) / RG-1.05 (type requis), mapping erreurs 409 (doublon) et 422 (violations)
- Composant `<CategoryDeleteModal>` : confirmation suppression (soft delete RG-1.12)
- Types TS `Category`, `CategoryType`, `User`
- i18n `admin.categories.*` ajouté dans `fr.json`
- Fix latent en passant : ajout de `'categories'` à `AdminLinkSlug` du Page Object e2e (oublié lors d'ERP-47 quand l'item sidebar a été ajouté)
## Décisions marquantes
- Logique `fetch` inline dans `categories.vue` (sera extraite en composables `useCategoriesAdmin` + `useCategoryForm` au ticket ERP-50 / 0.8)
- Drawer dans composant séparé pour réutilisabilité
- Aucun état de tableau persisté dans l'URL (règle ABSOLUE n°6)
- Tous les composants formulaires sont `Malio*` (`MalioDataTable`, `MalioInputText`, `MalioSelect`, `MalioButton`, `MalioDrawer`)
## Polish à venir (Tristan)
Tristan testera en navigateur et peaufinera : UX, classes Tailwind, animations, icônes, wording de toasts.
Les commits de polish suivront sur la même branche.
## Tests
- `npx nuxi typecheck` : net 0 nouvelle erreur (mêmes erreurs pré-existantes que sur `develop`, infrastructure auto-import) + 1 latente corrigée (AdminLinkSlug)
- `make nuxt-test` : 43/43 passent (0 régression)
- Tests manuels navigateur : voir cahier de test du ticket Lesstime #49
## Note pre-commit hook
Le hook a remonté un échec PHPUnit pré-existant sur `develop` (`CategoryDeleteTest::testPatchOnSoftDeletedReturns404` → 401 au lieu de 404, JWT non initialisé en test runner). Aucun PHP touché dans cette MR. Commit avec `--no-verify` autorisé par Tristan.
## Reviewer suggéré
Matthieu (back ↔ front + permissions).
---------
Co-authored-by: Matthieu <mtholot19@gmail.com>
Reviewed-on: #22
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.