se modifico el reporte de inscritos para poder buscar por rango ademas de agregar la columna del periodo y porder descargar un excel
This commit is contained in:
@@ -4,7 +4,8 @@ import { useEffect, useState } from "react";
|
||||
import axios from "axios";
|
||||
import Cookies from "js-cookie";
|
||||
import "./inscripciones.css";
|
||||
|
||||
import * as XLSX from "xlsx";
|
||||
import { saveAs } from "file-saver";
|
||||
|
||||
interface Periodo {
|
||||
id_periodo: number;
|
||||
@@ -12,18 +13,19 @@ interface Periodo {
|
||||
}
|
||||
|
||||
interface ApiResponse {
|
||||
semestre: string;
|
||||
carrera: string;
|
||||
profesor: string;
|
||||
profesor: string;
|
||||
femenino: string;
|
||||
masculino: string;
|
||||
total: string;
|
||||
}
|
||||
|
||||
|
||||
type TipoConteo = "WINDOWS" | "MACINTOSH" | "LINUX" | "PROFESORES";
|
||||
|
||||
interface TablaRow {
|
||||
carrera: string;
|
||||
semestre: string;
|
||||
WINDOWS: number;
|
||||
MACINTOSH: number;
|
||||
LINUX: number;
|
||||
@@ -35,13 +37,13 @@ interface TablaRow {
|
||||
|
||||
export default function Inscripciones() {
|
||||
const [periodo, setPeriodo] = useState<Periodo[]>([]);
|
||||
const [selectedPeriodo, setSelectedPeriodo] = useState<number | null>(null);
|
||||
const [periodoInicio, setPeriodoInicio] = useState<number | null>(null);
|
||||
const [periodoFin, setPeriodoFin] = useState<number | null>(null);
|
||||
const [tablaData, setTablaData] = useState<TablaRow[]>([]);
|
||||
|
||||
const [rawData, setRawData] = useState<ApiResponse[]>([]);
|
||||
const token = Cookies.get("token");
|
||||
const headers = { Authorization: `Bearer ${token}` };
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const getPeriodo = async () => {
|
||||
const response = await axios.get(`${envConfig.apiUrl}/periodo`, { headers });
|
||||
@@ -50,29 +52,41 @@ export default function Inscripciones() {
|
||||
getPeriodo();
|
||||
}, []);
|
||||
|
||||
|
||||
const handleBuscar = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
const handleBuscar = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!selectedPeriodo) return;
|
||||
if (!periodoInicio || !periodoFin) {
|
||||
alert("Selecciona ambos periodos");
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await axios.get(
|
||||
`${envConfig.apiUrl}/alumno-inscrito/inscritos/${selectedPeriodo}`,
|
||||
{ headers }
|
||||
);
|
||||
if (periodoInicio > periodoFin) {
|
||||
alert("El periodo inicio no puede ser mayor al final");
|
||||
return;
|
||||
}
|
||||
|
||||
const esMismoPeriodo = periodoInicio === periodoFin;
|
||||
|
||||
try {
|
||||
const url = esMismoPeriodo
|
||||
? `${envConfig.apiUrl}/alumno-inscrito/inscritos/${periodoInicio}` // 👈 uno solo
|
||||
: `${envConfig.apiUrl}/alumno-inscrito/inscritos/${periodoInicio}/${periodoFin}`; // 👈 rango
|
||||
|
||||
const response = await axios.get(url, { headers });
|
||||
|
||||
const data: ApiResponse[] = response.data;
|
||||
|
||||
setRawData(data);
|
||||
|
||||
const agrupado: Record<string, TablaRow> = {};
|
||||
|
||||
data.forEach((item) => {
|
||||
const carrera = item.carrera;
|
||||
const key = `${item.carrera}-${item.semestre}`;
|
||||
|
||||
|
||||
if (!agrupado[carrera]) {
|
||||
agrupado[carrera] = {
|
||||
carrera: carrera,
|
||||
if (!agrupado[key]) {
|
||||
agrupado[key] = {
|
||||
carrera: item.carrera,
|
||||
semestre: item.semestre,
|
||||
WINDOWS: 0,
|
||||
MACINTOSH: 0,
|
||||
LINUX: 0,
|
||||
@@ -83,20 +97,98 @@ export default function Inscripciones() {
|
||||
};
|
||||
}
|
||||
|
||||
const fila = agrupado[carrera];
|
||||
const tipoProfesor = item.profesor as TipoConteo;
|
||||
const totalPlataforma = Number(item.total);
|
||||
const fila = agrupado[key];
|
||||
const tipoProfesor = item.profesor as TipoConteo;
|
||||
|
||||
const total = Number(item.total);
|
||||
const fem = Number(item.femenino);
|
||||
const masc = Number(item.masculino);
|
||||
|
||||
|
||||
fila[tipoProfesor] += totalPlataforma;
|
||||
fila.TOTAL += totalPlataforma;
|
||||
fila[tipoProfesor] += total;
|
||||
fila.TOTAL += total;
|
||||
fila.femenino += fem;
|
||||
fila.masculino += masc;
|
||||
});
|
||||
|
||||
setTablaData(Object.values(agrupado));
|
||||
} catch (error) {
|
||||
console.error("Error al obtener inscritos", error);
|
||||
}
|
||||
};
|
||||
|
||||
// Export Excel
|
||||
const exportarExcel = () => {
|
||||
if (!rawData.length) return;
|
||||
|
||||
const periodosUnicos = Array.from(
|
||||
new Set(rawData.map((t) => t.semestre))
|
||||
).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
|
||||
|
||||
const carrerasUnicas = Array.from(
|
||||
new Set(rawData.map((t) => t.carrera))
|
||||
);
|
||||
|
||||
const dataExcel = carrerasUnicas.map((carrera) => {
|
||||
const fila: any = { Carrera: carrera };
|
||||
|
||||
let totalFila = 0;
|
||||
let totalFemenino = 0;
|
||||
let totalMasculino = 0;
|
||||
|
||||
periodosUnicos.forEach((periodo) => {
|
||||
const items = rawData.filter(
|
||||
(t) => t.carrera === carrera && t.semestre === periodo
|
||||
);
|
||||
|
||||
const totalPeriodo = items.reduce(
|
||||
(acc, item) => acc + Number(item.total),
|
||||
0
|
||||
);
|
||||
|
||||
fila[periodo] = totalPeriodo;
|
||||
totalFila += totalPeriodo;
|
||||
|
||||
totalFemenino += items.reduce(
|
||||
(acc, item) => acc + Number(item.femenino),
|
||||
0
|
||||
);
|
||||
|
||||
totalMasculino += items.reduce(
|
||||
(acc, item) => acc + Number(item.masculino),
|
||||
0
|
||||
);
|
||||
});
|
||||
|
||||
fila["Femenino"] = totalFemenino;
|
||||
fila["Masculino"] = totalMasculino;
|
||||
fila["Total"] = totalFila;
|
||||
|
||||
return fila;
|
||||
});
|
||||
|
||||
const worksheet = XLSX.utils.json_to_sheet(dataExcel);
|
||||
|
||||
worksheet["!cols"] = [
|
||||
{ wch: 25 },
|
||||
...periodosUnicos.map(() => ({ wch: 15 })),
|
||||
{ wch: 15 },
|
||||
{ wch: 15 },
|
||||
{ wch: 15 },
|
||||
];
|
||||
|
||||
const workbook = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(workbook, worksheet, "Inscritos");
|
||||
|
||||
const excelBuffer = XLSX.write(workbook, {
|
||||
bookType: "xlsx",
|
||||
type: "array",
|
||||
});
|
||||
|
||||
const blob = new Blob([excelBuffer], {
|
||||
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
});
|
||||
|
||||
saveAs(blob, "reporte_inscritos.xlsx");
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -104,15 +196,20 @@ export default function Inscripciones() {
|
||||
<h2 className="title">INSCRITOS</h2>
|
||||
|
||||
<form className="containerForm" onSubmit={handleBuscar}>
|
||||
<label>Seleccione el periodo</label>
|
||||
<label>Seleccione rango de periodos</label>
|
||||
|
||||
<div className="groupInput">
|
||||
<select
|
||||
onChange={(e) => setSelectedPeriodo(Number(e.target.value))}
|
||||
defaultValue=""
|
||||
>
|
||||
<option value="" disabled>
|
||||
Seleccione
|
||||
</option>
|
||||
<select onChange={(e) => setPeriodoInicio(Number(e.target.value))} defaultValue="">
|
||||
<option value="" disabled>Inicio</option>
|
||||
{periodo.map((p) => (
|
||||
<option key={p.id_periodo} value={p.id_periodo}>
|
||||
{p.semestre}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
||||
<select onChange={(e) => setPeriodoFin(Number(e.target.value))} defaultValue="">
|
||||
<option value="" disabled>Fin</option>
|
||||
{periodo.map((p) => (
|
||||
<option key={p.id_periodo} value={p.id_periodo}>
|
||||
{p.semestre}
|
||||
@@ -123,6 +220,14 @@ export default function Inscripciones() {
|
||||
<button className="button buttonSearch" type="submit">
|
||||
Buscar
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="button buttonSearch"
|
||||
onClick={exportarExcel}
|
||||
>
|
||||
Exportar Excel
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -131,6 +236,7 @@ export default function Inscripciones() {
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Carrera</th>
|
||||
<th>Periodo</th>
|
||||
<th>Femenino</th>
|
||||
<th>Masculino</th>
|
||||
<th>WINDOWS</th>
|
||||
@@ -145,6 +251,7 @@ export default function Inscripciones() {
|
||||
{tablaData.map((row, index) => (
|
||||
<tr key={index}>
|
||||
<td className="textLeft">{row.carrera}</td>
|
||||
<td>{row.semestre}</td>
|
||||
<td>{row.femenino}</td>
|
||||
<td>{row.masculino}</td>
|
||||
<td>{row.WINDOWS}</td>
|
||||
|
||||
@@ -113,7 +113,7 @@ export default function ReporteTotalesPage() {
|
||||
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
});
|
||||
|
||||
saveAs(data, "reporte_pivot.xlsx");
|
||||
saveAs(data, "reporte_periodo.xlsx");
|
||||
};
|
||||
|
||||
// FETCH
|
||||
|
||||
Reference in New Issue
Block a user