From 80739a4528a6bc2b1aa186524ab95a9ee9976999 Mon Sep 17 00:00:00 2001 From: Matthieu Date: Tue, 31 Mar 2026 16:52:50 +0200 Subject: [PATCH] feat(constructeur) : update composant edit flow with supplier references Co-Authored-By: Claude Opus 4.6 (1M context) --- app/composables/useComponentCreate.ts | 17 +++++++-- app/composables/useComponentEdit.ts | 35 ++++++++++++----- app/composables/useComposants.ts | 8 ++-- app/pages/component/[id]/edit.vue | 31 ++++++++++++++- app/pages/component/[id]/index.vue | 55 +++++++++++++++++++-------- app/pages/component/create.vue | 30 +++++++++++++++ 6 files changed, 143 insertions(+), 33 deletions(-) diff --git a/app/composables/useComponentCreate.ts b/app/composables/useComponentCreate.ts index bec753b..ed1b091 100644 --- a/app/composables/useComponentCreate.ts +++ b/app/composables/useComponentCreate.ts @@ -26,7 +26,9 @@ import { requiredCustomFieldsFilled as _requiredCustomFieldsFilled, saveCustomFieldValues as _saveCustomFieldValues, } from '~/shared/utils/customFieldFormUtils' -import { uniqueConstructeurIds } from '~/shared/constructeurUtils' +import { useConstructeurLinks } from '~/composables/useConstructeurLinks' +import { uniqueConstructeurIds, constructeurIdsFromLinks } from '~/shared/constructeurUtils' +import type { ConstructeurLinkEntry } from '~/shared/constructeurUtils' import { getStructurePieces, resolvePieceLabel as _resolvePieceLabel, @@ -77,6 +79,7 @@ export function useComponentCreate() { const toast = useToast() const { upsertCustomFieldValue, updateCustomFieldValue } = useCustomFields() const { uploadDocuments } = useDocuments() + const { syncLinks } = useConstructeurLinks() const { canEdit } = usePermissions() // ------------------------------------------------------------------------- @@ -92,6 +95,8 @@ export function useComponentCreate() { constructeurIds: [] as string[], prix: '' as string, }) + const constructeurLinks = ref([]) + const constructeurIdsFromForm = computed(() => constructeurIdsFromLinks(constructeurLinks.value)) const lastSuggestedName = ref('') const customFieldInputs = ref([]) const structureAssignments = ref(null) @@ -276,9 +281,7 @@ export function useComponentCreate() { payload.reference = reference } - if (creationForm.constructeurIds.length) { - payload.constructeurIds = uniqueConstructeurIds(creationForm.constructeurIds) - } + // constructeurIds are handled via link entities, not in the main payload const rawPrice = typeof creationForm.prix === 'string' ? creationForm.prix.trim() @@ -343,6 +346,10 @@ export function useComponentCreate() { } selectedDocuments.value = [] } + // Sync constructeur links after creation + if (constructeurLinks.value.length) { + await syncLinks('composant', createdComponent.id, [], constructeurLinks.value) + } toast.showSuccess('Composant créé avec succès') await router.replace(`/component/${createdComponent.id}?edit=true`) } @@ -380,6 +387,8 @@ export function useComponentCreate() { selectedTypeId, submitting, creationForm, + constructeurLinks, + constructeurIdsFromForm, customFieldInputs, structureAssignments, selectedDocuments, diff --git a/app/composables/useComponentEdit.ts b/app/composables/useComponentEdit.ts index 48e9afe..52858bc 100644 --- a/app/composables/useComponentEdit.ts +++ b/app/composables/useComponentEdit.ts @@ -12,9 +12,11 @@ import { useToast } from '~/composables/useToast' import { extractRelationId } from '~/shared/apiRelations' import { useDocuments } from '~/composables/useDocuments' import { useConstructeurs } from '~/composables/useConstructeurs' +import { useConstructeurLinks } from '~/composables/useConstructeurLinks' import { useComponentHistory } from '~/composables/useComponentHistory' import { formatStructurePreview, normalizeStructureForEditor } from '~/shared/modelUtils' -import { uniqueConstructeurIds } from '~/shared/constructeurUtils' +import { uniqueConstructeurIds, constructeurIdsFromLinks } from '~/shared/constructeurUtils' +import type { ConstructeurLinkEntry } from '~/shared/constructeurUtils' import { getStructurePieces, getStructureProducts, @@ -61,6 +63,7 @@ export function useComponentEdit(componentId: string) { const { pieces } = usePieces() const { products } = useProducts() const { ensureConstructeurs } = useConstructeurs() + const { fetchLinks, syncLinks } = useConstructeurLinks() const { upsertCustomFieldValue, updateCustomFieldValue } = useCustomFields() const toast = useToast() const { loadDocumentsByComponent, uploadDocuments, deleteDocument } = useDocuments() @@ -89,6 +92,9 @@ export function useComponentEdit(componentId: string) { constructeurIds: [] as string[], prix: '' as string, }) + const constructeurLinks = ref([]) + const originalConstructeurLinks = ref([]) + const constructeurIdsFromForm = computed(() => constructeurIdsFromLinks(constructeurLinks.value)) const customFieldInputs = ref([]) const fetchedPieceTypeMap = ref>({}) @@ -286,6 +292,7 @@ export function useComponentEdit(componentId: string) { slotId: slot.slotId, typePieceId: slot.typePieceId, selectedPieceId: edits && 'selectedPieceId' in edits ? edits.selectedPieceId : (slot.selectedPieceId ?? null), + selectedPieceName: slot.selectedPieceName ?? null, quantity: edits && 'quantity' in edits ? edits.quantity! : (slot.quantity ?? 1), position: slot.position ?? i, label: pieceTypeLabelMap.value[slot.typePieceId] || `Pièce #${i + 1}`, @@ -302,6 +309,7 @@ export function useComponentEdit(componentId: string) { slotId: slot.slotId, typeProductId: slot.typeProductId, selectedProductId: edits && 'selectedProductId' in edits ? edits.selectedProductId : (slot.selectedProductId ?? null), + selectedProductName: slot.selectedProductName ?? null, familyCode: slot.familyCode, position: slot.position ?? i, label: productTypeLabelMap.value[slot.typeProductId] || `Produit #${i + 1}`, @@ -318,6 +326,7 @@ export function useComponentEdit(componentId: string) { slotId: slot.slotId, typeComposantId: slot.typeComposantId, selectedComponentId: edits && 'selectedComposantId' in edits ? edits.selectedComposantId : (slot.selectedComponentId ?? null), + selectedComponentName: slot.selectedComponentName ?? null, alias: slot.alias, familyCode: slot.familyCode, position: slot.position ?? i, @@ -361,7 +370,6 @@ export function useComponentEdit(componentId: string) { const reference = editionForm.reference.trim() payload.reference = reference || null - payload.constructeurIds = uniqueConstructeurIds(editionForm.constructeurIds) if (rawPrice) { const parsed = Number(rawPrice) @@ -434,6 +442,9 @@ export function useComponentEdit(componentId: string) { slotEdits.products = {} slotEdits.subcomponents = {} + await syncLinks('composant', component.value.id, originalConstructeurLinks.value, constructeurLinks.value) + originalConstructeurLinks.value = constructeurLinks.value.map(l => ({ ...l })) + toast.showSuccess('Composant mis à jour avec succès.') } } @@ -468,15 +479,16 @@ export function useComponentEdit(componentId: string) { editionForm.name = currentComponent.name || '' editionForm.description = currentComponent.description || '' editionForm.reference = currentComponent.reference || '' - editionForm.constructeurIds = uniqueConstructeurIds( - currentComponent, - Array.isArray(currentComponent.constructeurs) ? currentComponent.constructeurs : [], - currentComponent.constructeur ? [currentComponent.constructeur] : [], - ) + // Load constructeur links + fetchLinks('composant', componentId).then((links) => { + constructeurLinks.value = links + originalConstructeurLinks.value = links.map(l => ({ ...l })) + editionForm.constructeurIds = constructeurIdsFromLinks(links) + if (editionForm.constructeurIds.length) { + void ensureConstructeurs(editionForm.constructeurIds) + } + }) editionForm.prix = currentComponent.prix !== null && currentComponent.prix !== undefined ? String(currentComponent.prix) : '' - if (editionForm.constructeurIds.length) { - void ensureConstructeurs(editionForm.constructeurIds) - } initialized.value = true } @@ -543,6 +555,9 @@ export function useComponentEdit(componentId: string) { previewVisible, selectedTypeId, editionForm, + constructeurLinks, + originalConstructeurLinks, + constructeurIdsFromForm, customFieldInputs, historyFieldLabels, diff --git a/app/composables/useComposants.ts b/app/composables/useComposants.ts index 7423d3a..61d6809 100644 --- a/app/composables/useComposants.ts +++ b/app/composables/useComposants.ts @@ -1,7 +1,7 @@ import { ref } from 'vue' import { useToast } from './useToast' import { useApi } from './useApi' -import { buildConstructeurRequestPayload, uniqueConstructeurIds } from '~/shared/constructeurUtils' +import { uniqueConstructeurIds } from '~/shared/constructeurUtils' import { useConstructeurs, type Constructeur } from './useConstructeurs' import { extractRelationId, normalizeRelationIds } from '~/shared/apiRelations' import { extractCollection } from '~/shared/utils/apiHelpers' @@ -182,7 +182,8 @@ export function useComposants() { const createComposant = async (composantData: Partial): Promise => { loading.value = true try { - const normalizedPayload = normalizeRelationIds(buildConstructeurRequestPayload(composantData)) + const { constructeurIds, constructeurs, constructeurId, constructeur, ...cleanPayload } = composantData as any + const normalizedPayload = normalizeRelationIds(cleanPayload) const result = await post('/composants', normalizedPayload) if (result.success && result.data) { const enriched = await withResolvedConstructeurs(result.data as Composant) @@ -209,7 +210,8 @@ export function useComposants() { const updateComposantData = async (id: string, composantData: Partial): Promise => { loading.value = true try { - const normalizedPayload = normalizeRelationIds(buildConstructeurRequestPayload(composantData)) + const { constructeurIds, constructeurs, constructeurId, constructeur, ...cleanPayload } = composantData as any + const normalizedPayload = normalizeRelationIds(cleanPayload) const result = await patch(`/composants/${id}`, normalizedPayload) if (result.success && result.data) { const updated = await withResolvedConstructeurs(result.data as Composant) diff --git a/app/pages/component/[id]/edit.vue b/app/pages/component/[id]/edit.vue index 73506ae..8e2d591 100644 --- a/app/pages/component/[id]/edit.vue +++ b/app/pages/component/[id]/edit.vue @@ -141,6 +141,11 @@ + +