feat: refactor Diploma and VistaPreviaDiplomaDialog components to use unified formacion structure and enhance competency handling

This commit is contained in:
SirRobert-1 2025-06-13 22:24:43 -06:00
parent 0f1c1458c5
commit 74cb6015dc
3 changed files with 116 additions and 38 deletions

View File

@ -35,7 +35,13 @@ const styles = StyleSheet.create({
},
});
export default function Diploma({ alumno, curso, competencias = [], fecha }) {
export default function Diploma({ alumno, formacion, fecha }) {
// formacion: { tipo, nombre, competencias }
let tipoTexto = "formación";
if (formacion?.tipo === "curso") tipoTexto = "curso";
else if (formacion?.tipo === "inyeccion") tipoTexto = "inyección";
else if (formacion?.tipo === "pildora") tipoTexto = "píldora educativa";
return (
<Document>
<Page size="A4" style={styles.page}>
@ -45,12 +51,29 @@ export default function Diploma({ alumno, curso, competencias = [], fecha }) {
<Text style={styles.title}>a: </Text>
<Text style={styles.nombre}>{alumno?.nombre} </Text>
<Text style={styles.title}>
Por su asistencia a la píldora educativa
</Text>
<Text style={styles.curso}>{curso?.nombre || "Sin curso"}</Text>
<Text style={styles.title}>
con duración de 2 horas, modalidad remota
Por su asistencia{" "}
{formacion?.tipo === "curso"
? "al curso"
: formacion?.tipo === "inyeccion"
? "a la inyección"
: formacion?.tipo === "pildora"
? "a la píldora educativa"
: "a la formación"}
</Text>
<Text style={styles.curso}>{formacion?.nombre || "Sin formación"}</Text>
{(formacion?.tipo === "curso" || formacion?.tipo === "inyeccion") &&
formacion?.competencias?.length > 0 && (
<View style={styles.competencias}>
<Text style={{ fontWeight: "bold", marginBottom: 4 }}>
Competencias acreditadas:
</Text>
{formacion.competencias.map((comp) => (
<Text key={comp.id} style={styles.competencia}>
- {comp.descripcion}
</Text>
))}
</View>
)}
<Text style={styles.title}>
Se expide en la ciudad de Xalapa, Ver., {fecha}
</Text>

View File

@ -97,23 +97,63 @@ function VistaPreviaDiplomaDialog({
};
useEffect(() => {
if (alumno && alumno.curso?.id) {
supabaseClient
.from("curso_competencia")
.select("competencia(id, descripcion)")
.eq("curso_id", alumno.curso.id)
.then(({ data }) => {
const comps = data?.map((c) => c.competencia).filter(Boolean) || [];
setCompetencias(comps);
});
if (alumno) {
if (alumno.tipo_formacion === "curso" && alumno.curso?.id) {
supabaseClient
.from("curso_competencia")
.select("competencia(id, descripcion)")
.eq("curso_id", alumno.curso.id)
.then(({ data }) => {
const comps = data?.map((c) => c.competencia).filter(Boolean) || [];
setCompetencias(comps);
});
} else if (
alumno.tipo_formacion === "inyeccion" &&
alumno.inyeccion?.id
) {
supabaseClient
.from("inyeccion_competencia_inyeccion")
.select("competencia_inyeccion(id, descripcion)")
.eq("inyeccion_id", alumno.inyeccion.id)
.then(({ data }) => {
const comps =
data?.map((c) => c.competencia_inyeccion).filter(Boolean) || [];
setCompetencias(comps);
});
} else {
setCompetencias([]);
}
}
}, [alumno]);
if (!alumno) return null;
const competenciasMostradas = competenciasAcreditadas
? competencias.filter((comp) => competenciasAcreditadas.includes(comp.id))
: competencias;
// Mostrar solo competencias acreditadas si corresponde
const competenciasMostradas =
alumno.tipo_formacion === "curso" || alumno.tipo_formacion === "inyeccion"
? competenciasAcreditadas
? competencias.filter((comp) =>
competenciasAcreditadas.includes(comp.id)
)
: competencias
: [];
// Obtener nombre de la formación según tipo
let nombreFormacion = "";
if (alumno.tipo_formacion === "curso") {
nombreFormacion = alumno.curso?.nombre || "Sin curso";
} else if (alumno.tipo_formacion === "inyeccion") {
nombreFormacion = alumno.inyeccion?.nombre || "Sin inyección";
} else if (alumno.tipo_formacion === "pildora") {
nombreFormacion = alumno.pildoras?.nombre || "Sin píldora";
}
// Para el PDF, pasar el nombre y tipo de formación
const datosFormacion = {
tipo: alumno.tipo_formacion,
nombre: nombreFormacion,
competencias: competenciasMostradas,
};
const handleEnviar = async () => {
setEnviando(true);
@ -165,7 +205,7 @@ function VistaPreviaDiplomaDialog({
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-lg h-screen text-black overflow-y-auto">
<DialogContent className="w-full h-screen text-black overflow-y-auto">
<DialogHeader>
<DialogTitle>Diploma</DialogTitle>
</DialogHeader>
@ -173,16 +213,29 @@ function VistaPreviaDiplomaDialog({
<b>Alumno:</b> {alumno.nombre}
</div>
<div className="text-lg mb-2">
<b>Curso:</b> {alumno.curso?.nombre || "Sin curso"}
</div>
<div className="text-lg mb-2">
<b>Competencias Acreditadas:</b>
<ul className="list-disc ml-6">
{competenciasMostradas.map((comp) => (
<li key={comp.id}>{comp.descripcion}</li>
))}
</ul>
<b>
{alumno.tipo_formacion === "curso"
? "Curso"
: alumno.tipo_formacion === "inyeccion"
? "Inyección"
: alumno.tipo_formacion === "pildora"
? "Píldora"
: "Formación"}
:
</b>{" "}
{nombreFormacion}
</div>
{(alumno.tipo_formacion === "curso" ||
alumno.tipo_formacion === "inyeccion") && (
<div className="text-lg mb-2">
<b>Competencias Acreditadas:</b>
<ul className="list-disc ml-6">
{competenciasMostradas.map((comp) => (
<li key={comp.id}>{comp.descripcion}</li>
))}
</ul>
</div>
)}
<div className="text-lg mb-2">
<b>Fecha:</b> {fecha || new Date().toLocaleDateString()}
</div>
@ -214,8 +267,7 @@ function VistaPreviaDiplomaDialog({
document={
<Diploma
alumno={alumno}
curso={curso}
competencias={competenciasMostradas}
formacion={datosFormacion}
fecha={fecha || new Date().toLocaleDateString()}
/>
}
@ -268,12 +320,11 @@ function VistaPreviaDiplomaDialog({
{mostrarVistaPrevia && (
<div className="fixed inset-0 bg-black bg-opacity-60 flex items-center justify-center z-50">
<div className="bg-white rounded shadow-lg p-4">
<div className="w-[80vw] h-[90vh] mb-4 border">
<div className="w-full h-[90vh] mb-4 border">
<PDFViewer width="100%" height="100%">
<Diploma
alumno={alumno}
curso={curso}
competencias={competenciasMostradas}
formacion={datosFormacion}
fecha={fecha || new Date().toLocaleDateString()}
/>
</PDFViewer>

View File

@ -18,7 +18,8 @@ export default function DiplomasVista() {
const cargarAlumnos = async () => {
const { data, error } = await supabaseClient
.from("alumno")
.select(`
.select(
`
id,
nombre,
correo,
@ -30,7 +31,8 @@ export default function DiplomasVista() {
inyeccion(id, nombre),
pildoras_id,
pildoras(id, nombre)
`)
`
)
.order("id", { ascending: true });
setAlumnos(data || []);
};
@ -97,8 +99,10 @@ export default function DiplomasVista() {
</td>
<td className="py-2 px-4 border-b">
{alumno.tipo_formacion === "curso" && alumno.curso?.nombre}
{alumno.tipo_formacion === "inyeccion" && alumno.inyeccion?.nombre}
{alumno.tipo_formacion === "pildora" && alumno.pildoras?.nombre}
{alumno.tipo_formacion === "inyeccion" &&
alumno.inyeccion?.nombre}
{alumno.tipo_formacion === "pildora" &&
alumno.pildoras?.nombre}
</td>
<td className="py-2 px-4 border-b">
<Button
@ -119,7 +123,7 @@ export default function DiplomasVista() {
</div>
{/* Dialog para crear diploma y vista previa juntos */}
{mostrarDialog && (
<div className="fixed inset-0 z-50 flex items-center justify-center">
<div className="fixed inset-0 z-50 flex items-center justify-center w-screen">
<div className="flex gap-8 bg-black bg-opacity-30 p-8 rounded">
<VistaPreviaDiplomaDialog
open={mostrarDialog}