import { createFileRoute, useRouterState } from '@tanstack/react-router' import { Sparkles, Send, Target, UserCheck, Lightbulb, FileText, GraduationCap, BookOpen, Check, X, } from 'lucide-react' import { useState, useEffect, useRef, useMemo } from 'react' import { Avatar, AvatarFallback } from '@/components/ui/avatar' import { Button } from '@/components/ui/button' import { ScrollArea } from '@/components/ui/scroll-area' import { Textarea } from '@/components/ui/textarea' import { usePlan } from '@/data/hooks/usePlans' const PRESETS = [ { id: 'objetivo', label: 'Mejorar objetivo general', icon: Target, prompt: 'Mejora la redacción del objetivo general...', }, { id: 'perfil-egreso', label: 'Redactar perfil de egreso', icon: GraduationCap, prompt: 'Genera un perfil de egreso detallado...', }, { id: 'competencias', label: 'Sugerir competencias', icon: BookOpen, prompt: 'Genera una lista de competencias...', }, { id: 'pertinencia', label: 'Justificar pertinencia', icon: FileText, prompt: 'Redacta una justificación de pertinencia...', }, ] // --- Tipado y Helpers --- interface SelectedField { key: string label: string value: string } const formatLabel = (key: string) => { const result = key.replace(/_/g, ' ') return result.charAt(0).toUpperCase() + result.slice(1) } export const Route = createFileRoute('/planes/$planId/_detalle/iaplan')({ component: RouteComponent, }) function RouteComponent() { const { planId } = Route.useParams() // Usamos el ID dinámico del plan o el hardcoded según tu necesidad const { data } = usePlan('0e0aea4d-b8b4-4e75-8279-6224c3ac769f') const routerState = useRouterState() // ESTADOS PRINCIPALES const [messages, setMessages] = useState>([ { id: '1', role: 'assistant', content: '¡Hola! Soy tu asistente de IA. ¿Qué campos deseas mejorar? Puedes escribir ":" para seleccionar uno.', }, ]) const [input, setInput] = useState('') const [selectedFields, setSelectedFields] = useState>([]) const [showSuggestions, setShowSuggestions] = useState(false) const [isLoading, setIsLoading] = useState(false) const [pendingSuggestion, setPendingSuggestion] = useState(null) const scrollRef = useRef(null) // 1. Transformar datos de la API para el menú de selección const availableFields = useMemo(() => { if (!data?.datos) return [] return Object.entries(data.datos).map(([key, value]) => ({ key, label: formatLabel(key), value: String(value || ''), })) }, [data]) // 2. Manejar el estado inicial si viene de "Datos Generales" useEffect(() => { const state = routerState.location.state as any if (state?.prefill && availableFields.length > 0) { // Intentamos encontrar qué campo es por su valor o si mandaste el fieldKey const field = availableFields.find( (f) => f.value === state.prefill || f.key === state.fieldKey, ) if (field && !selectedFields.find((sf) => sf.key === field.key)) { setSelectedFields([field]) } setInput(`Mejora este campo: `) } }, [availableFields]) // 3. Lógica para el disparador ":" const handleInputChange = (e: React.ChangeEvent) => { const val = e.target.value setInput(val) if (val.endsWith(':')) { setShowSuggestions(true) } else { setShowSuggestions(false) } } const toggleField = (field: SelectedField) => { setSelectedFields((prev) => prev.find((f) => f.key === field.key) ? prev.filter((f) => f.key !== field.key) : [...prev, field], ) if (input.endsWith(':')) setInput(input.slice(0, -1)) setShowSuggestions(false) } const handleSend = async (promptOverride?: string) => { const textToSend = promptOverride || input if (!textToSend.trim() && selectedFields.length === 0) return const userMsg = { id: Date.now().toString(), role: 'user', content: textToSend, } setMessages((prev) => [...prev, userMsg]) setInput('') setIsLoading(true) // Aquí simularías la llamada a la API enviando 'selectedFields' como contexto setTimeout(() => { const mockText = 'Sugerencia generada basada en los campos seleccionados...' setMessages((prev) => [ ...prev, { id: Date.now().toString(), role: 'assistant', content: `He analizado ${selectedFields.length > 0 ? selectedFields.map((f) => f.label).join(', ') : 'tu solicitud'}. Aquí tienes una propuesta:\n\n${mockText}`, }, ]) setPendingSuggestion({ text: mockText }) setIsLoading(false) }, 1200) } return (
{/* PANEL DE CHAT PRINCIPAL */}
{/* NUEVO: Barra superior de campos seleccionados */}
Campos a mejorar: {selectedFields.map((field) => (
{field.label}
))} {selectedFields.length === 0 && ( Escribe ":" para añadir campos )}
{/* CONTENIDO DEL CHAT */}
{messages.map((msg) => (
{msg.role === 'assistant' ? ( ) : ( )}
{msg.content}
))} {isLoading && (
)}
{/* Botones flotantes de aplicación */} {pendingSuggestion && !isLoading && (
)}
{/* INPUT FIJO AL FONDO CON SUGERENCIAS : */} {/* INPUT FIJO AL FONDO CON SUGERENCIAS : */}
{/* MENÚ DE SUGERENCIAS FLOTANTE (Se mantiene igual) */} {showSuggestions && (
Seleccionar campo para IA
{availableFields.map((field) => ( ))}
)} {/* CONTENEDOR DEL INPUT TRANSFORMADO */}
{/* 1. Visualización de campos dentro del input (Tags) */} {selectedFields.length > 0 && (
{selectedFields.map((field) => (
Campo: {field.label}
))}
)} {/* 2. Área de escritura */}