feat(component-edit) : add interactive slot selectors for pieces, products and subcomponents
Replace read-only selections display with PieceSelect, ProductSelect, ComposantSelect components that allow changing the assigned item in each slot directly from the edit page. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -270,6 +270,94 @@ export function useComponentEdit(componentId: string) {
|
||||
}
|
||||
})
|
||||
|
||||
// --- Slot selection entries (for selectors) ---
|
||||
|
||||
const pieceSlotEntries = computed(() => {
|
||||
const structure = component.value?.structure
|
||||
if (!structure?.pieces) return []
|
||||
return (structure.pieces as any[]).map((slot: any, i: number) => ({
|
||||
slotId: slot.slotId,
|
||||
typePieceId: slot.typePieceId,
|
||||
selectedPieceId: slot.selectedPieceId ?? null,
|
||||
quantity: slot.quantity ?? 1,
|
||||
position: slot.position ?? i,
|
||||
label: pieceTypeLabelMap.value[slot.typePieceId] || `Pièce #${i + 1}`,
|
||||
}))
|
||||
})
|
||||
|
||||
const productSlotEntries = computed(() => {
|
||||
const structure = component.value?.structure
|
||||
if (!structure?.products) return []
|
||||
return (structure.products as any[]).map((slot: any, i: number) => ({
|
||||
slotId: slot.slotId,
|
||||
typeProductId: slot.typeProductId,
|
||||
selectedProductId: slot.selectedProductId ?? null,
|
||||
familyCode: slot.familyCode,
|
||||
position: slot.position ?? i,
|
||||
label: productTypeLabelMap.value[slot.typeProductId] || `Produit #${i + 1}`,
|
||||
}))
|
||||
})
|
||||
|
||||
const subcomponentSlotEntries = computed(() => {
|
||||
const structure = component.value?.structure
|
||||
if (!structure?.subcomponents) return []
|
||||
return (structure.subcomponents as any[]).map((slot: any, i: number) => ({
|
||||
slotId: slot.slotId,
|
||||
typeComposantId: slot.typeComposantId,
|
||||
selectedComponentId: slot.selectedComponentId ?? null,
|
||||
alias: slot.alias,
|
||||
familyCode: slot.familyCode,
|
||||
position: slot.position ?? i,
|
||||
label: slot.alias || `Sous-composant #${i + 1}`,
|
||||
}))
|
||||
})
|
||||
|
||||
const savePieceSlotSelection = async (slotId: string, selectedPieceId: string | null) => {
|
||||
try {
|
||||
await patch(`/composant-piece-slots/${slotId}`, { selectedPieceId })
|
||||
// Update local structure
|
||||
const structure = component.value?.structure
|
||||
if (structure?.pieces) {
|
||||
const slot = (structure.pieces as any[]).find((s: any) => s.slotId === slotId)
|
||||
if (slot) slot.selectedPieceId = selectedPieceId
|
||||
}
|
||||
toast.showSuccess('Pièce mise à jour')
|
||||
}
|
||||
catch (error: any) {
|
||||
toast.showError(error?.message || 'Erreur lors de la mise à jour')
|
||||
}
|
||||
}
|
||||
|
||||
const saveProductSlotSelection = async (slotId: string, selectedProductId: string | null) => {
|
||||
try {
|
||||
await patch(`/composant-product-slots/${slotId}`, { selectedProductId })
|
||||
const structure = component.value?.structure
|
||||
if (structure?.products) {
|
||||
const slot = (structure.products as any[]).find((s: any) => s.slotId === slotId)
|
||||
if (slot) slot.selectedProductId = selectedProductId
|
||||
}
|
||||
toast.showSuccess('Produit mis à jour')
|
||||
}
|
||||
catch (error: any) {
|
||||
toast.showError(error?.message || 'Erreur lors de la mise à jour')
|
||||
}
|
||||
}
|
||||
|
||||
const saveSubcomponentSlotSelection = async (slotId: string, selectedComposantId: string | null) => {
|
||||
try {
|
||||
await patch(`/composant-subcomponent-slots/${slotId}`, { selectedComposantId })
|
||||
const structure = component.value?.structure
|
||||
if (structure?.subcomponents) {
|
||||
const slot = (structure.subcomponents as any[]).find((s: any) => s.slotId === slotId)
|
||||
if (slot) slot.selectedComponentId = selectedComposantId
|
||||
}
|
||||
toast.showSuccess('Sous-composant mis à jour')
|
||||
}
|
||||
catch (error: any) {
|
||||
toast.showError(error?.message || 'Erreur lors de la mise à jour')
|
||||
}
|
||||
}
|
||||
|
||||
const saveSlotQuantity = async (entry: SelectionEntry) => {
|
||||
const slotId = entry.slotId
|
||||
const quantity = typeof entry._definition?.quantity === 'number'
|
||||
@@ -423,14 +511,12 @@ export function useComponentEdit(componentId: string) {
|
||||
])
|
||||
loading.value = false
|
||||
|
||||
// Defer bulk catalog loads — only needed when component has structure selections
|
||||
if (component.value?.structure) {
|
||||
Promise.allSettled([
|
||||
loadPieces({ itemsPerPage: 200 }),
|
||||
loadProducts({ itemsPerPage: 200 }),
|
||||
loadComposants({ itemsPerPage: 200 }),
|
||||
]).catch(() => {})
|
||||
}
|
||||
// Load catalogs for slot selectors
|
||||
Promise.allSettled([
|
||||
loadPieces({ itemsPerPage: 200 }),
|
||||
loadProducts({ itemsPerPage: 200 }),
|
||||
loadComposants({ itemsPerPage: 200 }),
|
||||
]).catch(() => {})
|
||||
})
|
||||
|
||||
return {
|
||||
@@ -456,6 +542,9 @@ export function useComponentEdit(componentId: string) {
|
||||
selectedType,
|
||||
selectedTypeStructure,
|
||||
structureSelections,
|
||||
pieceSlotEntries,
|
||||
productSlotEntries,
|
||||
subcomponentSlotEntries,
|
||||
|
||||
// History
|
||||
history,
|
||||
@@ -470,6 +559,9 @@ export function useComponentEdit(componentId: string) {
|
||||
refreshDocuments,
|
||||
submitEdition,
|
||||
saveSlotQuantity,
|
||||
savePieceSlotSelection,
|
||||
saveProductSlotSelection,
|
||||
saveSubcomponentSlotSelection,
|
||||
resolvePieceLabel,
|
||||
resolveProductLabel,
|
||||
resolveSubcomponentLabel,
|
||||
|
||||
Reference in New Issue
Block a user