feat: Composants d'affichage des types de machines

- TypeComponentDisplay.vue : Affichage des composants existants avec hiérarchie
- TypeInfoDisplay.vue : Informations générales du type de machine
- TypeMachinePieceDisplay.vue : Affichage des pièces principales
- Support de l'affichage en lecture seule des structures complexes
- Gestion des champs personnalisés et sous-composants
This commit is contained in:
Matthieu
2025-07-30 08:17:01 +02:00
parent 36b7ce93ec
commit 9fb0353442
3 changed files with 230 additions and 0 deletions

View File

@@ -0,0 +1,157 @@
<template>
<div class="border border-gray-300 rounded-lg p-4 bg-base-100">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center gap-2">
<svg class="w-5 h-5 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"></path>
</svg>
<h4 class="text-lg font-medium">{{ component.name }}</h4>
</div>
<div class="text-sm text-gray-500">
{{ component.reference ? `Ref: ${component.reference}` : '' }}
</div>
</div>
<!-- Informations du composant -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<div v-if="component.prestataire" class="text-sm">
<span class="font-medium">Prestataire:</span> {{ component.prestataire }}
</div>
<div v-if="component.emplacement" class="text-sm">
<span class="font-medium">Emplacement:</span> {{ component.emplacement }}
</div>
<div v-if="component.prix" class="text-sm">
<span class="font-medium">Prix:</span> {{ component.prix }}
</div>
</div>
<!-- Champs personnalisés du composant -->
<div v-if="component.customFields && component.customFields.length > 0" class="mb-4">
<h5 class="text-sm font-medium text-gray-700 mb-2">Champs personnalisés:</h5>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2">
<div v-for="field in component.customFields" :key="field.id" class="bg-gray-50 rounded p-2">
<div class="text-xs font-medium">{{ field.name }}</div>
<div class="text-xs text-gray-600">{{ field.type }}</div>
<div v-if="field.required" class="text-xs text-red-500">Obligatoire</div>
<div v-if="field.defaultValue" class="text-xs text-gray-500">Défaut: {{ field.defaultValue }}</div>
</div>
</div>
</div>
<!-- Pièces du composant -->
<div v-if="component.pieces && component.pieces.length > 0" class="mb-4">
<h5 class="text-sm font-medium text-gray-700 mb-2">Pièces du composant:</h5>
<div class="space-y-2">
<div v-for="(piece, pieceIndex) in component.pieces" :key="pieceIndex" class="border border-gray-200 rounded p-3 bg-gray-50">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center gap-2">
<svg class="w-4 h-4 text-red-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"></path>
</svg>
<span class="font-medium">{{ piece.name }}</span>
</div>
<div class="text-xs text-gray-500">
{{ piece.reference ? `Ref: ${piece.reference}` : '' }}
</div>
</div>
<!-- Informations de la pièce -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-2 mb-2">
<div v-if="piece.prestataire" class="text-xs">
<span class="font-medium">Prestataire:</span> {{ piece.prestataire }}
</div>
<div v-if="piece.emplacement" class="text-xs">
<span class="font-medium">Emplacement:</span> {{ piece.emplacement }}
</div>
<div v-if="piece.prix" class="text-xs">
<span class="font-medium">Prix:</span> {{ piece.prix }}
</div>
</div>
<!-- Champs personnalisés de la pièce -->
<div v-if="piece.customFields && piece.customFields.length > 0">
<div class="text-xs font-medium text-gray-600 mb-1">Champs personnalisés:</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-1">
<div v-for="field in piece.customFields" :key="field.id" class="bg-white rounded p-1">
<div class="text-xs font-medium">{{ field.name }}</div>
<div class="text-xs text-gray-600">{{ field.type }}</div>
<div v-if="field.required" class="text-xs text-red-500">Obligatoire</div>
<div v-if="field.defaultValue" class="text-xs text-gray-500">Défaut: {{ field.defaultValue }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Sous-composants -->
<div v-if="component.subComponents && component.subComponents.length > 0" class="ml-4 border-l-2 border-gray-300 pl-4">
<h5 class="text-sm font-medium text-gray-700 mb-2">Sous-composants:</h5>
<div class="space-y-3">
<div v-for="(subComponent, subIndex) in component.subComponents" :key="subIndex" class="border border-gray-200 rounded p-3 bg-gray-50">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center gap-2">
<svg class="w-4 h-4 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<span class="font-medium">{{ subComponent.name }}</span>
</div>
<div class="text-xs text-gray-500">
{{ subComponent.reference ? `Ref: ${subComponent.reference}` : '' }}
</div>
</div>
<!-- Informations du sous-composant -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-2 mb-2">
<div v-if="subComponent.prestataire" class="text-xs">
<span class="font-medium">Prestataire:</span> {{ subComponent.prestataire }}
</div>
<div v-if="subComponent.emplacement" class="text-xs">
<span class="font-medium">Emplacement:</span> {{ subComponent.emplacement }}
</div>
<div v-if="subComponent.prix" class="text-xs">
<span class="font-medium">Prix:</span> {{ subComponent.prix }}
</div>
</div>
<!-- Champs personnalisés du sous-composant -->
<div v-if="subComponent.customFields && subComponent.customFields.length > 0" class="mb-2">
<div class="text-xs font-medium text-gray-600 mb-1">Champs personnalisés:</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-1">
<div v-for="field in subComponent.customFields" :key="field.id" class="bg-white rounded p-1">
<div class="text-xs font-medium">{{ field.name }}</div>
<div class="text-xs text-gray-600">{{ field.type }}</div>
<div v-if="field.required" class="text-xs text-red-500">Obligatoire</div>
<div v-if="field.defaultValue" class="text-xs text-gray-500">Défaut: {{ field.defaultValue }}</div>
</div>
</div>
</div>
<!-- Pièces du sous-composant -->
<div v-if="subComponent.pieces && subComponent.pieces.length > 0">
<div class="text-xs font-medium text-gray-600 mb-1">Pièces:</div>
<div class="space-y-1">
<div v-for="(piece, pieceIndex) in subComponent.pieces" :key="pieceIndex" class="flex items-center gap-2">
<svg class="w-3 h-3 text-red-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"></path>
</svg>
<span class="text-xs">{{ piece.name }}</span>
<span v-if="piece.reference" class="text-xs text-gray-500">({{ piece.reference }})</span>
<span v-if="piece.prix" class="text-xs text-green-600">{{ piece.prix }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
defineProps({
component: {
type: Object,
required: true
}
})
</script>

View File

@@ -0,0 +1,23 @@
<template>
<div class="alert alert-info mb-6">
<div>
<h3 class="font-bold">Type existant</h3>
<div class="text-sm">
<p><strong>Catégorie:</strong> {{ type.category || 'Non définie' }}</p>
<p><strong>Maintenance:</strong> {{ type.maintenanceFrequency || 'Non définie' }}</p>
<p><strong>Composants:</strong> {{ type.components?.length || 0 }}</p>
<p><strong>Pièces principales:</strong> {{ type.machinePieces?.length || 0 }}</p>
<p v-if="type.description"><strong>Description:</strong> {{ type.description }}</p>
</div>
</div>
</div>
</template>
<script setup>
defineProps({
type: {
type: Object,
required: true
}
})
</script>

View File

@@ -0,0 +1,50 @@
<template>
<div class="border border-gray-300 rounded-lg p-4 bg-base-100">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center gap-2">
<svg class="w-5 h-5 text-red-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"></path>
</svg>
<h4 class="font-medium">{{ piece.name }}</h4>
</div>
</div>
<!-- Informations de la pièce -->
<div class="space-y-1 mb-3">
<div v-if="piece.reference" class="text-sm">
<span class="font-medium">Référence:</span> {{ piece.reference }}
</div>
<div v-if="piece.prestataire" class="text-sm">
<span class="font-medium">Prestataire:</span> {{ piece.prestataire }}
</div>
<div v-if="piece.emplacement" class="text-sm">
<span class="font-medium">Emplacement:</span> {{ piece.emplacement }}
</div>
<div v-if="piece.prix" class="text-sm">
<span class="font-medium">Prix:</span> {{ piece.prix }}
</div>
</div>
<!-- Champs personnalisés de la pièce -->
<div v-if="piece.customFields && piece.customFields.length > 0">
<h5 class="text-sm font-medium text-gray-700 mb-2">Champs personnalisés:</h5>
<div class="grid grid-cols-1 gap-2">
<div v-for="field in piece.customFields" :key="field.id" class="bg-gray-50 rounded p-2">
<div class="text-sm font-medium">{{ field.name }}</div>
<div class="text-xs text-gray-600">{{ field.type }}</div>
<div v-if="field.required" class="text-xs text-red-500">Obligatoire</div>
<div v-if="field.defaultValue" class="text-xs text-gray-500">Défaut: {{ field.defaultValue }}</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
defineProps({
piece: {
type: Object,
required: true
}
})
</script>