update ui machine view

This commit is contained in:
Matthieu
2025-10-13 10:41:31 +02:00
parent 06ae0ca7aa
commit 469bcb82d1

View File

@@ -308,7 +308,63 @@
</div>
</div>
<!-- Requirement Summary -->
<!-- Components Section -->
<div class="card bg-base-100 shadow-lg">
<div class="card-body">
<div class="flex justify-between items-center mb-4">
<h2 class="card-title">Composants</h2>
<button
type="button"
class="btn btn-ghost btn-sm gap-2"
@click="toggleAllComponents"
:title="componentsCollapsed ? 'Déplier tous les composants' : 'Replier tous les composants'"
>
<IconLucideChevronRight
class="w-5 h-5 transition-transform"
:class="componentsCollapsed ? 'rotate-0' : 'rotate-90'"
aria-hidden="true"
/>
<span class="text-sm">
{{ componentsCollapsed ? 'Tout déplier' : 'Tout replier' }}
</span>
</button>
</div>
<ComponentHierarchy
:components="components"
:is-edit-mode="isEditMode"
:collapse-all="componentsCollapsed"
:toggle-token="collapseToggleToken"
@update="updateComponent"
@edit-piece="updatePieceFromComponent"
@custom-field-update="updatePieceCustomField"
/>
</div>
</div>
<!-- Machine Pieces Section -->
<div class="card bg-base-100 shadow-lg">
<div class="card-body">
<div class="flex justify-between items-center mb-4">
<h2 class="card-title">Pièces de la machine</h2>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<PieceItem
v-for="piece in machinePieces"
:key="piece.id"
:piece="piece"
:is-edit-mode="isEditMode"
@update="updatePieceInfo"
@edit="editPiece"
@custom-field-update="updatePieceCustomField"
/>
</div>
</div>
</div>
</template>
<template v-else>
<div
v-if="componentRequirementGroups.length || pieceRequirementGroups.length"
class="card bg-base-100 shadow-lg"
@@ -418,373 +474,6 @@
</div>
</div>
</div>
<!-- Components Section -->
<div class="card bg-base-100 shadow-lg">
<div class="card-body">
<div class="flex justify-between items-center mb-4">
<h2 class="card-title">Composants</h2>
<button
type="button"
class="btn btn-ghost btn-sm gap-2"
@click="toggleAllComponents"
:title="componentsCollapsed ? 'Déplier tous les composants' : 'Replier tous les composants'"
>
<IconLucideChevronRight
class="w-5 h-5 transition-transform"
:class="componentsCollapsed ? 'rotate-0' : 'rotate-90'"
aria-hidden="true"
/>
<span class="text-sm">
{{ componentsCollapsed ? 'Tout déplier' : 'Tout replier' }}
</span>
</button>
</div>
<ComponentHierarchy
:components="components"
:is-edit-mode="isEditMode"
:collapse-all="componentsCollapsed"
:toggle-token="collapseToggleToken"
@update="updateComponent"
@edit-piece="updatePieceFromComponent"
@custom-field-update="updatePieceCustomField"
/>
</div>
</div>
<!-- Machine Pieces Section -->
<div class="card bg-base-100 shadow-lg">
<div class="card-body">
<div class="flex justify-between items-center mb-4">
<h2 class="card-title">Pièces de la machine</h2>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<PieceItem
v-for="piece in machinePieces"
:key="piece.id"
:piece="piece"
:is-edit-mode="isEditMode"
@update="updatePieceInfo"
@edit="editPiece"
@custom-field-update="updatePieceCustomField"
/>
</div>
</div>
</div>
</template>
<template v-else>
<div class="card bg-base-100 shadow-lg border border-primary/20">
<div class="card-body space-y-6">
<div class="flex flex-wrap items-start justify-between gap-3">
<div>
<h2 class="card-title">
{{ skeletonEditorTitle }}
</h2>
<p class="text-sm text-gray-500">
Sélectionnez les composants et pièces à associer à cette machine selon les exigences du type.
</p>
</div>
<button
type="button"
class="btn btn-ghost btn-sm"
:disabled="skeletonEditor.submitting"
@click="changeMachineView('details')"
>
Fermer
</button>
</div>
<div v-if="skeletonEditor.loading" class="flex justify-center py-12">
<span class="loading loading-spinner loading-lg"></span>
</div>
<template v-else>
<div v-if="!machineHasSkeletonRequirements" class="text-sm text-gray-500">
Ce type de machine ne possède pas de squelette structuré.
</div>
<template v-else>
<div v-if="componentRequirements.length" class="space-y-4">
<h3 class="text-sm font-semibold text-gray-700">Sélection des composants</h3>
<div
v-for="requirement in componentRequirements"
:key="requirement.id"
class="border border-base-200 rounded-lg p-4 space-y-3"
:id="`component-reconfigure-${requirement.id}`"
>
<div class="flex flex-wrap items-start justify-between gap-3">
<div>
<h4 class="font-medium text-sm">
{{ requirement.label || requirement.typeComposant?.name || 'Famille de composants' }}
</h4>
<p class="text-xs text-gray-500">
Type : {{ requirement.typeComposant?.name || 'Non défini' }} · Min : {{ requirement.minCount ?? (requirement.required ? 1 : 0) }}
· Max : {{ requirement.maxCount ?? '∞' }} ·
{{ requirement.allowNewModels ? 'Nouveaux modèles autorisés' : 'Modèles existants uniquement' }}
</p>
</div>
<button
type="button"
class="btn btn-sm btn-outline"
@click="addComponentSelectionEntry(requirement)"
:disabled="requirement.maxCount !== null && getComponentRequirementEntries(requirement.id).length >= requirement.maxCount"
>
<IconLucidePlus class="w-4 h-4 mr-2" aria-hidden="true" />
Ajouter
</button>
</div>
<div v-if="getComponentRequirementEntries(requirement.id).length === 0" class="text-xs text-gray-500">
Aucun composant sélectionné pour ce groupe.
</div>
<div
v-for="(entry, entryIndex) in getComponentRequirementEntries(requirement.id)"
:key="`${requirement.id}-${entryIndex}`"
class="bg-base-200/60 rounded-md p-3 space-y-4"
>
<div class="flex flex-wrap items-center justify-between gap-2 text-xs text-gray-500">
<span>
Type appliqué :
{{ resolveComponentRequirementTypeLabel(requirement, entry) }}
</span>
<button
type="button"
class="btn btn-square btn-xs btn-error"
@click="removeComponentSelectionEntry(requirement.id, entryIndex)"
>
<IconLucideX class="w-4 h-4" aria-hidden="true" />
</button>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-3">
<div class="form-control md:col-span-2">
<label class="label">
<span class="label-text text-xs">Catégorie de composant</span>
</label>
<select
class="select select-bordered select-xs md:select-sm"
:value="entry.typeComposantId || requirement.typeComposantId || ''"
@change="setComponentRequirementType(requirement.id, entryIndex, ($event.target && $event.target.value) || '')"
>
<option value="">
{{ requirement.typeComposant?.name ? `Type du requirement (${requirement.typeComposant.name})` : 'Suivre le requirement' }}
</option>
<option
v-for="type in componentTypeOptions"
:key="type.id"
:value="type.id"
>
{{ type.name }}
</option>
</select>
</div>
<div class="form-control">
<label class="label">
<span class="label-text text-xs">Nom du composant</span>
</label>
<input
v-model="entry.definition.name"
type="text"
class="input input-bordered input-sm"
placeholder="Nom du composant"
/>
</div>
<div class="form-control">
<label class="label">
<span class="label-text text-xs">Référence (optionnel)</span>
</label>
<input
v-model="entry.definition.reference"
type="text"
class="input input-bordered input-sm"
placeholder="Référence du composant"
/>
</div>
<div class="form-control">
<label class="label">
<span class="label-text text-xs">Constructeur (optionnel)</span>
</label>
<ConstructeurSelect
class="w-full"
:model-value="entry.definition.constructeurId || null"
placeholder="Sélectionner un constructeur"
@update:modelValue="(value) => setComponentRequirementConstructeur(requirement.id, entryIndex, value)"
/>
</div>
<div class="form-control">
<label class="label">
<span class="label-text text-xs">Prix (optionnel)</span>
</label>
<input
v-model.number="entry.definition.prix"
type="number"
min="0"
step="0.01"
class="input input-bordered input-sm"
placeholder="0.00"
/>
</div>
</div>
</div>
</div>
</div>
<div v-if="pieceRequirements.length" class="space-y-4">
<h3 class="text-sm font-semibold text-gray-700">Sélection des pièces principales</h3>
<div
v-for="requirement in pieceRequirements"
:key="requirement.id"
class="border border-base-200 rounded-lg p-4 space-y-3"
:id="`piece-reconfigure-${requirement.id}`"
>
<div class="flex flex-wrap items-start justify-between gap-3">
<div>
<h4 class="font-medium text-sm">
{{ requirement.label || requirement.typePiece?.name || 'Groupe de pièces' }}
</h4>
<p class="text-xs text-gray-500">
Type : {{ requirement.typePiece?.name || 'Non défini' }} · Min : {{ requirement.minCount ?? (requirement.required ? 1 : 0) }}
· Max : {{ requirement.maxCount ?? '∞' }} ·
{{ requirement.allowNewModels ? 'Nouveaux modèles autorisés' : 'Modèles existants uniquement' }}
</p>
</div>
<button
type="button"
class="btn btn-sm btn-outline"
@click="addPieceSelectionEntry(requirement)"
:disabled="requirement.maxCount !== null && getPieceRequirementEntries(requirement.id).length >= requirement.maxCount"
>
<IconLucidePlus class="w-4 h-4 mr-2" aria-hidden="true" />
Ajouter
</button>
</div>
<div v-if="getPieceRequirementEntries(requirement.id).length === 0" class="text-xs text-gray-500">
Aucune pièce sélectionnée pour ce groupe.
</div>
<div
v-for="(entry, entryIndex) in getPieceRequirementEntries(requirement.id)"
:key="`${requirement.id}-piece-${entryIndex}`"
class="bg-base-200/60 rounded-md p-3 space-y-4"
>
<div class="flex flex-wrap items-center justify-between gap-2 text-xs text-gray-500">
<span>
Type appliqué :
{{ resolvePieceRequirementTypeLabel(requirement, entry) }}
</span>
<button
type="button"
class="btn btn-square btn-xs btn-error"
@click="removePieceSelectionEntry(requirement.id, entryIndex)"
>
<IconLucideX class="w-4 h-4" aria-hidden="true" />
</button>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-3">
<div class="form-control md:col-span-2">
<label class="label">
<span class="label-text text-xs">Catégorie de pièce</span>
</label>
<select
class="select select-bordered select-xs md:select-sm"
:value="entry.typePieceId || requirement.typePieceId || ''"
@change="setPieceRequirementType(requirement.id, entryIndex, ($event.target && $event.target.value) || '')"
>
<option value="">
{{ requirement.typePiece?.name ? `Type du requirement (${requirement.typePiece.name})` : 'Suivre le requirement' }}
</option>
<option
v-for="type in pieceTypeOptions"
:key="type.id"
:value="type.id"
>
{{ type.name }}
</option>
</select>
</div>
<div class="form-control">
<label class="label">
<span class="label-text text-xs">Nom de la pièce</span>
</label>
<input
v-model="entry.definition.name"
type="text"
class="input input-bordered input-sm"
placeholder="Nom de la pièce"
/>
</div>
<div class="form-control">
<label class="label">
<span class="label-text text-xs">Référence (optionnel)</span>
</label>
<input
v-model="entry.definition.reference"
type="text"
class="input input-bordered input-sm"
placeholder="Référence de la pièce"
/>
</div>
<div class="form-control">
<label class="label">
<span class="label-text text-xs">Constructeur (optionnel)</span>
</label>
<ConstructeurSelect
class="w-full"
:model-value="entry.definition.constructeurId || null"
placeholder="Sélectionner un constructeur"
@update:modelValue="(value) => setPieceRequirementConstructeur(requirement.id, entryIndex, value)"
/>
</div>
<div class="form-control">
<label class="label">
<span class="label-text text-xs">Prix (optionnel)</span>
</label>
<input
v-model.number="entry.definition.prix"
type="number"
min="0"
step="0.01"
class="input input-bordered input-sm"
placeholder="0.00"
/>
</div>
</div>
</div>
</div>
</div>
</template>
<div class="flex flex-wrap justify-end gap-2 pt-2 border-t border-base-200">
<button
type="button"
class="btn btn-ghost"
:disabled="skeletonEditor.submitting"
@click="changeMachineView('details')"
>
Annuler
</button>
<button
type="button"
class="btn btn-primary"
:class="{ loading: skeletonEditor.submitting }"
@click="saveSkeletonConfiguration"
>
Sauvegarder la configuration
</button>
</div>
</template>
</div>
</div>
</template>
</div>
@@ -1585,12 +1274,6 @@ const machineViewTitle = computed(() => {
return isEditMode.value ? 'Modification de la machine' : 'Détails de la machine'
})
const skeletonEditorTitle = computed(() =>
skeletonEditor.open
? 'Modification des éléments du squelette'
: 'Éléments du squelette'
)
// Gestion du pliage global des composants
const componentsCollapsed = ref(true)
const collapseToggleToken = ref(0)