set up new view for skeleton hiearchi
This commit is contained in:
@@ -300,6 +300,99 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Requirement Summary -->
|
||||
<div
|
||||
v-if="componentRequirementGroups.length || pieceRequirementGroups.length"
|
||||
class="card bg-base-100 shadow-lg"
|
||||
>
|
||||
<div class="card-body space-y-6">
|
||||
<div>
|
||||
<h2 class="card-title">Structure sélectionnée</h2>
|
||||
<p class="text-sm text-gray-500">
|
||||
Synthèse des familles définies dans le type et des modèles utilisés pour cette machine.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div v-if="componentRequirementGroups.length" class="space-y-4">
|
||||
<h3 class="text-sm font-semibold text-gray-700">Composants</h3>
|
||||
<div
|
||||
v-for="group in componentRequirementGroups"
|
||||
:key="group.requirement.id"
|
||||
class="rounded-lg border border-base-200 p-4"
|
||||
>
|
||||
<div class="flex flex-wrap items-center justify-between gap-2 mb-3">
|
||||
<div>
|
||||
<h4 class="font-medium text-sm">
|
||||
{{ group.requirement.label || group.requirement.typeComposant?.name || 'Famille de composants' }}
|
||||
</h4>
|
||||
<p class="text-xs text-gray-500">
|
||||
Type : {{ group.requirement.typeComposant?.name || 'Non défini' }} · Min {{ group.requirement.minCount ?? (group.requirement.required ? 1 : 0) }} · Max {{ group.requirement.maxCount ?? '∞' }}
|
||||
</p>
|
||||
</div>
|
||||
<span class="badge badge-outline badge-sm">{{ group.components.length }} composant(s)</span>
|
||||
</div>
|
||||
|
||||
<div v-if="group.components.length" class="space-y-2">
|
||||
<div
|
||||
v-for="component in group.components"
|
||||
:key="component.id"
|
||||
class="flex flex-wrap items-center gap-2 text-sm"
|
||||
>
|
||||
<span class="font-medium">{{ component.name }}</span>
|
||||
<span v-if="component.composantModel" class="badge badge-sm badge-primary badge-outline">
|
||||
Modèle : {{ component.composantModel.name }}
|
||||
</span>
|
||||
<span v-else class="badge badge-sm badge-outline">Défini manuellement</span>
|
||||
<span v-if="component.parentComposantId" class="text-xs text-gray-500">
|
||||
(Sous-composant)
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p v-else class="text-xs text-gray-500">Aucun composant rattaché à ce groupe.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="pieceRequirementGroups.length" class="space-y-4">
|
||||
<h3 class="text-sm font-semibold text-gray-700">Pièces principales</h3>
|
||||
<div
|
||||
v-for="group in pieceRequirementGroups"
|
||||
:key="group.requirement.id"
|
||||
class="rounded-lg border border-base-200 p-4"
|
||||
>
|
||||
<div class="flex flex-wrap items-center justify-between gap-2 mb-3">
|
||||
<div>
|
||||
<h4 class="font-medium text-sm">
|
||||
{{ group.requirement.label || group.requirement.typePiece?.name || 'Groupe de pièces' }}
|
||||
</h4>
|
||||
<p class="text-xs text-gray-500">
|
||||
Type : {{ group.requirement.typePiece?.name || 'Non défini' }} · Min {{ group.requirement.minCount ?? (group.requirement.required ? 1 : 0) }} · Max {{ group.requirement.maxCount ?? '∞' }}
|
||||
</p>
|
||||
</div>
|
||||
<span class="badge badge-outline badge-sm">{{ group.pieces.length }} pièce(s)</span>
|
||||
</div>
|
||||
|
||||
<div v-if="group.pieces.length" class="space-y-2">
|
||||
<div
|
||||
v-for="piece in group.pieces"
|
||||
:key="piece.id"
|
||||
class="flex flex-wrap items-center gap-2 text-sm"
|
||||
>
|
||||
<span class="font-medium">{{ piece.name }}</span>
|
||||
<span v-if="piece.pieceModel" class="badge badge-sm badge-primary badge-outline">
|
||||
Modèle : {{ piece.pieceModel.name }}
|
||||
</span>
|
||||
<span v-else class="badge badge-sm badge-outline">Définie manuellement</span>
|
||||
<span v-if="piece.parentComponentName" class="text-xs text-gray-500">
|
||||
(Rattachée à {{ piece.parentComponentName }})
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p v-else class="text-xs text-gray-500">Aucune pièce rattachée à ce groupe.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Components Section -->
|
||||
<div class="card bg-base-100 shadow-lg">
|
||||
<div class="card-body">
|
||||
@@ -327,8 +420,14 @@
|
||||
:is-edit-mode="isEditMode"
|
||||
:collapse-all="componentsCollapsed"
|
||||
:toggle-token="collapseToggleToken"
|
||||
:component-model-options-provider="getComponentModelOptions"
|
||||
:piece-model-options-provider="getPieceModelOptions"
|
||||
@update="updateComponent"
|
||||
@edit-piece="updatePieceFromComponent"
|
||||
@assign-model="assignComponentModel"
|
||||
@assign-piece-model="assignPieceModel"
|
||||
@custom-field-update="updatePieceCustomField"
|
||||
@create-model-from-component="openSaveComponentModelModal"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -346,9 +445,11 @@
|
||||
:key="piece.id"
|
||||
:piece="piece"
|
||||
:is-edit-mode="isEditMode"
|
||||
:piece-model-options="getPieceModelOptions(piece)"
|
||||
@update="updatePieceInfo"
|
||||
@edit="editPiece"
|
||||
@custom-field-update="updatePieceCustomField"
|
||||
@assign-model="assignPieceModel"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -378,7 +479,73 @@
|
||||
@select-all="setAllPrintSelection(true)"
|
||||
@deselect-all="setAllPrintSelection(false)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<div v-if="saveComponentAsModelModal.open" class="modal modal-open">
|
||||
<div class="modal-box max-w-2xl">
|
||||
<h3 class="font-bold text-lg">
|
||||
Enregistrer « {{ saveComponentAsModelModal.component?.name || 'Composant' }} » comme modèle
|
||||
</h3>
|
||||
<p class="text-xs text-gray-500 mb-4">
|
||||
Le modèle sera associé au type {{ saveComponentAsModelModal.typeLabel || 'de composant' }} et
|
||||
pourra être réutilisé lors de la configuration d'autres machines.
|
||||
</p>
|
||||
|
||||
<form class="space-y-4" @submit.prevent="submitSaveComponentModelModal">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="form-control">
|
||||
<label class="label"><span class="label-text">Nom du modèle</span></label>
|
||||
<input
|
||||
v-model="saveComponentAsModelModal.form.name"
|
||||
type="text"
|
||||
class="input input-bordered input-sm"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label"><span class="label-text">Type de composant</span></label>
|
||||
<select
|
||||
v-model="saveComponentAsModelModal.form.typeComposantId"
|
||||
class="select select-bordered select-sm"
|
||||
required
|
||||
disabled
|
||||
>
|
||||
<option :value="saveComponentAsModelModal.form.typeComposantId">
|
||||
{{ saveComponentAsModelModal.typeLabel || 'Type de composant' }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label"><span class="label-text">Description</span></label>
|
||||
<textarea
|
||||
v-model="saveComponentAsModelModal.form.description"
|
||||
class="textarea textarea-bordered textarea-sm"
|
||||
rows="3"
|
||||
placeholder="Notes optionnelles"
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<div class="bg-base-200/60 border border-base-200 rounded-lg p-3 space-y-3">
|
||||
<div class="flex flex-wrap items-center gap-2 text-xs text-gray-500">
|
||||
<span class="badge badge-outline badge-sm">{{ saveComponentStructureSummary }}</span>
|
||||
</div>
|
||||
<ModelStructureViewer :structure="saveComponentAsModelModal.structure" />
|
||||
</div>
|
||||
|
||||
<div class="modal-action">
|
||||
<button type="button" class="btn btn-outline" @click="closeSaveComponentModelModal">
|
||||
Annuler
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary" :class="{ loading: saveComponentAsModelModal.submitting }">
|
||||
Sauvegarder et assigner
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, computed, watch, nextTick } from 'vue'
|
||||
@@ -405,6 +572,14 @@ import IconLucideSquarePen from '~icons/lucide/square-pen'
|
||||
import IconLucideEye from '~icons/lucide/eye'
|
||||
import IconLucideChevronRight from '~icons/lucide/chevron-right'
|
||||
import IconLucidePrinter from '~icons/lucide/printer'
|
||||
import ModelStructureViewer from '~/components/ModelStructureViewer.vue'
|
||||
import { useComponentModels } from '~/composables/useComponentModels'
|
||||
import { usePieceModels } from '~/composables/usePieceModels'
|
||||
import {
|
||||
defaultStructure,
|
||||
extractStructureFromComponent,
|
||||
formatStructurePreview,
|
||||
} from '~/shared/modelUtils'
|
||||
|
||||
const route = useRoute()
|
||||
const machineId = route.params.id
|
||||
@@ -433,6 +608,16 @@ const {
|
||||
loadDocumentsByComponent,
|
||||
loadDocumentsByPiece
|
||||
} = useDocuments()
|
||||
const {
|
||||
loadComponentModels,
|
||||
getComponentModelsForType,
|
||||
createComponentModel,
|
||||
} = useComponentModels()
|
||||
const {
|
||||
loadPieceModels,
|
||||
getPieceModelsForType,
|
||||
} = usePieceModels()
|
||||
const toast = useToast()
|
||||
|
||||
// Data
|
||||
const loading = ref(true)
|
||||
@@ -473,11 +658,62 @@ const printSelection = reactive({
|
||||
pieces: {},
|
||||
})
|
||||
|
||||
const saveComponentAsModelModal = reactive({
|
||||
open: false,
|
||||
submitting: false,
|
||||
component: null,
|
||||
typeLabel: '',
|
||||
structure: defaultStructure(),
|
||||
form: {
|
||||
name: '',
|
||||
description: '',
|
||||
typeComposantId: '',
|
||||
},
|
||||
})
|
||||
|
||||
const saveComponentStructureSummary = computed(() =>
|
||||
formatStructurePreview(saveComponentAsModelModal.structure)
|
||||
)
|
||||
|
||||
const handleMachineConstructeurChange = async (value) => {
|
||||
machineConstructeurId.value = value
|
||||
await updateMachineInfo()
|
||||
}
|
||||
|
||||
const openSaveComponentModelModal = (component) => {
|
||||
if (!component) return
|
||||
const requirement = component.typeMachineComponentRequirement || null
|
||||
const typeComposantId = requirement?.typeComposantId
|
||||
|| component.typeComposantId
|
||||
|| component.typeComposant?.id
|
||||
|| ''
|
||||
|
||||
saveComponentAsModelModal.open = true
|
||||
saveComponentAsModelModal.submitting = false
|
||||
saveComponentAsModelModal.component = component
|
||||
saveComponentAsModelModal.typeLabel = requirement?.typeComposant?.name
|
||||
|| component.typeComposant?.name
|
||||
|| 'Composant'
|
||||
saveComponentAsModelModal.form = {
|
||||
name: component.name || '',
|
||||
description: component.description || '',
|
||||
typeComposantId,
|
||||
}
|
||||
saveComponentAsModelModal.structure = extractStructureFromComponent(component)
|
||||
}
|
||||
|
||||
const closeSaveComponentModelModal = () => {
|
||||
saveComponentAsModelModal.open = false
|
||||
saveComponentAsModelModal.component = null
|
||||
saveComponentAsModelModal.typeLabel = ''
|
||||
saveComponentAsModelModal.structure = defaultStructure()
|
||||
saveComponentAsModelModal.form = {
|
||||
name: '',
|
||||
description: '',
|
||||
typeComposantId: '',
|
||||
}
|
||||
}
|
||||
|
||||
// Mode d'édition
|
||||
const isEditMode = ref(false)
|
||||
const debug = ref(false) // Ajout de debug pour afficher les infos de debug
|
||||
@@ -521,16 +757,178 @@ const machinePieces = computed(() => {
|
||||
const machineDocumentsList = computed(() => machine.value?.documents || [])
|
||||
const documentIcon = (doc) => getFileIcon({ name: doc.filename || doc.name, mime: doc.mimeType })
|
||||
|
||||
const allComponents = computed(() => {
|
||||
return components.value
|
||||
})
|
||||
|
||||
const subComponents = (parentId) => {
|
||||
return components.value.filter(comp => comp.parentComposantId === parentId)
|
||||
const flattenComponents = (list = []) => {
|
||||
const result = []
|
||||
const traverse = (items) => {
|
||||
items.forEach((item) => {
|
||||
result.push(item)
|
||||
if (item.subComponents && item.subComponents.length) {
|
||||
traverse(item.subComponents)
|
||||
}
|
||||
})
|
||||
}
|
||||
traverse(list)
|
||||
return result
|
||||
}
|
||||
|
||||
const componentPieces = (composantId) => {
|
||||
return pieces.value.filter(piece => piece.composantId === composantId)
|
||||
const flattenedComponents = computed(() => flattenComponents(components.value))
|
||||
|
||||
const preloadModelsForTypeMachine = async (typeMachine) => {
|
||||
if (!typeMachine) return
|
||||
const componentTypeIds = new Set(
|
||||
(typeMachine.componentRequirements || [])
|
||||
.map((requirement) => requirement.typeComposantId)
|
||||
.filter(Boolean),
|
||||
)
|
||||
const pieceTypeIds = new Set(
|
||||
(typeMachine.pieceRequirements || [])
|
||||
.map((requirement) => requirement.typePieceId)
|
||||
.filter(Boolean),
|
||||
)
|
||||
|
||||
await Promise.all([
|
||||
...Array.from(componentTypeIds).map((id) => loadComponentModels(id)),
|
||||
...Array.from(pieceTypeIds).map((id) => loadPieceModels(id)),
|
||||
])
|
||||
}
|
||||
|
||||
const ensureModelsForExistingEntities = async () => {
|
||||
const componentTypeIds = new Set()
|
||||
const gatherComponentTypes = (items = []) => {
|
||||
items.forEach((item) => {
|
||||
const typeId = item.typeMachineComponentRequirement?.typeComposantId
|
||||
|| item.typeComposantId
|
||||
|| item.typeComposant?.id
|
||||
if (typeId) {
|
||||
componentTypeIds.add(typeId)
|
||||
}
|
||||
if (item.subComponents?.length) {
|
||||
gatherComponentTypes(item.subComponents)
|
||||
}
|
||||
})
|
||||
}
|
||||
gatherComponentTypes(components.value)
|
||||
|
||||
const pieceTypeIds = new Set()
|
||||
pieces.value.forEach((piece) => {
|
||||
const typeId = piece.typeMachinePieceRequirement?.typePieceId
|
||||
|| piece.typePieceId
|
||||
|| piece.typePiece?.id
|
||||
if (typeId) {
|
||||
pieceTypeIds.add(typeId)
|
||||
}
|
||||
})
|
||||
|
||||
await Promise.all([
|
||||
...Array.from(componentTypeIds).map((id) => loadComponentModels(id)),
|
||||
...Array.from(pieceTypeIds).map((id) => loadPieceModels(id)),
|
||||
])
|
||||
}
|
||||
|
||||
const componentRequirementGroups = computed(() => {
|
||||
const requirements = machine.value?.typeMachine?.componentRequirements || []
|
||||
if (!requirements.length) return []
|
||||
|
||||
const groups = requirements.map((requirement) => ({
|
||||
requirement,
|
||||
components: [],
|
||||
}))
|
||||
|
||||
const map = new Map(groups.map((group) => [group.requirement.id, group]))
|
||||
|
||||
flattenedComponents.value.forEach((component) => {
|
||||
const reqId = component.typeMachineComponentRequirementId
|
||||
if (reqId && map.has(reqId)) {
|
||||
map.get(reqId).components.push(component)
|
||||
}
|
||||
})
|
||||
|
||||
return groups
|
||||
})
|
||||
|
||||
const pieceRequirementGroups = computed(() => {
|
||||
const requirements = machine.value?.typeMachine?.pieceRequirements || []
|
||||
if (!requirements.length) return []
|
||||
|
||||
const groups = requirements.map((requirement) => ({
|
||||
requirement,
|
||||
pieces: [],
|
||||
}))
|
||||
|
||||
const map = new Map(groups.map((group) => [group.requirement.id, group]))
|
||||
|
||||
const collectPieces = () => {
|
||||
const collected = []
|
||||
|
||||
// Pièces rattachées à la machine directement
|
||||
machinePieces.value.forEach((piece) => {
|
||||
collected.push({ ...piece, parentComponentName: null })
|
||||
})
|
||||
|
||||
// Pièces rattachées aux composants
|
||||
flattenedComponents.value.forEach((component) => {
|
||||
if (component.pieces && component.pieces.length) {
|
||||
component.pieces.forEach((piece) => {
|
||||
collected.push({ ...piece, parentComponentName: component.name })
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return collected
|
||||
}
|
||||
|
||||
collectPieces().forEach((piece) => {
|
||||
const reqId = piece.typeMachinePieceRequirementId
|
||||
if (reqId && map.has(reqId)) {
|
||||
map.get(reqId).pieces.push(piece)
|
||||
}
|
||||
})
|
||||
|
||||
return groups
|
||||
})
|
||||
|
||||
const getComponentModelOptions = (entity) => {
|
||||
const requirement = entity?.typeMachineComponentRequirement
|
||||
const typeId = requirement?.typeComposantId
|
||||
|| entity?.typeComposantId
|
||||
|| entity?.typeComposant?.id
|
||||
if (!typeId) return []
|
||||
return getComponentModelsForType(typeId)
|
||||
}
|
||||
|
||||
const getPieceModelOptions = (entity) => {
|
||||
const requirement = entity?.typeMachinePieceRequirement
|
||||
const typeId = requirement?.typePieceId
|
||||
|| entity?.typePieceId
|
||||
|| entity?.typePiece?.id
|
||||
if (!typeId) return []
|
||||
return getPieceModelsForType(typeId)
|
||||
}
|
||||
|
||||
const findComponentById = (items, id) => {
|
||||
for (const item of items || []) {
|
||||
if (item.id === id) return item
|
||||
const found = findComponentById(item.subComponents, id)
|
||||
if (found) return found
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
const findPieceById = (pieceId) => {
|
||||
const direct = pieces.value.find((piece) => piece.id === pieceId)
|
||||
if (direct) return direct
|
||||
|
||||
const searchInComponents = (items) => {
|
||||
for (const item of items || []) {
|
||||
const match = (item.pieces || []).find((piece) => piece.id === pieceId)
|
||||
if (match) return match
|
||||
const nested = searchInComponents(item.subComponents)
|
||||
if (nested) return nested
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
return searchInComponents(components.value)
|
||||
}
|
||||
|
||||
const refreshMachineDocuments = async () => {
|
||||
@@ -756,7 +1154,12 @@ const transformComponentCustomFields = (componentsData) => {
|
||||
})) || [];
|
||||
|
||||
// Transform pieces for the current component
|
||||
const pieces = component.pieces ? transformCustomFields(component.pieces) : [];
|
||||
const pieces = component.pieces
|
||||
? transformCustomFields(component.pieces).map((piece) => ({
|
||||
...piece,
|
||||
parentComponentName: component.name,
|
||||
}))
|
||||
: [];
|
||||
|
||||
// Recursively transform sub-components (using 'sousComposants' from backend)
|
||||
const subComponents = component.sousComposants ? transformComponentCustomFields(component.sousComposants) : [];
|
||||
@@ -798,6 +1201,8 @@ const loadMachineData = async () => {
|
||||
machine.value.documents = machine.value.documents || []
|
||||
machineDocumentsLoaded.value = !!(machine.value.documents?.length)
|
||||
console.log('Machine trouvée et assignée:', machine.value)
|
||||
|
||||
await preloadModelsForTypeMachine(machine.value.typeMachine)
|
||||
} else {
|
||||
console.error('Machine non trouvée:', machineId)
|
||||
console.error('Erreur API:', machineResult.error)
|
||||
@@ -833,6 +1238,7 @@ const loadMachineData = async () => {
|
||||
}
|
||||
})
|
||||
console.log('=== FIN HIÉRARCHIE ===')
|
||||
await ensureModelsForExistingEntities()
|
||||
} else {
|
||||
console.error('Erreur lors du chargement des composants:', componentsResult.error)
|
||||
}
|
||||
@@ -843,6 +1249,7 @@ const loadMachineData = async () => {
|
||||
pieces.value = transformCustomFields(machine.value.pieces)
|
||||
console.log('Pièces transformées:', pieces.value)
|
||||
console.log('Pièces chargées:', pieces.value.length)
|
||||
await ensureModelsForExistingEntities()
|
||||
} else {
|
||||
console.log('Aucune pièce trouvée dans la réponse de la machine')
|
||||
}
|
||||
@@ -887,10 +1294,12 @@ const updateComponent = async (updatedComponent) => {
|
||||
reference: updatedComponent.reference,
|
||||
constructeurId: updatedComponent.constructeurId || updatedComponent.constructeur?.id || null,
|
||||
emplacement: updatedComponent.emplacement,
|
||||
prix: prixValue && prixValue !== '' ? parseFloat(prixValue) : null
|
||||
prix: prixValue && prixValue !== '' ? parseFloat(prixValue) : null,
|
||||
composantModelId: updatedComponent.composantModelId || updatedComponent.composantModel?.id || null,
|
||||
})
|
||||
if (result.success) {
|
||||
Object.assign(updatedComponent, result.data)
|
||||
const transformed = transformComponentCustomFields([result.data])[0]
|
||||
Object.assign(updatedComponent, transformed)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la mise à jour du composant:', error)
|
||||
@@ -904,10 +1313,12 @@ const updatePieceFromComponent = async (updatedPiece) => {
|
||||
reference: updatedPiece.reference,
|
||||
constructeurId: updatedPiece.constructeurId || updatedPiece.constructeur?.id || null,
|
||||
emplacement: updatedPiece.emplacement,
|
||||
prix: updatedPiece.prix && updatedPiece.prix !== '' ? parseFloat(updatedPiece.prix) : null
|
||||
prix: updatedPiece.prix && updatedPiece.prix !== '' ? parseFloat(updatedPiece.prix) : null,
|
||||
pieceModelId: updatedPiece.pieceModelId || updatedPiece.pieceModel?.id || null,
|
||||
})
|
||||
if (result.success) {
|
||||
Object.assign(updatedPiece, result.data)
|
||||
const transformed = transformCustomFields([result.data])[0]
|
||||
Object.assign(updatedPiece, transformed)
|
||||
// Si la pièce a des champs personnalisés mis à jour, les traiter
|
||||
if (updatedPiece.customFields) {
|
||||
for (const field of updatedPiece.customFields) {
|
||||
@@ -934,16 +1345,131 @@ const updatePieceInfo = async (updatedPiece) => {
|
||||
reference: updatedPiece.reference,
|
||||
constructeurId: updatedPiece.constructeurId || updatedPiece.constructeur?.id || null,
|
||||
emplacement: updatedPiece.emplacement,
|
||||
prix: updatedPiece.prix && updatedPiece.prix !== '' ? parseFloat(updatedPiece.prix) : null
|
||||
prix: updatedPiece.prix && updatedPiece.prix !== '' ? parseFloat(updatedPiece.prix) : null,
|
||||
pieceModelId: updatedPiece.pieceModelId || updatedPiece.pieceModel?.id || null,
|
||||
})
|
||||
if (result.success) {
|
||||
Object.assign(updatedPiece, result.data)
|
||||
const transformed = transformCustomFields([result.data])[0]
|
||||
Object.assign(updatedPiece, transformed)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la mise à jour de la pièce:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const assignComponentModel = async ({ componentId, composantModelId, previousModelId, previousModel }) => {
|
||||
if (!componentId) return
|
||||
try {
|
||||
const result = await updateComposantApi(componentId, {
|
||||
composantModelId: composantModelId || null,
|
||||
})
|
||||
if (result.success) {
|
||||
const transformed = transformComponentCustomFields([result.data])[0]
|
||||
const target = findComponentById(components.value, componentId)
|
||||
if (target) {
|
||||
Object.assign(target, transformed)
|
||||
}
|
||||
} else {
|
||||
const target = findComponentById(components.value, componentId)
|
||||
if (target) {
|
||||
target.composantModelId = previousModelId || null
|
||||
target.composantModel = previousModel || null
|
||||
}
|
||||
toast.showError(result.error || 'Impossible de mettre à jour le modèle du composant')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de l\'assignation du modèle de composant:', error)
|
||||
const target = findComponentById(components.value, componentId)
|
||||
if (target) {
|
||||
target.composantModelId = previousModelId || null
|
||||
target.composantModel = previousModel || null
|
||||
}
|
||||
toast.showError('Impossible de mettre à jour le modèle du composant')
|
||||
}
|
||||
}
|
||||
|
||||
const submitSaveComponentModelModal = async () => {
|
||||
if (!saveComponentAsModelModal.form.typeComposantId) {
|
||||
toast.showError('Type de composant manquant pour créer le modèle')
|
||||
return
|
||||
}
|
||||
|
||||
if (!saveComponentAsModelModal.form.name.trim()) {
|
||||
toast.showError('Veuillez renseigner un nom de modèle')
|
||||
return
|
||||
}
|
||||
|
||||
saveComponentAsModelModal.submitting = true
|
||||
try {
|
||||
const payload = {
|
||||
name: saveComponentAsModelModal.form.name.trim(),
|
||||
description: saveComponentAsModelModal.form.description.trim() || undefined,
|
||||
typeComposantId: saveComponentAsModelModal.form.typeComposantId,
|
||||
structure: saveComponentAsModelModal.structure,
|
||||
}
|
||||
|
||||
const result = await createComponentModel(payload)
|
||||
if (!result.success) {
|
||||
toast.showError(result.error || 'Impossible de créer le modèle de composant')
|
||||
return
|
||||
}
|
||||
|
||||
const newModel = result.data
|
||||
if (newModel?.typeComposantId) {
|
||||
await loadComponentModels(newModel.typeComposantId)
|
||||
}
|
||||
|
||||
const sourceComponent = saveComponentAsModelModal.component
|
||||
if (sourceComponent && newModel?.id) {
|
||||
await assignComponentModel({
|
||||
componentId: sourceComponent.id,
|
||||
composantModelId: newModel.id,
|
||||
previousModelId: sourceComponent.composantModelId,
|
||||
previousModel: sourceComponent.composantModel,
|
||||
})
|
||||
}
|
||||
|
||||
closeSaveComponentModelModal()
|
||||
toast.showSuccess('Composant enregistré comme modèle')
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la création du modèle de composant:', error)
|
||||
toast.showError('Impossible de créer le modèle de composant')
|
||||
} finally {
|
||||
saveComponentAsModelModal.submitting = false
|
||||
}
|
||||
}
|
||||
|
||||
const assignPieceModel = async ({ pieceId, pieceModelId, previousModelId, previousModel }) => {
|
||||
if (!pieceId) return
|
||||
try {
|
||||
const result = await updatePieceApi(pieceId, {
|
||||
pieceModelId: pieceModelId || null,
|
||||
})
|
||||
if (result.success) {
|
||||
const transformed = transformCustomFields([result.data])[0]
|
||||
const target = findPieceById(pieceId)
|
||||
if (target) {
|
||||
Object.assign(target, transformed)
|
||||
}
|
||||
} else {
|
||||
const target = findPieceById(pieceId)
|
||||
if (target) {
|
||||
target.pieceModelId = previousModelId || null
|
||||
target.pieceModel = previousModel || null
|
||||
}
|
||||
toast.showError(result.error || 'Impossible de mettre à jour le modèle de pièce')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de l\'assignation du modèle de pièce:', error)
|
||||
const target = findPieceById(pieceId)
|
||||
if (target) {
|
||||
target.pieceModelId = previousModelId || null
|
||||
target.pieceModel = previousModel || null
|
||||
}
|
||||
toast.showError('Impossible de mettre à jour le modèle de pièce')
|
||||
}
|
||||
}
|
||||
|
||||
// Méthodes pour les champs personnalisés de la machine
|
||||
const setMachineCustomFieldValue = (fieldValueId, value) => {
|
||||
const fieldValue = machine.value?.customFieldValues?.find(fv => fv.id === fieldValueId)
|
||||
|
||||
Reference in New Issue
Block a user