feat(catalog): add description column with hover popover + skeleton edit guard

- Add description column to pieces and component catalog tables
- Show full text in a popover on hover for truncated descriptions
- Block skeleton editing when machines are linked (warning alert)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Matthieu
2026-03-03 10:13:06 +01:00
parent efd0fbe407
commit 546cc37a09
3 changed files with 46 additions and 1 deletions

View File

@@ -116,6 +116,7 @@
<th class="w-24">Aperçu</th>
<th>Nom</th>
<th>Référence</th>
<th>Description</th>
<th>Type de composant</th>
<th>Actions</th>
</tr>
@@ -130,6 +131,15 @@
</td>
<td>{{ component.name || 'Composant sans nom' }}</td>
<td>{{ component.reference || '—' }}</td>
<td class="max-w-xs">
<div v-if="component.description" class="group relative">
<span class="block cursor-help truncate">{{ component.description }}</span>
<div class="pointer-events-none invisible absolute left-0 top-full z-50 mt-1 max-w-sm overflow-hidden rounded-lg border border-base-300 bg-base-100 p-3 text-sm shadow-lg group-hover:pointer-events-auto group-hover:visible">
<p class="break-words whitespace-pre-wrap">{{ component.description }}</p>
</div>
</div>
<span v-else></span>
</td>
<td>
<NuxtLink
v-if="component.typeComposant?.id"

View File

@@ -115,6 +115,7 @@
<th class="w-24">Aperçu</th>
<th>Nom</th>
<th>Référence</th>
<th>Description</th>
<th>Fournisseurs</th>
<th>Type de pièce</th>
<th>Actions</th>
@@ -130,6 +131,15 @@
</td>
<td>{{ row.piece.name || 'Pièce sans nom' }}</td>
<td>{{ row.piece.reference || '—' }}</td>
<td class="max-w-xs">
<div v-if="row.piece.description" class="group relative">
<span class="block cursor-help truncate">{{ row.piece.description }}</span>
<div class="pointer-events-none invisible absolute left-0 top-full z-50 mt-1 max-w-sm overflow-hidden rounded-lg border border-base-300 bg-base-100 p-3 text-sm shadow-lg group-hover:pointer-events-auto group-hover:visible">
<p class="break-words whitespace-pre-wrap">{{ row.piece.description }}</p>
</div>
</div>
<span v-else></span>
</td>
<td>
<div
v-if="row.suppliers.visible.length"

View File

@@ -8,6 +8,26 @@
</p>
</div>
<!-- Locked: machines linked -->
<div v-else-if="type && hasMachines" class="my-8">
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<div class="flex items-center justify-between mb-6">
<h2 class="card-title text-2xl">
{{ type.name }}
</h2>
<NuxtLink to="/machine-skeleton" class="btn btn-outline">
Retour
</NuxtLink>
</div>
<div class="alert alert-warning">
<IconLucideTriangleAlert class="w-5 h-5" />
<span>Ce squelette ne peut pas être modifié car des machines y sont rattachées.</span>
</div>
</div>
</div>
</div>
<!-- Edit Form -->
<div v-else-if="type" class="my-8">
<div class="card bg-base-100 shadow-xl">
@@ -48,11 +68,12 @@
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { ref, computed, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useMachineTypesApi } from '~/composables/useMachineTypesApi'
import { useToast } from '~/composables/useToast'
import { extractRelationId } from '~/shared/apiRelations'
import IconLucideTriangleAlert from '~icons/lucide/triangle-alert'
const { canEdit } = usePermissions()
const route = useRoute()
@@ -63,6 +84,10 @@ const { showSuccess, showError } = useToast()
const type = ref(null)
const loading = ref(true)
const saving = ref(false)
const hasMachines = computed(() => {
const machines = type.value?.machines
return Array.isArray(machines) && machines.length > 0
})
// Données éditées du type
const editedType = ref({