Se agrega avance de historial de chat y referencias de la ia

This commit is contained in:
2026-02-10 14:33:04 -06:00
parent 777be81d2a
commit ba188329dc

View File

@@ -1,3 +1,4 @@
/* eslint-disable jsx-a11y/no-static-element-interactions */
import { createFileRoute, useRouterState } from '@tanstack/react-router' import { createFileRoute, useRouterState } from '@tanstack/react-router'
import { import {
Sparkles, Sparkles,
@@ -10,6 +11,8 @@ import {
BookOpen, BookOpen,
Check, Check,
X, X,
MessageSquarePlus,
Trash2,
} from 'lucide-react' } from 'lucide-react'
import { useState, useEffect, useRef, useMemo } from 'react' import { useState, useEffect, useRef, useMemo } from 'react'
@@ -84,6 +87,52 @@ function RouteComponent() {
const [pendingSuggestion, setPendingSuggestion] = useState<any>(null) const [pendingSuggestion, setPendingSuggestion] = useState<any>(null)
const scrollRef = useRef<HTMLDivElement>(null) const scrollRef = useRef<HTMLDivElement>(null)
const [activeChatId, setActiveChatId] = useState('1')
const [chatHistory, setChatHistory] = useState([
{ id: '1', title: 'Chat inicial' },
])
const [allMessages, setAllMessages] = useState<{ [key: string]: Array<any> }>(
{
'1': [
{
id: 'm1',
role: 'assistant',
content: '¡Hola! Soy tu asistente de IA en este chat inicial.',
},
],
},
)
const currentMessages = allMessages[activeChatId] || []
const createNewChat = () => {
const newId = Date.now().toString()
const newChat = { id: newId, title: `Nuevo chat ${chatHistory.length + 1}` }
setChatHistory([newChat, ...chatHistory])
setAllMessages({
...allMessages,
[newId]: [
{
id: '1',
role: 'assistant',
content: '¡Nuevo chat creado! ¿En qué puedo ayudarte?',
},
],
})
setActiveChatId(newId)
}
const deleteChat = (e: React.MouseEvent, id: string) => {
e.stopPropagation() // Evita que se seleccione el chat al borrarlo
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)
}
}
// 1. Transformar datos de la API para el menú de selección // 1. Transformar datos de la API para el menú de selección
const availableFields = useMemo(() => { const availableFields = useMemo(() => {
@@ -208,6 +257,49 @@ ${fieldsText}
} }
return ( return (
<div className="flex h-[calc(100vh-160px)] max-h-[calc(100vh-160px)] w-full gap-6 overflow-hidden p-4"> <div className="flex h-[calc(100vh-160px)] max-h-[calc(100vh-160px)] w-full gap-6 overflow-hidden p-4">
{/* --- PANEL IZQUIERDO: HISTORIAL (NUEVO) --- */}
<div className="flex w-64 flex-col border-r pr-4">
<div className="mb-4">
<h2 className="mb-4 px-2 text-xs font-bold tracking-wider text-slate-500 uppercase">
Chats
</h2>
<Button
onClick={createNewChat}
variant="outline"
className="mb-4 w-full justify-start gap-2 border-slate-200 hover:bg-teal-50 hover:text-teal-700"
>
<MessageSquarePlus size={18} /> Nuevo chat
</Button>
</div>
<ScrollArea className="flex-1">
<div className="space-y-1">
{chatHistory.map((chat) => (
// eslint-disable-next-line jsx-a11y/click-events-have-key-events
<div
key={chat.id}
onClick={() => setActiveChatId(chat.id)}
className={`group relative flex w-full cursor-pointer items-center gap-3 rounded-lg px-3 py-3 text-sm transition-colors ${
activeChatId === chat.id
? 'bg-slate-100 font-medium text-slate-900'
: 'text-slate-600 hover:bg-slate-50'
}`}
>
<FileText size={16} className="shrink-0 opacity-40" />
<span className="truncate pr-6">{chat.title}</span>
{/* Botón de borrar que aparece al hacer hover */}
<button
onClick={(e) => deleteChat(e, chat.id)}
className="absolute right-2 p-1 opacity-0 transition-opacity group-hover:opacity-100 hover:text-red-600"
>
<Trash2 size={14} />
</button>
</div>
))}
</div>
</ScrollArea>
</div>
{/* PANEL DE CHAT PRINCIPAL */} {/* PANEL DE CHAT PRINCIPAL */}
<div className="relative flex min-w-0 flex-[3] flex-col overflow-hidden rounded-xl border border-slate-200 bg-slate-50/50 shadow-sm"> <div className="relative flex min-w-0 flex-[3] flex-col overflow-hidden rounded-xl border border-slate-200 bg-slate-50/50 shadow-sm">
{/* NUEVO: Barra superior de campos seleccionados */} {/* NUEVO: Barra superior de campos seleccionados */}
@@ -285,7 +377,6 @@ ${fieldsText}
)} )}
</div> </div>
{/* INPUT FIJO AL FONDO CON SUGERENCIAS : */}
{/* INPUT FIJO AL FONDO CON SUGERENCIAS : */} {/* INPUT FIJO AL FONDO CON SUGERENCIAS : */}
<div className="shrink-0 border-t bg-white p-4"> <div className="shrink-0 border-t bg-white p-4">
<div className="relative mx-auto max-w-4xl"> <div className="relative mx-auto max-w-4xl">