113 lines
3.7 KiB
Vue
113 lines
3.7 KiB
Vue
<template>
|
|
<main class="container mx-auto px-6 py-10 space-y-8">
|
|
<header class="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
|
|
<div>
|
|
<h1 class="text-3xl font-semibold text-base-content">Catalogue des pièces</h1>
|
|
<p class="text-sm text-gray-500">
|
|
Consultez et gérez toutes les pièces existantes.
|
|
</p>
|
|
</div>
|
|
<div class="flex flex-wrap gap-2">
|
|
<NuxtLink to="/pieces/create" class="btn btn-primary btn-sm md:btn-md">
|
|
Ajouter une pièce
|
|
</NuxtLink>
|
|
<NuxtLink to="/piece-category" class="btn btn-outline btn-sm md:btn-md">
|
|
Gérer les catégories
|
|
</NuxtLink>
|
|
</div>
|
|
</header>
|
|
<section class="card border border-base-200 bg-base-100 shadow-sm">
|
|
<div class="card-body space-y-4">
|
|
<header class="flex flex-col gap-2">
|
|
<h2 class="text-xl font-semibold text-base-content">Pièces créées</h2>
|
|
<p class="text-sm text-base-content/70">
|
|
Liste globale des pièces enregistrées, quel que soit leur squelette d'origine.
|
|
</p>
|
|
</header>
|
|
|
|
<div v-if="loadingPieces" class="flex justify-center py-8">
|
|
<span class="loading loading-spinner" aria-hidden="true" />
|
|
</div>
|
|
|
|
<p v-else-if="!piecesList.length" class="text-sm text-base-content/70">
|
|
Aucune pièce n'a encore été créée.
|
|
</p>
|
|
|
|
<div v-else class="overflow-x-auto">
|
|
<table class="table table-sm md:table-md">
|
|
<thead>
|
|
<tr>
|
|
<th>Nom</th>
|
|
<th>Catégorie</th>
|
|
<th>Référence</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="piece in piecesList" :key="piece.id">
|
|
<td>{{ piece.name || 'Pièce sans nom' }}</td>
|
|
<td>{{ piece.typePiece?.name || '—' }}</td>
|
|
<td>{{ piece.reference || '—' }}</td>
|
|
<td>
|
|
<div class="flex items-center gap-2">
|
|
<NuxtLink
|
|
:to="`/pieces/${piece.id}/edit`"
|
|
class="btn btn-ghost btn-xs"
|
|
>
|
|
Modifier
|
|
</NuxtLink>
|
|
<button
|
|
type="button"
|
|
class="btn btn-error btn-xs"
|
|
:disabled="loadingPieces"
|
|
@click="handleDeletePiece(piece)"
|
|
>
|
|
Supprimer
|
|
</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed, onMounted } from 'vue'
|
|
import { usePieces } from '~/composables/usePieces'
|
|
import { useToast } from '~/composables/useToast'
|
|
|
|
const { showError } = useToast()
|
|
const { pieces, loadPieces, loading: loadingPiecesRef, deletePiece } = usePieces()
|
|
const loadingPieces = computed(() => loadingPiecesRef.value)
|
|
const piecesList = computed(() => pieces.value || [])
|
|
|
|
const handleDeletePiece = async (piece: Record<string, any>) => {
|
|
const hasLinkedElements =
|
|
(piece?.machineLinks?.length ?? 0) > 0 ||
|
|
(piece?.documents?.length ?? 0) > 0 ||
|
|
(piece?.customFieldValues?.length ?? 0) > 0
|
|
|
|
if (hasLinkedElements) {
|
|
showError('Impossible de supprimer cette pièce car elle possède des éléments liés.')
|
|
return
|
|
}
|
|
|
|
const pieceName = piece?.name || 'cette pièce'
|
|
const confirmed = window.confirm(`Voulez-vous vraiment supprimer ${pieceName} ?`)
|
|
if (!confirmed) {
|
|
return
|
|
}
|
|
|
|
await deletePiece(piece.id)
|
|
}
|
|
|
|
onMounted(async () => {
|
|
await loadPieces()
|
|
})
|
|
</script>
|