153 lines
5.9 KiB
Vue
153 lines
5.9 KiB
Vue
<template>
|
|
<div>
|
|
<!-- En-tete : retour vers le repertoire + titre. -->
|
|
<div class="flex items-center gap-3 pt-11">
|
|
<MalioButtonIcon
|
|
icon="mdi:arrow-left-bold"
|
|
icon-size="24"
|
|
variant="ghost"
|
|
v-bind="{ ariaLabel: t('transport.carriers.form.back') }"
|
|
@click="goBack"
|
|
/>
|
|
<h1 class="text-[30px] font-semibold text-m-primary">{{ t('transport.carriers.form.title') }}</h1>
|
|
</div>
|
|
|
|
<!-- ── Formulaire principal (pre-onglets) ─────────────────────────────
|
|
Sans validation de ce bloc, les onglets restent inaccessibles. Au
|
|
succes du POST, les champs passent en lecture seule et on bascule
|
|
automatiquement sur l'onglet Qualimat. Les champs conditionnels
|
|
(indexation / benne / volume si affrete, decharge si AUTRE, cas LIOT)
|
|
et la saisie assistee QUALIMAT arrivent a ERP-166. -->
|
|
<div class="mt-[48px] grid grid-cols-3 xl:grid-cols-4 gap-x-[44px] gap-y-4">
|
|
<MalioInputText
|
|
v-model="main.name"
|
|
:label="t('transport.carriers.form.main.name')"
|
|
:required="true"
|
|
:readonly="mainLocked"
|
|
:error="mainErrors.errors.name"
|
|
/>
|
|
<MalioSelect
|
|
:model-value="main.certificationType"
|
|
:options="certificationOptions"
|
|
:label="t('transport.carriers.form.main.certificationType')"
|
|
empty-option-label=""
|
|
:required="true"
|
|
:readonly="mainLocked"
|
|
:error="mainErrors.errors.certificationType"
|
|
@update:model-value="(v: string | number | null) => main.certificationType = v === null ? null : String(v)"
|
|
/>
|
|
<!-- Wrapper h-12 + centrage vertical : aligne la case a cocher sur la
|
|
ligne de champ des inputs/selects (qui posent un h-12 items-center
|
|
en interne). reserve-message-space=false pour un centrage exact. -->
|
|
<div class="flex h-12 items-center">
|
|
<MalioCheckbox
|
|
id="carrier-is-chartered"
|
|
:label="t('transport.carriers.form.main.isChartered')"
|
|
:model-value="main.isChartered"
|
|
:readonly="mainLocked"
|
|
:reserve-message-space="false"
|
|
@update:model-value="(val: boolean) => main.isChartered = val"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div v-if="!mainLocked" class="mt-12 flex justify-center">
|
|
<MalioButton
|
|
variant="primary"
|
|
:label="t('transport.carriers.form.submit')"
|
|
:disabled="mainSubmitting"
|
|
@click="onSubmitMain"
|
|
/>
|
|
</div>
|
|
|
|
<!-- ── Onglets a validation incrementale ─────────────────────────────
|
|
Barre Qualimat · Adresses · Contacts · Prix. Onglets verrouilles tant
|
|
que le formulaire principal n'est pas valide (unlockedIndex = -1) puis
|
|
deverrouilles progressivement. Le contenu de chaque onglet arrive aux
|
|
tickets suivants (ERP-166+) : placeholders « A venir » pour l'instant. -->
|
|
<MalioTabList v-model="activeTab" :tabs="tabs" class="mt-[60px]">
|
|
<template
|
|
v-for="key in tabKeys"
|
|
:key="key"
|
|
#[key]
|
|
>
|
|
<div class="mt-12 flex justify-center text-m-muted">
|
|
{{ t('transport.carriers.form.comingSoon') }}
|
|
</div>
|
|
</template>
|
|
</MalioTabList>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed } from 'vue'
|
|
import { useCarrierForm } from '~/modules/transport/composables/useCarrierForm'
|
|
|
|
interface SelectOption {
|
|
value: string
|
|
label: string
|
|
}
|
|
|
|
const { t } = useI18n()
|
|
const router = useRouter()
|
|
const { can } = usePermissions()
|
|
|
|
useHead({ title: t('transport.carriers.form.title') })
|
|
|
|
// Gating de la route : la creation est reservee a `manage` (Admin / Bureau).
|
|
// Commerciale (consultation seule), Compta et Usine sont rediriges vers le repertoire.
|
|
if (!can('transport.carriers.manage')) {
|
|
await navigateTo('/carriers')
|
|
}
|
|
|
|
const {
|
|
main,
|
|
mainLocked,
|
|
mainSubmitting,
|
|
mainErrors,
|
|
tabKeys,
|
|
activeTab,
|
|
unlockedIndex,
|
|
submitMain,
|
|
} = useCarrierForm()
|
|
|
|
// Certifications selectionnables manuellement (spec § Formulaire principal).
|
|
// QUALIMAT n'est PAS dans cette liste : il est pose par la saisie assistee QUALIMAT
|
|
// (ERP-166), pas choisi a la main.
|
|
const SELECTABLE_CERTIFICATIONS = ['GMP_PLUS', 'OVOCOM', 'COMPTE_PROPRE', 'AUTRE'] as const
|
|
|
|
const certificationOptions = computed<SelectOption[]>(() =>
|
|
SELECTABLE_CERTIFICATIONS.map(code => ({
|
|
value: code,
|
|
label: t(`transport.carriers.certification.${code}`),
|
|
})),
|
|
)
|
|
|
|
// Icone (Iconify) affichee dans chaque onglet, par cle.
|
|
const TAB_ICONS: Record<string, string> = {
|
|
qualimat: 'mdi:truck-check-outline',
|
|
addresses: 'mdi:map-marker-outline',
|
|
contacts: 'mdi:account-box-plus-outline',
|
|
prices: 'mdi:currency-eur',
|
|
}
|
|
|
|
// Onglets desactives tant que le formulaire principal n'est pas valide
|
|
// (unlockedIndex = -1 au depart) ; deverrouillage progressif ensuite.
|
|
const tabs = computed(() => tabKeys.value.map((key, index) => ({
|
|
key,
|
|
label: t(`transport.carriers.tab.${key}`),
|
|
icon: TAB_ICONS[key],
|
|
disabled: index > unlockedIndex.value,
|
|
})))
|
|
|
|
/** Retour vers le repertoire transporteurs (fleche d'en-tete). */
|
|
function goBack(): void {
|
|
router.push('/carriers')
|
|
}
|
|
|
|
/** Valide le formulaire principal (POST /carriers ; bascule gerée par le composable). */
|
|
async function onSubmitMain(): Promise<void> {
|
|
await submitMain()
|
|
}
|
|
</script>
|