182 lines
7.5 KiB
Vue

<script setup lang="ts">
import { computed, ref } from 'vue';
import Card from 'primevue/card';
import Button from 'primevue/button';
import InputText from 'primevue/inputtext';
import type { ContentCondition, StructureContentAsset } from '../../types/fixedAssetStructure';
interface Props {
modelValue: StructureContentAsset[];
readOnly?: boolean;
}
const props = defineProps<Props>();
const emit = defineEmits<{
(e: 'update:modelValue', value: StructureContentAsset[]): void;
}>();
const serialQuery = ref('');
const availableAssets: StructureContentAsset[] = [
{
id: 'ACT-5001',
name: 'Monitor Curvo 34"',
category: 'Perifericos',
serial: 'MON-CV-4491',
condition: 'EXCELENTE',
value: 9850
},
{
id: 'ACT-5002',
name: 'Docking Station USB-C',
category: 'Perifericos',
serial: 'DCK-USB-112',
condition: 'BUENO',
value: 3150
},
{
id: 'ACT-5003',
name: 'Gabinete de Red 24U',
category: 'Infraestructura TI',
serial: 'NET-CAB-240',
condition: 'REGULAR',
value: 6250
}
];
const conditionClasses: Record<ContentCondition, string> = {
EXCELENTE: 'bg-emerald-100 text-emerald-700',
BUENO: 'bg-amber-100 text-amber-700',
REGULAR: 'bg-orange-100 text-orange-700'
};
const totalValue = computed(() =>
props.modelValue.reduce((sum, item) => sum + item.value, 0)
);
const formatCurrency = (value: number) =>
`$${value.toLocaleString('es-MX', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
const addAsset = () => {
const query = serialQuery.value.trim().toLowerCase();
if (!query) return;
const candidate = availableAssets.find((asset) =>
asset.serial.toLowerCase().includes(query) || asset.id.toLowerCase().includes(query)
);
if (!candidate) return;
const exists = props.modelValue.some((item) => item.id === candidate.id);
if (exists) return;
emit('update:modelValue', [...props.modelValue, candidate]);
serialQuery.value = '';
};
const removeAsset = (assetId: string) => {
emit('update:modelValue', props.modelValue.filter((item) => item.id !== assetId));
};
</script>
<template>
<Card class="shadow-sm">
<template #title>
<div class="flex flex-wrap items-center justify-between gap-2 text-xl">
<div class="flex items-center gap-2">
<i class="pi pi-list-check text-primary"></i>
<span>Inventario de Activos Contenidos</span>
</div>
<span class="rounded-full bg-surface-100 px-3 py-1 text-xs font-semibold text-surface-600 dark:bg-surface-800 dark:text-surface-200">
{{ modelValue.length }} ELEMENTOS
</span>
</div>
</template>
<template #content>
<div class="space-y-4">
<div class="flex flex-col gap-2 md:flex-row">
<InputText
v-model="serialQuery"
class="w-full"
:disabled="readOnly"
placeholder="Escriba o escanee numero de serie para anadir..."
@keyup.enter="addAsset"
/>
<Button
label="Agregar"
icon="pi pi-plus"
class="min-w-40"
:disabled="readOnly"
@click="addAsset"
/>
</div>
<p class="text-xs text-surface-500 dark:text-surface-400">
Tip: puede ingresar serie o ID del activo para anexarlo rapidamente.
</p>
<div class="overflow-x-auto rounded-xl border border-surface-200 dark:border-surface-700">
<table class="min-w-full border-collapse">
<thead>
<tr class="bg-surface-50 text-left text-xs font-semibold uppercase tracking-wide text-surface-500 dark:bg-surface-800 dark:text-surface-300">
<th class="px-4 py-3">Imagen</th>
<th class="px-4 py-3">Activo</th>
<th class="px-4 py-3">Serie</th>
<th class="px-4 py-3">Condicion</th>
<th class="px-4 py-3">Valor</th>
<th class="px-4 py-3 text-right">Accion</th>
</tr>
</thead>
<tbody>
<tr
v-for="asset in modelValue"
:key="asset.id"
class="border-t border-surface-200 text-sm dark:border-surface-700"
>
<td class="px-4 py-3">
<div class="flex h-10 w-10 items-center justify-center rounded-lg bg-surface-100 dark:bg-surface-800">
<i class="pi pi-image text-surface-400"></i>
</div>
</td>
<td class="px-4 py-3">
<p class="font-semibold text-surface-900 dark:text-surface-0">{{ asset.name }}</p>
<p class="text-xs text-surface-500 dark:text-surface-400">{{ asset.category }}</p>
</td>
<td class="px-4 py-3 font-mono text-xs text-surface-600 dark:text-surface-300">{{ asset.serial }}</td>
<td class="px-4 py-3">
<span class="inline-flex rounded-full px-2 py-1 text-xs font-semibold" :class="conditionClasses[asset.condition]">
{{ asset.condition }}
</span>
</td>
<td class="px-4 py-3 font-semibold text-surface-900 dark:text-surface-0">
{{ formatCurrency(asset.value) }}
</td>
<td class="px-4 py-3 text-right">
<Button
icon="pi pi-trash"
text
rounded
severity="danger"
size="small"
:disabled="readOnly"
@click="removeAsset(asset.id)"
/>
</td>
</tr>
<tr v-if="modelValue.length === 0">
<td colspan="6" class="px-4 py-8 text-center text-sm text-surface-500 dark:text-surface-400">
No hay activos vinculados a la estructura.
</td>
</tr>
</tbody>
</table>
</div>
<div class="text-right">
<span class="text-sm text-surface-500 dark:text-surface-400">Valor acumulado de contenidos: </span>
<strong class="text-lg text-surface-900 dark:text-surface-0">{{ formatCurrency(totalValue) }}</strong>
</div>
</div>
</template>
</Card>
</template>