165 lines
5.2 KiB
Vue
165 lines
5.2 KiB
Vue
<template>
|
||
<form @submit.prevent="validate">
|
||
<div class="flex items-center justify-between gap-10">
|
||
<h1 class="text-3xl font-bold uppercase">
|
||
{{ supplierId ? "Modifications du fournisseur" : "Ajout d'un fournisseur" }}
|
||
</h1>
|
||
|
||
<button
|
||
class="text-xl uppercase bg-primary-500 text-white h-[50px] w-[272px]"
|
||
type="submit"
|
||
:disabled="isLoading"
|
||
>
|
||
{{ supplierId ? "Sauvegarder" : "Ajouter" }}
|
||
</button>
|
||
</div>
|
||
|
||
<div class="grid grid-cols-2 gap-y-16 gap-x-12 mb-16">
|
||
<UiTextInput id="supplier-name" v-model="form.name" label="Nom du fournisseur" />
|
||
<UiTextInput id="supplier-email" v-model="form.email" label="Email" />
|
||
<UiTextInput id="supplier-phone" v-model="form.phone" label="Téléphone" />
|
||
|
||
<UiTextInput id="supplier-street" v-model="form.addresses[0].street" label="Rue" />
|
||
<UiTextInput id="supplier-street2" v-model="form.addresses[0].street2" label="Complément" />
|
||
<UiTextInput id="supplier-postalCode" v-model="form.addresses[0].postalCode" label="Code postal" />
|
||
<UiTextInput id="supplier-city" v-model="form.addresses[0].city" label="Ville" />
|
||
<UiTextInput id="supplier-country" v-model="form.addresses[0].countryCode" label="Pays" />
|
||
</div>
|
||
|
||
<p v-if="errorMsg" class="text-red-600 mt-4">{{ errorMsg }}</p>
|
||
</form>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { computed, reactive, ref, watch } from "vue"
|
||
import { createSupplier, getSupplier, updateSupplier } from "~/services/supplier"
|
||
import { createAddress, updateAddress, type AddressPayload } from "~/services/address"
|
||
import type { SupplierData, SupplierFormData, SupplierPayload } from "~/services/dto/supplier-data"
|
||
import type { AddressFormData } from "~/services/dto/address-data"
|
||
|
||
definePageMeta({ layout: "admin" })
|
||
|
||
const route = useRoute()
|
||
const router = useRouter()
|
||
|
||
const resolveId = (param: unknown) => {
|
||
const idStr = Array.isArray(param) ? param[0] : param
|
||
if (!idStr) return null
|
||
const id = Number(idStr)
|
||
return Number.isFinite(id) ? id : null
|
||
}
|
||
|
||
const supplierId = computed(() => resolveId(route.params.id))
|
||
|
||
const isLoading = ref(false)
|
||
const errorMsg = ref<string | null>(null)
|
||
|
||
const emptyAddress = (): AddressFormData => ({
|
||
id: null,
|
||
label: "",
|
||
street: "",
|
||
street2: null,
|
||
postalCode: "",
|
||
city: "",
|
||
countryCode: "",
|
||
})
|
||
|
||
const form = reactive<SupplierFormData>({
|
||
name: "",
|
||
email: "",
|
||
phone: "",
|
||
addresses: [emptyAddress()],
|
||
})
|
||
|
||
const hydrateFromSupplier = (supplier: SupplierData | null) => {
|
||
if (!supplier) return
|
||
|
||
form.name = supplier.name ?? ""
|
||
form.email = supplier.email ?? ""
|
||
form.phone = supplier.phone ?? ""
|
||
|
||
if (!Array.isArray(supplier.addresses) || supplier.addresses.length === 0) return
|
||
const a0 = supplier.addresses[0]
|
||
|
||
// si IRIs -> ignore
|
||
if (typeof a0 === "string") return
|
||
|
||
form.addresses[0].id = a0.id ?? null
|
||
form.addresses[0].label = a0.label ?? ""
|
||
form.addresses[0].street = a0.street ?? ""
|
||
form.addresses[0].street2 = a0.street2 ?? null
|
||
form.addresses[0].postalCode = a0.postalCode ?? ""
|
||
form.addresses[0].city = a0.city ?? ""
|
||
form.addresses[0].countryCode = a0.countryCode ?? ""
|
||
}
|
||
|
||
watch(
|
||
() => supplierId.value,
|
||
async (id) => {
|
||
if (id === null) return
|
||
isLoading.value = true
|
||
try {
|
||
const supplier = await getSupplier(id)
|
||
hydrateFromSupplier(supplier)
|
||
} finally {
|
||
isLoading.value = false
|
||
}
|
||
},
|
||
{ immediate: true }
|
||
)
|
||
|
||
async function validate() {
|
||
if (isLoading.value) return
|
||
isLoading.value = true
|
||
errorMsg.value = null
|
||
|
||
try {
|
||
const name = form.name.trim()
|
||
const email = (form.email ?? "").trim() || null
|
||
const phone = (form.phone ?? "").trim() || null
|
||
|
||
const a0 = form.addresses[0]
|
||
|
||
const label = a0.label.trim() || name || "Adresse"
|
||
|
||
const addressPayload: AddressPayload = {
|
||
label,
|
||
street: a0.street.trim(),
|
||
street2: a0.street2?.trim() || null,
|
||
postalCode: a0.postalCode.trim(),
|
||
city: a0.city.trim(),
|
||
countryCode: a0.countryCode.trim(),
|
||
}
|
||
|
||
let addressId: number
|
||
if (a0.id) {
|
||
const updated = await updateAddress(a0.id, addressPayload)
|
||
addressId = updated.id
|
||
} else {
|
||
const created = await createAddress(addressPayload)
|
||
addressId = created.id
|
||
a0.id = addressId
|
||
}
|
||
const supplierPayload: SupplierPayload = {
|
||
name,
|
||
email,
|
||
phone,
|
||
addresses: [`/api/addresses/${addressId}`],
|
||
}
|
||
|
||
if (supplierId.value !== null) {
|
||
await updateSupplier(supplierId.value, supplierPayload)
|
||
} else {
|
||
await createSupplier(supplierPayload)
|
||
}
|
||
|
||
await router.push("/admin/supplier/supplier-list")
|
||
} catch (e) {
|
||
errorMsg.value = "Erreur lors de l’enregistrement."
|
||
throw e
|
||
} finally {
|
||
isLoading.value = false
|
||
}
|
||
}
|
||
</script>
|