feat(constructeur) : update product edit flow with supplier references
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@ import { ref } from 'vue'
|
|||||||
import { useToast } from './useToast'
|
import { useToast } from './useToast'
|
||||||
import { useApi } from './useApi'
|
import { useApi } from './useApi'
|
||||||
import { humanizeError } from '~/shared/utils/errorMessages'
|
import { humanizeError } from '~/shared/utils/errorMessages'
|
||||||
import { buildConstructeurRequestPayload, uniqueConstructeurIds } from '~/shared/constructeurUtils'
|
import { uniqueConstructeurIds } from '~/shared/constructeurUtils'
|
||||||
import { useConstructeurs, type Constructeur } from './useConstructeurs'
|
import { useConstructeurs, type Constructeur } from './useConstructeurs'
|
||||||
import { extractRelationId, normalizeRelationIds } from '~/shared/apiRelations'
|
import { extractRelationId, normalizeRelationIds } from '~/shared/apiRelations'
|
||||||
import { extractCollection } from '~/shared/utils/apiHelpers'
|
import { extractCollection } from '~/shared/utils/apiHelpers'
|
||||||
@@ -196,7 +196,8 @@ export function useProducts() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const createProduct = async (payload: Partial<Product>): Promise<ProductSingleResult> => {
|
const createProduct = async (payload: Partial<Product>): Promise<ProductSingleResult> => {
|
||||||
const normalizedPayload = normalizeRelationIds(buildConstructeurRequestPayload(payload))
|
const { constructeurIds, constructeurs, constructeurId, constructeur, ...cleanPayload } = payload as any
|
||||||
|
const normalizedPayload = normalizeRelationIds(cleanPayload)
|
||||||
loading.value = true
|
loading.value = true
|
||||||
error.value = null
|
error.value = null
|
||||||
try {
|
try {
|
||||||
@@ -225,7 +226,8 @@ export function useProducts() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const updateProduct = async (id: string, payload: Partial<Product>): Promise<ProductSingleResult> => {
|
const updateProduct = async (id: string, payload: Partial<Product>): Promise<ProductSingleResult> => {
|
||||||
const normalizedPayload = normalizeRelationIds(buildConstructeurRequestPayload(payload))
|
const { constructeurIds, constructeurs, constructeurId, constructeur, ...cleanPayload } = payload as any
|
||||||
|
const normalizedPayload = normalizeRelationIds(cleanPayload)
|
||||||
loading.value = true
|
loading.value = true
|
||||||
error.value = null
|
error.value = null
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -105,6 +105,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<ConstructeurLinksTable
|
||||||
|
v-if="constructeurLinks.length"
|
||||||
|
v-model="constructeurLinks"
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<label class="label">
|
<label class="label">
|
||||||
@@ -237,9 +242,11 @@ import { useToast } from '~/composables/useToast'
|
|||||||
import { humanizeError } from '~/shared/utils/errorMessages'
|
import { humanizeError } from '~/shared/utils/errorMessages'
|
||||||
import { useDocuments } from '~/composables/useDocuments'
|
import { useDocuments } from '~/composables/useDocuments'
|
||||||
import { useConstructeurs } from '~/composables/useConstructeurs'
|
import { useConstructeurs } from '~/composables/useConstructeurs'
|
||||||
|
import { useConstructeurLinks } from '~/composables/useConstructeurLinks'
|
||||||
import { useProductHistory } from '~/composables/useProductHistory'
|
import { useProductHistory } from '~/composables/useProductHistory'
|
||||||
import { formatProductStructurePreview, normalizeProductStructureForSave } from '~/shared/modelUtils'
|
import { formatProductStructurePreview, normalizeProductStructureForSave } from '~/shared/modelUtils'
|
||||||
import { uniqueConstructeurIds } from '~/shared/constructeurUtils'
|
import { constructeurIdsFromLinks } from '~/shared/constructeurUtils'
|
||||||
|
import type { ConstructeurLinkEntry } from '~/shared/constructeurUtils'
|
||||||
import { getModelType } from '~/services/modelTypes'
|
import { getModelType } from '~/services/modelTypes'
|
||||||
import type { ProductModelStructure } from '~/shared/types/inventory'
|
import type { ProductModelStructure } from '~/shared/types/inventory'
|
||||||
import { canPreviewDocument } from '~/utils/documentPreview'
|
import { canPreviewDocument } from '~/utils/documentPreview'
|
||||||
@@ -263,7 +270,8 @@ const {
|
|||||||
deleteDocument: deleteProductDocument,
|
deleteDocument: deleteProductDocument,
|
||||||
updateDocument,
|
updateDocument,
|
||||||
} = useDocuments()
|
} = useDocuments()
|
||||||
const { ensureConstructeurs } = useConstructeurs()
|
const { ensureConstructeurs, getConstructeurById } = useConstructeurs()
|
||||||
|
const { fetchLinks, syncLinks } = useConstructeurLinks()
|
||||||
const {
|
const {
|
||||||
history,
|
history,
|
||||||
loading: historyLoading,
|
loading: historyLoading,
|
||||||
@@ -286,6 +294,9 @@ const previewVisible = ref(false)
|
|||||||
const editingDocument = ref<any | null>(null)
|
const editingDocument = ref<any | null>(null)
|
||||||
const editModalVisible = ref(false)
|
const editModalVisible = ref(false)
|
||||||
|
|
||||||
|
const constructeurLinks = ref<ConstructeurLinkEntry[]>([])
|
||||||
|
const originalConstructeurLinks = ref<ConstructeurLinkEntry[]>([])
|
||||||
|
|
||||||
const historyFieldLabels: Record<string, string> = {
|
const historyFieldLabels: Record<string, string> = {
|
||||||
name: 'Nom',
|
name: 'Nom',
|
||||||
reference: 'Référence',
|
reference: 'Référence',
|
||||||
@@ -457,18 +468,19 @@ const hydrateForm = () => {
|
|||||||
}
|
}
|
||||||
editionForm.name = product.value.name || ''
|
editionForm.name = product.value.name || ''
|
||||||
editionForm.reference = product.value.reference || ''
|
editionForm.reference = product.value.reference || ''
|
||||||
editionForm.constructeurIds = uniqueConstructeurIds(
|
// Load constructeur links
|
||||||
product.value,
|
fetchLinks('product', String(route.params.id)).then((links) => {
|
||||||
Array.isArray(product.value.constructeurs) ? product.value.constructeurs : [],
|
constructeurLinks.value = links
|
||||||
)
|
originalConstructeurLinks.value = links.map(l => ({ ...l }))
|
||||||
|
editionForm.constructeurIds = constructeurIdsFromLinks(links)
|
||||||
|
if (editionForm.constructeurIds.length) {
|
||||||
|
void ensureConstructeurs(editionForm.constructeurIds)
|
||||||
|
}
|
||||||
|
})
|
||||||
editionForm.supplierPrice = product.value.supplierPrice !== null && product.value.supplierPrice !== undefined
|
editionForm.supplierPrice = product.value.supplierPrice !== null && product.value.supplierPrice !== undefined
|
||||||
? String(product.value.supplierPrice)
|
? String(product.value.supplierPrice)
|
||||||
: ''
|
: ''
|
||||||
refreshCustomFieldInputs(structure.value, product.value.customFieldValues)
|
refreshCustomFieldInputs(structure.value, product.value.customFieldValues)
|
||||||
if (editionForm.constructeurIds.length) {
|
|
||||||
// Smart-cached + deduped — fire-and-forget, ConstructeurSelect handles its own loading
|
|
||||||
ensureConstructeurs(editionForm.constructeurIds).catch(() => {})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
@@ -486,12 +498,9 @@ const submitEdition = async () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const constructeurIds = uniqueConstructeurIds(editionForm.constructeurIds)
|
|
||||||
|
|
||||||
const payload: Record<string, any> = {
|
const payload: Record<string, any> = {
|
||||||
name: editionForm.name.trim(),
|
name: editionForm.name.trim(),
|
||||||
reference: editionForm.reference.trim() || null,
|
reference: editionForm.reference.trim() || null,
|
||||||
constructeurIds,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const rawPrice = typeof editionForm.supplierPrice === 'string'
|
const rawPrice = typeof editionForm.supplierPrice === 'string'
|
||||||
@@ -518,6 +527,8 @@ const submitEdition = async () => {
|
|||||||
toast.showError(`Impossible d'enregistrer ${failedFields.length} champ(s): ${failedFields.join(', ')}`)
|
toast.showError(`Impossible d'enregistrer ${failedFields.length} champ(s): ${failedFields.join(', ')}`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
await syncLinks('product', product.value.id, originalConstructeurLinks.value, constructeurLinks.value)
|
||||||
|
originalConstructeurLinks.value = constructeurLinks.value.map(l => ({ ...l }))
|
||||||
toast.showSuccess('Produit mis à jour avec succès')
|
toast.showSuccess('Produit mis à jour avec succès')
|
||||||
versionRefreshKey.value++
|
versionRefreshKey.value++
|
||||||
}
|
}
|
||||||
@@ -528,6 +539,25 @@ const submitEdition = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sync constructeurIds → constructeurLinks when IDs are added via ConstructeurSelect
|
||||||
|
watch(
|
||||||
|
() => editionForm.constructeurIds,
|
||||||
|
(ids) => {
|
||||||
|
const currentIds = new Set(constructeurLinks.value.map(l => l.constructeurId))
|
||||||
|
for (const id of ids) {
|
||||||
|
if (!currentIds.has(id)) {
|
||||||
|
const resolved = getConstructeurById(id)
|
||||||
|
constructeurLinks.value.push({
|
||||||
|
constructeurId: id,
|
||||||
|
constructeur: resolved ? { id: resolved.id, name: resolved.name } : null,
|
||||||
|
supplierReference: null,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
constructeurLinks.value = constructeurLinks.value.filter(l => ids.includes(l.constructeurId))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await loadProduct()
|
await loadProduct()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -133,6 +133,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Constructeur links table -->
|
||||||
|
<ConstructeurLinksTable
|
||||||
|
v-if="isEditMode && constructeurLinks.length"
|
||||||
|
v-model="constructeurLinks"
|
||||||
|
/>
|
||||||
|
<ConstructeurLinksTable
|
||||||
|
v-else-if="!isEditMode && constructeurLinks.length"
|
||||||
|
:model-value="constructeurLinks"
|
||||||
|
:readonly="true"
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- Prix fournisseur (if value or edit mode) -->
|
<!-- Prix fournisseur (if value or edit mode) -->
|
||||||
<div v-if="isEditMode || product.supplierPrice" class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
<div v-if="isEditMode || product.supplierPrice" class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
@@ -303,10 +314,12 @@ import { useToast } from '~/composables/useToast'
|
|||||||
import { humanizeError } from '~/shared/utils/errorMessages'
|
import { humanizeError } from '~/shared/utils/errorMessages'
|
||||||
import { useDocuments } from '~/composables/useDocuments'
|
import { useDocuments } from '~/composables/useDocuments'
|
||||||
import { useConstructeurs } from '~/composables/useConstructeurs'
|
import { useConstructeurs } from '~/composables/useConstructeurs'
|
||||||
|
import { useConstructeurLinks } from '~/composables/useConstructeurLinks'
|
||||||
import { useProductHistory } from '~/composables/useProductHistory'
|
import { useProductHistory } from '~/composables/useProductHistory'
|
||||||
import { usePermissions } from '~/composables/usePermissions'
|
import { usePermissions } from '~/composables/usePermissions'
|
||||||
import { formatProductStructurePreview, normalizeProductStructureForSave } from '~/shared/modelUtils'
|
import { formatProductStructurePreview, normalizeProductStructureForSave } from '~/shared/modelUtils'
|
||||||
import { uniqueConstructeurIds } from '~/shared/constructeurUtils'
|
import { constructeurIdsFromLinks } from '~/shared/constructeurUtils'
|
||||||
|
import type { ConstructeurLinkEntry } from '~/shared/constructeurUtils'
|
||||||
import { getModelType } from '~/services/modelTypes'
|
import { getModelType } from '~/services/modelTypes'
|
||||||
import type { ProductModelStructure } from '~/shared/types/inventory'
|
import type { ProductModelStructure } from '~/shared/types/inventory'
|
||||||
import { canPreviewDocument } from '~/utils/documentPreview'
|
import { canPreviewDocument } from '~/utils/documentPreview'
|
||||||
@@ -330,6 +343,7 @@ const {
|
|||||||
updateDocument,
|
updateDocument,
|
||||||
} = useDocuments()
|
} = useDocuments()
|
||||||
const { ensureConstructeurs, getConstructeurById } = useConstructeurs()
|
const { ensureConstructeurs, getConstructeurById } = useConstructeurs()
|
||||||
|
const { fetchLinks, syncLinks } = useConstructeurLinks()
|
||||||
const {
|
const {
|
||||||
history,
|
history,
|
||||||
loading: historyLoading,
|
loading: historyLoading,
|
||||||
@@ -339,6 +353,9 @@ const {
|
|||||||
|
|
||||||
const isEditMode = ref(false)
|
const isEditMode = ref(false)
|
||||||
|
|
||||||
|
const constructeurLinks = ref<ConstructeurLinkEntry[]>([])
|
||||||
|
const originalConstructeurLinks = ref<ConstructeurLinkEntry[]>([])
|
||||||
|
|
||||||
const product = ref<any | null>(null)
|
const product = ref<any | null>(null)
|
||||||
const productType = ref<any | null>(null)
|
const productType = ref<any | null>(null)
|
||||||
const structure = ref<ProductModelStructure | null>(null)
|
const structure = ref<ProductModelStructure | null>(null)
|
||||||
@@ -529,17 +546,19 @@ const hydrateForm = () => {
|
|||||||
}
|
}
|
||||||
editionForm.name = product.value.name || ''
|
editionForm.name = product.value.name || ''
|
||||||
editionForm.reference = product.value.reference || ''
|
editionForm.reference = product.value.reference || ''
|
||||||
editionForm.constructeurIds = uniqueConstructeurIds(
|
// Load constructeur links
|
||||||
product.value,
|
fetchLinks('product', String(route.params.id)).then((links) => {
|
||||||
Array.isArray(product.value.constructeurs) ? product.value.constructeurs : [],
|
constructeurLinks.value = links
|
||||||
)
|
originalConstructeurLinks.value = links.map(l => ({ ...l }))
|
||||||
|
editionForm.constructeurIds = constructeurIdsFromLinks(links)
|
||||||
|
if (editionForm.constructeurIds.length) {
|
||||||
|
void ensureConstructeurs(editionForm.constructeurIds)
|
||||||
|
}
|
||||||
|
})
|
||||||
editionForm.supplierPrice = product.value.supplierPrice !== null && product.value.supplierPrice !== undefined
|
editionForm.supplierPrice = product.value.supplierPrice !== null && product.value.supplierPrice !== undefined
|
||||||
? String(product.value.supplierPrice)
|
? String(product.value.supplierPrice)
|
||||||
: ''
|
: ''
|
||||||
refreshCustomFieldInputs(structure.value, product.value.customFieldValues)
|
refreshCustomFieldInputs(structure.value, product.value.customFieldValues)
|
||||||
if (editionForm.constructeurIds.length) {
|
|
||||||
ensureConstructeurs(editionForm.constructeurIds).catch(() => {})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
@@ -557,12 +576,9 @@ const submitEdition = async () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const constructeurIds = uniqueConstructeurIds(editionForm.constructeurIds)
|
|
||||||
|
|
||||||
const payload: Record<string, any> = {
|
const payload: Record<string, any> = {
|
||||||
name: editionForm.name.trim(),
|
name: editionForm.name.trim(),
|
||||||
reference: editionForm.reference.trim() || null,
|
reference: editionForm.reference.trim() || null,
|
||||||
constructeurIds,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const rawPrice = typeof editionForm.supplierPrice === 'string'
|
const rawPrice = typeof editionForm.supplierPrice === 'string'
|
||||||
@@ -589,6 +605,8 @@ const submitEdition = async () => {
|
|||||||
toast.showError(`Impossible d'enregistrer ${failedFields.length} champ(s): ${failedFields.join(', ')}`)
|
toast.showError(`Impossible d'enregistrer ${failedFields.length} champ(s): ${failedFields.join(', ')}`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
await syncLinks('product', product.value.id, originalConstructeurLinks.value, constructeurLinks.value)
|
||||||
|
originalConstructeurLinks.value = constructeurLinks.value.map(l => ({ ...l }))
|
||||||
toast.showSuccess('Produit mis à jour avec succès')
|
toast.showSuccess('Produit mis à jour avec succès')
|
||||||
await loadProduct()
|
await loadProduct()
|
||||||
isEditMode.value = false
|
isEditMode.value = false
|
||||||
@@ -600,6 +618,25 @@ const submitEdition = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sync constructeurIds → constructeurLinks when IDs are added via ConstructeurSelect
|
||||||
|
watch(
|
||||||
|
() => editionForm.constructeurIds,
|
||||||
|
(ids) => {
|
||||||
|
const currentIds = new Set(constructeurLinks.value.map(l => l.constructeurId))
|
||||||
|
for (const id of ids) {
|
||||||
|
if (!currentIds.has(id)) {
|
||||||
|
const resolved = getConstructeurById(id)
|
||||||
|
constructeurLinks.value.push({
|
||||||
|
constructeurId: id,
|
||||||
|
constructeur: resolved ? { id: resolved.id, name: resolved.name } : null,
|
||||||
|
supplierReference: null,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
constructeurLinks.value = constructeurLinks.value.filter(l => ids.includes(l.constructeurId))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await loadProduct()
|
await loadProduct()
|
||||||
if (route.query.edit === 'true' && canEdit.value) {
|
if (route.query.edit === 'true' && canEdit.value) {
|
||||||
|
|||||||
@@ -79,6 +79,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<ConstructeurLinksTable
|
||||||
|
v-if="constructeurLinks.length"
|
||||||
|
v-model="constructeurLinks"
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<label class="label">
|
<label class="label">
|
||||||
@@ -175,7 +180,10 @@ import { useToast } from '~/composables/useToast'
|
|||||||
import { useCustomFields } from '~/composables/useCustomFields'
|
import { useCustomFields } from '~/composables/useCustomFields'
|
||||||
import { useDocuments } from '~/composables/useDocuments'
|
import { useDocuments } from '~/composables/useDocuments'
|
||||||
import { formatProductStructurePreview, normalizeProductStructureForSave } from '~/shared/modelUtils'
|
import { formatProductStructurePreview, normalizeProductStructureForSave } from '~/shared/modelUtils'
|
||||||
import { uniqueConstructeurIds } from '~/shared/constructeurUtils'
|
import { constructeurIdsFromLinks } from '~/shared/constructeurUtils'
|
||||||
|
import type { ConstructeurLinkEntry } from '~/shared/constructeurUtils'
|
||||||
|
import { useConstructeurLinks } from '~/composables/useConstructeurLinks'
|
||||||
|
import { useConstructeurs } from '~/composables/useConstructeurs'
|
||||||
import type { ProductModelStructure } from '~/shared/types/inventory'
|
import type { ProductModelStructure } from '~/shared/types/inventory'
|
||||||
import type { ModelType } from '~/services/modelTypes'
|
import type { ModelType } from '~/services/modelTypes'
|
||||||
import {
|
import {
|
||||||
@@ -197,6 +205,8 @@ const toast = useToast()
|
|||||||
const { upsertCustomFieldValue } = useCustomFields()
|
const { upsertCustomFieldValue } = useCustomFields()
|
||||||
const { uploadDocuments } = useDocuments()
|
const { uploadDocuments } = useDocuments()
|
||||||
const { canEdit } = usePermissions()
|
const { canEdit } = usePermissions()
|
||||||
|
const { syncLinks } = useConstructeurLinks()
|
||||||
|
const { getConstructeurById } = useConstructeurs()
|
||||||
|
|
||||||
const initialTypeId = ref<string>(typeof route.query.typeId === 'string' ? route.query.typeId : '')
|
const initialTypeId = ref<string>(typeof route.query.typeId === 'string' ? route.query.typeId : '')
|
||||||
const selectedTypeId = ref<string>(initialTypeId.value)
|
const selectedTypeId = ref<string>(initialTypeId.value)
|
||||||
@@ -207,6 +217,7 @@ const creationForm = reactive({
|
|||||||
constructeurIds: [] as string[],
|
constructeurIds: [] as string[],
|
||||||
supplierPrice: '' as string,
|
supplierPrice: '' as string,
|
||||||
})
|
})
|
||||||
|
const constructeurLinks = ref<ConstructeurLinkEntry[]>([])
|
||||||
const selectedDocuments = ref<File[]>([])
|
const selectedDocuments = ref<File[]>([])
|
||||||
const uploadingDocuments = ref(false)
|
const uploadingDocuments = ref(false)
|
||||||
|
|
||||||
@@ -300,8 +311,6 @@ const buildPayload = () => {
|
|||||||
payload.reference = reference
|
payload.reference = reference
|
||||||
}
|
}
|
||||||
|
|
||||||
payload.constructeurIds = uniqueConstructeurIds(creationForm.constructeurIds)
|
|
||||||
|
|
||||||
const rawPrice = typeof creationForm.supplierPrice === 'string'
|
const rawPrice = typeof creationForm.supplierPrice === 'string'
|
||||||
? creationForm.supplierPrice.trim()
|
? creationForm.supplierPrice.trim()
|
||||||
: creationForm.supplierPrice
|
: creationForm.supplierPrice
|
||||||
@@ -333,6 +342,10 @@ const submitCreation = async () => {
|
|||||||
await router.replace(`/product/${result.data.id}?edit=true`)
|
await router.replace(`/product/${result.data.id}?edit=true`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Sync constructeur links after creation
|
||||||
|
if (constructeurLinks.value.length) {
|
||||||
|
await syncLinks('product', productId, [], constructeurLinks.value)
|
||||||
|
}
|
||||||
if (selectedDocuments.value.length) {
|
if (selectedDocuments.value.length) {
|
||||||
uploadingDocuments.value = true
|
uploadingDocuments.value = true
|
||||||
const uploadResult = await uploadDocuments(
|
const uploadResult = await uploadDocuments(
|
||||||
@@ -395,6 +408,25 @@ const saveCustomFieldValues = async (productId: string) => {
|
|||||||
return failed
|
return failed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sync constructeurIds → constructeurLinks when IDs are added via ConstructeurSelect
|
||||||
|
watch(
|
||||||
|
() => creationForm.constructeurIds,
|
||||||
|
(ids) => {
|
||||||
|
const currentIds = new Set(constructeurLinks.value.map(l => l.constructeurId))
|
||||||
|
for (const id of ids) {
|
||||||
|
if (!currentIds.has(id)) {
|
||||||
|
const resolved = getConstructeurById(id)
|
||||||
|
constructeurLinks.value.push({
|
||||||
|
constructeurId: id,
|
||||||
|
constructeur: resolved ? { id: resolved.id, name: resolved.name } : null,
|
||||||
|
supplierReference: null,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
constructeurLinks.value = constructeurLinks.value.filter(l => ids.includes(l.constructeurId))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await loadProductTypes()
|
await loadProductTypes()
|
||||||
if (selectedTypeId.value && !selectedType.value) {
|
if (selectedTypeId.value && !selectedType.value) {
|
||||||
|
|||||||
Reference in New Issue
Block a user