Files
seguidorDeLotes/nuxt4/app/components/lotes/Table.vue
josedario87 039bf47d21
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m4s
masiso
2025-11-21 23:03:31 -06:00

176 lines
4.3 KiB
Vue

<template>
<div class="space-y-4">
<div class="flex justify-between items-center">
<div>
<h2 class="text-2xl font-bold">Lotes</h2>
<p class="text-gray-500">Gestión de lotes de café</p>
</div>
<UButton
icon="i-heroicons-plus"
label="Nuevo Lote"
@click="$emit('create')"
/>
</div>
<div class="flex gap-2">
<USelect
v-model="filtroTipo"
:options="[{ value: '', label: 'Todos los tipos' }, ...TIPOS_LOTE]"
placeholder="Filtrar por tipo"
class="w-64"
/>
<UButton
icon="i-heroicons-arrow-path"
label="Refrescar"
variant="outline"
@click="loadLotes"
/>
</div>
<UCard>
<UTable
v-model="selected"
:rows="lotes"
:columns="columns"
:loading="loading"
:empty-state="{
icon: 'i-heroicons-inbox',
label: 'No hay lotes registrados'
}"
@select="handleSelect"
>
<template #codigo-data="{ row }">
<span class="font-mono font-semibold">{{ row.codigo || '-' }}</span>
</template>
<template #tipo-data="{ row }">
<UBadge :color="getTipoColor(row.tipo)" variant="subtle">
{{ getTipoLabel(row.tipo) }}
</UBadge>
</template>
<template #cantidad_kg-data="{ row }">
<span v-if="row.cantidad_kg" class="font-medium">
{{ row.cantidad_kg.toLocaleString('es-AR') }} kg
</span>
<span v-else class="text-gray-400">-</span>
</template>
<template #fecha_creado-data="{ row }">
{{ formatDate(row.fecha_creado) }}
</template>
<template #actions-data="{ row }">
<div class="flex gap-1">
<UButton
icon="i-heroicons-eye"
size="xs"
variant="ghost"
@click="$emit('view', row)"
/>
<UButton
icon="i-heroicons-pencil"
size="xs"
variant="ghost"
@click="$emit('edit', row)"
/>
<UButton
icon="i-heroicons-chart-bar"
size="xs"
variant="ghost"
color="green"
@click="$emit('trazabilidad', row)"
/>
</div>
</template>
</UTable>
</UCard>
</div>
</template>
<script setup lang="ts">
import type { Lote } from '~/composables/useLotes'
console.log('🟢 LotesTable: Script ejecutado')
const emit = defineEmits<{
create: []
view: [lote: Lote]
edit: [lote: Lote]
trazabilidad: [lote: Lote]
}>()
const { fetchLotes, TIPOS_LOTE } = useLotes()
console.log('🟢 LotesTable: Composable cargado, TIPOS_LOTE:', TIPOS_LOTE?.length)
const lotes = ref<Lote[]>([])
const loading = ref(false)
const selected = ref<Lote[]>([])
const filtroTipo = ref('')
const columns = [
{ key: 'codigo', label: 'Código' },
{ key: 'tipo', label: 'Tipo' },
{ key: 'cantidad_kg', label: 'Cantidad' },
{ key: 'fecha_creado', label: 'Fecha Creación' },
{ key: 'actions', label: 'Acciones' },
]
const loadLotes = async () => {
loading.value = true
try {
lotes.value = await fetchLotes({
tipo: filtroTipo.value || undefined,
})
} finally {
loading.value = false
}
}
const handleSelect = (rows: Lote[]) => {
selected.value = rows
}
const getTipoLabel = (tipo: string) => {
const found = TIPOS_LOTE.find((t) => t.value === tipo)
return found?.label || tipo
}
const getTipoColor = (tipo: string): string => {
const colorMap: Record<string, string> = {
uva: 'purple',
despulpado_primera: 'green',
despulpado_segunda: 'yellow',
despulpado_rechazos: 'red',
oreado: 'orange',
presecado: 'amber',
reposo: 'blue',
secado: 'emerald',
}
return colorMap[tipo] || 'gray'
}
const formatDate = (dateString: string) => {
return new Date(dateString).toLocaleDateString('es-AR', {
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
})
}
// Cargar lotes al montar
// onMounted(() => {
// console.log('🔵 LotesTable montado correctamente')
// loadLotes().catch(error => {
// console.error('❌ Error cargando lotes:', error)
// })
// })
// // Recargar cuando cambia el filtro
// watch(filtroTipo, () => {
// loadLotes()
// })
</script>