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:
157
app/components/TypeComponentDisplay.vue
Normal file
157
app/components/TypeComponentDisplay.vue
Normal 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>
|
||||
23
app/components/TypeInfoDisplay.vue
Normal file
23
app/components/TypeInfoDisplay.vue
Normal 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>
|
||||
50
app/components/TypeMachinePieceDisplay.vue
Normal file
50
app/components/TypeMachinePieceDisplay.vue
Normal 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>
|
||||
Reference in New Issue
Block a user