Files
acad-ia-2/src/features/planes/nuevo/hooks/useNuevoPlanWizard.ts
Guillermo Arrieta Medina f3414f23f6 Refactor: unifica wizards con WizardLayout/WizardResponsiveHeader y convierte asignaturas en layout con Outlet
- Se introdujo un layout genérico de wizard (WizardLayout) con headerSlot/footerSlot y se migraron los modales de Nuevo Plan y Nueva Asignatura a esta estructura usando defineStepper.
- Se creó y reutilizó WizardResponsiveHeader para un encabezado responsivo consistente (progreso en móvil y navegación en escritorio) en ambos wizards.
- Se homologó WizardControls del wizard de asignaturas para alinearlo al patrón del wizard de planes (props onPrev/onNext, flags de disable, manejo de error/loading y creación).
- Se mejoró la captura de datos en el wizard de asignatura: créditos como flotante con 2 decimales, placeholders/estilos en inputs/selects y uso de catálogo real de estructuras vía useSubjectEstructuras con qk.estructurasAsignatura.
- Se reorganizó la sección de asignaturas del detalle del plan: el contenido del antiguo index se movió a asignaturas.tsx como layout y se agregó <Outlet />; navegación a “nueva asignatura” ajustada al path correcto.
2026-02-04 13:36:46 -06:00

92 lines
2.6 KiB
TypeScript

import { useState } from 'react'
import type { NewPlanWizardState } from '../types'
export function useNuevoPlanWizard() {
const [wizard, setWizard] = useState<NewPlanWizardState>({
step: 1,
tipoOrigen: null,
datosBasicos: {
nombrePlan: '',
facultad: { id: '', nombre: '' },
carrera: { id: '', nombre: '' },
nivel: '',
tipoCiclo: '',
numCiclos: null,
estructuraPlanId: null,
},
// datosBasicos: {
// nombrePlan: "Medicina",
// carreraId: "medico",
// facultadId: "med",
// nivel: "Licenciatura",
// tipoCiclo: "SEMESTRE",
// numCiclos: 8,
// plantillaPlanId: "sep-2025",
// plantillaPlanVersion: "v2025.2 (Vigente)",
// plantillaMapaId: "sep-2017-xlsx",
// plantillaMapaVersion: "v2017.0",
// },
clonInterno: { planOrigenId: null },
clonTradicional: {
archivoWordPlanId: null,
archivoMapaExcelId: null,
archivoAsignaturasExcelId: null,
},
iaConfig: {
descripcionEnfoqueAcademico: '',
instruccionesAdicionalesIA: '',
archivosReferencia: [],
repositoriosReferencia: [],
archivosAdjuntos: [],
},
resumen: {},
isLoading: false,
errorMessage: null,
})
const canContinueDesdeModo =
wizard.tipoOrigen === 'MANUAL' ||
wizard.tipoOrigen === 'IA' ||
wizard.tipoOrigen === 'CLONADO_INTERNO' ||
wizard.tipoOrigen === 'CLONADO_TRADICIONAL'
const canContinueDesdeBasicos =
!!wizard.datosBasicos.nombrePlan &&
!!wizard.datosBasicos.carrera.id &&
!!wizard.datosBasicos.facultad.id &&
!!wizard.datosBasicos.nivel &&
wizard.datosBasicos.numCiclos !== null &&
wizard.datosBasicos.numCiclos > 0 &&
// Requerir ambas plantillas (plan y mapa) con versión
!!wizard.datosBasicos.estructuraPlanId
const canContinueDesdeDetalles = (() => {
if (wizard.tipoOrigen === 'MANUAL') return true
if (wizard.tipoOrigen === 'IA') {
// Requerimos descripción del enfoque y notas adicionales
return !!wizard.iaConfig?.descripcionEnfoqueAcademico
}
if (wizard.tipoOrigen === 'CLONADO_INTERNO') {
return !!wizard.clonInterno?.planOrigenId
}
if (wizard.tipoOrigen === 'CLONADO_TRADICIONAL') {
const t = wizard.clonTradicional
if (!t) return false
const tieneWord = !!t.archivoWordPlanId
const tieneAlMenosUnExcel =
!!t.archivoMapaExcelId || !!t.archivoAsignaturasExcelId
return tieneWord && tieneAlMenosUnExcel
}
return false
})()
return {
wizard,
setWizard,
canContinueDesdeModo,
canContinueDesdeBasicos,
canContinueDesdeDetalles,
}
}