1 Commits

Author SHA1 Message Date
frcarlos 88f2ac13d7 fechas 2025-11-04 13:22:07 -06:00
+236 -277
View File
@@ -2,312 +2,271 @@
import { useEffect, useState } from "react";
import { axiosInstance } from "@/api/config";
import { ServicioSocialConCasoEspecial, ServicioSocialResponse } from "@/types/responses";
import {
ServicioSocialConCasoEspecial,
ServicioSocialResponse,
} from "@/types/responses";
import { useRouter } from "next/navigation";
interface Props {
data?: ServicioSocialResponse[];
total?: number;
onPageChange?: (newPage: number) => void;
columnaFechaInicio?: boolean;
columnaFechaFin?: boolean;
idTipoUsuario?: number; // 1=admin, 2=responsable, 3=alumno, 4=caso especial
columnasResponsable?: boolean;
onRowAction?: (row: ServicioSocialResponse, path: string) => void;
columnaCuestionario?: boolean;
columnaCartaTermino?: boolean;
columnaCuestionarioCompleto?: boolean;
columnaFechaRegistro?: boolean;
data?: ServicioSocialResponse[];
total?: number;
onPageChange?: (newPage: number) => void;
columnaFechaInicio?: boolean;
columnaFechaFin?: boolean;
idTipoUsuario?: number; // 1=admin, 2=responsable, 3=alumno, 4=caso especial
columnasResponsable?: boolean;
onRowAction?: (row: ServicioSocialResponse, path: string) => void;
columnaCuestionario?: boolean;
columnaCartaTermino?: boolean;
columnaCuestionarioCompleto?: boolean;
columnaFechaRegistro?: boolean;
}
export default function ServicioSocialTabla({
data,
total = 0,
onPageChange,
idTipoUsuario,
columnasResponsable = false,
columnaFechaInicio = false,
columnaFechaFin = false,
columnaCuestionario = false,
columnaCartaTermino = false,
columnaCuestionarioCompleto = false,
columnaFechaRegistro = false,
onRowAction,
data,
total = 0,
onPageChange,
idTipoUsuario,
columnasResponsable = false,
columnaFechaInicio = true,
columnaFechaFin = true,
columnaCuestionario = false,
columnaCartaTermino = false,
columnaCuestionarioCompleto = false,
columnaFechaRegistro = false,
onRowAction,
}: Props) {
const [info, setInfo] = useState<ServicioSocialResponse[]>(data || []);
const [loading, setLoading] = useState(false);
const [currentPage, setCurrentPage] = useState(1);
const [info, setInfo] = useState<ServicioSocialResponse[]>(data || []);
const [loading, setLoading] = useState(false);
const [currentPage, setCurrentPage] = useState(1);
const router = useRouter();
const router = useRouter();
//const columnaFechaInicio = true;
//const columnaFechaFin = true;
// 🔹 Cargar datos del padre si existen
useEffect(() => {
if (data && data.length > 0) {
setInfo(data);
}
}, [data]);
// 🔹 Paginación simple
function handlePrev() {
if (currentPage > 1) {
const np = currentPage - 1;
setCurrentPage(np);
onPageChange?.(np);
}
// 🔹 Cargar datos del padre si existen
useEffect(() => {
if (data && data.length > 0) {
setInfo(data);
}
}, [data]);
function handleNext() {
const lastPage = Math.max(1, Math.ceil(total / 10));
if (currentPage < lastPage) {
const np = currentPage + 1;
setCurrentPage(np);
onPageChange?.(np);
}
// 🔹 Paginación simple
function handlePrev() {
if (currentPage > 1) {
const np = currentPage - 1;
setCurrentPage(np);
onPageChange?.(np);
}
const servicioSelected = (row: ServicioSocialResponse | ServicioSocialConCasoEspecial) => {
if (!row) return;
if (idTipoUsuario === 1) {
if (row.idServicio) {
localStorage.setItem("idServicio", String(row.idServicio));
}
if ("idCasoEspecial" in row && row.idCasoEspecial) {
localStorage.setItem("idCasoEspecial", String(row.idCasoEspecial));
}
router.push("/administrador/servicio");
} else if (
row.idServicio ||
("idCasoEspecial" in row && row.idCasoEspecial)
) {
console.log("Limpiando selección (no admin)");
}
}
/*
const servicioSelected = (row: ServicioSocialResponse | ServicioSocialConCasoEspecial) => {
if (!row) return;
if (idTipoUsuario === 1) {
if (row.idServicio) {
localStorage.setItem("idServicio", String(row.idServicio));
}
// ✅ forma segura sin any
if ("idCasoEspecial" in row && row.idCasoEspecial) {
localStorage.setItem("idCasoEspecial", String(row.idCasoEspecial));
}
router.push("/administrador/servicio");
} else if (
row.idServicio ||
("idCasoEspecial" in row && row.idCasoEspecial)
) {
console.log("Limpiando selección (no admin)");
}
};
// Codigo original
const servicioSelected = (row: ServicioSocialResponse | ServicioSocialConCasoEspecial) => {
if (!row) return;
function handleNext() {
const lastPage = Math.max(1, Math.ceil(total / 10));
if (currentPage < lastPage) {
const np = currentPage + 1;
setCurrentPage(np);
onPageChange?.(np);
}
}
if (idTipoUsuario === 1) {
const servicioSelected = (
row: ServicioSocialResponse | ServicioSocialConCasoEspecial
) => {
if (!row) return;
if (row.idServicio) {
localStorage.setItem("idServicio", String(row.idServicio));
}
if ((row as any).idCasoEspecial) {
localStorage.setItem("idCasoEspecial", String((row as any).idCasoEspecial));
}
if (idTipoUsuario === 1) {
if (row.idServicio) {
localStorage.setItem("idServicio", String(row.idServicio));
}
// Redirigir a la vista de detalle
router.push("/administrador/servicio");
} else if (row.idServicio || (row as any).idCasoEspecial) {
console.log("Limpiando selección (no admin)");
if ("idCasoEspecial" in row && row.idCasoEspecial) {
localStorage.setItem("idCasoEspecial", String(row.idCasoEspecial));
}
}
};
router.push("/administrador/servicio");
} else if (
row.idServicio ||
("idCasoEspecial" in row && row.idCasoEspecial)
) {
console.log("Limpiando selección (no admin)");
}
};
*/
return (
<section>
{loading ? (
<div>Cargando...</div>
) : (
<>
<div className="table-responsive">
<table className="table table-striped">
<thead>
<tr>
{columnaFechaRegistro && <th>Fecha Registro</th>}
<th>Número de Cuenta</th>
<th>Nombre</th>
<th>Carrera</th>
{columnaFechaInicio && <th>Fecha Inicio</th>}
{columnaFechaFin && <th>Fecha Fin</th>}
<th>Status</th>
{columnaCuestionarioCompleto && <th>Cuestionario Completo</th>}
{columnaCartaTermino && <th>Carta Termino</th>}
{columnaCuestionario && <th>Cuestionario</th>}
</tr>
</thead>
<tbody>
{info.map((item, index) => (
<tr
key={index}
style={{
cursor: idTipoUsuario === 1 ? "pointer" : "default",
}}
onClick={() => (
idTipoUsuario === 1 ? servicioSelected(item) : undefined
)}
//onClick={() => Falta corregir
//idTipoUsuario === 1 ? servicioSelected(item) : undefined
//}
>
<td>{item.Usuario?.usuario}</td>
<td>{item.Usuario?.nombre}</td>
<td>{item.Carrera?.carrera}</td>
{columnaFechaInicio && (
<td>{formatDate(item.fecha_inicio)}</td>
)}
{columnaFechaFin && <td>{formatDate(item.fecha_fin)}</td>}
<td>
{columnasResponsable && item.Status?.idStatus === 7 ? (
<button
className="btn btn-sm btn-danger"
onClick={() =>
onRowAction?.(item, "carta_aceptacion")
}
>
Carta Aceptación Rechazada
</button>
) : (
<span
className={`badge bg-${statusClass(
item.Status?.idStatus
)}`}
>
{item.Status?.status}
</span>
)}
</td>
{columnaCartaTermino && (
<td>{item.cartaTermino ? (
<span className="badge bg-success">Completado</span>
) : (
<span className="badge bg-danger">No Completado</span>
)}</td>
)}
{columnaCuestionarioCompleto && (
<td>{item.cuestionarioCompletado ? (
<span className="badge bg-success">Completado</span>
) : (
<span className="badge bg-danger">No Completado</span>
)}</td>
)}
{columnaCuestionario && (
<td>
{item.cuestionarioCompletado ? (
<span className="badge bg-success">Completado</span>
) : (
<span className="badge bg-danger">No Completado</span>
)}
</td>
)}
</tr>
))}
{info.length === 0 && (
<tr>
<td colSpan={7} className="text-center">
No hay registros
</td>
</tr>
)}
</tbody>
</table>
</div>
<div className="d-flex justify-content-between align-items-center mt-2">
<div>Total: {total}</div>
<div>
<button
className="btn btn-sm btn-outline-primary me-2"
onClick={handlePrev}
disabled={currentPage <= 1}
>
Anterior
</button>
<span>Página {currentPage}</span>
<button
className="btn btn-sm btn-outline-primary ms-2"
onClick={handleNext}
disabled={
currentPage >= Math.max(1, Math.ceil(total / 10))
return (
<section>
{loading ? (
<div>Cargando...</div>
) : (
<>
<div className="table-responsive">
<table className="table table-striped">
<thead>
<tr>
{columnaFechaRegistro && <th>Fecha Registro</th>}
<th>Número de Cuenta</th>
<th>Nombre</th>
<th>Carrera</th>
{columnaFechaInicio && <th>Fecha Inicio</th>}
{columnaFechaFin && <th>Fecha Fin</th>}
<th>Status</th>
{columnaCuestionarioCompleto && (
<th>Cuestionario Completo</th>
)}
{columnaCartaTermino && <th>Carta Termino</th>}
{columnaCuestionario && <th>Cuestionario</th>}
</tr>
</thead>
<tbody>
{info.map((item, index) => (
<tr
key={index}
style={{
cursor: idTipoUsuario === 1 ? "pointer" : "default",
}}
onClick={() =>
idTipoUsuario === 1 ? servicioSelected(item) : undefined
}
>
Siguiente
</button>
</div>
>
{/* Si el padre pidió mostrar Fecha Registro, la mostramos aquí (createdAt) */}
{columnaFechaRegistro && (
<td>{formatDate((item as any).createdAt)}</td>
)}
<td>{item.Usuario?.usuario}</td>
<td>{item.Usuario?.nombre}</td>
<td>{item.Carrera?.carrera}</td>
{/* Usar las propiedades en camelCase que vienen en tu JSON */}
{columnaFechaInicio && (
<td>{formatDate((item as any).fechaInicio)}</td>
)}
{columnaFechaFin && (
<td>{formatDate((item as any).fechaFin)}</td>
)}
<td>
{columnasResponsable && item.Status?.idStatus === 7 ? (
<button
className="btn btn-sm btn-danger"
onClick={() =>
onRowAction?.(item, "carta_aceptacion")
}
>
Carta Aceptación Rechazada
</button>
) : (
<span
className={`badge bg-${statusClass(
item.Status?.idStatus
)}`}
>
{item.Status?.status}
</span>
)}
</td>
{columnaCartaTermino && (
<td>
{item.cartaTermino ? (
<span className="badge bg-success">Completado</span>
) : (
<span className="badge bg-danger">No Completado</span>
)}
</td>
)}
{columnaCuestionarioCompleto && (
<td>
{item.cuestionarioCompletado ? (
<span className="badge bg-success">Completado</span>
) : (
<span className="badge bg-danger">No Completado</span>
)}
</td>
)}
{columnaCuestionario && (
<td>
{item.cuestionarioCompletado ? (
<span className="badge bg-success">Completado</span>
) : (
<span className="badge bg-danger">No Completado</span>
)}
</td>
)}
</tr>
))}
{info.length === 0 && (
<tr>
<td colSpan={7} className="text-center">
No hay registros
</td>
</tr>
)}
</tbody>
</table>
</div>
<div className="d-flex justify-content-between align-items-center mt-2">
<div>Total: {total}</div>
<div>
<button
className="btn btn-sm btn-outline-primary me-2"
onClick={handlePrev}
disabled={currentPage <= 1}
>
Anterior
</button>
<span>Página {currentPage}</span>
<button
className="btn btn-sm btn-outline-primary ms-2"
onClick={handleNext}
disabled={currentPage >= Math.max(1, Math.ceil(total / 10))}
>
Siguiente
</button>
</div>
</>
)}
</section>
);
</div>
</>
)}
</section>
);
}
function formatDate(value?: string | null): string {
if (!value) return "";
if (!value) return "";
// Si ya viene como fecha ISO, forzamos a hora local sin modificar el día
const d = new Date(value.includes("T") ? value : `${value}T00:00:00`);
const d = new Date(value.includes("T") ? value : `${value}T00:00:00`);
if (isNaN(d.getTime())) {
console.warn("⚠️ Fecha inválida:", value);
return "";
}
if (isNaN(d.getTime())) {
console.warn("⚠️ Fecha inválida:", value);
return "";
}
const day = String(d.getDate()).padStart(2, "0");
const month = String(d.getMonth() + 1).padStart(2, "0");
const year = d.getFullYear();
const day = String(d.getDate()).padStart(2, "0");
const month = String(d.getMonth() + 1).padStart(2, "0");
const year = d.getFullYear();
return `${day}/${month}/${year}`;
return `${day}/${month}/${year}`;
}
function statusClass(id?: number) {
switch (id) {
case 1:
return "dark";
case 2:
return "info";
case 3:
return "warning";
case 4:
return "primary";
case 5:
case 6:
return "success";
case 7:
case 8:
case 9:
case 10:
return "danger";
default:
return "secondary";
}
switch (id) {
case 1:
return "dark";
case 2:
return "info";
case 3:
return "warning";
case 4:
return "primary";
case 5:
case 6:
return "success";
case 7:
case 8:
case 9:
case 10:
return "danger";
default:
return "secondary";
}
}