feat: reorganize machine skeleton pages

This commit is contained in:
Matthieu
2025-09-29 15:05:54 +02:00
parent a78938a4d1
commit 43b615ac3e
8 changed files with 187 additions and 1381 deletions

View File

@@ -70,43 +70,29 @@
>
<div class="flex items-start justify-between gap-2">
<div class="flex-1 space-y-3">
<div class="grid grid-cols-1 md:grid-cols-2 gap-3">
<div class="form-control">
<label class="label"><span class="label-text">Famille de pièce</span></label>
<div>
<input
:list="`component-piece-type-options-${index}`"
v-model="piece.typePieceLabel"
type="search"
autocomplete="off"
class="input input-bordered input-xs"
placeholder="Sélectionner une famille"
@change="handlePieceTypeChange(piece)"
@blur="handlePieceTypeChange(piece)"
/>
<datalist :id="`component-piece-type-options-${index}`">
<option
v-for="type in availablePieceTypes"
:key="type.id"
:value="formatPieceTypeOption(type)"
/>
</datalist>
</div>
<p class="mt-1 text-[11px] text-gray-500">
{{ piece.typePieceId ? `Sélection : ${getPieceTypeLabel(piece.typePieceId) || 'Inconnue'}` : 'Aucune famille sélectionnée' }}
</p>
</div>
<div class="form-control">
<label class="label"><span class="label-text">Quantité (optionnel)</span></label>
<input
v-model.number="piece.quantity"
type="number"
min="0"
step="1"
class="input input-bordered input-xs"
placeholder="Quantité"
/>
<div class="form-control">
<label class="label"><span class="label-text">Famille de pièce</span></label>
<div>
<select
v-model="piece.typePieceId"
class="select select-bordered select-xs"
@change="handlePieceTypeSelect(piece)"
>
<option value="">
Sélectionner une famille
</option>
<option
v-for="type in availablePieceTypes"
:key="type.id"
:value="type.id"
>
{{ formatPieceTypeOption(type) }}
</option>
</select>
</div>
<p class="mt-1 text-[11px] text-gray-500">
{{ piece.typePieceId ? `Sélection : ${getPieceTypeLabel(piece.typePieceId) || 'Inconnue'}` : 'Aucune famille sélectionnée' }}
</p>
</div>
</div>
<button type="button" class="btn btn-error btn-xs btn-square" @click="removePiece(index)">
@@ -134,7 +120,6 @@
:key="`root-sub-${index}`"
:node="subComponent"
:depth="0"
:piece-types="availablePieceTypes"
:component-types="availableComponentTypes"
@remove="removeSubComponent(index)"
/>
@@ -151,7 +136,7 @@ import StructureSubComponentEditor from '~/components/StructureSubComponentEdito
import {
defaultStructure,
hydrateStructureForEditor,
normalizeStructureForSave,
cloneStructure,
} from '~/shared/modelUtils'
import { usePieceTypes } from '~/composables/usePieceTypes'
import { useComponentTypes } from '~/composables/useComponentTypes'
@@ -174,7 +159,7 @@ const syncFromProps = (value: any) => {
localStructure.customFields = hydrated.customFields
localStructure.pieces = hydrated.pieces
localStructure.subComponents = hydrated.subComponents
lastEmitted = JSON.stringify(normalizeStructureForSave(value))
lastEmitted = JSON.stringify(cloneStructure(value))
}
watch(
@@ -185,16 +170,16 @@ watch(
{ deep: true }
)
let lastEmitted = JSON.stringify(normalizeStructureForSave(props.modelValue))
let lastEmitted = JSON.stringify(cloneStructure(props.modelValue))
watch(
localStructure,
(value) => {
const normalized = normalizeStructureForSave(value)
const serialized = JSON.stringify(normalized)
const payload = cloneStructure(value)
const serialized = JSON.stringify(payload)
if (serialized !== lastEmitted) {
lastEmitted = serialized
emit('update:modelValue', normalized)
emit('update:modelValue', payload)
}
},
{ deep: true }
@@ -302,34 +287,35 @@ const updatePieceTypeLabel = (piece: any) => {
piece.typePieceId = match.id
piece.typePieceLabel = formatPieceTypeOption(match)
piece.name = match.name || formatPieceTypeOption(match)
} else {
piece.typePieceLabel = ''
piece.name = ''
} else if (!piece.name) {
piece.name = piece.typePieceLabel
}
}
}
const handlePieceTypeChange = (piece: any) => {
const handlePieceTypeSelect = (piece: any) => {
if (!piece) {
return
}
const value = typeof piece.typePieceLabel === 'string' ? piece.typePieceLabel.trim() : ''
if (!value) {
const id = typeof piece.typePieceId === 'string' ? piece.typePieceId : ''
if (!id) {
piece.typePieceId = ''
piece.typePieceLabel = ''
piece.name = ''
return
}
const match = resolvePieceType(value)
if (match) {
piece.typePieceId = match.id
piece.typePieceLabel = formatPieceTypeOption(match)
piece.name = match.name || formatPieceTypeOption(match)
} else {
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 applyPieceLabels = (pieces?: any[]) => {
@@ -345,9 +331,8 @@ const applyPieceLabels = (pieces?: any[]) => {
piece.typePieceId = match.id
piece.typePieceLabel = formatPieceTypeOption(match)
piece.name = match.name || formatPieceTypeOption(match)
} else {
piece.typePieceLabel = ''
piece.name = ''
} else if (!piece.name) {
piece.name = piece.typePieceLabel
}
} else if (!piece?.name) {
piece.name = ''
@@ -452,7 +437,6 @@ const addPiece = () => {
ensureArray('pieces')
localStructure.pieces.push({
name: '',
quantity: undefined,
typePieceId: '',
typePieceLabel: '',
})
@@ -467,13 +451,8 @@ const addSubComponent = () => {
ensureArray('subComponents')
localStructure.subComponents.push({
name: '',
description: '',
quantity: undefined,
typeComposantId: '',
typeComposantLabel: '',
customFields: [],
pieces: [],
subComponents: [],
})
}