Appearance
Archivos de la Carpeta src/pages
La carpeta src/pages contiene los componentes de alto nivel que representan las diferentes "páginas" o vistas principales de tu aplicación. Estas páginas suelen ser la capa que compone varios componentes y características para formar una vista completa.
login.page.tsx
Este archivo define la página de Inicio de Sesión, que sirve como la interfaz principal para que los usuarios accedan a la aplicación.
- Descripción:
LoginPagees un componente de página simple que se encarga de renderizar la interfaz de inicio de sesión. Delega la lógica de autenticación y la presentación del formulario a componentes especializados, manteniendo esta página limpia y enfocada en su propósito principal. - Propósito: Proporcionar una vista dedicada para el proceso de inicio de sesión, integrando el layout público y el componente de login.
- Funcionalidad clave:
<PublicLayout>: Este componente (importado de../components/layouts/public-layout/public.layout.tsx) envuelve el contenido del login, proporcionando una estructura visual común para las rutas que no requieren autenticación (por ejemplo, un diseño sin barra lateral de navegación).<Login />: Este componente (importado de../features/login/login.tsx) es el corazón de la funcionalidad de inicio de sesión. Contiene el formulario, la lógica para manejar las credenciales del usuario y la interacción con la API de autenticación.LoginPagesimplemente lo renderiza, desacoplando la lógica de la vista principal.
- Rol en la aplicación:
LoginPagees el punto de entrada principal para los usuarios que buscan autenticarse. Su diseño modular asegura que la lógica de la UI y la autenticación estén bien separadas, facilitando el mantenimiento y la reutilización.
tsx
// src/pages/login.page.tsx
import React from "react";
import PublicLayout from "../components/layouts/public-layout/public.layout";
import Login from "../features/login/login";
const LoginPage: React.FC = () => {
return (
<PublicLayout>
<Login />
</PublicLayout>
);
};
export default LoginPage;
dashboard.tsx
Este archivo define la página principal del Dashboard, que actúa como una vista general de los estudiantes en el sistema.
- Descripción:
Dashboardes un componente de página que se encarga de obtener la lista completa de estudiantes y presentarlos en un formato de tabla. Maneja los estados de carga y error para proporcionar una experiencia de usuario fluida. - Propósito: Mostrar una visión general de todos los estudiantes registrados, sirviendo como la página principal para la gestión y visualización rápida.
- Funcionalidad clave:
useStudentsList(): Este hook personalizado (importado de../hooks/use.students.list.ts) es el responsable de la lógica de obtención de la lista completa de estudiantes de la API. Retorna el array destudents, junto con los estadosloading(para indicar si los datos se están cargando) yerror(para capturar cualquier fallo en la operación).- Manejo de Estados de Carga y Error:
- Si
loadingestrue, la página muestra un mensaje "Cargando estudiantes...". - Si
errorcontiene un valor, se renderiza un mensaje de error correspondiente.
- Si
<Grid>: Un componente genérico de layout (importado de../components/common/grid/grid.tsx) utilizado para estructurar el contenido de la página, ofreciendo flexibilidad en el diseño.<StudentTable>: Este componente presentacional (importado de../components/student-table/student.table.tsx) es el encargado de renderizar la tabla de estudiantes. Recibe losstudentsobtenidos, untitledinámico (que incluye el conteo total de estudiantes), y laviewProfilePathbase para navegar a perfiles individuales.
- Rol en la aplicación:
Dashboardes una página central para la administración de estudiantes. Su enfoque en la delegación de responsabilidades a hooks y componentes presentacionales asegura una arquitectura limpia y eficiente.
tsx
// src/pages/dashboard.tsx
import { Grid } from "../components/common/grid/grid";
import { useStudentsList } from "../hooks/use.students.list";
import { StudentTable } from "../components/student-table/student.table";
export default function Dashboard() {
const { students, error, loading } = useStudentsList();
// Muestra un mensaje de carga mientras se obtienen los datos.
if (loading) return <p>Cargando estudiantes...</p>;
// Muestra un mensaje de error si la carga de datos falla.
if (error) return <p>Error: {error}</p>;
// Renderiza la tabla de estudiantes dentro de un componente Grid.
return (
<Grid>
<StudentTable
students={students} // Pasa la lista completa de estudiantes.
title={`Estudiantes (${students.length})`} // Título dinámico con el conteo de estudiantes.
viewProfilePath="/dashboard/student" // Ruta base para navegar al perfil de un estudiante.
/>
</Grid>
);
}
student.profile.tsx
Este archivo define la página del Perfil del Estudiante, la cual permite visualizar los detalles de un estudiante específico y ofrece la funcionalidad para editar su información o eliminarlo.
- Descripción:
StudentProfilees un componente de página que recupera el ID de un estudiante de la URL, utiliza un custom hook (useStudentProfile) para obtener los datos del estudiante y gestionar la lógica de edición/eliminación. Alterna entre la vista de detalles y un formulario de actualización dependiendo del estado de edición. - Propósito: Mostrar una vista detallada del perfil de un estudiante, permitiendo a los usuarios autorizados modificar o eliminar los datos del estudiante.
- Funcionalidad:
useParams<{ id: string }>(): Hook dereact-router-domque extrae eliddel estudiante de la URL (por ejemplo,/dashboard/student/123).useAuth().token: Obtiene el token de autenticación del contexto global de autenticación. Este token se pasa directamente aluseStudentProfilehook, asumiendo queuseStudentProfileestá tipado para aceptar eltokencomostring | null | undefined, lo que permite un manejo más conciso.useStudentProfile(id, token): Este es el custom hook central de la página. Encapsula toda la lógica para:- Obtener los datos del estudiante dado su
idytoken. - Manejar el estado de carga (
loading) y error (error). - Gestionar el estado de edición (
isEditing) y los datos temporales del formulario (updatedData). - Proveer funciones para la edición (
handleEdit,handleChange,handleSubmitEdit), eliminación de archivos (handleDeleteFile) y eliminación del estudiante (handleDelete). - Indicar si el estudiante ha sido eliminado (
isDeleted).
- Obtener los datos del estudiante dado su
useNavigate(): Hook dereact-router-dompara la navegación programática.useEffectpara Redirección: CuandoisDeletedcambia atrue(indicando que el estudiante fue eliminado exitosamente), el efecto redirige al usuario a la página/dashboard.- Manejo de Estados Iniciales:
- Si
errores verdadero, muestra un mensaje de error. - Si
studentno está cargado (esnulloundefined), muestra un mensaje de "Cargando...".
- Si
- Renderizado Condicional:
- Si
isEditingestrue, renderiza el componenteUpdateStudentForm. Este formulario recibe los datos del estudiante para la edición (updatedData), y los handlers para los cambios (handleChange), el envío (handleSubmitEdit) y la eliminación de archivos (handleDeleteFile). - Si
isEditingesfalse, renderiza el componenteStudentDetails. Este componente muestra la información del estudiante (student) y provee botones/acciones para activar el modo de edición (onEdit) y la eliminación (onDelete).
- Si
- Rol en la aplicación:
StudentProfileactúa como una página de detalle y gestión para un estudiante individual. Coordina la obtención de datos, el manejo de diferentes modos (vista/edición) y la interacción con los componentes UI específicos para esas tareas.
tsx
// src/pages/student.profile.tsx
import { useEffect } from "react";
import { useParams, useNavigate } from "react-router-dom";
import { useAuth } from "../components/auth/auth.context";
import { useStudentProfile } from "../hooks/use.profile.students";
import UpdateStudentForm from "../components/common/forms/update-student/update.student.form";
import StudentDetails from "../components/common/details-views/student.profile.details";
/**
* Componente StudentProfile.
* Página que muestra el perfil detallado de un estudiante y permite su edición/eliminación.
* Actúa como orquestador para la lógica de datos y la alternancia de vistas (detalles vs. edición).
*/
const StudentProfile = () => {
const { id } = useParams<{ id: string }>();
// Desestructura 'token' directamente de useAuth.
// Se asume que useAuth().token es de tipo `string | null | undefined`,
// y que useStudentProfile() acepta este tipo para el token.
const { token } = useAuth();
// Utiliza el hook useStudentProfile para gestionar toda la lógica del perfil:
// - Obtención de datos del estudiante.
// - Manejo de estados (carga, error, edición, eliminación).
// - Funciones para interactuar con los datos (editar, eliminar, manejar archivos).
const {
student,
error,
isEditing,
updatedData,
handleEdit,
handleChange,
handleSubmitEdit,
handleDelete,
handleDeleteFile,
isDeleted,
} = useStudentProfile(id, token); // Pasa 'token' directamente aquí.
const navigate = useNavigate();
// Efecto secundario para redirigir al dashboard si el estudiante ha sido eliminado con éxito.
// Se ejecuta cada vez que 'isDeleted' o 'navigate' cambian.
useEffect(() => {
if (isDeleted) {
navigate("/dashboard");
}
}, [isDeleted, navigate]);
// Renderizado condicional basado en el estado de error o carga.
// Muestra un mensaje de error si la carga de datos falló.
if (error) {
return <div>{error}</div>;
}
// Muestra un mensaje de carga si los datos del estudiante aún no están disponibles.
if (!student) {
return <div>Cargando...</div>;
}
// Renderiza el contenido principal de la página.
return (
<div>
{/* Renderizado condicional: muestra el formulario de edición o los detalles del estudiante. */}
{isEditing ? (
// Si 'isEditing' es true, muestra el formulario para actualizar el estudiante.
<UpdateStudentForm
student={updatedData!} // Pasa los datos actuales para el formulario (el '!' afirma que no será null aquí).
onChange={handleChange} // Handler para cambios en los campos del formulario.
onSubmit={handleSubmitEdit} // Handler para el envío del formulario.
onDeleteFile={handleDeleteFile} // Handler para eliminar archivos.
/>
) : (
// Si 'isEditing' es false, muestra los detalles del estudiante.
<StudentDetails
student={student} // Pasa los datos del estudiante para mostrar.
onEdit={handleEdit} // Handler para activar el modo de edición.
onDelete={handleDelete} // Handler para eliminar al estudiante.
/>
)}
</div>
);
};
export default StudentProfile;
add.student.tsx
Este archivo define la página "Agregar Estudiante", que permite a los usuarios crear nuevos registros de estudiantes en el sistema.
- Descripción:
AddStudentes un componente de página que orquesta la lógica de autenticación, el estado del formulario, la gestión del envío y la retroalimentación al usuario. Utiliza hooks personalizados y componentes presentacionales para mantener una arquitectura limpia y modular. - Propósito: Proporcionar una interfaz de usuario clara y funcional para que los usuarios autenticados puedan ingresar y guardar la información de nuevos estudiantes.
- Funcionalidad clave:
- Control de Autenticación: Al inicio, la página verifica si el usuario tiene un token de autenticación. Si no está autenticado, muestra un mensaje claro y prohíbe el acceso al formulario de adición. Esto es crucial para la seguridad y el control de acceso.
- Uso de
useAuth(): Este hook se emplea para obtener eltokendel contexto de autenticación, asegurando que solo usuarios válidos puedan realizar la operación. - Uso de
useAddStudent(): Este es el hook personalizado central de la página. Encapsula toda la lógica relacionada con el formulario de adición de estudiantes:- Manejo del estado de los datos del formulario (
studentData). - Gestión de los cambios en los campos de entrada (
handleChange). - Ejecución de la lógica de envío (
handleSubmit). - Provisión de mensajes de éxito (
successMessage) o error (errorMessage) después del intento de adición. - Proporciona una
formKey, una técnica muy útil para reiniciar completamente el formulario (forzando la re-montura del componenteAddStudentForm) después de un envío exitoso, lo que limpia los campos para una nueva entrada.
- Manejo del estado de los datos del formulario (
- Retroalimentación al Usuario con
react-toastify: Utiliza el hookuseEffectpara mostrar notificaciones toast al usuario cuando hay unsuccessMessageo unerrorMessage. Esto mejora la experiencia del usuario al proporcionar retroalimentación visual no intrusiva sobre el resultado de la operación. - Componente
AddStudentForm: La página delega la renderización del formulario a este componente presentacional. Recibe los datos del estudiante, el manejador de cambios y el manejador de envío como propiedades, manteniendo el formulario desacoplado y reutilizable.
- Rol en la aplicación:
AddStudentfunciona como un punto de entrada para la creación de nuevos registros. Su estructura modular y el uso de hooks la hacen fácil de entender y mantener.
tsx
// src/pages/add.student.tsx
import { useEffect } from "react";
import { AddStudentForm } from "../components/common/forms/add-student/add.student.form";
import { useAuth } from "../components/auth/auth.context";
import { useAddStudent } from "../hooks/use.add.students";
import { toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
export default function AddStudent() {
const { token } = useAuth();
const {
successMessage,
errorMessage,
handleSubmit, // Se utiliza directamente handleSubmit del hook
studentData,
handleChange,
formKey,
} = useAddStudent(token); // El hook useAddStudent ahora acepta 'token' directamente.
// handleAddStudent fue eliminado, ya que era un envoltorio redundante.
useEffect(() => {
if (successMessage) {
toast.success(successMessage, { position: "top-right", autoClose: 5000 });
}
if (errorMessage) {
toast.error(errorMessage, { position: "top-right", autoClose: 5000 });
}
}, [successMessage, errorMessage]);
// Si no hay token, se muestra un mensaje indicando que no está autenticado.
if (!token) {
return (
<div>
<h1>Agregar Estudiante</h1>
<p style={{ color: "red" }}>
No estás autenticado. Inicia sesión para agregar estudiantes.
</p>
</div>
);
}
// Renderizado del formulario para agregar estudiante.
return (
<div>
<h1>Agregar Estudiante</h1>
<AddStudentForm
key={formKey} // La clave es crucial para forzar el reinicio del formulario.
studentData={studentData}
handleChange={handleChange}
handleSubmit={handleSubmit} // Se pasa handleSubmit directamente.
/>
</div>
);
}
school.class.tsx
Este archivo define la página "Clase Escolar", la cual se encarga de mostrar una lista de estudiantes filtrada por un colegio y un curso específicos. Actúa como un orquestador que combina datos de diferentes fuentes para presentar una vista cohesiva.
- Descripción:
SchoolClasses un componente de página que utiliza hooks personalizados (useStudentsList,useSchoolClass) para obtener la lista completa de estudiantes, aplicar filtros de colegio y curso, y luego renderizar una tabla de estudiantes con la información relevante. - Propósito: Presentar una vista detallada de los estudiantes que pertenecen a una clase específica (definida por colegio y curso), facilitando la gestión y visualización por parte de los administradores.
- Funcionalidad clave:
- Obtención de datos de estudiantes (
useStudentsList): Utiliza el hookuseStudentsListpara recuperar la lista completa de estudiantes, su estado de carga (loading) y posibles errores (error). Este hook encapsula la lógica de fetching de datos de la API. - Lógica de Clase Escolar (
useSchoolClass): Este hook se encarga de obtener la información necesaria para definir la clase (colegio y curso) a partir de los parámetros de la URL. ProporcionanormalizedSchoolynormalizedCoursepara usar en el título de la tabla ygetFilteredStudentsBySchoolAndCourse, una función que toma la lista completa de estudiantes y devuelve solo aquellos que coinciden con el colegio y el curso. - Filtrado en la Página: La lógica principal de filtrado por colegio y curso se aplica directamente en esta página utilizando
useMemoy la funcióngetFilteredStudentsBySchoolAndCoursedel hookuseSchoolClass. Esto asegura que el componenteStudentTablereciba solo los datos ya procesados y filtrados. - Manejo de Estados de Carga, Error y Vacío:
- Muestra un mensaje "Cargando estudiantes..." mientras los datos están siendo fetched.
- Muestra un mensaje de error si ocurre un problema durante la carga de los estudiantes.
- Muestra un mensaje claro si no se encontraron estudiantes para el colegio y curso seleccionados (es decir, la lista
studentsForTableestá vacía después del filtrado).
- Componente
StudentTable: La página delega la renderización de la lista de estudiantes a este componente presentacional. Se le pasan losstudentsForTable(ya filtrados), untitleque se construye dinámicamente usando los nombres normalizados del colegio y curso, y laviewProfilePathbase para navegar al perfil individual de un estudiante. - Componente
Grid: Se utiliza un componenteGridgenérico (../components/common/grid/grid.tsx) para el layout general de la página.
- Obtención de datos de estudiantes (
- Rol en la aplicación:
SchoolClasses una página clave para la visualización segmentada de estudiantes, permitiendo a los usuarios enfocarse en grupos específicos. Su diseño modular con hooks y componentes presentacionales facilita la gestión de la lógica de datos y la presentación de la UI.
tsx
// src/pages/school.class.tsx
import { useMemo } from "react"; // Asegúrate de importar useMemo
import { Grid } from "../components/common/grid/grid";
import { useStudentsList } from "../hooks/use.students.list";
import { StudentTable } from "../components/student-table/student.table";
import { useSchoolClass } from "../hooks/use.school.class";
export default function SchoolClass() {
// Obtiene la lista completa de estudiantes y su estado de carga/error
const { students, error, loading } = useStudentsList();
// Obtiene los nombres normalizados del colegio/curso y la función de filtrado principal
const {
normalizedSchool,
normalizedCourse,
getFilteredStudentsBySchoolAndCourse,
} = useSchoolClass();
// Paso CRUCIAL: Aplicar el filtro de colegio y curso aquí
const studentsForTable = useMemo(() => {
if (!students) {
return [];
}
return getFilteredStudentsBySchoolAndCourse(students);
}, [students, getFilteredStudentsBySchoolAndCourse]);
// Manejo de estados de carga, error y "sin estudiantes"
if (loading) {
return <p>Cargando estudiantes...</p>;
}
if (error) {
return <p>Error al cargar estudiantes: {error}</p>;
}
if (studentsForTable.length === 0) {
return (
<p>
No se encontraron estudiantes para{" "}
<strong>
{normalizedSchool} - {normalizedCourse}
</strong>
.
</p>
);
}
// Renderiza la tabla de estudiantes con los datos ya filtrados
return (
<Grid>
<StudentTable
students={studentsForTable} // ¡Aquí se pasan los estudiantes ya filtrados!
title={`${normalizedSchool} - ${normalizedCourse}`}
// filterBySchoolAndCourse ya NO es una prop de StudentTable
viewProfilePath="/dashboard/student"
/>
</Grid>
);
}
statistics.tsx
Este archivo define la página "Estadísticas", la cual permite visualizar datos analíticos de los estudiantes mediante gráficos y tablas interactivas. Actúa como centro de control para filtrar, analizar y presentar datos clave relacionados con la matrícula y características del alumnado.
Descripción:
Statisticses un componente de página que utiliza un hook personalizado (useStudentsList) para obtener estudiantes desde el backend, y permite filtrarlos por fuente, colegio y curso. Luego, delega el análisis y visualización de datos a componentes especializados, siguiendo un enfoque modular y desacoplado.Propósito: Brindar una vista interactiva y analítica del cuerpo estudiantil que ayude a los administradores a identificar patrones, distribuciones y comportamientos clave para la toma de decisiones.
Funcionalidad clave:
- Obtención de datos (
useStudentsList): Hook que proporciona la lista completa de estudiantes, junto con su estado de carga (loading) y posibles errores (error). - Filtros dinámicos (
source,school,course): Mantenidos medianteuseState, permiten filtrar los datos mostrados en los componentes visuales. Los valores están basados en enums centralizados importados desde../interface/common/enums/enums. handleFilterChange: Función que actualiza el estado de los filtros y se pasa como prop al componenteStatisticsFilterControls.calculateStatistics: Función que procesa los estudiantes filtrados y devuelve un objetoFilteredStatisticscon los datos agrupados para cada gráfico o sección.- Manejo de estados:
- Muestra "Cargando estadísticas..." mientras se cargan los datos.
- Muestra un mensaje de error si ocurre una falla.
- Muestra "No hay datos disponibles." si la lista está vacía tras la carga.
- Componentes visuales (secciones):
StatisticsFilterControls: Selector de filtros para la vista.GeneralStudentStatsSection: Estadísticas generales y feedback positivo.CommunicationPreferenceSection: Preferencias de comunicación.EnrollmentSourceSection: Fuente de inscripción de los estudiantes.GenderDistributionSection: Distribución por género.CaptatorsTableSection: Tabla con información de captadores.StudentsByLevelSection: Estudiantes distribuidos por nivel académico.FeedbackBySchoolCourseSection: Feedback agrupado por escuela y curso.
- Constantes globales (
Constants.allFeedbacks): Se importa desdeutils/constantsy centraliza los valores disponibles de feedback para usarlos en visualizaciones.
- Obtención de datos (
Rol en la aplicación:
Statisticses una página clave para el monitoreo y análisis del sistema, ya que permite visualizar de manera intuitiva el estado general del alumnado. Su arquitectura modular mejora el mantenimiento, la extensibilidad y la claridad del código.
tsx
// src/pages/statistics.tsx
import { useState } from "react";
import { useStudentsList } from "../hooks/use.students.list";
import { calculateStatistics } from "../components/statistics/statistics.filters";
import { Source, School, Course } from "../interface/common/enums/enums";
import { Grid } from "../components/common/grid/grid";
import { StatisticsFilterControls } from "../components/statistics/filters/statistics.filter.controls";
import { GeneralStudentStatsSection } from "../components/statistics/sections/general.student.stats.section";
import { CommunicationPreferenceSection } from "../components/statistics/sections/communication.preference.section";
import { EnrollmentSourceSection } from "../components/statistics/sections/enrollment.source.section";
import { GenderDistributionSection } from "../components/statistics/sections/gender.distribution.section";
import { CaptatorsTableSection } from "../components/statistics/sections/captators.table.section";
import { StudentsByLevelSection } from "../components/statistics/sections/students.by.level.section";
import { FeedbackBySchoolCourseSection } from "../components/statistics/sections/feedback.by.school.course.section";
import Constants from "../utils/constants";
const Statistics = () => {
const { students, error, loading } = useStudentsList();
const [source, setSource] = useState<Source | null>(null);
const [school, setSchool] = useState<School | null>(null);
const [course, setCourse] = useState<Course | null>(null);
const handleFilterChange = (filters: {
source?: Source | null;
school?: School | null;
course?: Course | null;
}) => {
if (filters.source !== undefined) setSource(filters.source);
if (filters.school !== undefined) setSchool(filters.school);
if (filters.course !== undefined) setCourse(filters.course);
};
if (loading) return <p>Cargando estadísticas...</p>;
if (error) return <p>Error: {error}</p>;
if (!students || students.length === 0) {
return <p>No hay datos disponibles.</p>;
}
const filteredStatistics = calculateStatistics({
students,
source,
school,
course,
});
return (
<div>
<h1>Estadísticas</h1>
<StatisticsFilterControls
selectedSource={source}
selectedSchool={school}
selectedCourse={course}
onFilterChange={handleFilterChange}
/>
<Grid className="modulos">
<GeneralStudentStatsSection
filteredStatistics={filteredStatistics}
allFeedbacks={Constants.allFeedbacks}
/>
<CommunicationPreferenceSection filteredStatistics={filteredStatistics} />
<EnrollmentSourceSection filteredStatistics={filteredStatistics} />
<GenderDistributionSection filteredStatistics={filteredStatistics} />
<CaptatorsTableSection filteredStatistics={filteredStatistics} />
<StudentsByLevelSection filteredStatistics={filteredStatistics} />
<FeedbackBySchoolCourseSection filteredStatistics={filteredStatistics} />
</Grid>
</div>
);
};
export default Statistics;