feat(transport) : adresse unique par transporteur (OneToOne back + un seul bloc front) (ERP-172)
This commit is contained in:
@@ -124,19 +124,16 @@
|
||||
<MalioTabList v-model="activeTab" :tabs="tabs" class="mt-[60px]">
|
||||
<template #addresses>
|
||||
<div class="mt-12 flex flex-col gap-6">
|
||||
<!-- Adresse UNIQUE (ERP-172) : un seul bloc, sans ajouter/supprimer. -->
|
||||
<CarrierAddressBlock
|
||||
v-for="(address, index) in addresses"
|
||||
:key="index"
|
||||
:model-value="address"
|
||||
:country-options="countryOptions"
|
||||
:removable="isRowRemovable(addresses, index)"
|
||||
:errors="addressErrors[index]"
|
||||
@update:model-value="(v) => addresses[index] = v"
|
||||
@remove="askRemoveAddress(index)"
|
||||
:removable="false"
|
||||
:errors="addressErrors"
|
||||
@update:model-value="(v) => address = v"
|
||||
@degraded="onAddressDegraded"
|
||||
/>
|
||||
<div class="flex justify-center gap-6">
|
||||
<MalioButton variant="secondary" icon-name="mdi:add-bold" icon-position="left" :label="t('transport.carriers.form.address.add')" :disabled="!canAddAddress" @click="addAddress" />
|
||||
<MalioButton variant="primary" :label="t('transport.carriers.edit.save')" :disabled="tabSubmitting" @click="onSubmitAddresses" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -242,12 +239,9 @@ const {
|
||||
certificationReadonly,
|
||||
showCharteredFields,
|
||||
showDischarge,
|
||||
addresses,
|
||||
address,
|
||||
addressErrors,
|
||||
canAddAddress,
|
||||
addAddress,
|
||||
removeAddress,
|
||||
submitAddresses,
|
||||
submitAddress,
|
||||
contacts,
|
||||
contactErrors,
|
||||
canAddContact,
|
||||
@@ -368,7 +362,7 @@ async function onUpdateMain(): Promise<void> {
|
||||
}
|
||||
|
||||
async function onSubmitAddresses(): Promise<void> {
|
||||
const ok = await submitAddresses(err => toast.error({ title: t('transport.carriers.toast.error'), message: apiErrorMessage(err) }))
|
||||
const ok = await submitAddress(err => toast.error({ title: t('transport.carriers.toast.error'), message: apiErrorMessage(err) }))
|
||||
if (ok) toast.success({ title: t('transport.carriers.toast.addressSaved') })
|
||||
}
|
||||
async function onSubmitContacts(): Promise<void> {
|
||||
@@ -383,10 +377,6 @@ async function onSubmitPrices(): Promise<void> {
|
||||
// ── Suppression de bloc (modal de confirmation générique) ────────────────────
|
||||
const deleteConfirm = reactive({ open: false, action: null as null | (() => void) })
|
||||
|
||||
function askRemoveAddress(index: number): void {
|
||||
deleteConfirm.action = () => { void removeAddress(index) }
|
||||
deleteConfirm.open = true
|
||||
}
|
||||
function askRemoveContact(index: number): void {
|
||||
deleteConfirm.action = () => { void removeContact(index) }
|
||||
deleteConfirm.open = true
|
||||
|
||||
@@ -116,9 +116,8 @@
|
||||
<MalioTabList v-model="activeTab" :tabs="tabs" class="mt-[60px]">
|
||||
<template #addresses>
|
||||
<div class="mt-12 flex flex-col gap-6">
|
||||
<!-- Adresse UNIQUE (ERP-172). -->
|
||||
<CarrierAddressBlock
|
||||
v-for="(address, index) in addresses"
|
||||
:key="index"
|
||||
:model-value="address"
|
||||
:country-options="countryOptionsFor(address.country)"
|
||||
readonly
|
||||
@@ -311,11 +310,10 @@ const tabs = computed(() => ['addresses', 'contacts', 'prices'].map(key => ({
|
||||
icon: TAB_ICONS[key],
|
||||
})))
|
||||
|
||||
// Au moins un bloc affiché même sans donnée (bloc vide en lecture seule).
|
||||
const addresses = computed(() => {
|
||||
const list = (carrier.value?.addresses ?? []).map(mapAddressToDraft)
|
||||
return list.length > 0 ? list : [mapAddressToDraft({ id: 0, '@id': '' })]
|
||||
})
|
||||
// Adresse UNIQUE (ERP-172) : un seul bloc en lecture seule (vide si pas d'adresse).
|
||||
const address = computed(() => carrier.value?.address
|
||||
? mapAddressToDraft(carrier.value.address)
|
||||
: mapAddressToDraft({ id: 0, '@id': '' }))
|
||||
const contacts = computed(() => {
|
||||
const list = (carrier.value?.contacts ?? []).map(mapContactToDraft)
|
||||
return list.length > 0 ? list : [mapContactToDraft({ id: 0, '@id': '' })]
|
||||
|
||||
@@ -202,29 +202,19 @@
|
||||
préremplissage si QUALIMAT ; RG-4.07 pas de Valider si QUALIMAT. -->
|
||||
<template #addresses>
|
||||
<div class="mt-12 flex flex-col gap-6">
|
||||
<!-- Adresse UNIQUE (ERP-172) : un seul bloc, sans ajouter/supprimer. -->
|
||||
<CarrierAddressBlock
|
||||
v-for="(address, index) in addresses"
|
||||
:key="index"
|
||||
:model-value="address"
|
||||
:country-options="countryOptions"
|
||||
:removable="isRowRemovable(addresses, index)"
|
||||
:removable="false"
|
||||
:readonly="isQualimat || isValidated('addresses')"
|
||||
:errors="addressErrors[index]"
|
||||
@update:model-value="(v) => addresses[index] = v"
|
||||
@remove="askRemoveAddress(index)"
|
||||
:errors="addressErrors"
|
||||
@update:model-value="(v) => address = v"
|
||||
@degraded="onAddressDegraded"
|
||||
/>
|
||||
<!-- RG-4.07 : pas de bouton Valider pour un transporteur QUALIMAT
|
||||
(adresse copiée et persistée automatiquement). -->
|
||||
<div v-if="!isQualimat && !isValidated('addresses')" class="flex justify-center gap-6">
|
||||
<MalioButton
|
||||
variant="secondary"
|
||||
icon-name="mdi:add-bold"
|
||||
icon-position="left"
|
||||
:label="t('transport.carriers.form.address.add')"
|
||||
:disabled="!canAddAddress"
|
||||
@click="addAddress"
|
||||
/>
|
||||
<MalioButton
|
||||
variant="primary"
|
||||
:label="t('transport.carriers.form.submit')"
|
||||
@@ -412,12 +402,9 @@ const {
|
||||
activeTab,
|
||||
unlockedIndex,
|
||||
isValidated,
|
||||
addresses,
|
||||
address,
|
||||
addressErrors,
|
||||
canAddAddress,
|
||||
addAddress,
|
||||
removeAddress,
|
||||
submitAddresses,
|
||||
submitAddress,
|
||||
contacts,
|
||||
contactErrors,
|
||||
canAddContact,
|
||||
@@ -609,7 +596,7 @@ function apiErrorMessage(error: unknown): string {
|
||||
|
||||
/** Valide l'onglet Adresses (POST/PATCH par ligne ; avance gere par le composable). */
|
||||
async function onSubmitAddresses(): Promise<void> {
|
||||
const ok = await submitAddresses(error => toast.error({
|
||||
const ok = await submitAddress(error => toast.error({
|
||||
title: t('transport.carriers.toast.error'),
|
||||
message: apiErrorMessage(error),
|
||||
}))
|
||||
@@ -618,14 +605,9 @@ async function onSubmitAddresses(): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
// Modal de confirmation de suppression (générique : bloc adresse OU contact).
|
||||
// Modal de confirmation de suppression (générique : bloc contact OU prix).
|
||||
const deleteConfirm = reactive({ open: false, action: null as null | (() => void) })
|
||||
|
||||
function askRemoveAddress(index: number): void {
|
||||
deleteConfirm.action = () => { void removeAddress(index) }
|
||||
deleteConfirm.open = true
|
||||
}
|
||||
|
||||
/** Valide l'onglet Contacts (POST/PATCH par ligne ; avance gérée par le composable). */
|
||||
async function onSubmitContacts(): Promise<void> {
|
||||
const ok = await submitContacts(error => toast.error({
|
||||
@@ -764,7 +746,7 @@ function goBack(): void {
|
||||
async function onSubmitMain(): Promise<void> {
|
||||
const ok = await submitMain()
|
||||
if (ok && isQualimat.value) {
|
||||
await submitAddresses(error => toast.error({
|
||||
await submitAddress(error => toast.error({
|
||||
title: t('transport.carriers.toast.error'),
|
||||
message: apiErrorMessage(error),
|
||||
}))
|
||||
|
||||
Reference in New Issue
Block a user