feat(front) : page ajout prestataire + formulaire principal (ERP-141) (#103)
Auto Tag Develop / tag (push) Successful in 8s
Auto Tag Develop / tag (push) Successful in 8s
Empilée sur ERP-140 (#102). ## Périmètre ERP-141 Écran `/providers/new` — création par onglets + formulaire principal (POST). - **Page** `modules/technique/pages/providers/new.vue` : en-tête + retour, formulaire principal (Nom, Catégorie, Site), barre d'onglets **Contact · Adresse · Comptabilité** (pas d'onglet Information ; Rapports/Échanges absents en création). Contenu des onglets = placeholders « À venir » (ERP-142→144). - **`useProviderForm()`** : POST principal (groupe `provider:write:main`, IRIs catégories/sites), pré-check front RG-3.03 (≥1 site) / RG-3.09 (≥1 catégorie), 409 doublon (RG-3.10) inline, 422 mapping par champ via `useFormErrors`, orchestration des onglets (verrouillage + bascule auto sur Contact au succès), `patchProvider` (PATCH partiel mode strict pour les onglets à venir). - **`useProviderReferentials()`** : catégories type PRESTATAIRE + sites (`?pagination=false`, Hydra). - i18n `technique.providers.form/tab/toast`. ## Conformité - `useApi()` uniquement, composants `Malio*`, aucun texte FR en dur, bouton « Valider » toujours actif + erreurs sous les champs (ERP-101). ## Vérifications - Vitest : 402/402 (dont 9 nouveaux tests `useProviderForm`). - ESLint : OK. - `nuxi typecheck` : 0 erreur sur les fichiers source du ticket. - Golden path navigateur : page rendue, catégories filtrées PRESTATAIRE, sélecteur site, onglets désactivés avant validation, erreurs inline RG-3.03/3.09. Reviewed-on: #103 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr>
This commit was merged in pull request #103.
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
import { ref } from 'vue'
|
||||
|
||||
/**
|
||||
* Charge les referentiels (listes courtes) alimentant les selects du formulaire
|
||||
* principal de l'ecran « Ajouter un prestataire » (M3 Technique, ERP-141) :
|
||||
* categories (type PRESTATAIRE) et sites (86 / 17 / 82).
|
||||
*
|
||||
* Miroir reduit de `useSupplierReferentials` (M2) : a ce stade (formulaire
|
||||
* principal) seuls categories + sites sont necessaires. Les referentiels
|
||||
* comptables (modes de TVA, delais/types de reglement, banques) seront charges
|
||||
* par l'onglet Comptabilite (ERP-144).
|
||||
*
|
||||
* Toutes les collections sont recuperees en entier via l'echappatoire prevue
|
||||
* `?pagination=false` (referentiels de quelques entrees), avec l'en-tete
|
||||
* `Accept: application/ld+json` impose par API Platform 4 pour obtenir l'enveloppe
|
||||
* Hydra (`member`). La valeur d'option est l'IRI Hydra (`@id`), renvoyee telle
|
||||
* quelle dans le payload POST (relations M2M).
|
||||
*
|
||||
* Chargement RESILIENT (Promise.allSettled) : chaque referentiel est isole ; un
|
||||
* echec (permission manquante, reseau) laisse simplement la liste vide.
|
||||
*
|
||||
* Etat 100 % local a l'instance (refs) — aucune persistance URL.
|
||||
*/
|
||||
|
||||
/** Option generique au format attendu par MalioSelect / MalioSelectCheckbox. */
|
||||
export interface RefOption {
|
||||
value: string
|
||||
label: string
|
||||
}
|
||||
|
||||
interface HydraMember {
|
||||
'@id': string
|
||||
}
|
||||
|
||||
interface CategoryMember extends HydraMember {
|
||||
code: string
|
||||
name: string
|
||||
}
|
||||
|
||||
interface SiteMember extends HydraMember {
|
||||
name: string
|
||||
postalCode: string
|
||||
}
|
||||
|
||||
const LD_JSON_HEADERS = { Accept: 'application/ld+json' }
|
||||
|
||||
export function useProviderReferentials() {
|
||||
const api = useApi()
|
||||
|
||||
const categories = ref<RefOption[]>([])
|
||||
const sites = ref<RefOption[]>([])
|
||||
|
||||
/** Recupere une collection complete (pagination desactivee) en Hydra. */
|
||||
async function fetchAll<T extends HydraMember>(
|
||||
url: string,
|
||||
query: Record<string, string | string[]> = {},
|
||||
): Promise<T[]> {
|
||||
const res = await api.get<{ member?: T[] }>(
|
||||
url,
|
||||
{ pagination: 'false', ...query },
|
||||
{ headers: LD_JSON_HEADERS, toast: false },
|
||||
)
|
||||
return res.member ?? []
|
||||
}
|
||||
|
||||
/** Charge en parallele les referentiels du formulaire principal (categories + sites). */
|
||||
async function loadMain(): Promise<void> {
|
||||
await Promise.allSettled([
|
||||
// RG-3.09 : un prestataire ne porte que des categories de type
|
||||
// PRESTATAIRE -> filtre cote API. Libelle affiche = `name`.
|
||||
fetchAll<CategoryMember>('/categories', { typeCode: 'PRESTATAIRE' })
|
||||
.then((cats) => { categories.value = cats.map(c => ({ value: c['@id'], label: c.name })) }),
|
||||
// Sites (RG-3.03) : libelle = numero de departement (2 premiers chiffres
|
||||
// du code postal du site), ex: 86100 -> « 86 », 17400 -> « 17 ».
|
||||
fetchAll<SiteMember>('/sites')
|
||||
.then((sitesList) => { sites.value = sitesList.map(s => ({ value: s['@id'], label: (s.postalCode ?? '').slice(0, 2) })) }),
|
||||
])
|
||||
}
|
||||
|
||||
return {
|
||||
categories,
|
||||
sites,
|
||||
loadMain,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user