Skip to main content

Panel Cursos

Descripción

Gestión de cursos educativos del sistema. Cada curso tiene nombre, institución asociada (compañía), instructor, categoría, fechas de inicio/fin, límite de estudiantes y estado activo/inactivo. Usa SearchableSelect para buscar y seleccionar instituciones e instructores mediante búsqueda asíncrona.

Componentes

ComponenteRutaPropósito
CourseListPagecomponents/course/course-list-page.tsxPágina de listado con tabla paginada
CourseFormPagecomponents/course/course-form-page.tsxFormulario de creación/edición

CourseListPage

Tabla inline con columnas:

ColumnaRender
Nombrecourse.name (font-medium)
Institucióncourse.companyName || course.companyId || '-'
Instructorcourse.instructorName || course.instructorId || '-'
Categoríacourse.category || '-'
InicioFecha formateada desde course.startDate
FinFecha formateada desde course.endDate
EstadoBadge Activo/Inactivo según course.status
Acciones✏️ Editar y 🗑️ Eliminar

Paginación: pageSize default 12. Búsqueda con entity="course". Confirmación de eliminación vía ModalConfirm.

CourseFormPage

Formulario en grid de 2 columnas con los siguientes campos:

  • Nombre (obligatorio) — texto, colspan 2
  • Descripción — textarea 3 rows, colspan 2
  • Institución (obligatorio) — SearchableSelect que busca compañías con searchCompanies. Render: nombre, NIT y email. Preselecciona selectedCompany en edición.
  • Categoría — texto libre (ej: Matemáticas, Ciencias)
  • InstructorSearchableSelect que busca docentes con searchDocentes. Render: nombre, documento y email. Preselecciona selectedInstructor en edición.
  • Máx. estudiantes — número
  • Fecha inicio — datepicker
  • Fecha fin — datepicker
  • Curso activo — checkbox

SearchableSelect

El componente SearchableSelect (en components/forms/searchable-select.tsx) es un input de búsqueda con debounce (300ms) y dropdown de resultados. Soporta:

  • Búsqueda asíncrona vía searchFn (mínimo 2 caracteres)
  • Navegación por teclado (ArrowUp, ArrowDown, Enter, Escape)
  • Selección con render personalizado de opciones
  • Botón de limpiar selección
  • Spinner de carga
  • Texto "Sin resultados" cuando no hay coincidencias
  • Cierre automático al hacer clic fuera

Integración API

FunciónMétodoUso
getAll(page, pageSize)GETLista paginada (retorna { data, total })
getCourseById(id)GETCarga datos para edición
createCourse(payload)POSTCrear nuevo curso
updateCourse(id, payload)PUTActualizar curso existente
deleteCourse(id)DELETEEliminar curso
searchCompanies(term)GETBúsqueda asíncrona de instituciones
searchDocentes(term)GETBúsqueda asíncrona de instructores
getCourseProgress()GETProgreso de cursos (para Analytics)
getSimpleCourseList()GETLista simplificada para selector de cursos