fix(core): resolucion de multiples bugs criticos de backend y visuales

This commit is contained in:
2026-04-01 11:20:48 -05:00
parent b11d57465e
commit 1953be2da0
7 changed files with 22 additions and 11 deletions

View File

@ -3,7 +3,7 @@ import { supabase } from '../backend/lib/supabase.js'
export default async function handler(req, res) { export default async function handler(req, res) {
if (req.method !== 'GET') return res.status(405).json({ error: 'Método no permitido' }) if (req.method !== 'GET') return res.status(405).json({ error: 'Método no permitido' })
const { niche, cliente_id, plataforma, page = 1, limit = 20 } = req.query const { niche, cliente_id, plataforma, page = 1, limit = 20, todos } = req.query
const offset = (Number(page) - 1) * Number(limit) const offset = (Number(page) - 1) * Number(limit)
let query = supabase let query = supabase
@ -12,13 +12,14 @@ export default async function handler(req, res) {
id, niche, sub_niche, plataforma, url_origen, id, niche, sub_niche, plataforma, url_origen,
gancho_texto, gancho_tipo, estructura_narrativa, trigger_emocional, gancho_texto, gancho_tipo, estructura_narrativa, trigger_emocional,
tono, score_engagement, score_virabilidad, score_cialdini, tono, score_engagement, score_virabilidad, score_cialdini,
fecha_analisis, procesado_ok, vistas, likes, compartidos, fecha_analisis, procesado_ok, error_detalle, vistas, likes, compartidos,
tema_principal, resumen_patron tema_principal, resumen_patron
`, { count: 'exact' }) `, { count: 'exact' })
.eq('procesado_ok', true)
.order('fecha_analisis', { ascending: false }) .order('fecha_analisis', { ascending: false })
.range(offset, offset + Number(limit) - 1) .range(offset, offset + Number(limit) - 1)
if (todos !== '1' && todos !== 'true') query = query.eq('procesado_ok', true)
if (niche) query = query.eq('niche', niche) if (niche) query = query.eq('niche', niche)
if (cliente_id) query = query.eq('cliente_id', cliente_id) if (cliente_id) query = query.eq('cliente_id', cliente_id)
if (plataforma) query = query.eq('plataforma', plataforma) if (plataforma) query = query.eq('plataforma', plataforma)

View File

@ -69,6 +69,7 @@ export default async function handler(req, res) {
duracion_objetivo, tono, objetivo, duracion_objetivo, tono, objetivo,
estructura_usada: estructura, estructura_usada: estructura,
instrucciones_extra: instrucciones_extra || null, instrucciones_extra: instrucciones_extra || null,
referencias_ids: referencias_ids.length > 0 ? referencias_ids : (patrones.map ? patrones.map(p => p.id).filter(Boolean) : null),
titulo_sugerido: guion.titulo_sugerido, titulo_sugerido: guion.titulo_sugerido,
gancho: guion.gancho, gancho: guion.gancho,
desarrollo: guion.desarrollo, desarrollo: guion.desarrollo,

View File

@ -98,5 +98,9 @@ Genera el guion con EXACTAMENTE este JSON:
.replace(/\n?```$/, '') .replace(/\n?```$/, '')
.trim() .trim()
return JSON.parse(jsonLimpio) try {
return JSON.parse(jsonLimpio)
} catch (err) {
throw new Error(`Error parseando JSON de GPT: ${err.message}. Contenido crudo: ${contenido}`)
}
} }

View File

@ -33,7 +33,7 @@ app.get('/api/guiones', async (req, res) => {
.from('guiones') .from('guiones')
.select(` .select(`
id, niche, sub_niche, plataforma, url_origen, id, niche, sub_niche, plataforma, url_origen,
gancho_texto, estructura_narrativa, trigger_emocional, gancho_texto, gancho_tipo, estructura_narrativa, trigger_emocional,
tono, score_engagement, score_virabilidad, score_cialdini, tono, score_engagement, score_virabilidad, score_cialdini,
fecha_analisis, procesado_ok, error_detalle, vistas, likes, compartidos, fecha_analisis, procesado_ok, error_detalle, vistas, likes, compartidos,
tema_principal, resumen_patron tema_principal, resumen_patron
@ -41,7 +41,7 @@ app.get('/api/guiones', async (req, res) => {
.order('fecha_analisis', { ascending: false }) .order('fecha_analisis', { ascending: false })
.range(offset, offset + limit - 1) .range(offset, offset + limit - 1)
if (!todos) query = query.eq('procesado_ok', true) if (todos !== '1' && todos !== 'true') query = query.eq('procesado_ok', true)
if (niche) query = query.eq('niche', niche) if (niche) query = query.eq('niche', niche)
if (cliente_id) query = query.eq('cliente_id', cliente_id) if (cliente_id) query = query.eq('cliente_id', cliente_id)
if (plataforma) query = query.eq('plataforma', plataforma) if (plataforma) query = query.eq('plataforma', plataforma)

View File

@ -211,7 +211,7 @@
<div class="w-full bg-surface-subtle h-1.5 rounded-full overflow-hidden"> <div class="w-full bg-surface-subtle h-1.5 rounded-full overflow-hidden">
<div <div
class="bg-accent h-full rounded-full transition-all duration-500" class="bg-accent h-full rounded-full transition-all duration-500"
:style="{ width: ((currentStepIdx / 4) * 100) + '%' }" :style="{ width: ((currentStepIdx / 3) * 100) + '%' }"
></div> ></div>
</div> </div>
<p class="text-[11px] text-ink-3 text-center">Tiempo estimado: ~15 segundos · GPT-4o + Whisper</p> <p class="text-[11px] text-ink-3 text-center">Tiempo estimado: ~15 segundos · GPT-4o + Whisper</p>

View File

@ -89,7 +89,7 @@
<span class="material-symbols-outlined text-accent text-[16px]">analytics</span> <span class="material-symbols-outlined text-accent text-[16px]">analytics</span>
Puntaje de Viralidad Puntaje de Viralidad
</h3> </h3>
<div class="flex justify-center mb-5"> <div class="flex justify-center mb-5 relative">
<svg class="w-40 h-40 transform -rotate-90" viewBox="0 0 100 100"> <svg class="w-40 h-40 transform -rotate-90" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="42" fill="none" stroke="#e5e3de" stroke-width="7"/> <circle cx="50" cy="50" r="42" fill="none" stroke="#e5e3de" stroke-width="7"/>
<circle <circle

View File

@ -195,8 +195,8 @@ const filtrosEstado = [
{ valor: 'fallidos', label: 'Fallidos' }, { valor: 'fallidos', label: 'Fallidos' },
] ]
const totalOk = computed(() => guiones.value.filter(g => g.procesado_ok).length) const totalOk = ref(0)
const totalFallidos = computed(() => guiones.value.filter(g => !g.procesado_ok).length) const totalFallidos = ref(0)
async function cargarDatos() { async function cargarDatos() {
cargando.value = true cargando.value = true
@ -204,11 +204,16 @@ async function cargarDatos() {
const params = { page: filtros.value.page, limit: filtros.value.limit } const params = { page: filtros.value.page, limit: filtros.value.limit }
if (filtros.value.niche) params.niche = filtros.value.niche if (filtros.value.niche) params.niche = filtros.value.niche
const [dg, dn] = await Promise.all([ const [dg, dn, okReq, allReq] = await Promise.all([
api.guiones.listarTodos(params), api.guiones.listarTodos(params),
api.nichos(), api.nichos(),
api.guiones.listar({ limit: 1, ...(params.niche ? { niche: params.niche } : {}) }),
api.guiones.listarTodos({ limit: 1, ...(params.niche ? { niche: params.niche } : {}) }),
]) ])
totalOk.value = okReq.total || 0
totalFallidos.value = (allReq.total || 0) - (okReq.total || 0)
let lista = dg.guiones let lista = dg.guiones
if (filtroActivo.value === 'exitosos') lista = lista.filter(g => g.procesado_ok) if (filtroActivo.value === 'exitosos') lista = lista.filter(g => g.procesado_ok)
if (filtroActivo.value === 'fallidos') lista = lista.filter(g => !g.procesado_ok) if (filtroActivo.value === 'fallidos') lista = lista.filter(g => !g.procesado_ok)