From 82d047e1c220c73a5388f0d805e7c9bde4e6d5f1 Mon Sep 17 00:00:00 2001 From: "Roberto.silva" Date: Fri, 13 Mar 2026 12:17:01 -0600 Subject: [PATCH] Consistencia y mensajes del chat de la IA fix #179 fix #178 --- .../asignaturas/detalle/IAAsignaturaTab.tsx | 136 ++++++++----- src/routes/planes/$planId/_detalle/iaplan.tsx | 191 ++++++++++-------- 2 files changed, 191 insertions(+), 136 deletions(-) diff --git a/src/components/asignaturas/detalle/IAAsignaturaTab.tsx b/src/components/asignaturas/detalle/IAAsignaturaTab.tsx index 45e5bd5..34946ac 100644 --- a/src/components/asignaturas/detalle/IAAsignaturaTab.tsx +++ b/src/components/asignaturas/detalle/IAAsignaturaTab.tsx @@ -28,6 +28,12 @@ import { Button } from '@/components/ui/button' import { Drawer, DrawerContent } from '@/components/ui/drawer' import { ScrollArea } from '@/components/ui/scroll-area' import { Textarea } from '@/components/ui/textarea' +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from '@/components/ui/tooltip' import { useAISubjectChat, useConversationBySubject, @@ -371,11 +377,8 @@ export function IAAsignaturaTab({ + {/* PANEL IZQUIERDO - Cambios en ScrollArea y contenedor */} -
- {/* CORRECCIÓN: Mapear ambos casos */} +
+ {' '} + {/* Eliminado space-y-1 para mejor control con gap */} {(showArchived ? archivedChats : activeChats).map((chat: any) => (
{ + setEditingId(chat.id) + setTempName(chat.nombre || chat.titulo || 'Conversacion') + }} > - - {editingId === chat.id ? ( -
+
setTempName(e.target.value)} - onBlur={() => handleSaveName(chat.id)} // Guardar al hacer clic fuera + onBlur={() => handleSaveName(chat.id)} onKeyDown={(e) => { if (e.key === 'Enter') handleSaveName(chat.id) if (e.key === 'Escape') setEditingId(null) @@ -420,54 +428,78 @@ export function IAAsignaturaTab({
) : ( <> + {/* CLAVE 2: 'truncate' y 'min-w-0' en el span para que ceda ante los botones */} setActiveChatId(chat.id)} - className="flex-1 cursor-pointer truncate" + className="block max-w-[140px] min-w-0 flex-1 cursor-pointer truncate pr-1" + title={chat.nombre || chat.titulo} > - {/* CORRECCIÓN: Usar 'nombre' si así se llama en tu DB */} {chat.nombre || chat.titulo || 'Conversación'} -
- + {/* CLAVE 3: 'shrink-0' asegura que los botones NUNCA desaparezcan */} +
+ + + + + + + Editar nombre + + - {/* Botón para Archivar/Desarchivar dinámico */} - + + + + + + {chat.estado === 'ACTIVA' + ? 'Archivar' + : 'Desarchivar'} + + +
)} diff --git a/src/routes/planes/$planId/_detalle/iaplan.tsx b/src/routes/planes/$planId/_detalle/iaplan.tsx index a2e0ee8..e42398b 100644 --- a/src/routes/planes/$planId/_detalle/iaplan.tsx +++ b/src/routes/planes/$planId/_detalle/iaplan.tsx @@ -13,8 +13,8 @@ import { X, MessageSquarePlus, Archive, - RotateCcw, Loader2, + Sparkles, } from 'lucide-react' import { useState, useEffect, useRef, useMemo } from 'react' @@ -22,10 +22,17 @@ import type { UploadedFile } from '@/components/planes/wizard/PasoDetallesPanel/ import { ImprovementCard } from '@/components/planes/detalle/Ia/ImprovementCard' 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' import { Textarea } from '@/components/ui/textarea' +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from '@/components/ui/tooltip' import { useAIPlanChat, useConversationByPlan, @@ -507,76 +514,99 @@ function RouteComponent() {
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 ${ + className={`group relative flex w-full items-center justify-between overflow-hidden 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' }`} > - + {/* LADO IZQUIERDO: Icono + Texto con Tooltip */} +
+ - + + + {/* Este contenedor es el que obliga al span a truncarse */} +
+ { + e.stopPropagation() + setEditingChatId(chat.id) + }} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault() + e.currentTarget.blur() + } + if (e.key === 'Escape') { + setEditingChatId(null) + e.currentTarget.textContent = + chat.nombre || '' + } + }} + onBlur={(e) => { + if (editingChatId === chat.id) { + const newTitle = + e.currentTarget.textContent?.trim() || '' + if (newTitle && newTitle !== chat.nombre) { + updateTitleMutation({ + id: chat.id, + nombre: newTitle, + }) + } + setEditingChatId(null) + } + }} + > + {chat.nombre || + `Chat ${chat.creado_en.split('T')[0]}`} + +
+
+ + {/* Tooltip: Solo aparece si no estás editando y el texto es largo */} + {editingChatId !== chat.id && ( + + {chat.nombre || 'Conversación'} + + )} +
+ +
+ + {/* LADO DERECHO: Acciones con shrink-0 para que no se muevan */} +
{ - e.stopPropagation() - setEditingChatId(chat.id) - }} - onKeyDown={(e) => { - if (e.key === 'Enter') { - e.preventDefault() - const newTitle = e.currentTarget.textContent || '' - updateTitleMutation( - { id: chat.id, nombre: newTitle }, - { - onSuccess: () => setEditingChatId(null), - }, - ) - } - if (e.key === 'Escape') { - setEditingChatId(null) - - e.currentTarget.textContent = chat.nombre || '' - } - }} - onBlur={(e) => { - if (editingChatId === chat.id) { - const newTitle = e.currentTarget.textContent || '' - if (newTitle !== chat.nombre) { - updateTitleMutation({ id: chat.id, nombre: newTitle }) - } - setEditingChatId(null) - } - }} - onClick={(e) => { - if (editingChatId === chat.id) e.stopPropagation() - }} > - {chat.nombre || `Chat ${chat.creado_en.split('T')[0]}`} - - - {/* ACCIONES */} -
@@ -584,24 +614,26 @@ function RouteComponent() {
)) ) : ( - /* ... Resto del código de archivados (sin cambios) ... */ -
+ /* Sección de archivados */ +

Archivados

{archivedChats.map((chat) => (
- - - {chat.nombre || - `Archivado ${chat.creado_en.split('T')[0]}`} - +
+ + + {chat.nombre || + `Archivado ${chat.creado_en.split('T')[0]}`} + +
@@ -721,33 +753,24 @@ function RouteComponent() { ) })} - {(isSending || isSyncing) && - optimisticMessage && - !chatMessages.some( - (m) => m.content === optimisticMessage, - ) && ( -
-
- {optimisticMessage} -
-
- )} - {(isSending || isSyncing) && ( -
-
-
+
+ + + + + +
+
- - - + + +
- - {isSyncing - ? 'Actualizando historial...' - : 'Esperando respuesta...'} -
+ + La IA está analizando tu solicitud... +
)}