Persistencia en aplicar mejora #124
@@ -1,46 +1,92 @@
|
|||||||
import { Check } from 'lucide-react'
|
import { Check, Loader2 } from 'lucide-react'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
|
||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
|
import { useUpdatePlanFields } from '@/data' // Tu hook existente
|
||||||
|
|
||||||
export const ImprovementCard = ({
|
export const ImprovementCard = ({
|
||||||
suggestions,
|
suggestions,
|
||||||
onApply,
|
onApply,
|
||||||
|
planId, // Necesitamos el ID
|
||||||
|
currentDatos, // Necesitamos los datos actuales para no sobrescribir todo el JSON
|
||||||
}: {
|
}: {
|
||||||
suggestions: Array<any>
|
suggestions: Array<any>
|
||||||
onApply: (key: string, value: string) => void
|
onApply?: (key: string, value: string) => void
|
||||||
|
planId: string
|
||||||
|
currentDatos: any
|
||||||
}) => {
|
}) => {
|
||||||
// Estado para rastrear qué campos han sido aplicados
|
|
||||||
const [appliedFields, setAppliedFields] = useState<Array<string>>([])
|
const [appliedFields, setAppliedFields] = useState<Array<string>>([])
|
||||||
|
const updatePlan = useUpdatePlanFields()
|
||||||
|
|
||||||
const handleApply = (key: string, value: string) => {
|
const handleApply = (key: string, newValue: string) => {
|
||||||
onApply(key, value)
|
if (!currentDatos) return
|
||||||
setAppliedFields((prev) => [...prev, key])
|
|
||||||
|
// 1. Lógica para preparar el valor (idéntica a tu handleSave original)
|
||||||
|
const currentValue = currentDatos[key]
|
||||||
|
let finalValue: any
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof currentValue === 'object' &&
|
||||||
|
currentValue !== null &&
|
||||||
|
'description' in currentValue
|
||||||
|
) {
|
||||||
|
finalValue = { ...currentValue, description: newValue }
|
||||||
|
} else {
|
||||||
|
finalValue = newValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Construir el nuevo objeto 'datos' manteniendo lo que ya existía
|
||||||
|
const datosActualizados = {
|
||||||
|
...currentDatos,
|
||||||
|
[key]: finalValue,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Ejecutar la mutación directamente aquí
|
||||||
|
updatePlan.mutate(
|
||||||
|
{
|
||||||
|
planId: planId as any,
|
||||||
|
patch: { datos: datosActualizados },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
setAppliedFields((prev) => [...prev, key])
|
||||||
|
if (onApply) onApply(key, newValue)
|
||||||
|
console.log(`Campo ${key} guardado exitosamente`)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-2 flex w-full flex-col gap-4">
|
<div className="mt-2 flex w-full flex-col gap-4">
|
||||||
{suggestions.map((sug) => {
|
{suggestions.map((sug) => {
|
||||||
const isApplied = appliedFields.includes(sug.key)
|
const isApplied = appliedFields.includes(sug.key)
|
||||||
|
const isUpdating =
|
||||||
|
updatePlan.isPending &&
|
||||||
|
updatePlan.variables.patch.datos?.[sug.key] !== undefined
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={sug.key}
|
key={sug.key}
|
||||||
className="rounded-2xl border border-slate-100 bg-white p-5 shadow-sm"
|
className={`rounded-2xl border bg-white p-5 shadow-sm transition-all ${
|
||||||
|
isApplied ? 'border-teal-200 bg-teal-50/20' : 'border-slate-100'
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
<div className="mb-4 flex items-center justify-between">
|
<div className="mb-4 flex items-center justify-between">
|
||||||
<h3 className="text-sm font-bold text-slate-900">{sug.label}</h3>
|
<h3 className="text-sm font-bold text-slate-900">{sug.label}</h3>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => handleApply(sug.key, sug.newValue)}
|
onClick={() => handleApply(sug.key, sug.newValue)}
|
||||||
disabled={isApplied}
|
disabled={isApplied || !!isUpdating}
|
||||||
className={`h-8 rounded-full px-4 text-xs transition-all ${
|
className={`h-8 rounded-full px-4 text-xs transition-all ${
|
||||||
isApplied
|
isApplied
|
||||||
? 'cursor-not-allowed bg-slate-100 text-slate-400'
|
? 'cursor-not-allowed bg-slate-100 text-slate-400'
|
||||||
: 'bg-[#00a189] text-white hover:bg-[#008f7a]'
|
: 'bg-[#00a189] text-white hover:bg-[#008f7a]'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{isApplied ? (
|
{isUpdating ? (
|
||||||
|
<Loader2 size={12} className="animate-spin" />
|
||||||
|
) : isApplied ? (
|
||||||
<span className="flex items-center gap-1">
|
<span className="flex items-center gap-1">
|
||||||
<Check size={12} /> Aplicado
|
<Check size={12} /> Aplicado
|
||||||
</span>
|
</span>
|
||||||
@@ -53,7 +99,7 @@ export const ImprovementCard = ({
|
|||||||
<div
|
<div
|
||||||
className={`rounded-xl border p-3 text-sm transition-colors duration-300 ${
|
className={`rounded-xl border p-3 text-sm transition-colors duration-300 ${
|
||||||
isApplied
|
isApplied
|
||||||
? 'border-[#ccfbf1] bg-[#f0fdfa] text-slate-700'
|
? 'border-teal-100 bg-teal-50/50 text-slate-700'
|
||||||
: 'border-slate-200 bg-slate-50 text-slate-500'
|
: 'border-slate-200 bg-slate-50 text-slate-500'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -130,12 +130,19 @@ export async function get_chat_history(conversacionId: string) {
|
|||||||
return data // Retorna Array de mensajes
|
return data // Retorna Array de mensajes
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function archive_conversation(conversacionId: string) {
|
export async function update_conversation_status(
|
||||||
|
conversacionId: string,
|
||||||
|
nuevoEstado: 'ARCHIVADA' | 'ACTIVA',
|
||||||
|
) {
|
||||||
const supabase = supabaseBrowser()
|
const supabase = supabaseBrowser()
|
||||||
const { data, error } = await supabase.functions.invoke(
|
|
||||||
`create-chat-conversation/conversations/${conversacionId}/archive`,
|
const { data, error } = await supabase
|
||||||
{ method: 'DELETE' },
|
.from('conversaciones_plan') // Asegúrate que el nombre de la tabla sea exacto
|
||||||
)
|
.update({ estado: nuevoEstado })
|
||||||
|
.eq('id', conversacionId)
|
||||||
|
.select()
|
||||||
|
.single()
|
||||||
|
|
||||||
if (error) throw error
|
if (error) throw error
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
@@ -168,8 +175,9 @@ export async function getConversationByPlan(planId: string) {
|
|||||||
.from('conversaciones_plan')
|
.from('conversaciones_plan')
|
||||||
.select('*')
|
.select('*')
|
||||||
.eq('plan_estudio_id', planId)
|
.eq('plan_estudio_id', planId)
|
||||||
.order('creado_en', { ascending: true })
|
.order('creado_en', { ascending: false })
|
||||||
if (error) throw error
|
if (error) throw error
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
return data ?? []
|
return data ?? []
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,13 +5,16 @@ import {
|
|||||||
ai_plan_improve,
|
ai_plan_improve,
|
||||||
ai_subject_chat,
|
ai_subject_chat,
|
||||||
ai_subject_improve,
|
ai_subject_improve,
|
||||||
archive_conversation,
|
|
||||||
create_conversation,
|
create_conversation,
|
||||||
get_chat_history,
|
get_chat_history,
|
||||||
getConversationByPlan,
|
getConversationByPlan,
|
||||||
library_search,
|
library_search,
|
||||||
|
update_conversation_status,
|
||||||
} from '../api/ai.api'
|
} from '../api/ai.api'
|
||||||
|
|
||||||
|
// eslint-disable-next-line node/prefer-node-protocol
|
||||||
|
import type { UUID } from 'crypto'
|
||||||
|
|
||||||
export function useAIPlanImprove() {
|
export function useAIPlanImprove() {
|
||||||
return useMutation({ mutationFn: ai_plan_improve })
|
return useMutation({ mutationFn: ai_plan_improve })
|
||||||
}
|
}
|
||||||
@@ -62,13 +65,20 @@ export function useChatHistory(conversacionId?: string) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useArchiveConversation() {
|
export function useUpdateConversationStatus() {
|
||||||
const queryClient = useQueryClient()
|
const qc = useQueryClient()
|
||||||
|
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: (id: string) => archive_conversation(id),
|
mutationFn: ({
|
||||||
|
id,
|
||||||
|
estado,
|
||||||
|
}: {
|
||||||
|
id: string
|
||||||
|
estado: 'ARCHIVADA' | 'ACTIVA'
|
||||||
|
}) => update_conversation_status(id, estado),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
// Opcional: limpiar datos viejos de la caché
|
// Esto refresca las listas automáticamente
|
||||||
queryClient.invalidateQueries({ queryKey: ['chat-history'] })
|
qc.invalidateQueries({ queryKey: ['conversation-by-plan'] })
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ import { ScrollArea } from '@/components/ui/scroll-area'
|
|||||||
import { Textarea } from '@/components/ui/textarea'
|
import { Textarea } from '@/components/ui/textarea'
|
||||||
import {
|
import {
|
||||||
useAIPlanChat,
|
useAIPlanChat,
|
||||||
useArchiveConversation,
|
|
||||||
useChatHistory,
|
useChatHistory,
|
||||||
useConversationByPlan,
|
useConversationByPlan,
|
||||||
|
useUpdateConversationStatus,
|
||||||
} from '@/data'
|
} from '@/data'
|
||||||
import { usePlan } from '@/data/hooks/usePlans'
|
import { usePlan } from '@/data/hooks/usePlans'
|
||||||
|
|
||||||
@@ -73,13 +73,12 @@ export const Route = createFileRoute('/planes/$planId/_detalle/iaplan')({
|
|||||||
|
|
||||||
function RouteComponent() {
|
function RouteComponent() {
|
||||||
const { planId } = Route.useParams()
|
const { planId } = Route.useParams()
|
||||||
|
|
||||||
const { data } = usePlan(planId)
|
const { data } = usePlan(planId)
|
||||||
const routerState = useRouterState()
|
const routerState = useRouterState()
|
||||||
const [openIA, setOpenIA] = useState(false)
|
const [openIA, setOpenIA] = useState(false)
|
||||||
const [conversacionId, setConversacionId] = useState<string | null>(null)
|
const [conversacionId, setConversacionId] = useState<string | null>(null)
|
||||||
const { mutateAsync: sendChat, isLoading } = useAIPlanChat()
|
const { mutateAsync: sendChat, isLoading } = useAIPlanChat()
|
||||||
const { mutate: archiveChatMutation } = useArchiveConversation()
|
const { mutate: updateStatusMutation } = useUpdateConversationStatus()
|
||||||
|
|
||||||
const [activeChatId, setActiveChatId] = useState<string | undefined>(
|
const [activeChatId, setActiveChatId] = useState<string | undefined>(
|
||||||
undefined,
|
undefined,
|
||||||
@@ -102,27 +101,12 @@ function RouteComponent() {
|
|||||||
const [input, setInput] = useState('')
|
const [input, setInput] = useState('')
|
||||||
const [selectedFields, setSelectedFields] = useState<Array<SelectedField>>([])
|
const [selectedFields, setSelectedFields] = useState<Array<SelectedField>>([])
|
||||||
const [showSuggestions, setShowSuggestions] = useState(false)
|
const [showSuggestions, setShowSuggestions] = useState(false)
|
||||||
// const [isLoading, setIsLoading] = useState(false)
|
|
||||||
const [pendingSuggestion, setPendingSuggestion] = useState<any>(null)
|
const [pendingSuggestion, setPendingSuggestion] = useState<any>(null)
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const scrollRef = useRef<HTMLDivElement>(null)
|
const scrollRef = useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
const chatHistory = useMemo(() => {
|
|
||||||
return lastConversation || []
|
|
||||||
}, [lastConversation])
|
|
||||||
const [showArchived, setShowArchived] = useState(false)
|
const [showArchived, setShowArchived] = useState(false)
|
||||||
const [archivedHistory, setArchivedHistory] = useState<Array<any>>([])
|
|
||||||
const [allMessages, setAllMessages] = useState<{ [key: string]: Array<any> }>(
|
|
||||||
{
|
|
||||||
'1': [
|
|
||||||
{
|
|
||||||
id: 'm1',
|
|
||||||
role: 'assistant',
|
|
||||||
content: '¡Hola! Soy tu asistente de IA en este chat inicial.',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
)
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// 1. Si no hay ID o está cargando el historial, no hacemos nada
|
// 1. Si no hay ID o está cargando el historial, no hacemos nada
|
||||||
if (!activeChatId || isLoadingHistory) return
|
if (!activeChatId || isLoadingHistory) return
|
||||||
@@ -205,30 +189,39 @@ function RouteComponent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const archiveChat = (e: React.MouseEvent, id: string) => {
|
const archiveChat = (e: React.MouseEvent, id: string) => {
|
||||||
e.stopPropagation() // Evita que se seleccione el chat al intentar archivarlo
|
e.stopPropagation()
|
||||||
|
|
||||||
archiveChatMutation(id, {
|
updateStatusMutation(
|
||||||
onSuccess: () => {
|
{ id, estado: 'ARCHIVADA' },
|
||||||
// 1. Invalidamos las listas para que desaparezca de activos y aparezca en archivados
|
{
|
||||||
queryClient.invalidateQueries({
|
onSuccess: () => {
|
||||||
queryKey: ['conversation-by-plan', planId],
|
queryClient.invalidateQueries({
|
||||||
})
|
queryKey: ['conversation-by-plan', planId],
|
||||||
|
})
|
||||||
|
|
||||||
// 2. Si el chat archivado era el que tenías abierto, limpia la pantalla
|
if (activeChatId === id) {
|
||||||
if (activeChatId === id) {
|
setActiveChatId(undefined)
|
||||||
setActiveChatId(undefined)
|
setMessages([])
|
||||||
setMessages([])
|
}
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
const unarchiveChat = (e: React.MouseEvent, id: string) => {
|
const unarchiveChat = (e: React.MouseEvent, id: string) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
const chatToRestore = archivedHistory.find((chat) => chat.id === id)
|
|
||||||
if (chatToRestore) {
|
updateStatusMutation(
|
||||||
setChatHistory([chatToRestore, ...chatHistory])
|
{ id, estado: 'ACTIVA' },
|
||||||
setArchivedHistory(archivedHistory.filter((chat) => chat.id !== id))
|
{
|
||||||
}
|
onSuccess: () => {
|
||||||
|
// Al invalidar la query, React Query traerá la lista fresca
|
||||||
|
// y el chat se moverá solo de "archivados" a "activos"
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: ['conversation-by-plan', planId],
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Transformar datos de la API para el menú de selección
|
// 1. Transformar datos de la API para el menú de selección
|
||||||
@@ -296,22 +289,20 @@ function RouteComponent() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (isAdding) {
|
setInput((prev) => {
|
||||||
setInput((prev) => {
|
// 1. Eliminamos TODOS los ":" que existan en el texto actual
|
||||||
// 1. Eliminamos TODOS los ":" que existan en el texto actual
|
// 2. Quitamos espacios en blanco extra al final
|
||||||
// 2. Quitamos espacios en blanco extra al final
|
const cleanPrev = prev.replace(/:/g, '').trim()
|
||||||
const cleanPrev = prev.replace(/:/g, '').trim()
|
|
||||||
|
|
||||||
// 3. Si el input resultante está vacío, solo ponemos la frase
|
// 3. Si el input resultante está vacío, solo ponemos la frase
|
||||||
if (cleanPrev === '') {
|
if (cleanPrev === '') {
|
||||||
return `${field.label} `
|
return `${field.label} `
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Si ya había algo, lo concatenamos con un espacio
|
// 4. Si ya había algo, lo concatenamos con un espacio
|
||||||
// Usamos un espacio simple al final para que el usuario pueda seguir escribiendo
|
// Usamos un espacio simple al final para que el usuario pueda seguir escribiendo
|
||||||
return `${cleanPrev} ${field.label} `
|
return `${cleanPrev} ${field.label} `
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
setShowSuggestions(false)
|
setShowSuggestions(false)
|
||||||
}
|
}
|
||||||
@@ -368,7 +359,6 @@ function RouteComponent() {
|
|||||||
|
|
||||||
if (response.raw) {
|
if (response.raw) {
|
||||||
try {
|
try {
|
||||||
// Parseamos el string JSON que viene en 'raw'
|
|
||||||
const rawData = JSON.parse(response.raw)
|
const rawData = JSON.parse(response.raw)
|
||||||
|
|
||||||
// Extraemos el mensaje conversacional
|
// Extraemos el mensaje conversacional
|
||||||
@@ -419,6 +409,16 @@ function RouteComponent() {
|
|||||||
)
|
)
|
||||||
}, [selectedArchivoIds, selectedRepositorioIds, uploadedFiles])
|
}, [selectedArchivoIds, selectedRepositorioIds, uploadedFiles])
|
||||||
|
|
||||||
|
const { activeChats, archivedChats } = useMemo(() => {
|
||||||
|
const allChats = lastConversation || []
|
||||||
|
return {
|
||||||
|
activeChats: allChats.filter((chat: any) => chat.estado === 'ACTIVA'),
|
||||||
|
archivedChats: allChats.filter(
|
||||||
|
(chat: any) => chat.estado === 'ARCHIVADA',
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}, [lastConversation])
|
||||||
|
|
||||||
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 --- */}
|
{/* --- PANEL IZQUIERDO: HISTORIAL --- */}
|
||||||
@@ -453,10 +453,9 @@ function RouteComponent() {
|
|||||||
|
|
||||||
<ScrollArea className="flex-1">
|
<ScrollArea className="flex-1">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
{/* Lógica de renderizado condicional */}
|
|
||||||
{!showArchived ? (
|
{!showArchived ? (
|
||||||
// LISTA DE CHATS ACTIVOS
|
// --- LISTA DE CHATS ACTIVOS ---
|
||||||
chatHistory.map((chat) => (
|
activeChats.map((chat) => (
|
||||||
<div
|
<div
|
||||||
key={chat.id}
|
key={chat.id}
|
||||||
onClick={() => setActiveChatId(chat.id)}
|
onClick={() => setActiveChatId(chat.id)}
|
||||||
@@ -467,7 +466,10 @@ function RouteComponent() {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<FileText size={16} className="shrink-0 opacity-40" />
|
<FileText size={16} className="shrink-0 opacity-40" />
|
||||||
<span className="truncate pr-8">{chat.title}</span>
|
{/* Usamos el primer mensaje o un título por defecto */}
|
||||||
|
<span className="truncate pr-8">
|
||||||
|
{chat.title || `Chat ${chat.creado_en.split('T')[0]}`}
|
||||||
|
</span>
|
||||||
<button
|
<button
|
||||||
onClick={(e) => archiveChat(e, chat.id)}
|
onClick={(e) => archiveChat(e, chat.id)}
|
||||||
className="absolute right-2 p-1 opacity-0 transition-opacity group-hover:opacity-100 hover:text-amber-600"
|
className="absolute right-2 p-1 opacity-0 transition-opacity group-hover:opacity-100 hover:text-amber-600"
|
||||||
@@ -478,18 +480,21 @@ function RouteComponent() {
|
|||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
// LISTA DE CHATS ARCHIVADOS
|
// --- LISTA DE CHATS ARCHIVADOS ---
|
||||||
<div className="animate-in fade-in slide-in-from-left-2">
|
<div className="animate-in fade-in slide-in-from-left-2">
|
||||||
<p className="mb-2 px-2 text-[10px] font-bold text-slate-400 uppercase">
|
<p className="mb-2 px-2 text-[10px] font-bold text-slate-400 uppercase">
|
||||||
Archivados
|
Archivados
|
||||||
</p>
|
</p>
|
||||||
{archivedHistory.map((chat) => (
|
{archivedChats.map((chat) => (
|
||||||
<div
|
<div
|
||||||
key={chat.id}
|
key={chat.id}
|
||||||
className="group relative mb-1 flex w-full items-center gap-3 rounded-lg bg-slate-50/50 px-3 py-2 text-sm text-slate-400"
|
className="group relative mb-1 flex w-full items-center gap-3 rounded-lg bg-slate-50/50 px-3 py-2 text-sm text-slate-400"
|
||||||
>
|
>
|
||||||
<Archive size={14} className="shrink-0 opacity-30" />
|
<Archive size={14} className="shrink-0 opacity-30" />
|
||||||
<span className="truncate pr-8">{chat.title}</span>
|
<span className="truncate pr-8">
|
||||||
|
{chat.title ||
|
||||||
|
`Archivado ${chat.creado_en.split('T')[0]}`}
|
||||||
|
</span>
|
||||||
<button
|
<button
|
||||||
onClick={(e) => unarchiveChat(e, chat.id)}
|
onClick={(e) => unarchiveChat(e, chat.id)}
|
||||||
className="absolute right-2 p-1 opacity-0 group-hover:opacity-100 hover:text-teal-600"
|
className="absolute right-2 p-1 opacity-0 group-hover:opacity-100 hover:text-teal-600"
|
||||||
@@ -499,7 +504,7 @@ function RouteComponent() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
{archivedHistory.length === 0 && (
|
{archivedChats.length === 0 && (
|
||||||
<div className="px-2 py-4 text-center">
|
<div className="px-2 py-4 text-center">
|
||||||
<p className="text-xs text-slate-400 italic">
|
<p className="text-xs text-slate-400 italic">
|
||||||
No hay archivados
|
No hay archivados
|
||||||
@@ -558,12 +563,13 @@ function RouteComponent() {
|
|||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<ImprovementCard
|
<ImprovementCard
|
||||||
suggestions={msg.suggestions}
|
suggestions={msg.suggestions}
|
||||||
|
planId={planId} // Del useParams()
|
||||||
|
currentDatos={data?.datos} // De tu query usePlan(planId)
|
||||||
onApply={(key, val) => {
|
onApply={(key, val) => {
|
||||||
console.log(`Aplicando ${val} al campo ${key}`)
|
// Esto es opcional, si quieres hacer algo más en la UI del chat
|
||||||
setSelectedFields((prev) =>
|
console.log(
|
||||||
prev.filter((f) => f.key !== key),
|
'Evento onApply disparado desde el chat',
|
||||||
)
|
)
|
||||||
// Aquí llamarías a tu mutación de actualizar el plan
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ function DatosGeneralesPage() {
|
|||||||
if (!data?.datos) return
|
if (!data?.datos) return
|
||||||
|
|
||||||
const datosActualizados = prepararDatosActualizados(data, campo, valor)
|
const datosActualizados = prepararDatosActualizados(data, campo, valor)
|
||||||
|
console.log(datosActualizados)
|
||||||
|
|
||||||
updatePlan.mutate({
|
updatePlan.mutate({
|
||||||
planId,
|
planId,
|
||||||
|
|||||||
Reference in New Issue
Block a user