Se convirtió la lista de unidades en un sortable controlado usando @dnd-kit/react; al arrastrar desde el GripVertical se reordenan las unidades en la UI y persiste el orden en la base de datos.
Se colocó el botón "Nueva unidad" como un overlay que aparece debajo de cada unidad al hacer hover (posición bottom) y su clic inserta una unidad entre las existentes o al final si se pulsa después de la última, sin desplazar el layout.
Se hizo que, al cargar el componente por primera vez, la primera unidad quede desplegada automáticamente; una vez que el usuario realiza cualquier modificación y se guarda, se empieza a respetar el conjunto de unidades que el usuario tenga expandidas (la bandera de inicialización se activa durante la persistencia).
Se arregló un bug en el que al reordenar la lista de unidades sucedía una recarga de la lista.
Por qué ocurría el parpadeo y cómo fue arreglado:
- Causa: tras el reorder optimista la UI quedaba actualizada, pero cuando la lista fresca llegaba del servidor un useEffect reasignaba IDs por posición (índice), provocando que React creyera que los elementos eran nuevos, se destruyeran y se volvieran a montar — de ahí el "parpadeo" y la pérdida del estado de los acordiones.
- Solución (Escudo Optimista): se añadieron dos defensas.
1) Escudo de aborto temprano: si el payload actual (UI optimista) y el payload entrante del servidor son idénticos (JSON), se aborta el procesamiento del useEffect para evitar re-render innecesario.
2) Reciclaje por contenido: cuando los datos difieren, las IDs locales se reciclan buscando coincidencias por contenido (título) en lugar de por posición, de modo que cada unidad conserva su ID real aunque cambie de lugar; así React mueve las tarjetas en vez de destruirlas.
Con esto, el reorder es estable, el overlay de inserción funciona sin alterar el flow visual y el estado de expansiones se preserva tras ediciones del usuario.
- Se unificó el stepper en cinco pasos y se configuró para omitir el paso "Biblioteca" cuando el método sea MANUAL.
- Se añadió el paso "Biblioteca" con un accordion múltiple para comparar cada sugerencia con alternativas de la biblioteca; se eliminaron los estados de "Buscando" y su badge.
- Se incorporaron tres conjuntos hardcodeados de coincidencias (0, 2 y 5) que se asignan al azar si la sugerencia no trae datos de biblioteca; si no hay coincidencias la sugerencia se marca automáticamente como mantenida.
- Se implementó BookSelectionAccordion para elegir conservar la sugerencia o sustituirla por una coincidencia; se preservó el estilo visual de las opciones.
- Se añadieron validaciones y comportamientos de navegación: bloqueo de avance si quedan accordions por revisar, apertura y scroll al primer accordion sin resolver, y salto del paso "Biblioteca" en modo MANUAL.
- Se creó el modal de “Agregar Bibliografía” como ruta-modal y se enlazó desde el botón correspondiente con estilo consistente.
- Se implementó la búsqueda de sugerencias en línea mediante Edge Function y se conservó únicamente lo seleccionado al regenerar sugerencias.
- Se replicó el tooltip de “seleccionadas” con control total: se mostró solo en la primera generación y se permitió cerrarlo únicamente con el tache.
- Se integró la generación de citas con citeproc-js y se cargaron los recursos CSL/locale desde archivos locales en public/, usando BASE_URL.
- Se decodificaron entidades HTML en las citas generadas (p. ej., & → &).
- Se habilitó la regeneración forzada de citas por formato y se conservaron las citas (incluidas ediciones) al alternar formatos.
- Se mejoró la UI: se usó textarea autoajustable para citas y se estiró el select de tipo a ancho completo en sm+; se validó cantidad 1–40 o vacío (con deshabilitado del botón).
- Se tipó fuertemente la inserción a bibliografia_asignatura y se tiparon source/tipo en las referencias conforme a los tipos de Supabase.
- En los datos generales se renderizan como texto plano los criterios de evaluación.
- Si le picas a editar los Criterios de evaluación te dirige a Sistema de evaluación y lo pone en modo de edición.
- La infocard de SIstema de evaluación se edita adecuadamente y persiste en la BDD
- Mueve el botón "+ Nueva unidad" al final de la lista y lo centra.
- Al crear una unidad: hace scrollIntoView, la unidad queda expandida, el título entra en modo edición y recibe focus.
- Al crear un subtema: nombre y horas quedan editables y el input del nombre recibe focus.
- Click en título de unidad o en un subtema inicia la edición y pone focus en el campo correspondiente.
- Elimina el botón "Listo": los cambios se guardan al pulsar Enter o perder el foco (onBlur).
- Presionar Esc cancela la edición y restaura el valor anterior.
- Evita el bug donde pulsar Enter tras crear una unidad añadía unidades extra (se desenfoca el botón y se dirige el foco al input correspondiente).
- Persistencia inmediata: las modificaciones se guardan vía useUpdateSubjectContenido en los puntos de commit.
- Conserva el estado de unidades expandidas tras las actualizaciones para evitar colapsos inesperados.
- Elimina botón "Guardar": persistencia automática al pulsar "Listo", al confirmar eliminación y al terminar de editar nombre de unidad.
- Añade mapper (mapContenidoTematicoFromDb) y serializador (serializeUnidadesToApi) para normalizar contenido_tematico <-> Array<ContenidoApi>.
- Conecta persistencia a useUpdateSubjectContenido: hace update directo de asignaturas.contenido_tematico en la BDD.
- Manejo de caché: setQueryData con merge y invalidación de keys centralizadas (qk.planAsignaturas, qk.planHistorial, qk.asignaturaHistorial) para evitar caché desactualizada o pérdida de relaciones.
- UX/estabilidad: identificadores consistentes, expansión inicial, y persistencia inmediata en puntos clave (añadir, editar, eliminar).
- Persistencia de cambios de "Datos generales" usando updateAsignatura.mutate.
- Corregido el manejo de caché: uso de qk centralizada y merge en setQueryData para no perder relaciones.
- Corregidos los tipos devueltos por subjects_get.
- Evitado estado inválido tras guardar (merge local + actualización de cache).
Verificar: editar → guardar → volver al plan → reingresar muestra datos actualizados sin parpadeos.
fix#29:
- Se agregaron spinners en la creación con IA de un plan o una asignatura
- Se añadió la creación manual de asignaturas
- Al generar asignaturas a partir de sugerencias, el badge de estado de la asignatura dice 'Generando' y muestra una animación tipo respiro para indicar que está siendo generada. Adicionalmente, se actualiza automáticamente la UI una vez que acabó de ser generada
- Added Radix UI Accordion component for better UI organization in PasoDetallesPanel.
- Implemented structure selection and subject suggestions management in the wizard.
- Updated subject API to initialize new subjects with null values for structure and cycle.
- Modified state management in useNuevaAsignaturaWizard to include estructuraId.
- Adjusted types for suggested subjects to include line and cycle information.