refactor: adopt canonical component model structure schema

This commit is contained in:
MatthieuTD
2025-10-01 14:26:31 +02:00
parent d3f8ac3649
commit 386a1c9d1b
9 changed files with 470 additions and 146 deletions

View File

@@ -28,6 +28,17 @@
<p class="text-[11px] text-gray-500">
{{ node.typeComposantId ? `Sélection : ${getComponentTypeLabel(node.typeComposantId) || 'Inconnue'}` : 'Aucune famille sélectionnée' }}
</p>
<div v-if="!isRoot" class="form-control mt-2">
<label class="label py-1">
<span class="label-text text-[11px]">Alias (optionnel)</span>
</label>
<input
v-model="node.alias"
type="text"
class="input input-bordered input-xs"
placeholder="Alias du sous-composant"
/>
</div>
</template>
<template v-else>
<div class="input input-bordered input-sm bg-base-200 flex items-center">
@@ -170,12 +181,12 @@
<p v-if="!isRoot" class="text-[11px] text-gray-500">
Sélectionnez uniquement la famille de ce sous-composant ; il sera configuré via son propre modèle.
</p>
<p v-if="!(node.subComponents?.length)" class="text-xs text-gray-500">
<p v-if="!(node.subcomponents?.length)" class="text-xs text-gray-500">
Aucun sous-composant défini.
</p>
<div v-else class="space-y-3">
<StructureNodeEditor
v-for="(subComponent, index) in node.subComponents"
v-for="(subComponent, index) in node.subcomponents"
:key="`sub-${index}`"
:node="subComponent"
:depth="depth + 1"
@@ -194,6 +205,7 @@
import { computed, watch } from 'vue'
import IconLucidePlus from '~icons/lucide/plus'
import IconLucideTrash from '~icons/lucide/trash'
import type { ComponentModelPiece, ComponentModelStructureNode } from '~/shared/types/inventory'
defineOptions({ name: 'StructureNodeEditor' })
@@ -203,8 +215,13 @@ type ModelTypeOption = {
code?: string | null
}
type EditableStructureNode = ComponentModelStructureNode & {
customFields?: any[]
pieces?: ComponentModelPiece[]
}
const props = withDefaults(defineProps<{
node: Record<string, any>
node: EditableStructureNode
depth?: number
componentTypes?: ModelTypeOption[]
pieceTypes?: ModelTypeOption[]
@@ -281,23 +298,31 @@ const formatComponentTypeOption = (type: ModelTypeOption | undefined | null) =>
const formatPieceTypeOption = (type: ModelTypeOption | undefined | null) =>
formatModelTypeOption(type)
const ensureArray = (key: 'customFields' | 'pieces' | 'subComponents') => {
if (!Array.isArray(props.node[key])) {
props.node[key] = []
const ensureArray = (key: 'customFields' | 'pieces' | 'subcomponents') => {
if (!Array.isArray((props.node as any)[key])) {
if (key === 'subcomponents') {
props.node.subcomponents = []
} else {
(props.node as any)[key] = []
}
}
}
const syncComponentType = (component: any) => {
const syncComponentType = (component: EditableStructureNode) => {
if (!component) {
return
}
if (props.lockType && props.isRoot) {
if (props.lockedTypeLabel) {
component.typeComposantLabel = props.lockedTypeLabel
if (!component.name || component.name === component.typeComposantLabel) {
component.name = props.lockedTypeLabel
if (!component.alias || component.alias === component.typeComposantLabel) {
component.alias = props.lockedTypeLabel
}
}
if (component.typeComposantId) {
const option = componentTypeMap.value.get(component.typeComposantId)
component.familyCode = option?.code ?? component.familyCode
}
return
}
const id = typeof component.typeComposantId === 'string'
@@ -306,29 +331,31 @@ const syncComponentType = (component: any) => {
if (!id) {
component.typeComposantLabel = ''
component.name = ''
component.familyCode = ''
return
}
const option = componentTypeMap.value.get(id)
if (!option) {
component.typeComposantLabel = ''
component.name = ''
component.familyCode = ''
return
}
component.typeComposantLabel = formatModelTypeOption(option)
component.name = option.name || component.typeComposantLabel
component.familyCode = option.code ?? component.familyCode
if (!component.alias || component.alias === '' || component.alias === lockedTypeDisplay.value) {
component.alias = option.name || component.typeComposantLabel
}
}
const updatePieceTypeLabel = (piece: any) => {
const updatePieceTypeLabel = (piece: ComponentModelPiece & Record<string, any>) => {
if (!piece) return
if (piece.typePieceId) {
const option = pieceTypeMap.value.get(piece.typePieceId)
if (option) {
piece.typePieceLabel = formatPieceTypeOption(option)
piece.name = option.name || formatPieceTypeOption(option)
return
}
}
@@ -345,15 +372,10 @@ const updatePieceTypeLabel = (piece: any) => {
if (match) {
piece.typePieceId = match.id
piece.typePieceLabel = formatPieceTypeOption(match)
piece.name = match.name || formatPieceTypeOption(match)
return
}
}
}
if (!piece.name) {
piece.name = piece.typePieceLabel || ''
}
}
const syncPieceLabels = (pieces?: any[]) => {
@@ -369,25 +391,22 @@ const handleComponentTypeSelect = (component: any) => {
syncComponentType(component)
}
const handlePieceTypeSelect = (piece: any) => {
const handlePieceTypeSelect = (piece: ComponentModelPiece & Record<string, any>) => {
if (!piece) {
return
}
const id = typeof piece.typePieceId === 'string' ? piece.typePieceId : ''
if (!id) {
piece.typePieceLabel = ''
piece.name = ''
return
}
const option = pieceTypeMap.value.get(id)
if (!option) {
piece.typePieceId = ''
piece.typePieceLabel = ''
piece.name = ''
return
}
piece.typePieceLabel = formatPieceTypeOption(option)
piece.name = option.name || piece.typePieceLabel
}
const addCustomField = () => {
@@ -409,9 +428,9 @@ const removeCustomField = (index: number) => {
const addPiece = () => {
ensureArray('pieces')
props.node.pieces.push({
name: '',
typePieceId: '',
typePieceLabel: '',
reference: '',
})
}
@@ -421,17 +440,20 @@ const removePiece = (index: number) => {
}
const addSubComponent = () => {
ensureArray('subComponents')
props.node.subComponents.push({
name: '',
ensureArray('subcomponents')
props.node.subcomponents.push({
typeComposantId: '',
typeComposantLabel: '',
modelId: '',
familyCode: '',
alias: '',
subcomponents: [],
})
}
const removeSubComponent = (index: number) => {
if (!Array.isArray(props.node.subComponents)) return
props.node.subComponents.splice(index, 1)
if (!Array.isArray(props.node.subcomponents)) return
props.node.subcomponents.splice(index, 1)
}
watch(componentTypes, () => {
@@ -463,8 +485,12 @@ watch(
if (props.lockType && props.isRoot) {
const label = props.lockedTypeLabel || lockedTypeDisplay.value
props.node.typeComposantLabel = label
if (label && (!props.node.name || props.node.name === lockedTypeDisplay.value)) {
props.node.name = label
if (label && (!props.node.alias || props.node.alias === lockedTypeDisplay.value)) {
props.node.alias = label
}
if (props.node.typeComposantId) {
const option = componentTypeMap.value.get(props.node.typeComposantId)
props.node.familyCode = option?.code ?? props.node.familyCode
}
}
},