From 2ec222694de97e175ab4f598e8bf2985b77343b0 Mon Sep 17 00:00:00 2001 From: "Roberto.silva" Date: Thu, 12 Feb 2026 10:01:27 -0600 Subject: [PATCH] Se agrega editar por campos en ia y archivar chats --- src/routes/planes/$planId/_detalle/iaplan.tsx | 269 +++++++++++++----- 1 file changed, 191 insertions(+), 78 deletions(-) diff --git a/src/routes/planes/$planId/_detalle/iaplan.tsx b/src/routes/planes/$planId/_detalle/iaplan.tsx index f9a98e2..b9f2b0a 100644 --- a/src/routes/planes/$planId/_detalle/iaplan.tsx +++ b/src/routes/planes/$planId/_detalle/iaplan.tsx @@ -1,10 +1,9 @@ +/* eslint-disable jsx-a11y/click-events-have-key-events */ /* eslint-disable jsx-a11y/no-static-element-interactions */ import { createFileRoute, useRouterState } from '@tanstack/react-router' import { - Sparkles, Send, Target, - UserCheck, Lightbulb, FileText, GraduationCap, @@ -12,14 +11,14 @@ import { Check, X, MessageSquarePlus, - Trash2, + Archive, + RotateCcw, } from 'lucide-react' import { useState, useEffect, useRef, useMemo } from 'react' import type { UploadedFile } from '@/components/planes/wizard/PasoDetallesPanel/FileDropZone' import ReferenciasParaIA from '@/components/planes/wizard/PasoDetallesPanel/ReferenciasParaIA' -import { Avatar, AvatarFallback } from '@/components/ui/avatar' import { Button } from '@/components/ui/button' import { Drawer, DrawerContent } from '@/components/ui/drawer' import { ScrollArea } from '@/components/ui/scroll-area' @@ -99,6 +98,8 @@ function RouteComponent() { const [chatHistory, setChatHistory] = useState([ { id: '1', title: 'Chat inicial' }, ]) + const [showArchived, setShowArchived] = useState(false) + const [archivedHistory, setArchivedHistory] = useState>([]) const [allMessages, setAllMessages] = useState<{ [key: string]: Array }>( { '1': [ @@ -110,8 +111,6 @@ function RouteComponent() { ], }, ) - const currentMessages = allMessages[activeChatId] || [] - const createNewChat = () => { const newId = Date.now().toString() const newChat = { id: newId, title: `Nuevo chat ${chatHistory.length + 1}` } @@ -130,15 +129,25 @@ function RouteComponent() { setActiveChatId(newId) } - const deleteChat = (e: React.MouseEvent, id: string) => { - e.stopPropagation() // Evita que se seleccione el chat al borrarlo + const archiveChat = (e: React.MouseEvent, id: string) => { + e.stopPropagation() - const newHistory = chatHistory.filter((chat) => chat.id !== id) - setChatHistory(newHistory) - - // Si borramos el chat activo, pasamos al primero disponible - if (activeChatId === id && newHistory.length > 0) { - setActiveChatId(newHistory[0].id) + const chatToArchive = chatHistory.find((chat) => chat.id === id) + if (chatToArchive) { + setArchivedHistory([chatToArchive, ...archivedHistory]) + const newHistory = chatHistory.filter((chat) => chat.id !== id) + setChatHistory(newHistory) + if (activeChatId === id && newHistory.length > 0) { + setActiveChatId(newHistory[0].id) + } + } + } + const unarchiveChat = (e: React.MouseEvent, id: string) => { + e.stopPropagation() + const chatToRestore = archivedHistory.find((chat) => chat.id === id) + if (chatToRestore) { + setChatHistory([chatToRestore, ...chatHistory]) + setArchivedHistory(archivedHistory.filter((chat) => chat.id !== id)) } } @@ -225,11 +234,11 @@ function RouteComponent() { .join('\n') return ` -${userInput || 'Mejora los siguientes campos:'} + ${userInput || 'Mejora los siguientes campos:'} -Campos a analizar: -${fieldsText} -`.trim() + Campos a analizar: + ${fieldsText} + `.trim() } const handleSend = async (promptOverride?: string) => { @@ -249,32 +258,49 @@ ${fieldsText} setIsLoading(true) setTimeout(() => { - const mockText = - 'Sugerencia generada basada en los campos seleccionados...' + const suggestions = selectedFields.map((field) => ({ + key: field.key, + label: field.label, + newValue: field.value, + })) setMessages((prev) => [ ...prev, { id: Date.now().toString(), role: 'assistant', - content: `He analizado ${selectedFields - .map((f) => f.label) - .join(', ')}. Aquí tienes una propuesta:\n\n${mockText}`, + type: 'improvement-card', + content: + 'He analizado los campos seleccionados. Aquí tienes mis sugerencias de mejora:', + suggestions: suggestions, }, ]) - - setPendingSuggestion({ text: mockText }) setIsLoading(false) }, 1200) } return (
- {/* --- PANEL IZQUIERDO: HISTORIAL (NUEVO) --- */} + {/* --- PANEL IZQUIERDO: HISTORIAL --- */}
-

- Chats -

+
+

+ Chats +

+ {/* Botón de toggle archivados movido aquí arriba */} + +
+ + + {chat.title} + +
+ )) + ) : ( + // LISTA DE CHATS ARCHIVADOS +
+

+ Archivados +

+ {archivedHistory.map((chat) => ( +
+ + {chat.title} + +
+ ))} + {archivedHistory.length === 0 && ( +
+

+ No hay archivados +

+
+ )}
- ))} + )}
@@ -335,32 +393,26 @@ ${fieldsText}
{messages.map((msg) => (
- - - {msg.role === 'assistant' ? ( - - ) : ( - - )} - -
-
- {msg.content} -
+ {msg.content} + + {msg.type === 'improvement-card' && ( + { + console.log(`Aplicando ${val} al campo ${key}`) + // Aquí llamarías a tu función de actualización de datos real + }} + /> + )}
))} @@ -398,7 +450,7 @@ ${fieldsText} {/* INPUT FIJO AL FONDO CON SUGERENCIAS : */}
- {/* MENÚ DE SUGERENCIAS FLOTANTE (Se mantiene igual) */} + {/* MENÚ DE SUGERENCIAS FLOTANTE */} {showSuggestions && (
@@ -425,7 +477,7 @@ ${fieldsText} {/* CONTENEDOR DEL INPUT TRANSFORMADO */}
- {/* 1. Visualización de campos dentro del input (Tags) */} + {/* 1. Visualización de campos dentro del input ) */} {selectedFields.length > 0 && (
{selectedFields.map((field) => ( @@ -472,8 +524,7 @@ ${fieldsText}
- - {/* PANEL LATERAL (PRESETS) - SE MANTIENE COMO LO TENÍAS */} + {/* PANEL LATERAL */}

Acciones rápidas @@ -495,7 +546,6 @@ ${fieldsText} ))}

-
@@ -533,3 +583,66 @@ ${fieldsText}
) } + +const ImprovementCard = ({ + suggestions, + onApply, +}: { + suggestions: Array + onApply: (key: string, value: string) => void +}) => { + // Estado para rastrear qué campos han sido aplicados + const [appliedFields, setAppliedFields] = useState>([]) + + const handleApply = (key: string, value: string) => { + onApply(key, value) + setAppliedFields((prev) => [...prev, key]) + } + + return ( +
+ {suggestions.map((sug) => { + const isApplied = appliedFields.includes(sug.key) + + return ( +
+
+

{sug.label}

+ +
+ +
+ {sug.newValue} +
+
+ ) + })} +
+ ) +}