feat: infrastructure assets management with warranty tracking and EAN lookup integration
This commit is contained in:
151
resources/js/Pages/Assets/Show.vue
Normal file
151
resources/js/Pages/Assets/Show.vue
Normal file
@@ -0,0 +1,151 @@
|
||||
<script setup>
|
||||
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout.vue'
|
||||
import { Head, Link } from '@inertiajs/vue3'
|
||||
|
||||
const props = defineProps({
|
||||
asset: Object,
|
||||
})
|
||||
|
||||
function formatDate(d) {
|
||||
if (!d) return '—'
|
||||
return new Intl.DateTimeFormat('fr-FR').format(new Date(d))
|
||||
}
|
||||
|
||||
const statutLabels = {
|
||||
en_service: 'En service',
|
||||
hors_service: 'Hors service',
|
||||
en_reparation: 'En réparation',
|
||||
stock: 'En stock',
|
||||
}
|
||||
|
||||
const statutColors = {
|
||||
en_service: 'bg-green-100 text-green-800',
|
||||
hors_service: 'bg-red-100 text-red-800',
|
||||
en_reparation: 'bg-orange-100 text-orange-800',
|
||||
stock: 'bg-blue-100 text-blue-800',
|
||||
}
|
||||
|
||||
function checkWarranty(date) {
|
||||
if (!date) return 'text-gray-400'
|
||||
const today = new Date()
|
||||
const exp = new Date(date)
|
||||
if (exp < today) return 'text-red-600 font-bold'
|
||||
const diff = (exp - today) / (1000 * 60 * 60 * 24)
|
||||
if (diff <= 30) return 'text-orange-600 font-bold'
|
||||
return 'text-gray-600'
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head :title="asset.nom" />
|
||||
<AuthenticatedLayout>
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<Link :href="route('assets.index')" class="text-gray-400 hover:text-gray-600 transition-colors">
|
||||
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
|
||||
</svg>
|
||||
</Link>
|
||||
<div>
|
||||
<h1 class="text-xl font-semibold text-gray-900">{{ asset.nom }}</h1>
|
||||
<p class="text-sm text-gray-500">{{ asset.type }} - {{ asset.marque }} {{ asset.modele }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Action Buttons: Edit -->
|
||||
<Link :href="route('assets.edit', asset.id)"
|
||||
class="rounded-lg bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 transition-colors">
|
||||
Modifier
|
||||
</Link>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="grid gap-6 lg:grid-cols-3">
|
||||
<div class="space-y-6 lg:col-span-2">
|
||||
<!-- Informations de base -->
|
||||
<div class="rounded-xl bg-white p-6 shadow-sm border border-gray-100">
|
||||
<h2 class="mb-5 text-sm font-semibold uppercase tracking-wide text-gray-500">Détails du matériel</h2>
|
||||
<div class="grid gap-4 sm:grid-cols-2">
|
||||
<div>
|
||||
<p class="text-xs text-gray-500">Nom / Hostname</p>
|
||||
<p class="mt-0.5 font-medium text-gray-900">{{ asset.nom }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs text-gray-500">Type de matériel</p>
|
||||
<p class="mt-0.5 font-medium text-gray-900">{{ asset.type }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs text-gray-500">Marque & Modèle</p>
|
||||
<p class="mt-0.5 font-medium text-gray-900">{{ asset.marque || '—' }} {{ asset.modele || '' }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs text-gray-500">Code EAN/UPC</p>
|
||||
<p class="mt-0.5 font-mono text-sm text-gray-900">{{ asset.code_ean || '—' }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs text-gray-500 font-bold">Numéro de série / SN</p>
|
||||
<p class="mt-0.5 font-mono text-sm text-gray-900">{{ asset.numero_serie || '—' }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs text-gray-500 border-t pt-4 mt-2">Statut actuel</p>
|
||||
<span :class="['mt-2 inline-block px-2 py-0.5 rounded-full text-xs font-medium', statutColors[asset.statut]]">
|
||||
{{ statutLabels[asset.statut] }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Notes / Config -->
|
||||
<div v-if="asset.notes" class="rounded-xl bg-white p-6 shadow-sm border border-gray-100">
|
||||
<h2 class="mb-4 text-sm font-semibold uppercase tracking-wide text-gray-500">Notes & Configuration</h2>
|
||||
<div class="whitespace-pre-wrap text-sm text-gray-700">{{ asset.notes }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-6 lg:col-span-1">
|
||||
<!-- Localisation -->
|
||||
<div class="rounded-xl bg-white p-6 shadow-sm border border-gray-100">
|
||||
<h2 class="mb-4 text-sm font-semibold uppercase tracking-wide text-gray-500">Localisation</h2>
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<p class="text-xs text-gray-500">Ville / Commune</p>
|
||||
<p class="mt-0.5 font-medium text-gray-900">{{ asset.commune?.nom || 'Infrastructure Globale (Agglo)' }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs text-gray-500">Emplacement précis</p>
|
||||
<p class="mt-0.5 font-medium text-gray-900">{{ asset.emplacement || '—' }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Cycle de vie & Garantie -->
|
||||
<div class="rounded-xl bg-white p-6 shadow-sm border border-gray-100">
|
||||
<h2 class="mb-4 text-sm font-semibold uppercase tracking-wide text-gray-500">Cycle de vie</h2>
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<p class="text-xs text-gray-500">Date d'achat</p>
|
||||
<p class="mt-0.5 font-medium text-gray-900">{{ formatDate(asset.date_achat) }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs text-gray-500">Fin de garantie (constructeur)</p>
|
||||
<p class="mt-0.5 font-medium" :class="checkWarranty(asset.date_fin_garantie)">
|
||||
{{ formatDate(asset.date_fin_garantie) }}
|
||||
<span v-if="checkWarranty(asset.date_fin_garantie).includes('red')" class="ml-1" title="Expirée">⚠️ Expirée</span>
|
||||
<span v-else-if="checkWarranty(asset.date_fin_garantie).includes('orange')" class="ml-1" title="Proche échéance">⏳ À renouveler</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Commande associée -->
|
||||
<div v-if="asset.commande" class="rounded-xl bg-white p-6 shadow-sm border border-gray-100">
|
||||
<h2 class="mb-4 text-sm font-semibold uppercase tracking-wide text-gray-500">Commande associée</h2>
|
||||
<Link :href="route('commandes.show', asset.commande.id)" class="block rounded-lg border border-gray-100 bg-gray-50 p-4 hover:bg-gray-100 transition-colors">
|
||||
<div class="font-medium text-indigo-600">{{ asset.commande.numero_commande }}</div>
|
||||
<div class="mt-1 text-xs text-gray-600">{{ asset.commande.objet }}</div>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</AuthenticatedLayout>
|
||||
</template>
|
||||
Reference in New Issue
Block a user