feat(transport) : contenant du formulaire principal en radios centrés (Benne par défaut) (ERP-170)

This commit is contained in:
2026-06-17 14:34:46 +02:00
parent b5749520bc
commit 07ed57f283
4 changed files with 55 additions and 35 deletions
@@ -111,6 +111,8 @@ describe('useCarrierForm', () => {
form.main.name = 'Acme'
form.main.certificationType = 'GMP_PLUS'
form.main.isChartered = true
// Annule le défaut « BENNE » pour vérifier la garde « contenant obligatoire ».
form.main.containerType = null
const created = await form.submitMain()
@@ -323,16 +325,18 @@ describe('useCarrierForm — champs conditionnels (ERP-166)', () => {
})
})
it('RG-4.03 affrété mais champs vides : omis du payload (422 NotBlank back)', () => {
it('RG-4.03 affrété, indexation/volume vides : omis du payload (containerType garde son défaut BENNE)', () => {
const form = useCarrierForm()
form.main.name = 'Acme'
form.main.certificationType = 'GMP_PLUS'
form.main.isChartered = true
// indexation / volume vides → omis (422 NotBlank back) ; containerType défaut « BENNE » envoyé.
expect(form.buildMainPayload()).toEqual({
name: 'Acme',
certificationType: 'GMP_PLUS',
isChartered: true,
containerType: 'BENNE',
})
})
@@ -73,15 +73,29 @@
:error="mainErrors.errors.indexationRate"
@update:model-value="onIndexationInput"
/>
<MalioSelect
:model-value="main.containerType"
:options="containerOptions"
:label="t('transport.carriers.form.main.containerType')"
empty-option-label=""
:required="true"
:error="mainErrors.errors.containerType"
@update:model-value="(v: string | number | null) => main.containerType = v === null ? null : String(v)"
/>
<!-- Contenant : Benne / Fond mouvant en radios, centrés (h-12) comme
à l'onglet Prix (Benne par défaut). -->
<div>
<div class="flex h-12 items-center gap-4">
<MalioRadioButton
:model-value="main.containerType"
name="carrier-main-container"
value="BENNE"
:label="t('transport.carriers.containerType.BENNE')"
group-class="mt-0"
@update:model-value="(v: string | number | boolean | null) => main.containerType = v === null ? null : String(v)"
/>
<MalioRadioButton
:model-value="main.containerType"
name="carrier-main-container"
value="FOND_MOUVANT"
:label="t('transport.carriers.containerType.FOND_MOUVANT')"
group-class="mt-0"
@update:model-value="(v: string | number | boolean | null) => main.containerType = v === null ? null : String(v)"
/>
</div>
<p v-if="mainErrors.errors.containerType" class="ml-[2px] text-xs text-m-danger">{{ mainErrors.errors.containerType }}</p>
</div>
<MalioInputText
:model-value="main.volumeM3"
:label="t('transport.carriers.form.main.volumeM3')"
@@ -250,10 +264,6 @@ const certificationOptions = computed<SelectOption[]>(() => {
return codes.map(code => ({ value: code, label: t(`transport.carriers.certification.${code}`) }))
})
const CONTAINER_TYPES = ['BENNE', 'FOND_MOUVANT'] as const
const containerOptions = computed<SelectOption[]>(() =>
CONTAINER_TYPES.map(code => ({ value: code, label: t(`transport.carriers.containerType.${code}`) })),
)
const TAB_ICONS: Record<string, string> = {
addresses: 'mdi:map-marker-outline',
@@ -101,17 +101,31 @@
@update:model-value="onIndexationInput"
/>
<!-- Contenant : Benne / Fond mouvant (RG-4.03). -->
<MalioSelect
:model-value="main.containerType"
:options="containerOptions"
:label="t('transport.carriers.form.main.containerType')"
empty-option-label=""
:required="true"
:readonly="mainLocked"
:error="mainErrors.errors.containerType"
@update:model-value="(v: string | number | null) => main.containerType = v === null ? null : String(v)"
/>
<!-- Contenant : Benne / Fond mouvant en radios, centrés (h-12) comme
à l'onglet Prix (Benne par défaut). -->
<div>
<div class="flex h-12 items-center gap-4">
<MalioRadioButton
:model-value="main.containerType"
name="carrier-main-container"
value="BENNE"
:label="t('transport.carriers.containerType.BENNE')"
:disabled="mainLocked"
group-class="mt-0"
@update:model-value="(v: string | number | boolean | null) => main.containerType = v === null ? null : String(v)"
/>
<MalioRadioButton
:model-value="main.containerType"
name="carrier-main-container"
value="FOND_MOUVANT"
:label="t('transport.carriers.containerType.FOND_MOUVANT')"
:disabled="mainLocked"
group-class="mt-0"
@update:model-value="(v: string | number | boolean | null) => main.containerType = v === null ? null : String(v)"
/>
</div>
<p v-if="mainErrors.errors.containerType" class="ml-[2px] text-xs text-m-danger">{{ mainErrors.errors.containerType }}</p>
</div>
<!-- Volume m³ : champ texte restreint aux nombres à décimales (point). -->
<MalioInputText
@@ -474,15 +488,6 @@ const qualimatEmptyMessage = computed(() => hasQualimatSearch.value
? t('transport.carriers.form.qualimat.empty')
: t('transport.carriers.form.qualimat.searchHint'))
// Contenant (RG-4.03) : Benne / Fond mouvant — select simple.
const CONTAINER_TYPES = ['BENNE', 'FOND_MOUVANT'] as const
const containerOptions = computed<SelectOption[]>(() =>
CONTAINER_TYPES.map(code => ({
value: code,
label: t(`transport.carriers.containerType.${code}`),
})),
)
// Icone (Iconify) affichee dans chaque onglet, par cle.
const TAB_ICONS: Record<string, string> = {
@@ -40,7 +40,8 @@ export function emptyCarrierMain(): CarrierMainDraft {
certificationType: null,
isChartered: false,
indexationRate: '',
containerType: null,
// Défaut métier : Benne pré-sélectionné (radio du formulaire principal).
containerType: 'BENNE',
volumeM3: '',
liotPlates: '',
dischargeDocumentIri: null,