import { createFileRoute, Link, useParams, useRouterState, } from '@tanstack/react-router' import { ArrowLeft, GraduationCap, Pencil, Sparkles } from 'lucide-react' import { useCallback, useState, useEffect } from 'react' import { BibliographyItem } from './BibliographyItem' import { ContenidoTematico } from './ContenidoTematico' import { DocumentoSEPTab } from './DocumentoSEPTab' import { HistorialTab } from './HistorialTab' import { IAMateriaTab } from './IAMateriaTab' import type { CampoEstructura, IAMessage, IASugerencia } from '@/types/materia' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { Separator } from '@/components/ui/separator' import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs' import { Textarea } from '@/components/ui/textarea' import { useSubject } from '@/data/hooks/useSubjects' import { mockMateria, mockEstructura, mockDocumentoSep, } from '@/data/mockMateriaData' export interface BibliografiaEntry { id: string tipo: 'BASICA' | 'COMPLEMENTARIA' cita: string fuenteBibliotecaId?: string fuenteBiblioteca?: any } export interface BibliografiaTabProps { bibliografia: Array onSave: (bibliografia: Array) => void isSaving: boolean } export interface AsignaturaDatos { [key: string]: string } export interface AsignaturaResponse { datos: AsignaturaDatos } function EditableHeaderField({ value, onSave, className, }: { value: string | number onSave: (val: string) => void className?: string }) { const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { e.preventDefault() ;(e.currentTarget as HTMLElement).blur() // Quita el foco } } const handleBlur = (e: React.FocusEvent) => { const newValue = e.currentTarget.textContent || '' if (newValue !== value.toString()) { onSave(newValue) } } return ( {value} ) } export const Route = createFileRoute( '/planes/$planId/asignaturas/$asignaturaId', )({ component: MateriaDetailPage, }) export default function MateriaDetailPage() { const routerState = useRouterState() const state = routerState.location.state as any const { asignaturaId } = useParams({ from: '/planes/$planId/asignaturas/$asignaturaId', }) const { data: asignaturasApi, isLoading: loadingAsig } = useSubject(asignaturaId) // 1. Aseg煤rate de tener estos estados en tu componente principal const [messages, setMessages] = useState>([]) const [datosGenerales, setDatosGenerales] = useState({}) const [campos, setCampos] = useState>([]) // Dentro de MateriaDetailPage const [headerData, setHeaderData] = useState({ codigo: '', nombre: '', creditos: 0, ciclo: 0, }) // Sincronizar cuando llegue la API useEffect(() => { if (asignaturasApi) { setHeaderData({ codigo: asignaturasApi?.codigo ?? '', nombre: asignaturasApi?.nombre ?? '', creditos: asignaturasApi?.creditos ?? '', ciclo: asignaturasApi?.numero_ciclo ?? 0, }) } }, [asignaturasApi]) const handleUpdateHeader = (key: string, value: string | number) => { const newData = { ...headerData, [key]: value } setHeaderData(newData) console.log('馃捑 Guardando en estado y base de datos:', key, value) } /* ---------- sincronizar API ---------- */ useEffect(() => { if (asignaturasApi?.datos) { setDatosGenerales(asignaturasApi.datos) } }, [asignaturasApi]) // 2. Funciones de manejo para la IA const handleSendMessage = (text: string, campoId?: string) => { const newMessage: IAMessage = { id: Date.now().toString(), role: 'user', content: text, timestamp: new Date(), campoAfectado: campoId, } setMessages([...messages, newMessage]) // Aqu铆 llamar铆as a tu API de OpenAI/Claude // toast.info("Enviando consulta a la IA..."); } const handleAcceptSuggestion = (sugerencia: IASugerencia) => { // L贸gica para actualizar el valor del campo en tu estado de datosGenerales // toast.success(`Sugerencia aplicada a ${sugerencia.campoNombre}`); } // Dentro de tu componente principal (donde est谩n los Tabs) const [bibliografia, setBibliografia] = useState>([ { id: '1', tipo: 'BASICA', cita: 'Russell, S., & Norvig, P. (2020). Artificial Intelligence: A Modern Approach. Pearson.', }, ]) const [isSaving, setIsSaving] = useState(false) const handleSaveBibliografia = (data: Array) => { setIsSaving(true) // Aqu铆 ir铆a tu llamada a la API setBibliografia(data) // Simulamos un guardado setTimeout(() => { setIsSaving(false) // toast.success("Cambios guardados"); }, 1000) } const [isRegenerating, setIsRegenerating] = useState(false) const handleRegenerateDocument = useCallback(() => { setIsRegenerating(true) setTimeout(() => { setIsRegenerating(false) }, 2000) }, []) return (
{/* ================= HEADER ACTUALIZADO ================= */}
Volver al plan
{/* C脫DIGO EDITABLE */} handleUpdateHeader('codigo', val)} /> {/* NOMBRE EDITABLE */}

handleUpdateHeader('nombre', val)} />

{asignaturasApi?.planes_estudio?.datos?.nombre} {asignaturasApi?.planes_estudio?.carreras?.facultades?.nombre}

Pertenece al plan:{' '} {asignaturasApi?.planes_estudio?.nombre}

{/* CR脡DITOS EDITABLES */} handleUpdateHeader('creditos', parseInt(val) || 0) } /> cr茅ditos {/* SEMESTRE EDITABLE */} handleUpdateHeader('ciclo', parseInt(val) || 0) } /> 掳 ciclo {asignaturasApi?.tipo}
{/* ================= TABS ================= */}
Datos generales Contenido tem谩tico Bibliograf铆a IA de la materia Documento SEP Historial {/* ================= TAB: DATOS GENERALES ================= */} console.log( 'Rechazada', ) /* toast.error("Sugerencia rechazada")*/ } />
) } /* ================= TAB CONTENT ================= */ interface DatosGeneralesProps { data: AsignaturaDatos isLoading: boolean } function DatosGenerales({ data, isLoading }: DatosGeneralesProps) { const formatTitle = (key: string): string => key.replace(/_/g, ' ').replace(/\b\w/g, (l: string) => l.toUpperCase()) return (
{/* Encabezado de la Secci贸n */}

Datos Generales

Informaci贸n oficial estructurada bajo los lineamientos de la SEP.

{/* Grid de Informaci贸n */}
{/* Columna Principal (M谩s ancha) */}
{isLoading &&

Cargando informaci贸n...

} {!isLoading && Object.entries(data).map(([key, value]) => ( { console.log('Llevar a IA:', contenido) // Aqu铆 tu l贸gica: setPesta帽aActiva('mejorar-con-ia'); }} /> ))}
{/* Columna Lateral (Informaci贸n Secundaria) */}
{/* Tarjeta de Requisitos */} {/* Tarjeta de Evaluaci贸n */}
) } interface InfoCardProps { title: string initialContent: any type?: 'text' | 'requirements' | 'evaluation' onEnhanceAI?: (content: any) => void // Nueva prop para la acci贸n de IA } function InfoCard({ title, initialContent, type = 'text', onEnhanceAI, }: InfoCardProps) { const [isEditing, setIsEditing] = useState(false) const [data, setData] = useState(initialContent) const [tempText, setTempText] = useState( type === 'text' ? initialContent : JSON.stringify(initialContent, null, 2), ) const handleSave = () => { setData(tempText) setIsEditing(false) } return ( {title} {!isEditing && (
{/* NUEVO: Bot贸n de Mejorar con IA */} {/* Bot贸n de Editar original */}
)}
{isEditing ? (