Correctifs frontend ecran categories + alignement boutons admin (ERP-117) (#77)
Auto Tag Develop / tag (push) Successful in 9s

## Contexte
ERP-117 — correctifs frontend sur l'ecran de gestion des categories et alignement des boutons d'action des ecrans admin.

## Changements
### Drawer categories
- Titre stable « Modifier la categorie » (plus de bascule view → edit selon l'etat « dirty »), aligne sur les drawers simples du projet.
- Bouton Enregistrer toujours actif : il sauvegarde a tout moment, meme sans modification (PATCH du payload complet `name` + `categoryTypes`, comme `SiteDrawer`).
- Champ « Types de categorie » : suppression du label « Selectionner un ou plusieurs types ».

### Alignement des boutons admin
- Ecran Categories : ordre des boutons Filtres avant Ajouter + gap reduit (`gap-8`), comme le repertoire client.
- Boutons d'ajout admin (categories, roles, sites) passes en `variant=secondary`.
- Boutons Filtres (categories, audit-log, clients) en `tertiary` simple : suppression des surcharges de classe, icone a gauche 24px.

## Tests
- `useCategoryForm` mis a jour (PATCH payload complet).
- `make nuxt-test` : 256/256 OK.
- `make nuxt-lint` : OK.

Reviewed-on: #77
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
This commit was merged in pull request #77.
This commit is contained in:
2026-06-09 06:06:52 +00:00
committed by Autin
parent edfb2b1619
commit 191fd42406
9 changed files with 61 additions and 74 deletions
@@ -31,7 +31,6 @@
v-model="form.categoryTypeIds.value"
:options="typeOptions"
:label="t('admin.categories.form.types')"
:empty-option-label="t('admin.categories.form.typesPlaceholder')"
:error="form.errors.categoryTypes"
:display-tag="true"
:disabled="loadingTypes"
@@ -91,28 +90,17 @@ const emit = defineEmits<{
delete: []
}>()
/**
* Mode du drawer (dérivé du composable `useCategoryForm`) :
* - 'create' : pas de category prop, formulaire vide, POST au save.
* - 'view' : category prop set, formulaire pre-rempli, save MASQUE
* jusqu'a ce que l'utilisateur modifie un champ.
* - 'edit' : category prop set et formulaire « dirty » (au moins un
* champ different de l'original), PATCH au save.
*/
type DrawerMode = 'create' | 'view' | 'edit'
// Mode du drawer : creation (pas de category prop, POST au save) ou
// modification d'une categorie existante (PATCH au save). Pas de distinction
// view/edit : comme les autres drawers, le titre et le bouton Enregistrer sont
// stables quel que soit l'etat « dirty » du formulaire.
const isCreateMode = computed(() => props.category === null)
const mode = computed<DrawerMode>(() => {
if (isCreateMode.value) return 'create'
return form.isDirty.value ? 'edit' : 'view'
})
const headerLabel = computed(() => {
if (mode.value === 'create') return t('admin.categories.createCategory')
if (mode.value === 'edit') return t('admin.categories.editCategory')
return t('admin.categories.viewCategory')
})
const headerLabel = computed(() =>
isCreateMode.value
? t('admin.categories.createCategory')
: t('admin.categories.editCategory'),
)
// Le bouton Supprimer n'est visible qu'en consultation/edition d'une categorie
// existante et seulement pour les users ayant la permission manage. En mode
@@ -121,10 +109,12 @@ const canShowDelete = computed(
() => !isCreateMode.value && can('catalog.categories.manage'),
)
// Save : visible en creation, ou en edition (apres modification d'un champ).
// Masque en view tant que rien n'a change.
// Save : visible en creation, et en consultation/edition d'une categorie
// existante (l'utilisateur doit pouvoir enregistrer sans qu'un champ ait
// d'abord ete modifie). Le bouton reste neanmoins protege par son `disabled`
// pendant la soumission / le chargement des types.
const canShowSave = computed(
() => mode.value === 'create' || mode.value === 'edit',
() => isCreateMode.value || can('catalog.categories.manage'),
)
const typeOptions = computed(() =>
@@ -154,18 +144,18 @@ watch(
)
/**
* Sauvegarde : delegue au composable (POST en mode create, PATCH en mode
* edit). Le toast succes + mapping erreur 409/422 est gere par le composable.
* En cas de succes, on ferme le drawer et on previent le parent pour qu'il
* refresh la liste.
* Sauvegarde : delegue au composable (POST en creation, PATCH en modification).
* Le toast succes + mapping erreur 409/422 est gere par le composable. Le PATCH
* envoie le payload complet, donc le bouton Enregistrer sauvegarde a tout
* moment (meme sans modification). En cas de succes, on ferme le drawer et on
* previent le parent pour qu'il refresh la liste.
*/
async function handleSave(): Promise<void> {
let result: Category | null = null
if (mode.value === 'create') {
result = await form.submitCreate()
} else if (mode.value === 'edit' && props.category) {
result = await form.submitUpdate(props.category.id)
}
const result = isCreateMode.value
? await form.submitCreate()
: props.category
? await form.submitUpdate(props.category.id)
: null
if (result) {
emit('saved')
emit('update:modelValue', false)