Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2e50a760c6 | |||
| 49e5e5548e | |||
| fd430bc123 | |||
| a6b48b1dd1 |
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
parameters:
|
parameters:
|
||||||
app.version: '0.1.148'
|
app.version: '0.1.150'
|
||||||
|
|||||||
@@ -183,6 +183,7 @@
|
|||||||
"degraded": "Service d'adresse indisponible : saisie de la ville et de l'adresse en mode libre."
|
"degraded": "Service d'adresse indisponible : saisie de la ville et de l'adresse en mode libre."
|
||||||
},
|
},
|
||||||
"accounting": {
|
"accounting": {
|
||||||
|
"infoTitle": "Informations",
|
||||||
"siren": "SIREN",
|
"siren": "SIREN",
|
||||||
"accountNumber": "Numéro de compte",
|
"accountNumber": "Numéro de compte",
|
||||||
"tvaMode": "Mode de TVA",
|
"tvaMode": "Mode de TVA",
|
||||||
@@ -190,6 +191,7 @@
|
|||||||
"paymentDelay": "Délai de règlement",
|
"paymentDelay": "Délai de règlement",
|
||||||
"paymentType": "Type de règlement",
|
"paymentType": "Type de règlement",
|
||||||
"bank": "Banque",
|
"bank": "Banque",
|
||||||
|
"ribTitle": "RIB {n}",
|
||||||
"ribLabel": "Libellé",
|
"ribLabel": "Libellé",
|
||||||
"ribBic": "BIC",
|
"ribBic": "BIC",
|
||||||
"ribIban": "IBAN",
|
"ribIban": "IBAN",
|
||||||
@@ -350,6 +352,7 @@
|
|||||||
"degraded": "Service d'adresse indisponible : saisie de la ville et de l'adresse en mode libre."
|
"degraded": "Service d'adresse indisponible : saisie de la ville et de l'adresse en mode libre."
|
||||||
},
|
},
|
||||||
"accounting": {
|
"accounting": {
|
||||||
|
"infoTitle": "Informations",
|
||||||
"siren": "SIREN",
|
"siren": "SIREN",
|
||||||
"accountNumber": "Numéro de compte",
|
"accountNumber": "Numéro de compte",
|
||||||
"tvaMode": "Mode de TVA",
|
"tvaMode": "Mode de TVA",
|
||||||
@@ -441,6 +444,7 @@
|
|||||||
"categoryRequired": "Sélectionnez au moins une catégorie."
|
"categoryRequired": "Sélectionnez au moins une catégorie."
|
||||||
},
|
},
|
||||||
"contact": {
|
"contact": {
|
||||||
|
"title": "Contact {n}",
|
||||||
"lastName": "Nom",
|
"lastName": "Nom",
|
||||||
"firstName": "Prénom",
|
"firstName": "Prénom",
|
||||||
"jobTitle": "Fonction",
|
"jobTitle": "Fonction",
|
||||||
@@ -452,6 +456,7 @@
|
|||||||
"add": "Nouveau contact"
|
"add": "Nouveau contact"
|
||||||
},
|
},
|
||||||
"address": {
|
"address": {
|
||||||
|
"title": "Adresse {n}",
|
||||||
"sites": "Sites",
|
"sites": "Sites",
|
||||||
"contacts": "Contact(s) rattaché(s)",
|
"contacts": "Contact(s) rattaché(s)",
|
||||||
"country": "Pays",
|
"country": "Pays",
|
||||||
@@ -465,6 +470,7 @@
|
|||||||
"degraded": "Service d'adresse indisponible : saisie de la ville et de l'adresse en mode libre."
|
"degraded": "Service d'adresse indisponible : saisie de la ville et de l'adresse en mode libre."
|
||||||
},
|
},
|
||||||
"accounting": {
|
"accounting": {
|
||||||
|
"infoTitle": "Informations",
|
||||||
"siren": "SIREN",
|
"siren": "SIREN",
|
||||||
"accountNumber": "Numéro de compte",
|
"accountNumber": "Numéro de compte",
|
||||||
"tvaMode": "Mode de TVA",
|
"tvaMode": "Mode de TVA",
|
||||||
@@ -472,6 +478,7 @@
|
|||||||
"paymentDelay": "Délai de règlement",
|
"paymentDelay": "Délai de règlement",
|
||||||
"paymentType": "Type de règlement",
|
"paymentType": "Type de règlement",
|
||||||
"bank": "Banque",
|
"bank": "Banque",
|
||||||
|
"ribTitle": "RIB {n}",
|
||||||
"ribLabel": "Libellé",
|
"ribLabel": "Libellé",
|
||||||
"ribBic": "BIC",
|
"ribBic": "BIC",
|
||||||
"ribIban": "IBAN",
|
"ribIban": "IBAN",
|
||||||
@@ -628,6 +635,7 @@
|
|||||||
"uploadFailed": "Le téléversement de la décharge a échoué."
|
"uploadFailed": "Le téléversement de la décharge a échoué."
|
||||||
},
|
},
|
||||||
"address": {
|
"address": {
|
||||||
|
"title": "Adresse",
|
||||||
"country": "Pays",
|
"country": "Pays",
|
||||||
"postalCode": "Code postal",
|
"postalCode": "Code postal",
|
||||||
"city": "Ville",
|
"city": "Ville",
|
||||||
@@ -637,6 +645,7 @@
|
|||||||
"degraded": "Service d'adresse indisponible : saisie de la ville et de l'adresse en mode libre."
|
"degraded": "Service d'adresse indisponible : saisie de la ville et de l'adresse en mode libre."
|
||||||
},
|
},
|
||||||
"contact": {
|
"contact": {
|
||||||
|
"title": "Contact {n}",
|
||||||
"lastName": "Nom",
|
"lastName": "Nom",
|
||||||
"firstName": "Prénom",
|
"firstName": "Prénom",
|
||||||
"jobTitle": "Fonction",
|
"jobTitle": "Fonction",
|
||||||
@@ -654,6 +663,7 @@
|
|||||||
"confirm": "Supprimer"
|
"confirm": "Supprimer"
|
||||||
},
|
},
|
||||||
"price": {
|
"price": {
|
||||||
|
"title": "Prix {n}",
|
||||||
"direction": "Sens",
|
"direction": "Sens",
|
||||||
"directionClient": "Client",
|
"directionClient": "Client",
|
||||||
"directionSupplier": "Fournisseur",
|
"directionSupplier": "Fournisseur",
|
||||||
|
|||||||
@@ -1,15 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative grid grid-cols-4 gap-x-[44px] gap-y-4 bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<!-- Bloc a plat (sans box-shadow) : un filet noir 1px le separe du suivant
|
||||||
|
(pas de bordure sous le dernier bloc). -->
|
||||||
|
<div class="pb-[20px]" :class="{ 'border-b border-black': !last }">
|
||||||
|
<!-- En-tete : titre du bloc (noir) a gauche, poubelle de suppression a droite. -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ title }}</h2>
|
||||||
<!-- ariaLabel via v-bind objet (prop camelCase ; aria-* serait un attribut HTML). -->
|
<!-- ariaLabel via v-bind objet (prop camelCase ; aria-* serait un attribut HTML). -->
|
||||||
<MalioButtonIcon
|
<MalioButtonIcon
|
||||||
v-if="removable && !readonly && !disabled"
|
v-if="removable && !readonly && !disabled"
|
||||||
icon="mdi:delete-outline"
|
icon="mdi:delete-outline"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
button-class="absolute top-3 right-3"
|
button-class="p-0"
|
||||||
v-bind="{ ariaLabel: t('commercial.clients.form.address.remove') }"
|
v-bind="{ ariaLabel: t('commercial.clients.form.address.remove') }"
|
||||||
@click="$emit('remove')"
|
@click="$emit('remove')"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Grille 4 colonnes des champs de l'adresse. -->
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<!-- Usage de l'adresse : Select unique (plus simple pour l'utilisateur)
|
<!-- Usage de l'adresse : Select unique (plus simple pour l'utilisateur)
|
||||||
remplacant les 3 cases. Les options encodent les combinaisons valides
|
remplacant les 3 cases. Les options encodent les combinaisons valides
|
||||||
(exclusivite Prospect, RG-1.06/07/08) ; le back recoit toujours les
|
(exclusivite Prospect, RG-1.06/07/08) ; le back recoit toujours les
|
||||||
@@ -197,7 +205,7 @@
|
|||||||
@update:model-value="(v: string) => update('streetComplement', v)"
|
@update:model-value="(v: string) => update('streetComplement', v)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -230,6 +238,8 @@ const props = defineProps<{
|
|||||||
/** Pays disponibles (France par defaut). */
|
/** Pays disponibles (France par defaut). */
|
||||||
countryOptions: RefOption[]
|
countryOptions: RefOption[]
|
||||||
removable?: boolean
|
removable?: boolean
|
||||||
|
/** Dernier bloc de la liste : supprime le filet de separation bas. */
|
||||||
|
last?: boolean
|
||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
/** Bloc desactive (champs grises, consultation — distinct de readonly). */
|
/** Bloc desactive (champs grises, consultation — distinct de readonly). */
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative grid grid-cols-4 gap-x-[44px] gap-y-4 bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<!-- Bloc a plat (sans box-shadow) : un filet noir 1px le separe du suivant
|
||||||
|
(pas de bordure sous le dernier bloc). -->
|
||||||
|
<div class="pb-[20px]" :class="{ 'border-b border-black': !last }">
|
||||||
|
<!-- En-tete : titre du bloc (noir) a gauche, poubelle de suppression a droite. -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ title }}</h2>
|
||||||
<!-- Suppression : ouvre une modal de confirmation cote parent. Masquee si
|
<!-- Suppression : ouvre une modal de confirmation cote parent. Masquee si
|
||||||
non supprimable (1er bloc obligatoire RG-1.14) ou en lecture seule.
|
non supprimable (1er bloc obligatoire RG-1.14) ou en lecture seule.
|
||||||
ariaLabel via v-bind objet (prop camelCase ; aria-* serait un attribut HTML). -->
|
ariaLabel via v-bind objet (prop camelCase ; aria-* serait un attribut HTML). -->
|
||||||
@@ -7,11 +12,14 @@
|
|||||||
v-if="removable && !readonly && !disabled"
|
v-if="removable && !readonly && !disabled"
|
||||||
icon="mdi:delete-outline"
|
icon="mdi:delete-outline"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
button-class="absolute top-3 right-3"
|
button-class="p-0"
|
||||||
v-bind="{ ariaLabel: t('commercial.clients.form.contact.remove') }"
|
v-bind="{ ariaLabel: t('commercial.clients.form.contact.remove') }"
|
||||||
@click="$emit('remove')"
|
@click="$emit('remove')"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Grille 4 colonnes des champs du contact. -->
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-if="!hideEmpty || isFilled(model.lastName)"
|
v-if="!hideEmpty || isFilled(model.lastName)"
|
||||||
:model-value="model.lastName"
|
:model-value="model.lastName"
|
||||||
@@ -80,6 +88,7 @@
|
|||||||
@update:model-value="(v: string) => update('phoneSecondary', v)"
|
@update:model-value="(v: string) => update('phoneSecondary', v)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -98,6 +107,8 @@ const props = defineProps<{
|
|||||||
title: string
|
title: string
|
||||||
/** Affiche l'icone de suppression (1er bloc non supprimable, RG-1.14). */
|
/** Affiche l'icone de suppression (1er bloc non supprimable, RG-1.14). */
|
||||||
removable?: boolean
|
removable?: boolean
|
||||||
|
/** Dernier bloc de la liste : supprime le filet de separation bas. */
|
||||||
|
last?: boolean
|
||||||
/** Bloc en lecture seule (onglet valide). */
|
/** Bloc en lecture seule (onglet valide). */
|
||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
/** Bloc desactive (champs grises, consultation — distinct de readonly). */
|
/** Bloc desactive (champs grises, consultation — distinct de readonly). */
|
||||||
|
|||||||
@@ -1,15 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative grid grid-cols-4 gap-x-[44px] gap-y-4 bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<!-- Bloc a plat (sans box-shadow) : un filet noir 1px le separe du suivant
|
||||||
|
(pas de bordure sous le dernier bloc). -->
|
||||||
|
<div class="pb-[20px]" :class="{ 'border-b border-black': !last }">
|
||||||
|
<!-- En-tete : titre du bloc (noir) a gauche, poubelle de suppression a droite. -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ title }}</h2>
|
||||||
<!-- Suppression : modal de confirmation cote parent. -->
|
<!-- Suppression : modal de confirmation cote parent. -->
|
||||||
<MalioButtonIcon
|
<MalioButtonIcon
|
||||||
v-if="removable && !readonly && !disabled"
|
v-if="removable && !readonly && !disabled"
|
||||||
icon="mdi:delete-outline"
|
icon="mdi:delete-outline"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
button-class="absolute top-3 right-3"
|
button-class="p-0"
|
||||||
v-bind="{ ariaLabel: t('commercial.suppliers.form.address.remove') }"
|
v-bind="{ ariaLabel: t('commercial.suppliers.form.address.remove') }"
|
||||||
@click="$emit('remove')"
|
@click="$emit('remove')"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Grille 4 colonnes des champs de l'adresse. -->
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<!-- Type d'adresse : Prospect / Depart / Rendu (RG-2.09). Select en attendant
|
<!-- Type d'adresse : Prospect / Depart / Rendu (RG-2.09). Select en attendant
|
||||||
l'arbitrage metier (radio vs select) ; l'erreur 422 (propertyPath
|
l'arbitrage metier (radio vs select) ; l'erreur 422 (propertyPath
|
||||||
`addressType`) s'affiche via la prop native :error de MalioSelect. -->
|
`addressType`) s'affiche via la prop native :error de MalioSelect. -->
|
||||||
@@ -185,6 +193,7 @@
|
|||||||
@update:model-value="(v: boolean) => update('triageProvider', v)"
|
@update:model-value="(v: boolean) => update('triageProvider', v)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -210,6 +219,8 @@ const props = defineProps<{
|
|||||||
/** Pays disponibles (France par defaut). */
|
/** Pays disponibles (France par defaut). */
|
||||||
countryOptions: RefOption[]
|
countryOptions: RefOption[]
|
||||||
removable?: boolean
|
removable?: boolean
|
||||||
|
/** Dernier bloc de la liste : supprime le filet de separation bas. */
|
||||||
|
last?: boolean
|
||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
/** Bloc desactive (champs grises, consultation — distinct de readonly). */
|
/** Bloc desactive (champs grises, consultation — distinct de readonly). */
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
|
|||||||
@@ -1,16 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative grid grid-cols-4 gap-x-[44px] gap-y-4 bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<!-- Bloc a plat (sans box-shadow) : un filet noir 1px le separe du suivant
|
||||||
|
(pas de bordure sous le dernier bloc). -->
|
||||||
|
<div class="pb-[20px]" :class="{ 'border-b border-black': !last }">
|
||||||
|
<!-- En-tete : titre du bloc (noir) a gauche, poubelle de suppression a droite. -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ title }}</h2>
|
||||||
<!-- Suppression : ouvre une modal de confirmation cote parent. Masquee si
|
<!-- Suppression : ouvre une modal de confirmation cote parent. Masquee si
|
||||||
non supprimable (1er bloc, RG-2.13) ou en lecture seule. -->
|
non supprimable (1er bloc, RG-2.13) ou en lecture seule. -->
|
||||||
<MalioButtonIcon
|
<MalioButtonIcon
|
||||||
v-if="removable && !readonly && !disabled"
|
v-if="removable && !readonly && !disabled"
|
||||||
icon="mdi:delete-outline"
|
icon="mdi:delete-outline"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
button-class="absolute top-3 right-3"
|
button-class="p-0"
|
||||||
v-bind="{ ariaLabel: t('commercial.suppliers.form.contact.remove') }"
|
v-bind="{ ariaLabel: t('commercial.suppliers.form.contact.remove') }"
|
||||||
@click="$emit('remove')"
|
@click="$emit('remove')"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Grille 4 colonnes des champs du contact. -->
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-if="!hideEmpty || isFilled(model.lastName)"
|
v-if="!hideEmpty || isFilled(model.lastName)"
|
||||||
:model-value="model.lastName"
|
:model-value="model.lastName"
|
||||||
@@ -79,6 +87,7 @@
|
|||||||
@update:model-value="(v: string) => update('phoneSecondary', v)"
|
@update:model-value="(v: string) => update('phoneSecondary', v)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -96,6 +105,8 @@ const props = defineProps<{
|
|||||||
title: string
|
title: string
|
||||||
/** Affiche l'icone de suppression (1er bloc non supprimable, RG-2.13). */
|
/** Affiche l'icone de suppression (1er bloc non supprimable, RG-2.13). */
|
||||||
removable?: boolean
|
removable?: boolean
|
||||||
|
/** Dernier bloc de la liste : supprime le filet de separation bas. */
|
||||||
|
last?: boolean
|
||||||
/** Bloc en lecture seule (onglet valide). */
|
/** Bloc en lecture seule (onglet valide). */
|
||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
/** Bloc desactive (champs grises, consultation — distinct de readonly). */
|
/** Bloc desactive (champs grises, consultation — distinct de readonly). */
|
||||||
|
|||||||
@@ -93,7 +93,7 @@
|
|||||||
<MalioTabList v-model="activeTab" :tabs="tabs" :max-visible-tabs="5" :max-width="1100" class="mt-[60px]">
|
<MalioTabList v-model="activeTab" :tabs="tabs" :max-visible-tabs="5" :max-width="1100" class="mt-[60px]">
|
||||||
<!-- Onglet Information -->
|
<!-- Onglet Information -->
|
||||||
<template #information>
|
<template #information>
|
||||||
<div class="mt-12 grid grid-cols-4 gap-x-[44px] gap-y-4 bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<div class="mt-12 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<!-- pt-1/pb-1 alignent le textarea (h-full) en haut ET en bas
|
<!-- pt-1/pb-1 alignent le textarea (h-full) en haut ET en bas
|
||||||
sur les inputs (champ 40px centre dans un h-12 -> ~4px de
|
sur les inputs (champ 40px centre dans un h-12 -> ~4px de
|
||||||
coussin de chaque cote). -->
|
coussin de chaque cote). -->
|
||||||
@@ -178,6 +178,7 @@
|
|||||||
:model-value="contact"
|
:model-value="contact"
|
||||||
:title="t('commercial.clients.form.contact.title', { n: index + 1 })"
|
:title="t('commercial.clients.form.contact.title', { n: index + 1 })"
|
||||||
:removable="isRowRemovable(contacts, index)"
|
:removable="isRowRemovable(contacts, index)"
|
||||||
|
:last="index === contacts.length - 1"
|
||||||
:disabled="businessReadonly"
|
:disabled="businessReadonly"
|
||||||
:errors="contactErrors[index]"
|
:errors="contactErrors[index]"
|
||||||
@update:model-value="(v) => contacts[index] = v"
|
@update:model-value="(v) => contacts[index] = v"
|
||||||
@@ -210,6 +211,7 @@
|
|||||||
:key="address.id ?? `new-${index}`"
|
:key="address.id ?? `new-${index}`"
|
||||||
:model-value="address"
|
:model-value="address"
|
||||||
:title="t('commercial.clients.form.address.title', { n: index + 1 })"
|
:title="t('commercial.clients.form.address.title', { n: index + 1 })"
|
||||||
|
:last="index === addresses.length - 1"
|
||||||
:category-options="addressCategoryOptions"
|
:category-options="addressCategoryOptions"
|
||||||
:site-options="siteOptions"
|
:site-options="siteOptions"
|
||||||
:contact-options="contactOptions"
|
:contact-options="contactOptions"
|
||||||
@@ -244,8 +246,10 @@
|
|||||||
editable uniquement si accounting.manage). -->
|
editable uniquement si accounting.manage). -->
|
||||||
<template v-if="canAccountingView" #accounting>
|
<template v-if="canAccountingView" #accounting>
|
||||||
<div class="mt-12 flex flex-col gap-6">
|
<div class="mt-12 flex flex-col gap-6">
|
||||||
<div class="bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<!-- Bloc infos comptables : titre + filet bas (filet uniquement s'il y a des RIB en dessous). -->
|
||||||
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
|
<div class="pb-[20px]" :class="{ 'border-b border-black': visibleRibs.length > 0 }">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ t('commercial.clients.form.accounting.infoTitle') }}</h2>
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-model="accounting.siren"
|
v-model="accounting.siren"
|
||||||
:label="t('commercial.clients.form.accounting.siren')"
|
:label="t('commercial.clients.form.accounting.siren')"
|
||||||
@@ -314,21 +318,27 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Blocs RIB — affiches uniquement si type de reglement = LCR (RG-1.13). -->
|
<!-- Blocs RIB — affiches uniquement si type de reglement = LCR (RG-1.13).
|
||||||
|
Titre « RIB N » + poubelle, filet de separation sauf sous le dernier. -->
|
||||||
<div
|
<div
|
||||||
v-for="(rib, index) in visibleRibs"
|
v-for="(rib, index) in visibleRibs"
|
||||||
:key="rib.id ?? `new-${index}`"
|
:key="rib.id ?? `new-${index}`"
|
||||||
class="relative bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]"
|
class="pb-[20px]"
|
||||||
|
:class="{ 'border-b border-black': index !== visibleRibs.length - 1 }"
|
||||||
>
|
>
|
||||||
|
<!-- En-tete : titre du bloc (noir) a gauche, poubelle a droite. -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ t('commercial.clients.form.accounting.ribTitle', { n: index + 1 }) }}</h2>
|
||||||
<MalioButtonIcon
|
<MalioButtonIcon
|
||||||
v-if="!accountingReadonly && isRowRemovable(visibleRibs, index)"
|
v-if="!accountingReadonly && isRowRemovable(visibleRibs, index)"
|
||||||
icon="mdi:delete-outline"
|
icon="mdi:delete-outline"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
button-class="absolute top-3 right-3"
|
button-class="p-0"
|
||||||
v-bind="{ ariaLabel: t('commercial.clients.form.accounting.removeRib') }"
|
v-bind="{ ariaLabel: t('commercial.clients.form.accounting.removeRib') }"
|
||||||
@click="askRemoveRib(index)"
|
@click="askRemoveRib(index)"
|
||||||
/>
|
/>
|
||||||
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
|
</div>
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-model="rib.label"
|
v-model="rib.label"
|
||||||
:label="t('commercial.clients.form.accounting.ribLabel')"
|
:label="t('commercial.clients.form.accounting.ribLabel')"
|
||||||
|
|||||||
@@ -96,7 +96,7 @@
|
|||||||
<MalioTabList v-if="visibleTabKeys.length" v-model="activeTab" :tabs="tabs" :max-visible-tabs="5" :max-width="1100" class="mt-[60px]">
|
<MalioTabList v-if="visibleTabKeys.length" v-model="activeTab" :tabs="tabs" :max-visible-tabs="5" :max-width="1100" class="mt-[60px]">
|
||||||
<!-- Onglet Information -->
|
<!-- Onglet Information -->
|
||||||
<template #information>
|
<template #information>
|
||||||
<div class="mt-12 grid grid-cols-4 gap-x-[44px] gap-y-4 bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<div class="mt-12 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<!-- pt-1/pb-1 alignent le textarea (h-full) en haut ET en bas
|
<!-- pt-1/pb-1 alignent le textarea (h-full) en haut ET en bas
|
||||||
sur les inputs (champ 40px centre dans un h-12 -> ~4px de
|
sur les inputs (champ 40px centre dans un h-12 -> ~4px de
|
||||||
coussin de chaque cote). -->
|
coussin de chaque cote). -->
|
||||||
@@ -156,6 +156,7 @@
|
|||||||
:key="contact.id ?? index"
|
:key="contact.id ?? index"
|
||||||
:model-value="contact"
|
:model-value="contact"
|
||||||
:title="t('commercial.clients.form.contact.title', { n: index + 1 })"
|
:title="t('commercial.clients.form.contact.title', { n: index + 1 })"
|
||||||
|
:last="index === contacts.length - 1"
|
||||||
disabled
|
disabled
|
||||||
hide-empty
|
hide-empty
|
||||||
/>
|
/>
|
||||||
@@ -170,6 +171,7 @@
|
|||||||
:key="view.draft.id ?? index"
|
:key="view.draft.id ?? index"
|
||||||
:model-value="view.draft"
|
:model-value="view.draft"
|
||||||
:title="t('commercial.clients.form.address.title', { n: index + 1 })"
|
:title="t('commercial.clients.form.address.title', { n: index + 1 })"
|
||||||
|
:last="index === addressViews.length - 1"
|
||||||
:category-options="view.categoryOptions"
|
:category-options="view.categoryOptions"
|
||||||
:site-options="allSiteOptions"
|
:site-options="allSiteOptions"
|
||||||
:contact-options="contactOptions"
|
:contact-options="contactOptions"
|
||||||
@@ -183,8 +185,10 @@
|
|||||||
<!-- Onglet Comptabilite (present uniquement si accounting.view). -->
|
<!-- Onglet Comptabilite (present uniquement si accounting.view). -->
|
||||||
<template v-if="canAccountingView" #accounting>
|
<template v-if="canAccountingView" #accounting>
|
||||||
<div class="mt-12 flex flex-col gap-6">
|
<div class="mt-12 flex flex-col gap-6">
|
||||||
<div class="bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<!-- Bloc infos comptables : titre + filet bas (filet uniquement s'il y a des RIB en dessous). -->
|
||||||
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
|
<div class="pb-[20px]" :class="{ 'border-b border-black': ribs.length > 0 }">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ t('commercial.clients.form.accounting.infoTitle') }}</h2>
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-if="isFilled(accounting.siren)"
|
v-if="isFilled(accounting.siren)"
|
||||||
:model-value="accounting.siren"
|
:model-value="accounting.siren"
|
||||||
@@ -239,13 +243,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Blocs RIB (0..n), lecture seule. -->
|
<!-- Blocs RIB (0..n), lecture seule.
|
||||||
|
Titre « RIB N », filet de separation sauf sous le dernier. -->
|
||||||
<div
|
<div
|
||||||
v-for="(rib, index) in ribs"
|
v-for="(rib, index) in ribs"
|
||||||
:key="rib.id ?? index"
|
:key="rib.id ?? index"
|
||||||
class="bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]"
|
class="pb-[20px]"
|
||||||
|
:class="{ 'border-b border-black': index !== ribs.length - 1 }"
|
||||||
>
|
>
|
||||||
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
|
<h2 class="text-[20px] font-semibold text-black">{{ t('commercial.clients.form.accounting.ribTitle', { n: index + 1 }) }}</h2>
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-if="isFilled(rib.label)"
|
v-if="isFilled(rib.label)"
|
||||||
:model-value="rib.label"
|
:model-value="rib.label"
|
||||||
|
|||||||
@@ -87,7 +87,7 @@
|
|||||||
<MalioTabList v-model="activeTab" :tabs="tabs" class="mt-[60px]">
|
<MalioTabList v-model="activeTab" :tabs="tabs" class="mt-[60px]">
|
||||||
<!-- Onglet Information -->
|
<!-- Onglet Information -->
|
||||||
<template #information>
|
<template #information>
|
||||||
<div class="mt-12 grid grid-cols-4 gap-x-[44px] gap-y-4 bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<div class="mt-12 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<!-- pt-1/pb-1 alignent le textarea (h-full) sur les inputs, dont
|
<!-- pt-1/pb-1 alignent le textarea (h-full) sur les inputs, dont
|
||||||
le champ de 40px est centre dans un conteneur h-12 (~4px de
|
le champ de 40px est centre dans un conteneur h-12 (~4px de
|
||||||
coussin en HAUT et en BAS). Sans pb-1, le textarea descend ~4px
|
coussin en HAUT et en BAS). Sans pb-1, le textarea descend ~4px
|
||||||
@@ -177,6 +177,7 @@
|
|||||||
:model-value="contact"
|
:model-value="contact"
|
||||||
:title="t('commercial.clients.form.contact.title', { n: index + 1 })"
|
:title="t('commercial.clients.form.contact.title', { n: index + 1 })"
|
||||||
:removable="isRowRemovable(contacts, index)"
|
:removable="isRowRemovable(contacts, index)"
|
||||||
|
:last="index === contacts.length - 1"
|
||||||
:disabled="isValidated('contact')"
|
:disabled="isValidated('contact')"
|
||||||
:errors="contactErrors[index]"
|
:errors="contactErrors[index]"
|
||||||
@update:model-value="(v) => contacts[index] = v"
|
@update:model-value="(v) => contacts[index] = v"
|
||||||
@@ -209,6 +210,7 @@
|
|||||||
:key="index"
|
:key="index"
|
||||||
:model-value="address"
|
:model-value="address"
|
||||||
:title="t('commercial.clients.form.address.title', { n: index + 1 })"
|
:title="t('commercial.clients.form.address.title', { n: index + 1 })"
|
||||||
|
:last="index === addresses.length - 1"
|
||||||
:category-options="addressCategoryOptions"
|
:category-options="addressCategoryOptions"
|
||||||
:site-options="referentials.sites.value"
|
:site-options="referentials.sites.value"
|
||||||
:contact-options="contactOptions"
|
:contact-options="contactOptions"
|
||||||
@@ -242,8 +244,10 @@
|
|||||||
<!-- Onglet Comptabilite (present uniquement si accounting.view) -->
|
<!-- Onglet Comptabilite (present uniquement si accounting.view) -->
|
||||||
<template v-if="canAccountingView" #accounting>
|
<template v-if="canAccountingView" #accounting>
|
||||||
<div class="mt-12 flex flex-col gap-6">
|
<div class="mt-12 flex flex-col gap-6">
|
||||||
<div class="bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<!-- Bloc infos comptables : titre + filet bas (filet uniquement s'il y a des RIB en dessous). -->
|
||||||
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
|
<div class="pb-[20px]" :class="{ 'border-b border-black': visibleRibs.length > 0 }">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ t('commercial.clients.form.accounting.infoTitle') }}</h2>
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-model="accounting.siren"
|
v-model="accounting.siren"
|
||||||
:label="t('commercial.clients.form.accounting.siren')"
|
:label="t('commercial.clients.form.accounting.siren')"
|
||||||
@@ -312,22 +316,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Blocs RIB — affiches uniquement si type de reglement = LCR (RG-1.13). -->
|
<!-- Blocs RIB — affiches uniquement si type de reglement = LCR (RG-1.13).
|
||||||
|
Titre « RIB N » + poubelle, filet de separation sauf sous le dernier. -->
|
||||||
<div
|
<div
|
||||||
v-for="(rib, index) in visibleRibs"
|
v-for="(rib, index) in visibleRibs"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="relative bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]"
|
class="pb-[20px]"
|
||||||
|
:class="{ 'border-b border-black': index !== visibleRibs.length - 1 }"
|
||||||
>
|
>
|
||||||
|
<!-- En-tete : titre du bloc (noir) a gauche, poubelle a droite. -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ t('commercial.clients.form.accounting.ribTitle', { n: index + 1 }) }}</h2>
|
||||||
<!-- ariaLabel via v-bind objet (prop camelCase ; aria-* serait un attribut HTML). -->
|
<!-- ariaLabel via v-bind objet (prop camelCase ; aria-* serait un attribut HTML). -->
|
||||||
<MalioButtonIcon
|
<MalioButtonIcon
|
||||||
v-if="!accountingReadonly && isRowRemovable(visibleRibs, index)"
|
v-if="!accountingReadonly && isRowRemovable(visibleRibs, index)"
|
||||||
icon="mdi:delete-outline"
|
icon="mdi:delete-outline"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
button-class="absolute top-3 right-3"
|
button-class="p-0"
|
||||||
v-bind="{ ariaLabel: t('commercial.clients.form.accounting.removeRib') }"
|
v-bind="{ ariaLabel: t('commercial.clients.form.accounting.removeRib') }"
|
||||||
@click="askRemoveRib(index)"
|
@click="askRemoveRib(index)"
|
||||||
/>
|
/>
|
||||||
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
|
</div>
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-model="rib.label"
|
v-model="rib.label"
|
||||||
:label="t('commercial.clients.form.accounting.ribLabel')"
|
:label="t('commercial.clients.form.accounting.ribLabel')"
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
<MalioTabList v-model="activeTab" :tabs="tabs" :max-visible-tabs="5" :max-width="1100" class="mt-[60px]">
|
<MalioTabList v-model="activeTab" :tabs="tabs" :max-visible-tabs="5" :max-width="1100" class="mt-[60px]">
|
||||||
<!-- Onglet Information -->
|
<!-- Onglet Information -->
|
||||||
<template #information>
|
<template #information>
|
||||||
<div class="mt-12 grid grid-cols-4 gap-x-[44px] gap-y-4 bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<div class="mt-12 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<!-- pt-1/pb-1 alignent le textarea (h-full) sur les inputs. -->
|
<!-- pt-1/pb-1 alignent le textarea (h-full) sur les inputs. -->
|
||||||
<MalioInputTextArea
|
<MalioInputTextArea
|
||||||
v-model="information.description"
|
v-model="information.description"
|
||||||
@@ -147,6 +147,7 @@
|
|||||||
:model-value="contact"
|
:model-value="contact"
|
||||||
:title="t('commercial.suppliers.form.contact.title', { n: index + 1 })"
|
:title="t('commercial.suppliers.form.contact.title', { n: index + 1 })"
|
||||||
:removable="isRowRemovable(contacts, index)"
|
:removable="isRowRemovable(contacts, index)"
|
||||||
|
:last="index === contacts.length - 1"
|
||||||
:disabled="businessReadonly"
|
:disabled="businessReadonly"
|
||||||
:errors="contactErrors[index]"
|
:errors="contactErrors[index]"
|
||||||
@update:model-value="(v) => contacts[index] = v"
|
@update:model-value="(v) => contacts[index] = v"
|
||||||
@@ -179,6 +180,7 @@
|
|||||||
:key="address.id ?? `new-${index}`"
|
:key="address.id ?? `new-${index}`"
|
||||||
:model-value="address"
|
:model-value="address"
|
||||||
:title="t('commercial.suppliers.form.address.title', { n: index + 1 })"
|
:title="t('commercial.suppliers.form.address.title', { n: index + 1 })"
|
||||||
|
:last="index === addresses.length - 1"
|
||||||
:category-options="mainCategoryOptions"
|
:category-options="mainCategoryOptions"
|
||||||
:site-options="siteOptions"
|
:site-options="siteOptions"
|
||||||
:contact-options="contactOptions"
|
:contact-options="contactOptions"
|
||||||
@@ -213,8 +215,10 @@
|
|||||||
editable uniquement si accounting.manage). -->
|
editable uniquement si accounting.manage). -->
|
||||||
<template v-if="canAccountingView" #accounting>
|
<template v-if="canAccountingView" #accounting>
|
||||||
<div class="mt-12 flex flex-col gap-6">
|
<div class="mt-12 flex flex-col gap-6">
|
||||||
<div class="bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<!-- Bloc infos comptables : titre + filet bas (filet uniquement s'il y a des RIB en dessous). -->
|
||||||
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
|
<div class="pb-[20px]" :class="{ 'border-b border-black': visibleRibs.length > 0 }">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ t('commercial.suppliers.form.accounting.infoTitle') }}</h2>
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-model="accounting.siren"
|
v-model="accounting.siren"
|
||||||
:label="t('commercial.suppliers.form.accounting.siren')"
|
:label="t('commercial.suppliers.form.accounting.siren')"
|
||||||
@@ -283,21 +287,27 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Blocs RIB — affiches uniquement si type de reglement = LCR (RG-2.08). -->
|
<!-- Blocs RIB — affiches uniquement si type de reglement = LCR (RG-2.08).
|
||||||
|
Titre « RIB N » + poubelle, filet de separation sauf sous le dernier. -->
|
||||||
<div
|
<div
|
||||||
v-for="(rib, index) in visibleRibs"
|
v-for="(rib, index) in visibleRibs"
|
||||||
:key="rib.id ?? `new-${index}`"
|
:key="rib.id ?? `new-${index}`"
|
||||||
class="relative bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]"
|
class="pb-[20px]"
|
||||||
|
:class="{ 'border-b border-black': index !== visibleRibs.length - 1 }"
|
||||||
>
|
>
|
||||||
|
<!-- En-tete : titre du bloc (noir) a gauche, poubelle a droite. -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ t('commercial.suppliers.form.accounting.ribTitle', { n: index + 1 }) }}</h2>
|
||||||
<MalioButtonIcon
|
<MalioButtonIcon
|
||||||
v-if="!accountingReadonly && isRowRemovable(visibleRibs, index)"
|
v-if="!accountingReadonly && isRowRemovable(visibleRibs, index)"
|
||||||
icon="mdi:delete-outline"
|
icon="mdi:delete-outline"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
button-class="absolute top-3 right-3"
|
button-class="p-0"
|
||||||
v-bind="{ ariaLabel: t('commercial.suppliers.form.accounting.removeRib') }"
|
v-bind="{ ariaLabel: t('commercial.suppliers.form.accounting.removeRib') }"
|
||||||
@click="askRemoveRib(index)"
|
@click="askRemoveRib(index)"
|
||||||
/>
|
/>
|
||||||
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
|
</div>
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-model="rib.label"
|
v-model="rib.label"
|
||||||
:label="t('commercial.suppliers.form.accounting.ribLabel')"
|
:label="t('commercial.suppliers.form.accounting.ribLabel')"
|
||||||
|
|||||||
@@ -71,7 +71,7 @@
|
|||||||
<MalioTabList v-if="visibleTabKeys.length" v-model="activeTab" :tabs="tabs" :max-visible-tabs="5" :max-width="1100" class="mt-[60px]">
|
<MalioTabList v-if="visibleTabKeys.length" v-model="activeTab" :tabs="tabs" :max-visible-tabs="5" :max-width="1100" class="mt-[60px]">
|
||||||
<!-- Onglet Information -->
|
<!-- Onglet Information -->
|
||||||
<template #information>
|
<template #information>
|
||||||
<div class="mt-12 grid grid-cols-4 gap-x-[44px] gap-y-4 bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<div class="mt-12 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<!-- pt-1/pb-1 alignent le textarea (h-full) en haut ET en bas
|
<!-- pt-1/pb-1 alignent le textarea (h-full) en haut ET en bas
|
||||||
sur les inputs (champ 40px centre dans un h-12). -->
|
sur les inputs (champ 40px centre dans un h-12). -->
|
||||||
<MalioInputTextArea
|
<MalioInputTextArea
|
||||||
@@ -137,6 +137,7 @@
|
|||||||
:key="contact.id ?? index"
|
:key="contact.id ?? index"
|
||||||
:model-value="contact"
|
:model-value="contact"
|
||||||
:title="t('commercial.suppliers.form.contact.title', { n: index + 1 })"
|
:title="t('commercial.suppliers.form.contact.title', { n: index + 1 })"
|
||||||
|
:last="index === contacts.length - 1"
|
||||||
disabled
|
disabled
|
||||||
hide-empty
|
hide-empty
|
||||||
/>
|
/>
|
||||||
@@ -151,6 +152,7 @@
|
|||||||
:key="view.draft.id ?? index"
|
:key="view.draft.id ?? index"
|
||||||
:model-value="view.draft"
|
:model-value="view.draft"
|
||||||
:title="t('commercial.suppliers.form.address.title', { n: index + 1 })"
|
:title="t('commercial.suppliers.form.address.title', { n: index + 1 })"
|
||||||
|
:last="index === addressViews.length - 1"
|
||||||
:category-options="view.categoryOptions"
|
:category-options="view.categoryOptions"
|
||||||
:site-options="allSiteOptions"
|
:site-options="allSiteOptions"
|
||||||
:contact-options="contactOptions"
|
:contact-options="contactOptions"
|
||||||
@@ -164,8 +166,10 @@
|
|||||||
<!-- Onglet Comptabilite (present uniquement si accounting.view). -->
|
<!-- Onglet Comptabilite (present uniquement si accounting.view). -->
|
||||||
<template v-if="canAccountingView" #accounting>
|
<template v-if="canAccountingView" #accounting>
|
||||||
<div class="mt-12 flex flex-col gap-6">
|
<div class="mt-12 flex flex-col gap-6">
|
||||||
<div class="bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<!-- Bloc infos comptables : titre + filet bas (filet uniquement s'il y a des RIB en dessous). -->
|
||||||
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
|
<div class="pb-[20px]" :class="{ 'border-b border-black': ribs.length > 0 }">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ t('commercial.suppliers.form.accounting.infoTitle') }}</h2>
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-if="isFilled(accounting.siren)"
|
v-if="isFilled(accounting.siren)"
|
||||||
:model-value="accounting.siren"
|
:model-value="accounting.siren"
|
||||||
@@ -220,13 +224,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Blocs RIB (0..n), lecture seule. -->
|
<!-- Blocs RIB (0..n), lecture seule.
|
||||||
|
Titre « RIB N », filet de separation sauf sous le dernier. -->
|
||||||
<div
|
<div
|
||||||
v-for="(rib, index) in ribs"
|
v-for="(rib, index) in ribs"
|
||||||
:key="rib.id ?? index"
|
:key="rib.id ?? index"
|
||||||
class="bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]"
|
class="pb-[20px]"
|
||||||
|
:class="{ 'border-b border-black': index !== ribs.length - 1 }"
|
||||||
>
|
>
|
||||||
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
|
<h2 class="text-[20px] font-semibold text-black">{{ t('commercial.suppliers.form.accounting.ribTitle', { n: index + 1 }) }}</h2>
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-if="isFilled(rib.label)"
|
v-if="isFilled(rib.label)"
|
||||||
:model-value="rib.label"
|
:model-value="rib.label"
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
<MalioTabList v-model="activeTab" :tabs="tabs" class="mt-[60px]">
|
<MalioTabList v-model="activeTab" :tabs="tabs" class="mt-[60px]">
|
||||||
<!-- Onglet Information -->
|
<!-- Onglet Information -->
|
||||||
<template #information>
|
<template #information>
|
||||||
<div class="mt-12 grid grid-cols-4 gap-x-[44px] gap-y-4 bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<div class="mt-12 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputTextArea
|
<MalioInputTextArea
|
||||||
v-model="information.description"
|
v-model="information.description"
|
||||||
:label="t('commercial.suppliers.form.information.description')"
|
:label="t('commercial.suppliers.form.information.description')"
|
||||||
@@ -145,6 +145,7 @@
|
|||||||
:model-value="contact"
|
:model-value="contact"
|
||||||
:title="t('commercial.suppliers.form.contact.title', { n: index + 1 })"
|
:title="t('commercial.suppliers.form.contact.title', { n: index + 1 })"
|
||||||
:removable="isRowRemovable(contacts, index)"
|
:removable="isRowRemovable(contacts, index)"
|
||||||
|
:last="index === contacts.length - 1"
|
||||||
:disabled="isValidated('contacts')"
|
:disabled="isValidated('contacts')"
|
||||||
:errors="contactErrors[index]"
|
:errors="contactErrors[index]"
|
||||||
@update:model-value="(v) => contacts[index] = v"
|
@update:model-value="(v) => contacts[index] = v"
|
||||||
@@ -177,6 +178,7 @@
|
|||||||
:key="index"
|
:key="index"
|
||||||
:model-value="address"
|
:model-value="address"
|
||||||
:title="t('commercial.suppliers.form.address.title', { n: index + 1 })"
|
:title="t('commercial.suppliers.form.address.title', { n: index + 1 })"
|
||||||
|
:last="index === addresses.length - 1"
|
||||||
:category-options="referentials.categories.value"
|
:category-options="referentials.categories.value"
|
||||||
:site-options="referentials.sites.value"
|
:site-options="referentials.sites.value"
|
||||||
:contact-options="contactOptions"
|
:contact-options="contactOptions"
|
||||||
@@ -210,8 +212,10 @@
|
|||||||
<!-- Onglet Comptabilite (present uniquement si accounting.view) -->
|
<!-- Onglet Comptabilite (present uniquement si accounting.view) -->
|
||||||
<template v-if="canAccountingView" #accounting>
|
<template v-if="canAccountingView" #accounting>
|
||||||
<div class="mt-12 flex flex-col gap-6">
|
<div class="mt-12 flex flex-col gap-6">
|
||||||
<div class="bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<!-- Bloc infos comptables : titre + filet bas (filet uniquement s'il y a des RIB en dessous). -->
|
||||||
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
|
<div class="pb-[20px]" :class="{ 'border-b border-black': visibleRibs.length > 0 }">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ t('commercial.suppliers.form.accounting.infoTitle') }}</h2>
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-model="accounting.siren"
|
v-model="accounting.siren"
|
||||||
:label="t('commercial.suppliers.form.accounting.siren')"
|
:label="t('commercial.suppliers.form.accounting.siren')"
|
||||||
@@ -280,21 +284,27 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Blocs RIB — affiches uniquement si type de reglement = LCR (RG-2.08). -->
|
<!-- Blocs RIB — affiches uniquement si type de reglement = LCR (RG-2.08).
|
||||||
|
Titre « RIB N » + poubelle, filet de separation sauf sous le dernier. -->
|
||||||
<div
|
<div
|
||||||
v-for="(rib, index) in visibleRibs"
|
v-for="(rib, index) in visibleRibs"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="relative bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]"
|
class="pb-[20px]"
|
||||||
|
:class="{ 'border-b border-black': index !== visibleRibs.length - 1 }"
|
||||||
>
|
>
|
||||||
|
<!-- En-tete : titre du bloc (noir) a gauche, poubelle a droite. -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ t('commercial.suppliers.form.accounting.ribTitle', { n: index + 1 }) }}</h2>
|
||||||
<MalioButtonIcon
|
<MalioButtonIcon
|
||||||
v-if="!accountingReadonly && isRowRemovable(visibleRibs, index)"
|
v-if="!accountingReadonly && isRowRemovable(visibleRibs, index)"
|
||||||
icon="mdi:delete-outline"
|
icon="mdi:delete-outline"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
button-class="absolute top-3 right-3"
|
button-class="p-0"
|
||||||
v-bind="{ ariaLabel: t('commercial.suppliers.form.accounting.removeRib') }"
|
v-bind="{ ariaLabel: t('commercial.suppliers.form.accounting.removeRib') }"
|
||||||
@click="askRemoveRib(index)"
|
@click="askRemoveRib(index)"
|
||||||
/>
|
/>
|
||||||
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
|
</div>
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-model="rib.label"
|
v-model="rib.label"
|
||||||
:label="t('commercial.suppliers.form.accounting.ribLabel')"
|
:label="t('commercial.suppliers.form.accounting.ribLabel')"
|
||||||
|
|||||||
@@ -1,15 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative grid grid-cols-4 gap-x-[44px] gap-y-4 bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<!-- Bloc a plat (sans box-shadow) : un filet noir 1px le separe du suivant
|
||||||
|
(pas de bordure sous le dernier bloc). -->
|
||||||
|
<div class="pb-[20px]" :class="{ 'border-b border-black': !last }">
|
||||||
|
<!-- En-tete : titre du bloc (noir) a gauche, poubelle de suppression a droite. -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ title }}</h2>
|
||||||
<!-- Suppression : modal de confirmation cote parent. -->
|
<!-- Suppression : modal de confirmation cote parent. -->
|
||||||
<MalioButtonIcon
|
<MalioButtonIcon
|
||||||
v-if="removable && !readonly && !disabled"
|
v-if="removable && !readonly && !disabled"
|
||||||
icon="mdi:delete-outline"
|
icon="mdi:delete-outline"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
button-class="absolute top-3 right-3"
|
button-class="p-0"
|
||||||
v-bind="{ ariaLabel: t('technique.providers.form.address.remove') }"
|
v-bind="{ ariaLabel: t('technique.providers.form.address.remove') }"
|
||||||
@click="$emit('remove')"
|
@click="$emit('remove')"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Grille 4 colonnes des champs de l'adresse. -->
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<!-- Sites Starseed : multiselect a tags (>= 1 obligatoire, RG-3.05). -->
|
<!-- Sites Starseed : multiselect a tags (>= 1 obligatoire, RG-3.05). -->
|
||||||
<MalioSelectCheckbox
|
<MalioSelectCheckbox
|
||||||
v-if="!hideEmpty || isFilled(model.siteIris)"
|
v-if="!hideEmpty || isFilled(model.siteIris)"
|
||||||
@@ -128,6 +136,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -143,6 +152,8 @@ const POSTAL_CODE_MASK = '#####'
|
|||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
/** Brouillon de l'adresse (v-model). */
|
/** Brouillon de l'adresse (v-model). */
|
||||||
modelValue: ProviderAddressFormDraft
|
modelValue: ProviderAddressFormDraft
|
||||||
|
/** Titre du bloc (ex: « Adresse 1 »). */
|
||||||
|
title: string
|
||||||
/** Sites Starseed disponibles. */
|
/** Sites Starseed disponibles. */
|
||||||
siteOptions: RefOption[]
|
siteOptions: RefOption[]
|
||||||
/** Contacts deja saisis, rattachables a l'adresse. */
|
/** Contacts deja saisis, rattachables a l'adresse. */
|
||||||
@@ -150,6 +161,8 @@ const props = defineProps<{
|
|||||||
/** Pays disponibles (France par defaut). */
|
/** Pays disponibles (France par defaut). */
|
||||||
countryOptions: RefOption[]
|
countryOptions: RefOption[]
|
||||||
removable?: boolean
|
removable?: boolean
|
||||||
|
/** Dernier bloc de la liste : supprime le filet de separation bas. */
|
||||||
|
last?: boolean
|
||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
/** Bloc desactive (champs grises, consultation — distinct de readonly). */
|
/** Bloc desactive (champs grises, consultation — distinct de readonly). */
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
|
|||||||
@@ -1,16 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative grid grid-cols-4 gap-x-[44px] gap-y-4 bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<!-- Bloc a plat (sans box-shadow) : un filet noir 1px le separe du suivant
|
||||||
|
(pas de bordure sous le dernier bloc). -->
|
||||||
|
<div class="pb-[20px]" :class="{ 'border-b border-black': !last }">
|
||||||
|
<!-- En-tete : titre du bloc (noir) a gauche, poubelle de suppression a droite. -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ title }}</h2>
|
||||||
<!-- Suppression : ouvre une modal de confirmation cote parent. Masquee si
|
<!-- Suppression : ouvre une modal de confirmation cote parent. Masquee si
|
||||||
non supprimable (1er bloc) ou en lecture seule. -->
|
non supprimable (1er bloc) ou en lecture seule. -->
|
||||||
<MalioButtonIcon
|
<MalioButtonIcon
|
||||||
v-if="removable && !readonly && !disabled"
|
v-if="removable && !readonly && !disabled"
|
||||||
icon="mdi:delete-outline"
|
icon="mdi:delete-outline"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
button-class="absolute top-3 right-3"
|
button-class="p-0"
|
||||||
v-bind="{ ariaLabel: t('technique.providers.form.contact.remove') }"
|
v-bind="{ ariaLabel: t('technique.providers.form.contact.remove') }"
|
||||||
@click="$emit('remove')"
|
@click="$emit('remove')"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Grille 4 colonnes des champs du contact. -->
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-if="!hideEmpty || isFilled(model.lastName)"
|
v-if="!hideEmpty || isFilled(model.lastName)"
|
||||||
:model-value="model.lastName"
|
:model-value="model.lastName"
|
||||||
@@ -80,6 +88,7 @@
|
|||||||
@update:model-value="(v: string) => update('phoneSecondary', v)"
|
@update:model-value="(v: string) => update('phoneSecondary', v)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -93,8 +102,12 @@ const PHONE_MASK = '## ## ## ## ##'
|
|||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
/** Brouillon du contact (v-model). */
|
/** Brouillon du contact (v-model). */
|
||||||
modelValue: ProviderContactFormDraft
|
modelValue: ProviderContactFormDraft
|
||||||
|
/** Titre du bloc (ex: « Contact 1 »). */
|
||||||
|
title: string
|
||||||
/** Affiche l'icone de suppression (1er bloc non supprimable). */
|
/** Affiche l'icone de suppression (1er bloc non supprimable). */
|
||||||
removable?: boolean
|
removable?: boolean
|
||||||
|
/** Dernier bloc de la liste : supprime le filet de separation bas. */
|
||||||
|
last?: boolean
|
||||||
/** Bloc en lecture seule (onglet valide). */
|
/** Bloc en lecture seule (onglet valide). */
|
||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
/** Bloc desactive (champs grises, consultation — distinct de readonly). */
|
/** Bloc desactive (champs grises, consultation — distinct de readonly). */
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ function mountBlock(overrides: Record<string, unknown> = {}, errors?: Record<str
|
|||||||
return mount(ProviderAddressBlock, {
|
return mount(ProviderAddressBlock, {
|
||||||
props: {
|
props: {
|
||||||
modelValue: { ...emptyProviderAddress(), ...overrides },
|
modelValue: { ...emptyProviderAddress(), ...overrides },
|
||||||
|
title: 'Adresse 1',
|
||||||
siteOptions: [],
|
siteOptions: [],
|
||||||
contactOptions: [],
|
contactOptions: [],
|
||||||
countryOptions: [],
|
countryOptions: [],
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ function mountBlock(errors?: Record<string, string>) {
|
|||||||
return mount(ProviderContactBlock, {
|
return mount(ProviderContactBlock, {
|
||||||
props: {
|
props: {
|
||||||
modelValue: emptyProviderContact(),
|
modelValue: emptyProviderContact(),
|
||||||
|
title: 'Contact 1',
|
||||||
...(errors ? { errors } : {}),
|
...(errors ? { errors } : {}),
|
||||||
},
|
},
|
||||||
global: {
|
global: {
|
||||||
|
|||||||
@@ -72,7 +72,9 @@
|
|||||||
v-for="(contact, index) in contacts"
|
v-for="(contact, index) in contacts"
|
||||||
:key="index"
|
:key="index"
|
||||||
:model-value="contact"
|
:model-value="contact"
|
||||||
|
:title="t('technique.providers.form.contact.title', { n: index + 1 })"
|
||||||
:removable="isRowRemovable(contacts, index)"
|
:removable="isRowRemovable(contacts, index)"
|
||||||
|
:last="index === contacts.length - 1"
|
||||||
:disabled="businessReadonly"
|
:disabled="businessReadonly"
|
||||||
:errors="contactErrors[index]"
|
:errors="contactErrors[index]"
|
||||||
@update:model-value="(v) => contacts[index] = v"
|
@update:model-value="(v) => contacts[index] = v"
|
||||||
@@ -104,6 +106,8 @@
|
|||||||
v-for="(address, index) in addresses"
|
v-for="(address, index) in addresses"
|
||||||
:key="index"
|
:key="index"
|
||||||
:model-value="address"
|
:model-value="address"
|
||||||
|
:title="t('technique.providers.form.address.title', { n: index + 1 })"
|
||||||
|
:last="index === addresses.length - 1"
|
||||||
:site-options="referentials.sites.value"
|
:site-options="referentials.sites.value"
|
||||||
:contact-options="contactOptions"
|
:contact-options="contactOptions"
|
||||||
:country-options="countryOptions"
|
:country-options="countryOptions"
|
||||||
@@ -136,8 +140,10 @@
|
|||||||
<!-- Onglet Comptabilite (present si accounting.view ; editable si manage). -->
|
<!-- Onglet Comptabilite (present si accounting.view ; editable si manage). -->
|
||||||
<template v-if="canAccountingView" #accounting>
|
<template v-if="canAccountingView" #accounting>
|
||||||
<div class="mt-12 flex flex-col gap-6">
|
<div class="mt-12 flex flex-col gap-6">
|
||||||
<div class="bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<!-- Bloc infos comptables : titre + filet bas (filet uniquement s'il y a des RIB en dessous). -->
|
||||||
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
|
<div class="pb-[20px]" :class="{ 'border-b border-black': visibleRibs.length > 0 }">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ t('technique.providers.form.accounting.infoTitle') }}</h2>
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-model="accounting.siren"
|
v-model="accounting.siren"
|
||||||
:label="t('technique.providers.form.accounting.siren')"
|
:label="t('technique.providers.form.accounting.siren')"
|
||||||
@@ -206,21 +212,27 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Blocs RIB — affiches uniquement si type de reglement = LCR (RG-3.08). -->
|
<!-- Blocs RIB — affiches uniquement si type de reglement = LCR (RG-3.08).
|
||||||
|
Titre « RIB N » + poubelle, filet de separation sauf sous le dernier. -->
|
||||||
<div
|
<div
|
||||||
v-for="(rib, index) in visibleRibs"
|
v-for="(rib, index) in visibleRibs"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="relative bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]"
|
class="pb-[20px]"
|
||||||
|
:class="{ 'border-b border-black': index !== visibleRibs.length - 1 }"
|
||||||
>
|
>
|
||||||
|
<!-- En-tete : titre du bloc (noir) a gauche, poubelle a droite. -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ t('technique.providers.form.accounting.ribTitle', { n: index + 1 }) }}</h2>
|
||||||
<MalioButtonIcon
|
<MalioButtonIcon
|
||||||
v-if="!accountingReadonly && isRowRemovable(visibleRibs, index)"
|
v-if="!accountingReadonly && isRowRemovable(visibleRibs, index)"
|
||||||
icon="mdi:delete-outline"
|
icon="mdi:delete-outline"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
button-class="absolute top-3 right-3"
|
button-class="p-0"
|
||||||
v-bind="{ ariaLabel: t('technique.providers.form.accounting.removeRib') }"
|
v-bind="{ ariaLabel: t('technique.providers.form.accounting.removeRib') }"
|
||||||
@click="askRemoveRib(index)"
|
@click="askRemoveRib(index)"
|
||||||
/>
|
/>
|
||||||
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
|
</div>
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-model="rib.label"
|
v-model="rib.label"
|
||||||
:label="t('technique.providers.form.accounting.ribLabel')"
|
:label="t('technique.providers.form.accounting.ribLabel')"
|
||||||
|
|||||||
@@ -81,6 +81,8 @@
|
|||||||
v-for="(contact, index) in contacts"
|
v-for="(contact, index) in contacts"
|
||||||
:key="index"
|
:key="index"
|
||||||
:model-value="contact"
|
:model-value="contact"
|
||||||
|
:title="t('technique.providers.form.contact.title', { n: index + 1 })"
|
||||||
|
:last="index === contacts.length - 1"
|
||||||
disabled
|
disabled
|
||||||
hide-empty
|
hide-empty
|
||||||
/>
|
/>
|
||||||
@@ -94,6 +96,8 @@
|
|||||||
v-for="(view, index) in addressViews"
|
v-for="(view, index) in addressViews"
|
||||||
:key="index"
|
:key="index"
|
||||||
:model-value="view.draft"
|
:model-value="view.draft"
|
||||||
|
:title="t('technique.providers.form.address.title', { n: index + 1 })"
|
||||||
|
:last="index === addressViews.length - 1"
|
||||||
:site-options="view.siteOptions"
|
:site-options="view.siteOptions"
|
||||||
:contact-options="contactOptions"
|
:contact-options="contactOptions"
|
||||||
:country-options="countryOptionsFor(view.draft.country)"
|
:country-options="countryOptionsFor(view.draft.country)"
|
||||||
@@ -108,8 +112,10 @@
|
|||||||
<!-- Onglet Comptabilite (present uniquement si accounting.view). -->
|
<!-- Onglet Comptabilite (present uniquement si accounting.view). -->
|
||||||
<template v-if="canAccountingView" #accounting>
|
<template v-if="canAccountingView" #accounting>
|
||||||
<div class="mt-12 flex flex-col gap-6">
|
<div class="mt-12 flex flex-col gap-6">
|
||||||
<div class="bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<!-- Bloc infos comptables : titre + filet bas (filet uniquement s'il y a des RIB en dessous). -->
|
||||||
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
|
<div class="pb-[20px]" :class="{ 'border-b border-black': visibleRibs.length > 0 }">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ t('technique.providers.form.accounting.infoTitle') }}</h2>
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText v-if="isFilled(accounting.siren)" :model-value="accounting.siren" :label="t('technique.providers.form.accounting.siren')" disabled />
|
<MalioInputText v-if="isFilled(accounting.siren)" :model-value="accounting.siren" :label="t('technique.providers.form.accounting.siren')" disabled />
|
||||||
<MalioInputText v-if="isFilled(accounting.accountNumber)" :model-value="accounting.accountNumber" :label="t('technique.providers.form.accounting.accountNumber')" disabled />
|
<MalioInputText v-if="isFilled(accounting.accountNumber)" :model-value="accounting.accountNumber" :label="t('technique.providers.form.accounting.accountNumber')" disabled />
|
||||||
<MalioSelect v-if="isFilled(accounting.tvaModeIri)" :model-value="accounting.tvaModeIri" :options="tvaModeOptions" :label="t('technique.providers.form.accounting.tvaMode')" disabled empty-option-label="" />
|
<MalioSelect v-if="isFilled(accounting.tvaModeIri)" :model-value="accounting.tvaModeIri" :options="tvaModeOptions" :label="t('technique.providers.form.accounting.tvaMode')" disabled empty-option-label="" />
|
||||||
@@ -120,13 +126,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Blocs RIB (uniquement si type de reglement = LCR). -->
|
<!-- Blocs RIB (uniquement si type de reglement = LCR).
|
||||||
|
Titre « RIB N », filet de separation sauf sous le dernier. -->
|
||||||
<div
|
<div
|
||||||
v-for="(rib, index) in visibleRibs"
|
v-for="(rib, index) in visibleRibs"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]"
|
class="pb-[20px]"
|
||||||
|
:class="{ 'border-b border-black': index !== visibleRibs.length - 1 }"
|
||||||
>
|
>
|
||||||
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
|
<h2 class="text-[20px] font-semibold text-black">{{ t('technique.providers.form.accounting.ribTitle', { n: index + 1 }) }}</h2>
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText v-if="isFilled(rib.label)" :model-value="rib.label" :label="t('technique.providers.form.accounting.ribLabel')" disabled />
|
<MalioInputText v-if="isFilled(rib.label)" :model-value="rib.label" :label="t('technique.providers.form.accounting.ribLabel')" disabled />
|
||||||
<MalioInputText v-if="isFilled(rib.bic)" :model-value="rib.bic" :label="t('technique.providers.form.accounting.ribBic')" disabled />
|
<MalioInputText v-if="isFilled(rib.bic)" :model-value="rib.bic" :label="t('technique.providers.form.accounting.ribBic')" disabled />
|
||||||
<MalioInputText v-if="isFilled(rib.iban)" :model-value="rib.iban" :label="t('technique.providers.form.accounting.ribIban')" disabled />
|
<MalioInputText v-if="isFilled(rib.iban)" :model-value="rib.iban" :label="t('technique.providers.form.accounting.ribIban')" disabled />
|
||||||
|
|||||||
@@ -73,7 +73,9 @@
|
|||||||
v-for="(contact, index) in contacts"
|
v-for="(contact, index) in contacts"
|
||||||
:key="index"
|
:key="index"
|
||||||
:model-value="contact"
|
:model-value="contact"
|
||||||
|
:title="t('technique.providers.form.contact.title', { n: index + 1 })"
|
||||||
:removable="isRowRemovable(contacts, index)"
|
:removable="isRowRemovable(contacts, index)"
|
||||||
|
:last="index === contacts.length - 1"
|
||||||
:disabled="isValidated('contact')"
|
:disabled="isValidated('contact')"
|
||||||
:errors="contactErrors[index]"
|
:errors="contactErrors[index]"
|
||||||
@update:model-value="(v) => contacts[index] = v"
|
@update:model-value="(v) => contacts[index] = v"
|
||||||
@@ -108,6 +110,8 @@
|
|||||||
v-for="(address, index) in addresses"
|
v-for="(address, index) in addresses"
|
||||||
:key="index"
|
:key="index"
|
||||||
:model-value="address"
|
:model-value="address"
|
||||||
|
:title="t('technique.providers.form.address.title', { n: index + 1 })"
|
||||||
|
:last="index === addresses.length - 1"
|
||||||
:site-options="referentials.sites.value"
|
:site-options="referentials.sites.value"
|
||||||
:contact-options="contactOptions"
|
:contact-options="contactOptions"
|
||||||
:country-options="countryOptions"
|
:country-options="countryOptions"
|
||||||
@@ -139,8 +143,10 @@
|
|||||||
<!-- Onglet Comptabilite (present uniquement si accounting.view ; editable si manage). -->
|
<!-- Onglet Comptabilite (present uniquement si accounting.view ; editable si manage). -->
|
||||||
<template v-if="canAccountingView" #accounting>
|
<template v-if="canAccountingView" #accounting>
|
||||||
<div class="mt-12 flex flex-col gap-6">
|
<div class="mt-12 flex flex-col gap-6">
|
||||||
<div class="bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<!-- Bloc infos comptables : titre + filet bas (filet uniquement s'il y a des RIB en dessous). -->
|
||||||
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
|
<div class="pb-[20px]" :class="{ 'border-b border-black': visibleRibs.length > 0 }">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ t('technique.providers.form.accounting.infoTitle') }}</h2>
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-model="accounting.siren"
|
v-model="accounting.siren"
|
||||||
:label="t('technique.providers.form.accounting.siren')"
|
:label="t('technique.providers.form.accounting.siren')"
|
||||||
@@ -210,21 +216,27 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Blocs RIB — affiches uniquement si type de reglement = LCR (RG-3.08). -->
|
<!-- Blocs RIB — affiches uniquement si type de reglement = LCR (RG-3.08).
|
||||||
|
Titre « RIB N » + poubelle, filet de separation sauf sous le dernier. -->
|
||||||
<div
|
<div
|
||||||
v-for="(rib, index) in visibleRibs"
|
v-for="(rib, index) in visibleRibs"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="relative bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]"
|
class="pb-[20px]"
|
||||||
|
:class="{ 'border-b border-black': index !== visibleRibs.length - 1 }"
|
||||||
>
|
>
|
||||||
|
<!-- En-tete : titre du bloc (noir) a gauche, poubelle a droite. -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ t('technique.providers.form.accounting.ribTitle', { n: index + 1 }) }}</h2>
|
||||||
<MalioButtonIcon
|
<MalioButtonIcon
|
||||||
v-if="!accountingReadonly && isRowRemovable(visibleRibs, index)"
|
v-if="!accountingReadonly && isRowRemovable(visibleRibs, index)"
|
||||||
icon="mdi:delete-outline"
|
icon="mdi:delete-outline"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
button-class="absolute top-3 right-3"
|
button-class="p-0"
|
||||||
v-bind="{ ariaLabel: t('technique.providers.form.accounting.removeRib') }"
|
v-bind="{ ariaLabel: t('technique.providers.form.accounting.removeRib') }"
|
||||||
@click="askRemoveRib(index)"
|
@click="askRemoveRib(index)"
|
||||||
/>
|
/>
|
||||||
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
|
</div>
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-model="rib.label"
|
v-model="rib.label"
|
||||||
:label="t('technique.providers.form.accounting.ribLabel')"
|
:label="t('technique.providers.form.accounting.ribLabel')"
|
||||||
|
|||||||
@@ -1,6 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- Adresse UNIQUE par transporteur (ERP-172) : un seul bloc, jamais supprimable. -->
|
<!-- Adresse UNIQUE par transporteur (ERP-172) : un seul bloc, jamais supprimable. -->
|
||||||
<div class="relative grid grid-cols-4 gap-x-[44px] gap-y-4 bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<!-- Bloc a plat (sans box-shadow) : un filet noir 1px le separe du suivant
|
||||||
|
(pas de bordure sous le dernier bloc). -->
|
||||||
|
<div class="pb-[20px]" :class="{ 'border-b border-black': !last }">
|
||||||
|
<!-- En-tete : titre du bloc, en noir (adresse unique, sans suppression). -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ title }}</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Grille 4 colonnes des champs de l'adresse. -->
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<!-- Pays : prerempli « France » (RG-4.05). -->
|
<!-- Pays : prerempli « France » (RG-4.05). -->
|
||||||
<MalioSelect
|
<MalioSelect
|
||||||
v-if="!hideEmpty || isFilled(model.country)"
|
v-if="!hideEmpty || isFilled(model.country)"
|
||||||
@@ -99,6 +108,7 @@
|
|||||||
@update:model-value="(v: string) => update('streetComplement', v)"
|
@update:model-value="(v: string) => update('streetComplement', v)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -118,8 +128,12 @@ const POSTAL_CODE_MASK = '#####'
|
|||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
/** Brouillon de l'adresse (v-model). */
|
/** Brouillon de l'adresse (v-model). */
|
||||||
modelValue: CarrierAddressFormDraft
|
modelValue: CarrierAddressFormDraft
|
||||||
|
/** Titre du bloc (ex: « Adresse 1 »). */
|
||||||
|
title: string
|
||||||
/** Pays disponibles (France par defaut). */
|
/** Pays disponibles (France par defaut). */
|
||||||
countryOptions: RefOption[]
|
countryOptions: RefOption[]
|
||||||
|
/** Dernier bloc de la liste : supprime le filet de separation bas. */
|
||||||
|
last?: boolean
|
||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
/** Bloc desactive (champs grises, consultation — distinct de readonly). */
|
/** Bloc desactive (champs grises, consultation — distinct de readonly). */
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
|
|||||||
@@ -1,16 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative grid grid-cols-4 gap-x-[44px] gap-y-4 bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<!-- Bloc a plat (sans box-shadow) : un filet noir 1px le separe du suivant
|
||||||
|
(pas de bordure sous le dernier bloc). -->
|
||||||
|
<div class="pb-[20px]" :class="{ 'border-b border-black': !last }">
|
||||||
|
<!-- En-tete : titre du bloc (noir) a gauche, poubelle de suppression a droite. -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ title }}</h2>
|
||||||
<!-- Suppression : ouvre une modal de confirmation côté parent. Masquée si
|
<!-- Suppression : ouvre une modal de confirmation côté parent. Masquée si
|
||||||
non supprimable (1er bloc) ou en lecture seule. -->
|
non supprimable (1er bloc) ou en lecture seule. -->
|
||||||
<MalioButtonIcon
|
<MalioButtonIcon
|
||||||
v-if="removable && !readonly && !disabled"
|
v-if="removable && !readonly && !disabled"
|
||||||
icon="mdi:delete-outline"
|
icon="mdi:delete-outline"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
button-class="absolute top-3 right-3"
|
button-class="p-0"
|
||||||
v-bind="{ ariaLabel: t('transport.carriers.form.contact.remove') }"
|
v-bind="{ ariaLabel: t('transport.carriers.form.contact.remove') }"
|
||||||
@click="$emit('remove')"
|
@click="$emit('remove')"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Grille 4 colonnes des champs du contact. -->
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<MalioInputText
|
<MalioInputText
|
||||||
v-if="!hideEmpty || isFilled(model.lastName)"
|
v-if="!hideEmpty || isFilled(model.lastName)"
|
||||||
:model-value="model.lastName"
|
:model-value="model.lastName"
|
||||||
@@ -80,6 +88,7 @@
|
|||||||
@update:model-value="(v: string) => update('phoneSecondary', v)"
|
@update:model-value="(v: string) => update('phoneSecondary', v)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -93,8 +102,12 @@ const PHONE_MASK = '## ## ## ## ##'
|
|||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
/** Brouillon du contact (v-model). */
|
/** Brouillon du contact (v-model). */
|
||||||
modelValue: CarrierContactFormDraft
|
modelValue: CarrierContactFormDraft
|
||||||
|
/** Titre du bloc (ex: « Contact 1 »). */
|
||||||
|
title: string
|
||||||
/** Affiche l'icône de suppression (1er bloc non supprimable). */
|
/** Affiche l'icône de suppression (1er bloc non supprimable). */
|
||||||
removable?: boolean
|
removable?: boolean
|
||||||
|
/** Dernier bloc de la liste : supprime le filet de separation bas. */
|
||||||
|
last?: boolean
|
||||||
/** Bloc en lecture seule (onglet validé). */
|
/** Bloc en lecture seule (onglet validé). */
|
||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
/** Bloc desactive (champs grises, consultation — distinct de readonly). */
|
/** Bloc desactive (champs grises, consultation — distinct de readonly). */
|
||||||
|
|||||||
@@ -1,15 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative grid grid-cols-4 gap-x-[44px] gap-y-4 bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
|
<!-- Bloc a plat (sans box-shadow) : un filet noir 1px le separe du suivant
|
||||||
|
(pas de bordure sous le dernier bloc), aligne sur les blocs contact / adresse. -->
|
||||||
|
<div class="pb-[20px]" :class="{ 'border-b border-black': !last }">
|
||||||
|
<!-- En-tete : titre du bloc (noir) a gauche, poubelle de suppression a droite. -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h2 class="text-[20px] font-semibold text-black">{{ title }}</h2>
|
||||||
<!-- Suppression : modal de confirmation côté parent. -->
|
<!-- Suppression : modal de confirmation côté parent. -->
|
||||||
<MalioButtonIcon
|
<MalioButtonIcon
|
||||||
v-if="removable && !readonly && !disabled"
|
v-if="removable && !readonly && !disabled"
|
||||||
icon="mdi:delete-outline"
|
icon="mdi:delete-outline"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
button-class="absolute top-3 right-3"
|
button-class="p-0"
|
||||||
v-bind="{ ariaLabel: t('transport.carriers.form.price.remove') }"
|
v-bind="{ ariaLabel: t('transport.carriers.form.price.remove') }"
|
||||||
@click="$emit('remove')"
|
@click="$emit('remove')"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Grille 4 colonnes des champs du prix. -->
|
||||||
|
<div class="mt-6 grid grid-cols-4 gap-x-[44px] gap-y-4">
|
||||||
<!-- RG-4.09 : sens du prix (CLIENT / FOURNISSEUR) en colonne 1 / ligne 1, radios
|
<!-- RG-4.09 : sens du prix (CLIENT / FOURNISSEUR) en colonne 1 / ligne 1, radios
|
||||||
EN LIGNE (horizontaux), centrés sur la hauteur de champ (h-12) comme la
|
EN LIGNE (horizontaux), centrés sur la hauteur de champ (h-12) comme la
|
||||||
case « Affréter ». Pas de label de groupe. -->
|
case « Affréter ». Pas de label de groupe. -->
|
||||||
@@ -186,6 +194,7 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -200,6 +209,10 @@ interface SelectOption {
|
|||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
/** Brouillon du prix (v-model). */
|
/** Brouillon du prix (v-model). */
|
||||||
modelValue: CarrierPriceFormDraft
|
modelValue: CarrierPriceFormDraft
|
||||||
|
/** Titre du bloc (ex: « Prix 1 »). */
|
||||||
|
title: string
|
||||||
|
/** Dernier bloc de la liste : supprime le filet de separation bas. */
|
||||||
|
last?: boolean
|
||||||
/** Clients disponibles (IRI en value). */
|
/** Clients disponibles (IRI en value). */
|
||||||
clientOptions: SelectOption[]
|
clientOptions: SelectOption[]
|
||||||
/** Fournisseurs disponibles (IRI en value). */
|
/** Fournisseurs disponibles (IRI en value). */
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ function mountBlock(overrides: Record<string, unknown> = {}) {
|
|||||||
return mount(CarrierAddressBlock, {
|
return mount(CarrierAddressBlock, {
|
||||||
props: {
|
props: {
|
||||||
modelValue: { ...emptyCarrierAddress(), ...overrides },
|
modelValue: { ...emptyCarrierAddress(), ...overrides },
|
||||||
|
title: 'Adresse 1',
|
||||||
countryOptions: [{ value: 'France', label: 'France' }],
|
countryOptions: [{ value: 'France', label: 'France' }],
|
||||||
},
|
},
|
||||||
global: {
|
global: {
|
||||||
|
|||||||
@@ -143,6 +143,8 @@
|
|||||||
<!-- Adresse UNIQUE (ERP-172) : un seul bloc, sans ajouter/supprimer. -->
|
<!-- Adresse UNIQUE (ERP-172) : un seul bloc, sans ajouter/supprimer. -->
|
||||||
<CarrierAddressBlock
|
<CarrierAddressBlock
|
||||||
:model-value="address"
|
:model-value="address"
|
||||||
|
:title="t('transport.carriers.form.address.title')"
|
||||||
|
:last="true"
|
||||||
:country-options="countryOptions"
|
:country-options="countryOptions"
|
||||||
:errors="addressErrors"
|
:errors="addressErrors"
|
||||||
@update:model-value="(v) => address = v"
|
@update:model-value="(v) => address = v"
|
||||||
@@ -160,7 +162,9 @@
|
|||||||
v-for="(contact, index) in contacts"
|
v-for="(contact, index) in contacts"
|
||||||
:key="index"
|
:key="index"
|
||||||
:model-value="contact"
|
:model-value="contact"
|
||||||
|
:title="t('transport.carriers.form.contact.title', { n: index + 1 })"
|
||||||
:removable="isRowRemovable(contacts, index)"
|
:removable="isRowRemovable(contacts, index)"
|
||||||
|
:last="index === contacts.length - 1"
|
||||||
:errors="contactErrors[index]"
|
:errors="contactErrors[index]"
|
||||||
@update:model-value="(v) => contacts[index] = v"
|
@update:model-value="(v) => contacts[index] = v"
|
||||||
@remove="askRemoveContact(index)"
|
@remove="askRemoveContact(index)"
|
||||||
@@ -178,10 +182,12 @@
|
|||||||
v-for="(price, index) in prices"
|
v-for="(price, index) in prices"
|
||||||
:key="index"
|
:key="index"
|
||||||
:model-value="price"
|
:model-value="price"
|
||||||
|
:title="t('transport.carriers.form.price.title', { n: index + 1 })"
|
||||||
:client-options="clientOptions"
|
:client-options="clientOptions"
|
||||||
:supplier-options="supplierOptions"
|
:supplier-options="supplierOptions"
|
||||||
:site-options="siteOptions"
|
:site-options="siteOptions"
|
||||||
removable
|
removable
|
||||||
|
:last="index === prices.length - 1"
|
||||||
:errors="priceErrors[index]"
|
:errors="priceErrors[index]"
|
||||||
@update:model-value="(v) => prices[index] = v"
|
@update:model-value="(v) => prices[index] = v"
|
||||||
@remove="askRemovePrice(index)"
|
@remove="askRemovePrice(index)"
|
||||||
|
|||||||
@@ -123,6 +123,8 @@
|
|||||||
<!-- Adresse UNIQUE (ERP-172). -->
|
<!-- Adresse UNIQUE (ERP-172). -->
|
||||||
<CarrierAddressBlock
|
<CarrierAddressBlock
|
||||||
:model-value="address"
|
:model-value="address"
|
||||||
|
:title="t('transport.carriers.form.address.title')"
|
||||||
|
:last="true"
|
||||||
:country-options="countryOptionsFor(address.country)"
|
:country-options="countryOptionsFor(address.country)"
|
||||||
disabled
|
disabled
|
||||||
hide-empty
|
hide-empty
|
||||||
@@ -136,6 +138,8 @@
|
|||||||
v-for="(contact, index) in contacts"
|
v-for="(contact, index) in contacts"
|
||||||
:key="index"
|
:key="index"
|
||||||
:model-value="contact"
|
:model-value="contact"
|
||||||
|
:title="t('transport.carriers.form.contact.title', { n: index + 1 })"
|
||||||
|
:last="index === contacts.length - 1"
|
||||||
disabled
|
disabled
|
||||||
hide-empty
|
hide-empty
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -180,6 +180,8 @@
|
|||||||
<!-- Adresse UNIQUE (ERP-172) : un seul bloc, sans ajouter/supprimer. -->
|
<!-- Adresse UNIQUE (ERP-172) : un seul bloc, sans ajouter/supprimer. -->
|
||||||
<CarrierAddressBlock
|
<CarrierAddressBlock
|
||||||
:model-value="address"
|
:model-value="address"
|
||||||
|
:title="t('transport.carriers.form.address.title')"
|
||||||
|
:last="true"
|
||||||
:country-options="countryOptions"
|
:country-options="countryOptions"
|
||||||
:disabled="isQualimat || isValidated('addresses')"
|
:disabled="isQualimat || isValidated('addresses')"
|
||||||
:errors="addressErrors"
|
:errors="addressErrors"
|
||||||
@@ -207,7 +209,9 @@
|
|||||||
v-for="(contact, index) in contacts"
|
v-for="(contact, index) in contacts"
|
||||||
:key="index"
|
:key="index"
|
||||||
:model-value="contact"
|
:model-value="contact"
|
||||||
|
:title="t('transport.carriers.form.contact.title', { n: index + 1 })"
|
||||||
:removable="isRowRemovable(contacts, index)"
|
:removable="isRowRemovable(contacts, index)"
|
||||||
|
:last="index === contacts.length - 1"
|
||||||
:disabled="isValidated('contacts')"
|
:disabled="isValidated('contacts')"
|
||||||
:errors="contactErrors[index]"
|
:errors="contactErrors[index]"
|
||||||
@update:model-value="(v) => contacts[index] = v"
|
@update:model-value="(v) => contacts[index] = v"
|
||||||
@@ -240,11 +244,13 @@
|
|||||||
v-for="(price, index) in prices"
|
v-for="(price, index) in prices"
|
||||||
:key="index"
|
:key="index"
|
||||||
:model-value="price"
|
:model-value="price"
|
||||||
|
:title="t('transport.carriers.form.price.title', { n: index + 1 })"
|
||||||
:client-options="clientOptions"
|
:client-options="clientOptions"
|
||||||
:supplier-options="supplierOptions"
|
:supplier-options="supplierOptions"
|
||||||
:site-options="siteOptions"
|
:site-options="siteOptions"
|
||||||
:removable="!isValidated('prices')"
|
:removable="!isValidated('prices')"
|
||||||
:disabled="isValidated('prices')"
|
:disabled="isValidated('prices')"
|
||||||
|
:last="index === prices.length - 1"
|
||||||
:errors="priceErrors[index]"
|
:errors="priceErrors[index]"
|
||||||
@update:model-value="(v) => prices[index] = v"
|
@update:model-value="(v) => prices[index] = v"
|
||||||
@remove="askRemovePrice(index)"
|
@remove="askRemovePrice(index)"
|
||||||
|
|||||||
Reference in New Issue
Block a user