feat(front) : onglet contact prestataire (ERP-142) (#104)
Auto Tag Develop / tag (push) Successful in 8s
Auto Tag Develop / tag (push) Successful in 8s
Empilée sur ERP-141 (#103). ## Périmètre ERP-142 Onglet **Contact** de l'écran `/providers/new` — saisie multi-contacts (blocs ajoutables) via la sous-ressource contacts. - **`ProviderContactBlock.vue`** (miroir `SupplierContactBlock`) : Nom / Prénom / Fonction / Email / Téléphone (x1, +1 révélable, **max 2**), erreurs 422 par champ (prop `:errors`). - **`useProviderForm`** étendu : état `contacts`, `canAddContact` (RG-3.04), `addContact`/`removeContact`, `submitContacts` (POST `/providers/{id}/contacts` pour les nouveaux, PATCH `/provider_contacts/{id}` pour les existants, groupe `provider:write:contacts`), `submitRows` (erreurs collectées **par ligne**, non bloquant). - **RG-3.04** : « + Nouveau contact » désactivé tant que le bloc courant est vide (≥1 champ parmi prénom/nom/fonction/tél/email — aligné back). - **RG-3.12** : onglet non validable vide ; une amorce vide est soumise pour déclencher la 422 `firstName` inline. - Suppression d'un bloc → modal de confirmation. - Helpers purs `utils/forms/providerContact.ts` (`isProviderContactBlank`, `buildProviderContactPayload`). - i18n `technique.providers.form.contact/confirmDelete` + `toast.updateSuccess`. ## Vérifications - Vitest : 418/418 (16 nouveaux : helpers, bloc, workflow contacts). - ESLint : OK. - `nuxi typecheck` : 0 erreur sur les fichiers source du ticket. - Golden path navigateur : bloc Contact rendu, « Nouveau contact » désactivé tant que vide puis activé après saisie, révélation du 2e téléphone (max 2). Reviewed-on: #104 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr>
This commit was merged in pull request #104.
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import {
|
||||
buildProviderContactPayload,
|
||||
hasAtLeastOneFilledContact,
|
||||
isProviderContactBlank,
|
||||
} from '../providerContact'
|
||||
import { emptyProviderContact } from '~/modules/technique/types/providerForm'
|
||||
|
||||
/**
|
||||
* Helpers purs de l'onglet Contact prestataire (ERP-142). On verifie la
|
||||
* definition de « bloc vide » (RG-3.04, alignee sur le back) et la construction
|
||||
* du payload de sous-ressource.
|
||||
*/
|
||||
describe('providerContact helpers', () => {
|
||||
describe('isProviderContactBlank (RG-3.04)', () => {
|
||||
it('un bloc vierge est vide', () => {
|
||||
expect(isProviderContactBlank(emptyProviderContact())).toBe(true)
|
||||
})
|
||||
|
||||
it('un seul champ rempli parmi nom/prenom/fonction/tel/email suffit a le rendre non vide', () => {
|
||||
for (const field of ['firstName', 'lastName', 'jobTitle', 'phonePrimary', 'email'] as const) {
|
||||
const contact = { ...emptyProviderContact(), [field]: 'x' }
|
||||
expect(isProviderContactBlank(contact)).toBe(false)
|
||||
}
|
||||
})
|
||||
|
||||
it('ignore les espaces (trim) — un champ blanc ne compte pas', () => {
|
||||
expect(isProviderContactBlank({ ...emptyProviderContact(), lastName: ' ' })).toBe(true)
|
||||
})
|
||||
|
||||
it('un 2e telephone seul NE suffit PAS (exclu, comme le back)', () => {
|
||||
const contact = { ...emptyProviderContact(), hasSecondaryPhone: true, phoneSecondary: '0102030405' }
|
||||
expect(isProviderContactBlank(contact)).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('hasAtLeastOneFilledContact (RG-3.12)', () => {
|
||||
it('false si tous les blocs sont vides', () => {
|
||||
expect(hasAtLeastOneFilledContact([emptyProviderContact(), emptyProviderContact()])).toBe(false)
|
||||
})
|
||||
|
||||
it('true des qu\'un bloc porte une donnee', () => {
|
||||
expect(hasAtLeastOneFilledContact([
|
||||
emptyProviderContact(),
|
||||
{ ...emptyProviderContact(), email: 'a@b.fr' },
|
||||
])).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('buildProviderContactPayload', () => {
|
||||
it('mappe les champs et envoie null pour les vides', () => {
|
||||
const payload = buildProviderContactPayload({ ...emptyProviderContact(), lastName: 'Doe' })
|
||||
expect(payload).toEqual({
|
||||
firstName: null,
|
||||
lastName: 'Doe',
|
||||
jobTitle: null,
|
||||
phonePrimary: null,
|
||||
phoneSecondary: null,
|
||||
email: null,
|
||||
})
|
||||
})
|
||||
|
||||
it('n\'envoie le 2e telephone que si revele (max 2)', () => {
|
||||
const masque = buildProviderContactPayload({
|
||||
...emptyProviderContact(),
|
||||
phoneSecondary: '0102030405',
|
||||
hasSecondaryPhone: false,
|
||||
})
|
||||
expect(masque.phoneSecondary).toBeNull()
|
||||
|
||||
const revele = buildProviderContactPayload({
|
||||
...emptyProviderContact(),
|
||||
phoneSecondary: '0102030405',
|
||||
hasSecondaryPhone: true,
|
||||
})
|
||||
expect(revele.phoneSecondary).toBe('0102030405')
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user