M1 · 2/3 (Front) — Retirer le bloc contact principal des ecrans Client (#57)
Auto Tag Develop / tag (push) Successful in 10s

## Objectif

Retirer le bloc « contact principal » (Nom, Prénom, Téléphone, Téléphone 2, Email) des trois écrans Client — **création**, **consultation**, **modification** — ainsi que des types, mappeurs, validations et clés i18n associés. La saisie des contacts passe désormais exclusivement par l'onglet **Contacts** (`ClientContactBlock`, inchangé).

Dépend du ticket **1/3 (back)** : l'API ne renvoie/n'accepte plus ces 5 champs sur `client`. Contexte : `docs/specs/M1-clients/refonte-contact/README.md`.

## Changements

- **`pages/clients/new.vue`** : bloc principal réduit à Nom entreprise / Catégories / Relation / Triage. Suppression de `main.firstName/lastName/email`, `mainPhones`, `addMainPhone()`, `prefillFirstContact()`. `isMainValid` ne dépend plus que de `companyName` + ≥ 1 catégorie + relation valide. Payload POST et `ClientResponse` nettoyés.
- **`pages/clients/[id]/edit.vue`** : mêmes champs retirés, `isMainValid` simplifié.
- **`pages/clients/[id]/index.vue`** : affichage lecture seule des 5 champs retiré.
- **`utils/clientEdit.ts`** : `MainFormDraft`, `mapMainDraft()`, `buildMainPayload()` débarrassés des 5 champs + `hasSecondaryPhone`.
- **`utils/clientConsultation.ts`** : `ClientDetail` débarrassé des champs inline (`ContactRead` conservé).
- **`i18n/locales/fr.json`** : clés `form.main.firstName/lastName/email/phonePrimary/phoneSecondary/addPhone` supprimées. `form.contact.*` conservé.
- **Tests** : `clientEdit.spec.ts` ajusté (factory, `MAIN_KEYS`, assertions `mapMainDraft`, test téléphone secondaire obsolète retiré).

## Vérifications

- `make nuxt-test` : suites `clientEdit` / `clientConsultation` / `clientFormRules` vertes. Les 2 échecs restants (`useClientReferentials.spec.ts`, libellé de site) sont **pré-existants** sur `develop` (confirmé par `git stash`), sans rapport avec ce ticket.
- `eslint` sur les fichiers touchés : OK, aucun import/variable mort.
- Zéro référence orpheline aux clés `form.main.*` supprimées ; JSON i18n valide.

## Reste à faire

- Golden path navigateur (création → consultation → modification sans bloc inline) à valider manuellement.

Reviewed-on: #57
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
This commit was merged in pull request #57.
This commit is contained in:
2026-06-03 14:48:55 +00:00
committed by Autin
parent 468894cfad
commit ec952896ba
8 changed files with 34 additions and 216 deletions
@@ -24,23 +24,16 @@ import {
type ClientDetail,
} from '~/modules/commercial/utils/clientConsultation'
import type { AddressFormDraft, ContactFormDraft, RibFormDraft } from '~/modules/commercial/types/clientForm'
import { formatPhoneFR } from '~/shared/utils/phone'
/**
* Etat « plat » du bloc principal (groupe client:write:main). Distinct des
* brouillons Contact : ces champs vivent sur le Client lui-meme (companyName,
* contact principal, telephones, email, categories, relation, triage), pas sur
* une sous-ressource ClientContact.
* categories, relation, triage), pas sur une sous-ressource ClientContact. Les
* coordonnees de contact (nom, prenom, telephones, email) ne sont plus portees
* par le Client : elles vivent exclusivement dans l'onglet Contacts.
*/
export interface MainFormDraft {
companyName: string | null
firstName: string | null
lastName: string | null
email: string | null
phonePrimary: string | null
phoneSecondary: string | null
/** UI : le 2e numero a ete revele (ou existait deja au chargement). */
hasSecondaryPhone: boolean
/** IRI des categories rattachees (M2M). */
categoryIris: string[]
relationType: 'distributeur' | 'courtier' | null
@@ -96,22 +89,15 @@ export interface TabEditability {
// ── Pre-remplissage (GET detail -> brouillons) ──────────────────────────────
/**
* Mappe le detail client vers le brouillon du bloc principal. Les telephones
* sont reformates XX XX XX XX XX (RG d'affichage). La relation Distributeur/
* Courtier est resolue par exclusivite (RG-1.03) et son IRI extrait de l'embed.
* Mappe le detail client vers le brouillon du bloc principal. La relation
* Distributeur/Courtier est resolue par exclusivite (RG-1.03) et son IRI extrait
* de l'embed.
*/
export function mapMainDraft(client: ClientDetail): MainFormDraft {
const relation = relationOf(client)
const phoneSecondary = client.phoneSecondary ?? null
return {
companyName: client.companyName ?? null,
firstName: client.firstName ?? null,
lastName: client.lastName ?? null,
email: client.email ?? null,
phonePrimary: client.phonePrimary ? formatPhoneFR(client.phonePrimary) : null,
phoneSecondary: phoneSecondary ? formatPhoneFR(phoneSecondary) : null,
hasSecondaryPhone: phoneSecondary !== null && phoneSecondary !== '',
categoryIris: (client.categories ?? []).map(c => c['@id']),
relationType: relation.type,
distributorIri: iriOf(client.distributor),
@@ -157,11 +143,6 @@ export function mapAccountingFormDraft(client: ClientDetail): AccountingFormDraf
export function buildMainPayload(main: MainFormDraft): Record<string, unknown> {
return {
companyName: main.companyName,
firstName: main.firstName || null,
lastName: main.lastName || null,
email: main.email,
phonePrimary: main.phonePrimary || null,
phoneSecondary: main.hasSecondaryPhone ? (main.phoneSecondary || null) : null,
categories: main.categoryIris,
distributor: main.relationType === 'distributeur' ? main.distributorIri : null,
broker: main.relationType === 'courtier' ? main.brokerIri : null,