From a08b2abf87f0865d995a80eedac766ab3bd0972b Mon Sep 17 00:00:00 2001 From: "Roberto.silva" Date: Mon, 23 Mar 2026 13:02:31 -0600 Subject: [PATCH] Que aparezcan los campos a mitad de texto fix #213 --- .../asignaturas/detalle/IAAsignaturaTab.tsx | 78 +++++++++++++++---- 1 file changed, 63 insertions(+), 15 deletions(-) diff --git a/src/components/asignaturas/detalle/IAAsignaturaTab.tsx b/src/components/asignaturas/detalle/IAAsignaturaTab.tsx index 3deb579..613cef5 100644 --- a/src/components/asignaturas/detalle/IAAsignaturaTab.tsx +++ b/src/components/asignaturas/detalle/IAAsignaturaTab.tsx @@ -229,12 +229,38 @@ export function IAAsignaturaTab() { } }, [activeChats, loadingConv]) - const filteredFields = useMemo(() => { - if (!showSuggestions) return availableFields + const handleInputChange = (e: React.ChangeEvent) => { + const value = e.target.value + const selectionStart = e.target.selectionStart // Posición del cursor + setInput(value) + + // Buscamos si el carácter anterior al cursor es ':' + const lastChar = value.slice(selectionStart - 1, selectionStart) + + if (lastChar === ':') { + setShowSuggestions(true) + } else if (!value.includes(':')) { + // Si borran todos los dos puntos, cerramos + setShowSuggestions(false) + } + } + + const filteredFields = useMemo(() => { + if (!showSuggestions || !input) return availableFields + + // 1. Encontrar el ":" más cercano a la IZQUIERDA del cursor + // Usamos una posición de referencia (si no tienes ref, usaremos el final del string, + // pero para mayor precisión lo ideal es usar e.target.selectionStart en el onChange) - // Extraemos lo que hay después del último ':' para filtrar const lastColonIndex = input.lastIndexOf(':') - const query = input.slice(lastColonIndex + 1).toLowerCase() + if (lastColonIndex === -1) return availableFields + + // 2. Extraer solo el fragmento de "búsqueda" + // Cortamos desde el ":" hasta el final, y luego tomamos solo la primera palabra + const textAfterColon = input.slice(lastColonIndex + 1) + const query = textAfterColon.split(/\s/)[0].toLowerCase() // Se detiene al encontrar un espacio + + if (!query) return availableFields return availableFields.filter( (f) => @@ -254,24 +280,28 @@ export function IAAsignaturaTab() { // 3. Función para insertar el campo y limpiar el prompt const handleSelectField = (field: SelectedField) => { - // 1. Agregamos al array de objetos (para tu lógica de API) if (!selectedFields.find((f) => f.key === field.key)) { setSelectedFields((prev) => [...prev, field]) } - // 2. Lógica de autocompletado en el texto const lastColonIndex = input.lastIndexOf(':') if (lastColonIndex !== -1) { - // Tomamos lo que había antes del ":" + el Nombre del Campo + un espacio - const nuevoTexto = input.slice(0, lastColonIndex) + `${field.label} ` + const parteAntesDelColon = input.slice(0, lastColonIndex) + + // Buscamos si hay texto después de la palabra que estamos escribiendo + const textoDespuesDelColon = input.slice(lastColonIndex + 1) + const espacioIndex = textoDespuesDelColon.indexOf(' ') + + // Si hay un espacio, guardamos lo que sigue. Si no, es el final del texto. + const parteRestante = + espacioIndex !== -1 ? textoDespuesDelColon.slice(espacioIndex) : '' + + // Reconstruimos: [Antes] + [Label] + [Lo que ya estaba después] + const nuevoTexto = `${parteAntesDelColon}${field.label}${parteRestante}` setInput(nuevoTexto) } - // 3. Cerramos el buscador y devolvemos el foco al textarea setShowSuggestions(false) - - // Opcional: Si tienes una ref del textarea, puedes hacer: - // textareaRef.current?.focus() } const handleSaveName = (id: string) => { @@ -740,10 +770,28 @@ export function IAAsignaturaTab() {