- 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.
92 lines
2.6 KiB
TypeScript
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,
|
|
}
|
|
}
|