All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m4s
- Botones simples para probar GET /api/lotes, /api/operaciones y trazabilidad - Resultados se muestran en console.log del navegador - Facilita debugging de la API desde el frontend
264 lines
7.7 KiB
Vue
264 lines
7.7 KiB
Vue
<template>
|
|
<UApp>
|
|
<NuxtRouteAnnouncer />
|
|
<UNotifications />
|
|
|
|
<UContainer class="py-8">
|
|
<div class="space-y-6">
|
|
<!-- Header -->
|
|
<div class="flex justify-between items-center mb-8">
|
|
<div>
|
|
<h1 class="text-3xl font-bold">Seguidor de Lotes</h1>
|
|
<p class="text-gray-600 dark:text-gray-400">
|
|
Sistema de trazabilidad de café
|
|
</p>
|
|
</div>
|
|
<div class="flex items-center gap-3">
|
|
<AuthUserAvatar v-if="isAuthenticated" />
|
|
<AuthLogoutButton v-if="isAuthenticated" />
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Botones de Prueba API -->
|
|
<UCard class="mb-4">
|
|
<div class="flex gap-2 flex-wrap">
|
|
<UButton @click="testGetLotes" color="primary">
|
|
Probar GET /api/lotes
|
|
</UButton>
|
|
<UButton @click="testGetOperaciones" color="primary">
|
|
Probar GET /api/operaciones
|
|
</UButton>
|
|
<UButton @click="testGetTrazabilidad" color="primary">
|
|
Probar Trazabilidad
|
|
</UButton>
|
|
</div>
|
|
<p class="text-sm text-gray-500 mt-2">
|
|
Los resultados se mostrarán en la consola del navegador (F12)
|
|
</p>
|
|
</UCard>
|
|
|
|
<!-- Contenido principal -->
|
|
<div v-if="isAuthenticated">
|
|
<!-- Navegación por Tabs -->
|
|
<UTabs v-model="selectedTab" :items="tabs" class="mb-6">
|
|
<!-- Tab: Lotes -->
|
|
<template #lotes>
|
|
<div class="py-4">
|
|
<LotesLotesTable
|
|
@create="showCreateLoteModal = true"
|
|
@view="handleViewLote"
|
|
@edit="handleEditLote"
|
|
@trazabilidad="handleViewTrazabilidad"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<!-- Tab: Operaciones -->
|
|
<template #operaciones>
|
|
<div class="py-4">
|
|
<OperacionesOperacionesTable
|
|
@create="showCreateOperacionModal = true"
|
|
@view="handleViewOperacion"
|
|
/>
|
|
</div>
|
|
</template>
|
|
</UTabs>
|
|
</div>
|
|
|
|
<!-- Mensaje si no está autenticado -->
|
|
<UCard v-else class="text-center">
|
|
<div class="py-8">
|
|
<UIcon name="i-heroicons-shield-exclamation" class="w-16 h-16 mx-auto mb-4 text-gray-400" />
|
|
<h2 class="text-2xl font-semibold mb-2">No autenticado</h2>
|
|
<p class="text-gray-600 dark:text-gray-400">
|
|
Authentik Proxy Outpost debería redirigirte automáticamente.
|
|
</p>
|
|
</div>
|
|
</UCard>
|
|
</div>
|
|
</UContainer>
|
|
|
|
<!-- Modal: Crear/Editar Lote -->
|
|
<UModal v-model="showLoteFormModal">
|
|
<LotesLoteForm
|
|
:lote="selectedLote"
|
|
@cancel="closeLoteFormModal"
|
|
@success="handleLoteFormSuccess"
|
|
/>
|
|
</UModal>
|
|
|
|
<!-- Modal: Ver Detalle de Lote -->
|
|
<UModal v-model="showLoteDetailModal">
|
|
<LotesLoteCard
|
|
v-if="selectedLote"
|
|
:lote="selectedLote"
|
|
@edit="handleEditLoteFromDetail"
|
|
@trazabilidad="handleViewTrazabilidadFromDetail"
|
|
/>
|
|
</UModal>
|
|
|
|
<!-- Modal: Ver Trazabilidad -->
|
|
<UModal v-model="showTrazabilidadModal" :ui="{ width: 'max-w-4xl' }">
|
|
<LotesTrazabilidadTree
|
|
v-if="trazabilidadLoteId"
|
|
:lote-id="trazabilidadLoteId"
|
|
@close="showTrazabilidadModal = false"
|
|
/>
|
|
</UModal>
|
|
|
|
<!-- Modal: Crear Operación -->
|
|
<UModal v-model="showCreateOperacionModal" :ui="{ width: 'max-w-3xl' }">
|
|
<OperacionesOperacionForm
|
|
@cancel="showCreateOperacionModal = false"
|
|
@success="handleOperacionFormSuccess"
|
|
/>
|
|
</UModal>
|
|
</UApp>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type { Lote, Operacion } from '~/composables/useLotes'
|
|
|
|
const { isAuthenticated } = useAuthentik()
|
|
|
|
// Navegación
|
|
const selectedTab = ref(0)
|
|
const tabs = [
|
|
{ label: 'Lotes', icon: 'i-heroicons-cube', slot: 'lotes' },
|
|
{ label: 'Operaciones', icon: 'i-heroicons-beaker', slot: 'operaciones' },
|
|
]
|
|
|
|
// Estados de modales
|
|
const showLoteFormModal = ref(false)
|
|
const showLoteDetailModal = ref(false)
|
|
const showTrazabilidadModal = ref(false)
|
|
const showCreateLoteModal = ref(false)
|
|
const showCreateOperacionModal = ref(false)
|
|
|
|
// Estados de datos
|
|
const selectedLote = ref<Lote | null>(null)
|
|
const trazabilidadLoteId = ref<string | null>(null)
|
|
|
|
// Handlers para Lotes
|
|
const handleViewLote = (lote: Lote) => {
|
|
selectedLote.value = lote
|
|
showLoteDetailModal.value = true
|
|
}
|
|
|
|
const handleEditLote = (lote: Lote) => {
|
|
selectedLote.value = lote
|
|
showLoteFormModal.value = true
|
|
}
|
|
|
|
const handleEditLoteFromDetail = () => {
|
|
showLoteDetailModal.value = false
|
|
showLoteFormModal.value = true
|
|
}
|
|
|
|
const handleViewTrazabilidad = (lote: Lote) => {
|
|
trazabilidadLoteId.value = lote.id
|
|
showTrazabilidadModal.value = true
|
|
}
|
|
|
|
const handleViewTrazabilidadFromDetail = () => {
|
|
if (selectedLote.value) {
|
|
showLoteDetailModal.value = false
|
|
trazabilidadLoteId.value = selectedLote.value.id
|
|
showTrazabilidadModal.value = true
|
|
}
|
|
}
|
|
|
|
const closeLoteFormModal = () => {
|
|
showLoteFormModal.value = false
|
|
selectedLote.value = null
|
|
}
|
|
|
|
const handleLoteFormSuccess = () => {
|
|
closeLoteFormModal()
|
|
// La tabla se recargará automáticamente
|
|
}
|
|
|
|
// Handlers para Operaciones
|
|
const handleViewOperacion = (operacion: Operacion) => {
|
|
// TODO: Implementar vista de detalle de operación si es necesario
|
|
console.log('Ver operación:', operacion)
|
|
}
|
|
|
|
const handleOperacionFormSuccess = () => {
|
|
showCreateOperacionModal.value = false
|
|
// Las tablas se recargarán automáticamente
|
|
}
|
|
|
|
// Funciones de prueba de API
|
|
const testGetLotes = async () => {
|
|
console.log('=== Probando GET /api/lotes ===')
|
|
try {
|
|
const response = await fetch('/api/lotes')
|
|
const data = await response.json()
|
|
console.log('Status:', response.status)
|
|
console.log('Datos recibidos:', data)
|
|
} catch (error) {
|
|
console.error('Error:', error)
|
|
}
|
|
}
|
|
|
|
const testGetOperaciones = async () => {
|
|
console.log('=== Probando GET /api/operaciones ===')
|
|
try {
|
|
const response = await fetch('/api/operaciones')
|
|
const data = await response.json()
|
|
console.log('Status:', response.status)
|
|
console.log('Datos recibidos:', data)
|
|
} catch (error) {
|
|
console.error('Error:', error)
|
|
}
|
|
}
|
|
|
|
const testGetTrazabilidad = async () => {
|
|
console.log('=== Probando Trazabilidad ===')
|
|
try {
|
|
// Primero obtener lotes para tener un ID
|
|
const lotesResponse = await fetch('/api/lotes')
|
|
const lotesData = await lotesResponse.json()
|
|
console.log('Lotes disponibles:', lotesData)
|
|
|
|
if (lotesData.data && lotesData.data.length > 0) {
|
|
const primerLoteId = lotesData.data[0].id
|
|
console.log('Obteniendo trazabilidad para lote:', primerLoteId)
|
|
|
|
const trazResponse = await fetch(`/api/lotes/${primerLoteId}/trazabilidad`)
|
|
const trazData = await trazResponse.json()
|
|
console.log('Status:', trazResponse.status)
|
|
console.log('Trazabilidad:', trazData)
|
|
}
|
|
} catch (error) {
|
|
console.error('Error:', error)
|
|
}
|
|
}
|
|
|
|
// Watch para crear lote
|
|
watch(showCreateLoteModal, (value) => {
|
|
if (value) {
|
|
selectedLote.value = null
|
|
showLoteFormModal.value = true
|
|
showCreateLoteModal.value = false
|
|
}
|
|
})
|
|
|
|
// Configurar meta tags para PWA
|
|
useHead({
|
|
title: 'Seguidor de Lotes - Trazabilidad de Café',
|
|
link: [
|
|
{ rel: 'manifest', href: '/manifest.webmanifest' },
|
|
{ rel: 'icon', type: 'image/svg+xml', href: '/icon.svg' },
|
|
{ rel: 'apple-touch-icon', href: '/apple-touch-icon.png' }
|
|
],
|
|
meta: [
|
|
{ name: 'theme-color', content: '#00DC82' },
|
|
{ name: 'mobile-web-app-capable', content: 'yes' },
|
|
{ name: 'apple-mobile-web-app-capable', content: 'yes' },
|
|
{ name: 'apple-mobile-web-app-status-bar-style', content: 'default' }
|
|
]
|
|
})
|
|
</script>
|