feat(constructeur) : update composant edit flow with supplier references
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -26,7 +26,9 @@ import {
|
|||||||
requiredCustomFieldsFilled as _requiredCustomFieldsFilled,
|
requiredCustomFieldsFilled as _requiredCustomFieldsFilled,
|
||||||
saveCustomFieldValues as _saveCustomFieldValues,
|
saveCustomFieldValues as _saveCustomFieldValues,
|
||||||
} from '~/shared/utils/customFieldFormUtils'
|
} 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 {
|
import {
|
||||||
getStructurePieces,
|
getStructurePieces,
|
||||||
resolvePieceLabel as _resolvePieceLabel,
|
resolvePieceLabel as _resolvePieceLabel,
|
||||||
@@ -77,6 +79,7 @@ export function useComponentCreate() {
|
|||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
const { upsertCustomFieldValue, updateCustomFieldValue } = useCustomFields()
|
const { upsertCustomFieldValue, updateCustomFieldValue } = useCustomFields()
|
||||||
const { uploadDocuments } = useDocuments()
|
const { uploadDocuments } = useDocuments()
|
||||||
|
const { syncLinks } = useConstructeurLinks()
|
||||||
const { canEdit } = usePermissions()
|
const { canEdit } = usePermissions()
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
@@ -92,6 +95,8 @@ export function useComponentCreate() {
|
|||||||
constructeurIds: [] as string[],
|
constructeurIds: [] as string[],
|
||||||
prix: '' as string,
|
prix: '' as string,
|
||||||
})
|
})
|
||||||
|
const constructeurLinks = ref<ConstructeurLinkEntry[]>([])
|
||||||
|
const constructeurIdsFromForm = computed(() => constructeurIdsFromLinks(constructeurLinks.value))
|
||||||
const lastSuggestedName = ref('')
|
const lastSuggestedName = ref('')
|
||||||
const customFieldInputs = ref<CustomFieldInput[]>([])
|
const customFieldInputs = ref<CustomFieldInput[]>([])
|
||||||
const structureAssignments = ref<StructureAssignmentNode | null>(null)
|
const structureAssignments = ref<StructureAssignmentNode | null>(null)
|
||||||
@@ -276,9 +281,7 @@ export function useComponentCreate() {
|
|||||||
payload.reference = reference
|
payload.reference = reference
|
||||||
}
|
}
|
||||||
|
|
||||||
if (creationForm.constructeurIds.length) {
|
// constructeurIds are handled via link entities, not in the main payload
|
||||||
payload.constructeurIds = uniqueConstructeurIds(creationForm.constructeurIds)
|
|
||||||
}
|
|
||||||
|
|
||||||
const rawPrice = typeof creationForm.prix === 'string'
|
const rawPrice = typeof creationForm.prix === 'string'
|
||||||
? creationForm.prix.trim()
|
? creationForm.prix.trim()
|
||||||
@@ -343,6 +346,10 @@ export function useComponentCreate() {
|
|||||||
}
|
}
|
||||||
selectedDocuments.value = []
|
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')
|
toast.showSuccess('Composant créé avec succès')
|
||||||
await router.replace(`/component/${createdComponent.id}?edit=true`)
|
await router.replace(`/component/${createdComponent.id}?edit=true`)
|
||||||
}
|
}
|
||||||
@@ -380,6 +387,8 @@ export function useComponentCreate() {
|
|||||||
selectedTypeId,
|
selectedTypeId,
|
||||||
submitting,
|
submitting,
|
||||||
creationForm,
|
creationForm,
|
||||||
|
constructeurLinks,
|
||||||
|
constructeurIdsFromForm,
|
||||||
customFieldInputs,
|
customFieldInputs,
|
||||||
structureAssignments,
|
structureAssignments,
|
||||||
selectedDocuments,
|
selectedDocuments,
|
||||||
|
|||||||
@@ -12,9 +12,11 @@ import { useToast } from '~/composables/useToast'
|
|||||||
import { extractRelationId } from '~/shared/apiRelations'
|
import { extractRelationId } from '~/shared/apiRelations'
|
||||||
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 { useComponentHistory } from '~/composables/useComponentHistory'
|
import { useComponentHistory } from '~/composables/useComponentHistory'
|
||||||
import { formatStructurePreview, normalizeStructureForEditor } from '~/shared/modelUtils'
|
import { formatStructurePreview, normalizeStructureForEditor } from '~/shared/modelUtils'
|
||||||
import { uniqueConstructeurIds } from '~/shared/constructeurUtils'
|
import { uniqueConstructeurIds, constructeurIdsFromLinks } from '~/shared/constructeurUtils'
|
||||||
|
import type { ConstructeurLinkEntry } from '~/shared/constructeurUtils'
|
||||||
import {
|
import {
|
||||||
getStructurePieces,
|
getStructurePieces,
|
||||||
getStructureProducts,
|
getStructureProducts,
|
||||||
@@ -61,6 +63,7 @@ export function useComponentEdit(componentId: string) {
|
|||||||
const { pieces } = usePieces()
|
const { pieces } = usePieces()
|
||||||
const { products } = useProducts()
|
const { products } = useProducts()
|
||||||
const { ensureConstructeurs } = useConstructeurs()
|
const { ensureConstructeurs } = useConstructeurs()
|
||||||
|
const { fetchLinks, syncLinks } = useConstructeurLinks()
|
||||||
const { upsertCustomFieldValue, updateCustomFieldValue } = useCustomFields()
|
const { upsertCustomFieldValue, updateCustomFieldValue } = useCustomFields()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
const { loadDocumentsByComponent, uploadDocuments, deleteDocument } = useDocuments()
|
const { loadDocumentsByComponent, uploadDocuments, deleteDocument } = useDocuments()
|
||||||
@@ -89,6 +92,9 @@ export function useComponentEdit(componentId: string) {
|
|||||||
constructeurIds: [] as string[],
|
constructeurIds: [] as string[],
|
||||||
prix: '' as string,
|
prix: '' as string,
|
||||||
})
|
})
|
||||||
|
const constructeurLinks = ref<ConstructeurLinkEntry[]>([])
|
||||||
|
const originalConstructeurLinks = ref<ConstructeurLinkEntry[]>([])
|
||||||
|
const constructeurIdsFromForm = computed(() => constructeurIdsFromLinks(constructeurLinks.value))
|
||||||
|
|
||||||
const customFieldInputs = ref<CustomFieldInput[]>([])
|
const customFieldInputs = ref<CustomFieldInput[]>([])
|
||||||
const fetchedPieceTypeMap = ref<Record<string, string>>({})
|
const fetchedPieceTypeMap = ref<Record<string, string>>({})
|
||||||
@@ -286,6 +292,7 @@ export function useComponentEdit(componentId: string) {
|
|||||||
slotId: slot.slotId,
|
slotId: slot.slotId,
|
||||||
typePieceId: slot.typePieceId,
|
typePieceId: slot.typePieceId,
|
||||||
selectedPieceId: edits && 'selectedPieceId' in edits ? edits.selectedPieceId : (slot.selectedPieceId ?? null),
|
selectedPieceId: edits && 'selectedPieceId' in edits ? edits.selectedPieceId : (slot.selectedPieceId ?? null),
|
||||||
|
selectedPieceName: slot.selectedPieceName ?? null,
|
||||||
quantity: edits && 'quantity' in edits ? edits.quantity! : (slot.quantity ?? 1),
|
quantity: edits && 'quantity' in edits ? edits.quantity! : (slot.quantity ?? 1),
|
||||||
position: slot.position ?? i,
|
position: slot.position ?? i,
|
||||||
label: pieceTypeLabelMap.value[slot.typePieceId] || `Pièce #${i + 1}`,
|
label: pieceTypeLabelMap.value[slot.typePieceId] || `Pièce #${i + 1}`,
|
||||||
@@ -302,6 +309,7 @@ export function useComponentEdit(componentId: string) {
|
|||||||
slotId: slot.slotId,
|
slotId: slot.slotId,
|
||||||
typeProductId: slot.typeProductId,
|
typeProductId: slot.typeProductId,
|
||||||
selectedProductId: edits && 'selectedProductId' in edits ? edits.selectedProductId : (slot.selectedProductId ?? null),
|
selectedProductId: edits && 'selectedProductId' in edits ? edits.selectedProductId : (slot.selectedProductId ?? null),
|
||||||
|
selectedProductName: slot.selectedProductName ?? null,
|
||||||
familyCode: slot.familyCode,
|
familyCode: slot.familyCode,
|
||||||
position: slot.position ?? i,
|
position: slot.position ?? i,
|
||||||
label: productTypeLabelMap.value[slot.typeProductId] || `Produit #${i + 1}`,
|
label: productTypeLabelMap.value[slot.typeProductId] || `Produit #${i + 1}`,
|
||||||
@@ -318,6 +326,7 @@ export function useComponentEdit(componentId: string) {
|
|||||||
slotId: slot.slotId,
|
slotId: slot.slotId,
|
||||||
typeComposantId: slot.typeComposantId,
|
typeComposantId: slot.typeComposantId,
|
||||||
selectedComponentId: edits && 'selectedComposantId' in edits ? edits.selectedComposantId : (slot.selectedComponentId ?? null),
|
selectedComponentId: edits && 'selectedComposantId' in edits ? edits.selectedComposantId : (slot.selectedComponentId ?? null),
|
||||||
|
selectedComponentName: slot.selectedComponentName ?? null,
|
||||||
alias: slot.alias,
|
alias: slot.alias,
|
||||||
familyCode: slot.familyCode,
|
familyCode: slot.familyCode,
|
||||||
position: slot.position ?? i,
|
position: slot.position ?? i,
|
||||||
@@ -361,7 +370,6 @@ export function useComponentEdit(componentId: string) {
|
|||||||
|
|
||||||
const reference = editionForm.reference.trim()
|
const reference = editionForm.reference.trim()
|
||||||
payload.reference = reference || null
|
payload.reference = reference || null
|
||||||
payload.constructeurIds = uniqueConstructeurIds(editionForm.constructeurIds)
|
|
||||||
|
|
||||||
if (rawPrice) {
|
if (rawPrice) {
|
||||||
const parsed = Number(rawPrice)
|
const parsed = Number(rawPrice)
|
||||||
@@ -434,6 +442,9 @@ export function useComponentEdit(componentId: string) {
|
|||||||
slotEdits.products = {}
|
slotEdits.products = {}
|
||||||
slotEdits.subcomponents = {}
|
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.')
|
toast.showSuccess('Composant mis à jour avec succès.')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -468,15 +479,16 @@ export function useComponentEdit(componentId: string) {
|
|||||||
editionForm.name = currentComponent.name || ''
|
editionForm.name = currentComponent.name || ''
|
||||||
editionForm.description = currentComponent.description || ''
|
editionForm.description = currentComponent.description || ''
|
||||||
editionForm.reference = currentComponent.reference || ''
|
editionForm.reference = currentComponent.reference || ''
|
||||||
editionForm.constructeurIds = uniqueConstructeurIds(
|
// Load constructeur links
|
||||||
currentComponent,
|
fetchLinks('composant', componentId).then((links) => {
|
||||||
Array.isArray(currentComponent.constructeurs) ? currentComponent.constructeurs : [],
|
constructeurLinks.value = links
|
||||||
currentComponent.constructeur ? [currentComponent.constructeur] : [],
|
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) : ''
|
editionForm.prix = currentComponent.prix !== null && currentComponent.prix !== undefined ? String(currentComponent.prix) : ''
|
||||||
if (editionForm.constructeurIds.length) {
|
|
||||||
void ensureConstructeurs(editionForm.constructeurIds)
|
|
||||||
}
|
|
||||||
|
|
||||||
initialized.value = true
|
initialized.value = true
|
||||||
}
|
}
|
||||||
@@ -543,6 +555,9 @@ export function useComponentEdit(componentId: string) {
|
|||||||
previewVisible,
|
previewVisible,
|
||||||
selectedTypeId,
|
selectedTypeId,
|
||||||
editionForm,
|
editionForm,
|
||||||
|
constructeurLinks,
|
||||||
|
originalConstructeurLinks,
|
||||||
|
constructeurIdsFromForm,
|
||||||
customFieldInputs,
|
customFieldInputs,
|
||||||
historyFieldLabels,
|
historyFieldLabels,
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useToast } from './useToast'
|
import { useToast } from './useToast'
|
||||||
import { useApi } from './useApi'
|
import { useApi } from './useApi'
|
||||||
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'
|
||||||
@@ -182,7 +182,8 @@ export function useComposants() {
|
|||||||
const createComposant = async (composantData: Partial<Composant>): Promise<ComposantSingleResult> => {
|
const createComposant = async (composantData: Partial<Composant>): Promise<ComposantSingleResult> => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
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)
|
const result = await post('/composants', normalizedPayload)
|
||||||
if (result.success && result.data) {
|
if (result.success && result.data) {
|
||||||
const enriched = await withResolvedConstructeurs(result.data as Composant)
|
const enriched = await withResolvedConstructeurs(result.data as Composant)
|
||||||
@@ -209,7 +210,8 @@ export function useComposants() {
|
|||||||
const updateComposantData = async (id: string, composantData: Partial<Composant>): Promise<ComposantSingleResult> => {
|
const updateComposantData = async (id: string, composantData: Partial<Composant>): Promise<ComposantSingleResult> => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
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)
|
const result = await patch(`/composants/${id}`, normalizedPayload)
|
||||||
if (result.success && result.data) {
|
if (result.success && result.data) {
|
||||||
const updated = await withResolvedConstructeurs(result.data as Composant)
|
const updated = await withResolvedConstructeurs(result.data as Composant)
|
||||||
|
|||||||
@@ -141,6 +141,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">
|
||||||
@@ -350,13 +355,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref, watch } from 'vue'
|
||||||
import { useRoute } from '#imports'
|
import { useRoute } from '#imports'
|
||||||
import { useComponentEdit } from '~/composables/useComponentEdit'
|
import { useComponentEdit } from '~/composables/useComponentEdit'
|
||||||
import { useDocuments } from '~/composables/useDocuments'
|
import { useDocuments } from '~/composables/useDocuments'
|
||||||
|
import { useConstructeurs } from '~/composables/useConstructeurs'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const { updateDocument } = useDocuments()
|
const { updateDocument } = useDocuments()
|
||||||
|
const { getConstructeurById } = useConstructeurs()
|
||||||
const versionRefreshKey = ref(0)
|
const versionRefreshKey = ref(0)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -371,6 +378,8 @@ const {
|
|||||||
previewVisible,
|
previewVisible,
|
||||||
selectedTypeId,
|
selectedTypeId,
|
||||||
editionForm,
|
editionForm,
|
||||||
|
constructeurLinks,
|
||||||
|
constructeurIdsFromForm,
|
||||||
customFieldInputs,
|
customFieldInputs,
|
||||||
historyFieldLabels,
|
historyFieldLabels,
|
||||||
canEdit,
|
canEdit,
|
||||||
@@ -401,6 +410,26 @@ const {
|
|||||||
fetchComponent,
|
fetchComponent,
|
||||||
} = useComponentEdit(String(route.params.id))
|
} = useComponentEdit(String(route.params.id))
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Remove links whose ID was removed from the select
|
||||||
|
constructeurLinks.value = constructeurLinks.value.filter(l => ids.includes(l.constructeurId))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
const editingDocument = ref<any | null>(null)
|
const editingDocument = ref<any | null>(null)
|
||||||
const editModalVisible = ref(false)
|
const editModalVisible = ref(false)
|
||||||
|
|
||||||
|
|||||||
@@ -128,7 +128,7 @@
|
|||||||
|
|
||||||
<!-- Référence + Fournisseurs (if value or edit mode) -->
|
<!-- Référence + Fournisseurs (if value or edit mode) -->
|
||||||
<div
|
<div
|
||||||
v-if="isEditMode || component.reference || editionForm.constructeurIds.length"
|
v-if="isEditMode || component.reference || constructeurLinks.length"
|
||||||
class="grid grid-cols-1 gap-4 md:grid-cols-2"
|
class="grid grid-cols-1 gap-4 md:grid-cols-2"
|
||||||
>
|
>
|
||||||
<div v-if="isEditMode || component.reference" class="form-control">
|
<div v-if="isEditMode || component.reference" class="form-control">
|
||||||
@@ -148,7 +148,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="isEditMode || editionForm.constructeurIds.length" class="form-control">
|
<div v-if="isEditMode || constructeurLinks.length" class="form-control">
|
||||||
<label class="label">
|
<label class="label">
|
||||||
<span class="label-text">Fournisseur</span>
|
<span class="label-text">Fournisseur</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -160,18 +160,20 @@
|
|||||||
placeholder="Rechercher un ou plusieurs fournisseurs..."
|
placeholder="Rechercher un ou plusieurs fournisseurs..."
|
||||||
:initial-options="component?.constructeurs || []"
|
:initial-options="component?.constructeurs || []"
|
||||||
/>
|
/>
|
||||||
<div v-else class="flex flex-wrap gap-2">
|
|
||||||
<span
|
|
||||||
v-for="id in editionForm.constructeurIds"
|
|
||||||
:key="id"
|
|
||||||
class="badge badge-outline"
|
|
||||||
>
|
|
||||||
{{ getConstructeurById(id)?.name || id }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</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 (if value or edit mode) -->
|
<!-- Prix (if value or edit mode) -->
|
||||||
<div v-if="isEditMode || component.prix" class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
<div v-if="isEditMode || component.prix" class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
@@ -254,7 +256,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div v-else class="input input-bordered input-sm md:input-md bg-base-200 flex items-center gap-2">
|
<div v-else class="input input-bordered input-sm md:input-md bg-base-200 flex items-center gap-2">
|
||||||
{{ resolvePieceLabel(slot.selectedPieceId) || '— Non sélectionné' }}
|
{{ slot.selectedPieceName || '— Non sélectionné' }}
|
||||||
<span v-if="slot.quantity > 1" class="badge badge-sm">x{{ slot.quantity }}</span>
|
<span v-if="slot.quantity > 1" class="badge badge-sm">x{{ slot.quantity }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -281,7 +283,7 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<div v-else class="input input-bordered input-sm md:input-md bg-base-200 flex items-center">
|
<div v-else class="input input-bordered input-sm md:input-md bg-base-200 flex items-center">
|
||||||
{{ resolveProductLabel(slot.selectedProductId) || '— Non sélectionné' }}
|
{{ slot.selectedProductName || '— Non sélectionné' }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -307,7 +309,7 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<div v-else class="input input-bordered input-sm md:input-md bg-base-200 flex items-center">
|
<div v-else class="input input-bordered input-sm md:input-md bg-base-200 flex items-center">
|
||||||
{{ resolveSubcomponentLabel(slot.selectedComponentId) || '— Non sélectionné' }}
|
{{ slot.selectedComponentName || '— Non sélectionné' }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -435,12 +437,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, ref } from 'vue'
|
import { computed, onMounted, ref, watch } from 'vue'
|
||||||
import { useRoute } from '#imports'
|
import { useRoute } from '#imports'
|
||||||
import { useComponentEdit } from '~/composables/useComponentEdit'
|
import { useComponentEdit } from '~/composables/useComponentEdit'
|
||||||
import { useDocuments } from '~/composables/useDocuments'
|
import { useDocuments } from '~/composables/useDocuments'
|
||||||
import { usePermissions } from '~/composables/usePermissions'
|
import { usePermissions } from '~/composables/usePermissions'
|
||||||
import { useConstructeurs } from '~/composables/useConstructeurs'
|
import { useConstructeurs } from '~/composables/useConstructeurs'
|
||||||
|
import type { ConstructeurLinkEntry } from '~/shared/constructeurUtils'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const { canEdit } = usePermissions()
|
const { canEdit } = usePermissions()
|
||||||
@@ -461,6 +464,8 @@ const {
|
|||||||
previewVisible,
|
previewVisible,
|
||||||
selectedTypeId,
|
selectedTypeId,
|
||||||
editionForm,
|
editionForm,
|
||||||
|
constructeurLinks,
|
||||||
|
constructeurIdsFromForm,
|
||||||
customFieldInputs,
|
customFieldInputs,
|
||||||
historyFieldLabels,
|
historyFieldLabels,
|
||||||
canSubmit,
|
canSubmit,
|
||||||
@@ -497,6 +502,26 @@ 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,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Remove links whose ID was removed from the select
|
||||||
|
constructeurLinks.value = constructeurLinks.value.filter(l => ids.includes(l.constructeurId))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
const editingDocument = ref<any | null>(null)
|
const editingDocument = ref<any | null>(null)
|
||||||
const editModalVisible = ref(false)
|
const editModalVisible = ref(false)
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,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">
|
||||||
@@ -215,10 +220,16 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { watch } from 'vue'
|
||||||
|
import { useConstructeurs } from '~/composables/useConstructeurs'
|
||||||
|
|
||||||
|
const { getConstructeurById } = useConstructeurs()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
selectedTypeId,
|
selectedTypeId,
|
||||||
submitting,
|
submitting,
|
||||||
creationForm,
|
creationForm,
|
||||||
|
constructeurLinks,
|
||||||
customFieldInputs,
|
customFieldInputs,
|
||||||
structureAssignments,
|
structureAssignments,
|
||||||
selectedDocuments,
|
selectedDocuments,
|
||||||
@@ -249,4 +260,23 @@ const {
|
|||||||
resolveSubcomponentLabel,
|
resolveSubcomponentLabel,
|
||||||
submitCreation,
|
submitCreation,
|
||||||
} = useComponentCreate()
|
} = useComponentCreate()
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
},
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user