Files
seguidorDeLotes/nuxt4/app/app.vue
josedario87 f24f2373f9
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m4s
Agregar botones de prueba de API en frontend
- 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
2025-11-21 19:28:59 -06:00

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>