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 ( return (
<Document> <Document>
<Page size="A4" style={styles.page}> <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.title}>a: </Text>
<Text style={styles.nombre}>{alumno?.nombre} </Text> <Text style={styles.nombre}>{alumno?.nombre} </Text>
<Text style={styles.title}> <Text style={styles.title}>
Por su asistencia a la píldora educativa Por su asistencia{" "}
</Text> {formacion?.tipo === "curso"
<Text style={styles.curso}>{curso?.nombre || "Sin curso"}</Text> ? "al curso"
<Text style={styles.title}> : formacion?.tipo === "inyeccion"
con duración de 2 horas, modalidad remota ? "a la inyección"
: formacion?.tipo === "pildora"
? "a la píldora educativa"
: "a la formación"}
</Text> </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}> <Text style={styles.title}>
Se expide en la ciudad de Xalapa, Ver., {fecha} Se expide en la ciudad de Xalapa, Ver., {fecha}
</Text> </Text>

View File

@ -97,23 +97,63 @@ function VistaPreviaDiplomaDialog({
}; };
useEffect(() => { useEffect(() => {
if (alumno && alumno.curso?.id) { if (alumno) {
supabaseClient if (alumno.tipo_formacion === "curso" && alumno.curso?.id) {
.from("curso_competencia") supabaseClient
.select("competencia(id, descripcion)") .from("curso_competencia")
.eq("curso_id", alumno.curso.id) .select("competencia(id, descripcion)")
.then(({ data }) => { .eq("curso_id", alumno.curso.id)
const comps = data?.map((c) => c.competencia).filter(Boolean) || []; .then(({ data }) => {
setCompetencias(comps); 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]); }, [alumno]);
if (!alumno) return null; if (!alumno) return null;
const competenciasMostradas = competenciasAcreditadas // Mostrar solo competencias acreditadas si corresponde
? competencias.filter((comp) => competenciasAcreditadas.includes(comp.id)) const competenciasMostradas =
: competencias; 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 () => { const handleEnviar = async () => {
setEnviando(true); setEnviando(true);
@ -165,7 +205,7 @@ function VistaPreviaDiplomaDialog({
return ( return (
<Dialog open={open} onOpenChange={onOpenChange}> <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> <DialogHeader>
<DialogTitle>Diploma</DialogTitle> <DialogTitle>Diploma</DialogTitle>
</DialogHeader> </DialogHeader>
@ -173,16 +213,29 @@ function VistaPreviaDiplomaDialog({
<b>Alumno:</b> {alumno.nombre} <b>Alumno:</b> {alumno.nombre}
</div> </div>
<div className="text-lg mb-2"> <div className="text-lg mb-2">
<b>Curso:</b> {alumno.curso?.nombre || "Sin curso"} <b>
</div> {alumno.tipo_formacion === "curso"
<div className="text-lg mb-2"> ? "Curso"
<b>Competencias Acreditadas:</b> : alumno.tipo_formacion === "inyeccion"
<ul className="list-disc ml-6"> ? "Inyección"
{competenciasMostradas.map((comp) => ( : alumno.tipo_formacion === "pildora"
<li key={comp.id}>{comp.descripcion}</li> ? "Píldora"
))} : "Formación"}
</ul> :
</b>{" "}
{nombreFormacion}
</div> </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"> <div className="text-lg mb-2">
<b>Fecha:</b> {fecha || new Date().toLocaleDateString()} <b>Fecha:</b> {fecha || new Date().toLocaleDateString()}
</div> </div>
@ -214,8 +267,7 @@ function VistaPreviaDiplomaDialog({
document={ document={
<Diploma <Diploma
alumno={alumno} alumno={alumno}
curso={curso} formacion={datosFormacion}
competencias={competenciasMostradas}
fecha={fecha || new Date().toLocaleDateString()} fecha={fecha || new Date().toLocaleDateString()}
/> />
} }
@ -268,12 +320,11 @@ function VistaPreviaDiplomaDialog({
{mostrarVistaPrevia && ( {mostrarVistaPrevia && (
<div className="fixed inset-0 bg-black bg-opacity-60 flex items-center justify-center z-50"> <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="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%"> <PDFViewer width="100%" height="100%">
<Diploma <Diploma
alumno={alumno} alumno={alumno}
curso={curso} formacion={datosFormacion}
competencias={competenciasMostradas}
fecha={fecha || new Date().toLocaleDateString()} fecha={fecha || new Date().toLocaleDateString()}
/> />
</PDFViewer> </PDFViewer>

View File

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