+
diff --git a/diplomas/src/pages/alumno/[id].jsx b/diplomas/src/pages/alumno/[id].jsx
new file mode 100644
index 0000000..adb8fba
--- /dev/null
+++ b/diplomas/src/pages/alumno/[id].jsx
@@ -0,0 +1,132 @@
+import { useRouter } from "next/router";
+import { useEffect, useState } from "react";
+import { supabaseClient } from "@/utils/supabase";
+import { Card } from "@/components/ui/card";
+
+export default function AlumnoId() {
+ const router = useRouter();
+ const { id } = router.query;
+ const [alumno, setAlumno] = useState(null);
+ const [formacionNombre, setFormacionNombre] = useState("");
+ const [competencias, setCompetencias] = useState([]);
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ if (!id) return;
+ const fetchAlumno = async () => {
+ // Traer datos del alumno y su formación
+ const { data, error } = await supabaseClient
+ .from("alumno")
+ .select(
+ `
+ id, nombre, correo, tipo_formacion,
+ curso(id, nombre),
+ inyeccion(id, nombre),
+ pildoras(id, nombre)
+ `
+ )
+ .eq("id", id)
+ .single();
+
+ if (data) {
+ setAlumno(data);
+ let nombreFormacion = "";
+ if (data.tipo_formacion === "curso")
+ nombreFormacion = data.curso?.nombre || "";
+ if (data.tipo_formacion === "inyeccion")
+ nombreFormacion = data.inyeccion?.nombre || "";
+ if (data.tipo_formacion === "pildora")
+ nombreFormacion = data.pildoras?.nombre || "";
+ setFormacionNombre(nombreFormacion);
+
+ // Traer competencias según tipo
+ if (data.tipo_formacion === "curso" && data.curso?.id) {
+ const { data: comps } = await supabaseClient
+ .from("curso_competencia")
+ .select("competencia(id, descripcion)")
+ .eq("curso_id", data.curso.id);
+ setCompetencias(comps?.map((c) => c.competencia) || []);
+ } else if (data.tipo_formacion === "inyeccion" && data.inyeccion?.id) {
+ const { data: comps } = await supabaseClient
+ .from("inyeccion_competencia_inyeccion")
+ .select("competencia_inyeccion(id, descripcion)")
+ .eq("inyeccion_id", data.inyeccion.id);
+ setCompetencias(comps?.map((c) => c.competencia_inyeccion) || []);
+ } else {
+ setCompetencias([]);
+ }
+ }
+ setLoading(false);
+ };
+ fetchAlumno();
+ }, [id]);
+
+ if (loading) return
Cargando...
;
+ if (!alumno)
+ return
Alumno no encontrado
;
+
+ return (
+
+
+
+ Información de {alumno.nombre}
+
+
+ Nombre: {alumno.nombre}
+
+
+ Correo: {alumno.correo}
+
+
+ Tipo de formación:{" "}
+ {alumno.tipo_formacion === "curso"
+ ? "Curso"
+ : alumno.tipo_formacion === "inyeccion"
+ ? "Inyección"
+ : alumno.tipo_formacion === "pildora"
+ ? "Píldora"
+ : ""}
+
+
+
+ {alumno.tipo_formacion === "curso"
+ ? "Curso"
+ : alumno.tipo_formacion === "inyeccion"
+ ? "Inyección"
+ : alumno.tipo_formacion === "pildora"
+ ? "Píldora"
+ : "Formación"}
+ :
+ {" "}
+ {formacionNombre}
+
+ {(alumno.tipo_formacion === "curso" ||
+ alumno.tipo_formacion === "inyeccion") && (
+
+
Competencias:
+
+ {competencias.map((comp) => (
+ - {comp.descripcion}
+ ))}
+
+
+ )}
+
+ Felicidades {alumno.nombre} por haber concluido tu{" "}
+ {alumno.tipo_formacion === "curso"
+ ? "curso"
+ : alumno.tipo_formacion === "inyeccion"
+ ? "inyección"
+ : alumno.tipo_formacion === "pildora"
+ ? "píldora"
+ : "formación"}{" "}
+ {formacionNombre}, agradecemos tu participación, te esperamos pronto por
+ aquí para seguir formando tu camino.
+
+
+ );
+}
diff --git a/diplomas/src/pages/alumnosManual.jsx b/diplomas/src/pages/alumnosManual.jsx
index 9bccdd0..ab26b84 100644
--- a/diplomas/src/pages/alumnosManual.jsx
+++ b/diplomas/src/pages/alumnosManual.jsx
@@ -11,7 +11,6 @@ import {
} from "@/components/ui/select";
import {
Dialog,
- DialogTrigger,
DialogContent,
DialogHeader,
DialogTitle,
@@ -24,61 +23,99 @@ import { alumnoSchema } from "@/schemas/AlumnosSchema";
export default function AlumnosManual() {
const [cursos, setCursos] = useState([]);
- const [isDialogOpen, setIsDialogOpen] = useState(false); // Estado para controlar el diálogo
+ const [inyecciones, setInyecciones] = useState([]);
+ const [pildoras, setPildoras] = useState([]);
+ const [isDialogOpen, setIsDialogOpen] = useState(false);
- // Configurar React Hook Form con zod
const {
register,
handleSubmit,
setValue,
+ watch,
formState: { errors },
reset,
+ clearErrors,
} = useForm({
resolver: zodResolver(alumnoSchema),
defaultValues: {
nombre: "",
correo: "",
telefono: "",
+ tipo: "",
cursoSeleccionado: "",
},
});
- // Cargar cursos al iniciar el componente
+ const tipo = watch("tipo");
+ const cursoSeleccionado = watch("cursoSeleccionado");
+
+ // Cargar opciones según tipo seleccionado
useEffect(() => {
- const cargarCursos = async () => {
- const { data, error } = await supabaseClient
- .from("curso")
- .select("id, nombre");
- if (error) {
- console.error("Error al cargar cursos:", error.message);
- } else {
- setCursos(data);
- }
- };
- cargarCursos();
- }, []);
+ if (!tipo) {
+ setValue("cursoSeleccionado", "");
+ clearErrors("cursoSeleccionado");
+ return;
+ }
+ setValue("cursoSeleccionado", "");
+ clearErrors("cursoSeleccionado");
+ if (tipo === "curso") {
+ cargarCursos();
+ } else if (tipo === "inyeccion") {
+ cargarInyecciones();
+ } else if (tipo === "pildora") {
+ cargarPildoras();
+ }
+ // eslint-disable-next-line
+ }, [tipo]);
+
+ const cargarCursos = async () => {
+ const { data, error } = await supabaseClient
+ .from("curso")
+ .select("id, nombre");
+ if (!error) setCursos(data || []);
+ };
+ const cargarInyecciones = async () => {
+ const { data, error } = await supabaseClient
+ .from("inyeccion")
+ .select("id, nombre");
+ if (!error) setInyecciones(data || []);
+ };
+ const cargarPildoras = async () => {
+ const { data, error } = await supabaseClient
+ .from("pildoras")
+ .select("id, nombre");
+ if (!error) setPildoras(data || []);
+ };
// Guardar alumno
const manejarGuardar = async (data) => {
try {
- const { error } = await supabaseClient.from("alumno").insert([
- {
- nombre: data.nombre,
- correo: data.correo,
- telefono: data.telefono,
- curso_id: Number(data.cursoSeleccionado), // Guardar el ID del curso
- },
- ]);
+ let campos = {
+ nombre: data.nombre,
+ correo: data.correo,
+ telefono: data.telefono,
+ tipo_formacion: data.tipo,
+ curso_id: null,
+ inyeccion_id: null,
+ pildoras_id: null,
+ };
+ if (data.tipo === "curso")
+ campos.curso_id = Number(data.cursoSeleccionado);
+ if (data.tipo === "inyeccion")
+ campos.inyeccion_id = Number(data.cursoSeleccionado);
+ if (data.tipo === "pildora")
+ campos.pildoras_id = Number(data.cursoSeleccionado);
+
+ const { error } = await supabaseClient.from("alumno").insert([campos]);
if (error) {
- console.error("Error al guardar:", error.message);
- setIsDialogOpen(false); // Asegurarse de cerrar el diálogo en caso de error
+ setIsDialogOpen(false);
} else {
- setIsDialogOpen(true); // Mostrar el diálogo al guardar exitosamente
- reset(); // Reiniciar el formulario
+ setIsDialogOpen(true);
+ reset();
}
} catch (err) {
- console.error("Error inesperado:", err);
+ // Manejo de error inesperado
}
};
@@ -118,20 +155,77 @@ export default function AlumnosManual() {
{errors.telefono.message}
)}
+
+ {/* Select para tipo de formación */}
+ {errors.tipo && (
+
{errors.tipo.message}
+ )}
+
+ {/* Select para la opción según tipo */}
+ {tipo === "curso" && (
+
+ )}
+ {tipo === "inyeccion" && (
+
+ )}
+ {tipo === "pildora" && (
+
+ )}
{errors.cursoSeleccionado && (
{errors.cursoSeleccionado.message}
diff --git a/diplomas/src/pages/alumnosVista.jsx b/diplomas/src/pages/alumnosVista.jsx
index 2951e9d..c7f607b 100644
--- a/diplomas/src/pages/alumnosVista.jsx
+++ b/diplomas/src/pages/alumnosVista.jsx
@@ -33,6 +33,10 @@ export default function AlumnosVista() {
const [modalMensaje, setModalMensaje] = useState("");
const [nuevoCurso, setNuevoCurso] = useState("");
const [cursos, setCursos] = useState([]);
+ const [nuevoTipo, setNuevoTipo] = useState("");
+ const [nuevaFormacion, setNuevaFormacion] = useState("");
+ const [inyecciones, setInyecciones] = useState([]);
+ const [pildoras, setPildoras] = useState([]);
// Estado para confirmación de eliminación
const [confirmarEliminar, setConfirmarEliminar] = useState(false);
@@ -40,7 +44,10 @@ export default function AlumnosVista() {
useEffect(() => {
cargarAlumnos();
+ // ...cargar cursos, inyecciones, pildoras...
cargarCursos();
+ cargarInyecciones();
+ cargarPildoras();
}, []);
const cargarCursos = async () => {
@@ -52,16 +59,36 @@ export default function AlumnosVista() {
}
};
+ const cargarInyecciones = async () => {
+ const { data, error } = await supabaseClient.from("inyeccion").select("*");
+ if (!error) setInyecciones(data || []);
+ };
+
+ const cargarPildoras = async () => {
+ const { data, error } = await supabaseClient.from("pildoras").select("*");
+ if (!error) setPildoras(data || []);
+ };
+
const cargarAlumnos = async () => {
const { data, error } = await supabaseClient
.from("alumno")
- .select("id, nombre, correo, telefono, curso_id, curso(nombre)")
+ .select(
+ `
+ id,
+ nombre,
+ correo,
+ telefono,
+ tipo_formacion,
+ curso_id,
+ curso(nombre),
+ inyeccion_id,
+ inyeccion(nombre),
+ pildoras_id,
+ pildoras(nombre)
+ `
+ )
.order("id", { ascending: true });
- if (error) {
- console.error("Error al cargar alumnos:", error.message);
- } else {
- setAlumnos(data);
- }
+ setAlumnos(data || []);
};
const {
@@ -83,10 +110,18 @@ export default function AlumnosVista() {
// Iniciar edición
const iniciarEdicion = (alumno) => {
setAlumnoEditando(alumno.id);
- setValue("nombre", alumno.nombre);
- setValue("correo", alumno.correo);
- setValue("telefono", alumno.telefono);
- setValue("cursoSeleccionado", alumno.curso_id?.toString() || "");
+ setNuevoNombre(alumno.nombre || "");
+ setNuevoCorreo(alumno.correo || "");
+ setNuevoNumero(alumno.telefono || "");
+ setNuevoTipo(alumno.tipo_formacion || "");
+ // Detecta la formación actual según el tipo
+ if (alumno.tipo_formacion === "curso")
+ setNuevaFormacion(alumno.curso_id ? String(alumno.curso_id) : "");
+ else if (alumno.tipo_formacion === "inyeccion")
+ setNuevaFormacion(alumno.inyeccion_id ? String(alumno.inyeccion_id) : "");
+ else if (alumno.tipo_formacion === "pildora")
+ setNuevaFormacion(alumno.pildoras_id ? String(alumno.pildoras_id) : "");
+ else setNuevaFormacion("");
};
// Cancelar edición
@@ -96,25 +131,37 @@ export default function AlumnosVista() {
};
// Guardar cambios
- const guardarEdicion = async (data) => {
+ const guardarEdicion = async (id) => {
+ // Prepara el objeto de actualización
+ let updateObj = {
+ tipo_formacion: nuevoTipo,
+ curso_id: null,
+ inyeccion_id: null,
+ pildoras_id: null,
+ nombre: nuevoNombre,
+ correo: nuevoCorreo,
+ telefono: nuevoNumero,
+ };
+
+ if (nuevoTipo === "curso") updateObj.curso_id = Number(nuevaFormacion);
+ if (nuevoTipo === "inyeccion")
+ updateObj.inyeccion_id = Number(nuevaFormacion);
+ if (nuevoTipo === "pildora") updateObj.pildoras_id = Number(nuevaFormacion);
+
const { error } = await supabaseClient
.from("alumno")
- .update({
- nombre: data.nombre,
- correo: data.correo,
- telefono: data.telefono,
- curso_id: data.cursoSeleccionado,
- })
- .eq("id", alumnoEditando);
+ .update(updateObj)
+ .eq("id", id);
- if (error) {
- setModalMensaje("Error al actualizar el alumno");
+ if (!error) {
+ setModalMensaje("Alumno actualizado correctamente");
+ setMostrarModal(true);
+ setAlumnoEditando(null);
+ await cargarAlumnos(); // <--- Refresca la tabla
} else {
- setModalMensaje("Alumno actualizado exitosamente");
- await cargarAlumnos();
- cancelarEdicion();
+ setModalMensaje("Error al actualizar el alumno");
+ setMostrarModal(true);
}
- setMostrarModal(true);
};
// Confirmar eliminación
@@ -149,12 +196,13 @@ export default function AlumnosVista() {
-
+
ID |
Nombre |
Correo |
Teléfono |
- Curso |
+ Tipo |
+ Formación |
Acciones |
@@ -166,70 +214,101 @@ export default function AlumnosVista() {
{alumno.id}
-
- {errors.nombre && (
-
- {errors.nombre.message}
-
- )}
+ setNuevoNombre(e.target.value)}
+ className="border rounded px-2 py-1 text-black"
+ />
|
-
- {errors.correo && (
-
- {errors.correo.message}
-
- )}
+ setNuevoCorreo(e.target.value)}
+ className="border rounded px-2 py-1 text-black"
+ />
|
-
- {errors.telefono && (
-
- {errors.telefono.message}
-
- )}
+ setNuevoNumero(e.target.value)}
+ className="border rounded px-2 py-1 text-black"
+ />
|
- |
+
+ {nuevoTipo === "curso" && (
+ setNuevaFormacion(e.target.value)}
+ className="border rounded px-2 py-1 text-black"
+ required
+ >
+
{cursos.map((curso) => (
-
+
+
))}
-
-
- {errors.cursoSeleccionado && (
-
- {errors.cursoSeleccionado.message}
-
+
+ )}
+ {nuevoTipo === "inyeccion" && (
+ setNuevaFormacion(e.target.value)}
+ className="border rounded px-2 py-1 text-black"
+ required
+ >
+
+ {inyecciones.map((inyeccion) => (
+
+ ))}
+
+ )}
+ {nuevoTipo === "pildora" && (
+ setNuevaFormacion(e.target.value)}
+ className="border rounded px-2 py-1 text-black"
+ required
+ >
+
+ {pildoras.map((pildora) => (
+
+ ))}
+
)}
|
-
- |
) : (
@@ -239,22 +318,35 @@ export default function AlumnosVista() {
{alumno.correo} |
{alumno.telefono} |
- {alumno.curso?.nombre || "Sin curso"}
+ {alumno.tipo_formacion === "curso"
+ ? "Curso"
+ : alumno.tipo_formacion === "inyeccion"
+ ? "Inyección"
+ : alumno.tipo_formacion === "pildora"
+ ? "Píldora"
+ : ""}
|
-
-
+ {alumno.tipo_formacion === "curso" &&
+ alumno.curso?.nombre}
+ {alumno.tipo_formacion === "inyeccion" &&
+ alumno.inyeccion?.nombre}
+ {alumno.tipo_formacion === "pildora" &&
+ alumno.pildoras?.nombre}
+ |
+
+ iniciarEdicion(alumno)}
+ className="bg-blue-500 hover:bg-blue-700 text-white px-3 py-1 rounded mr-2"
>
Editar
-
-
-
+ confirmarEliminacion(alumno.id)}
+ className="bg-red-500 hover:bg-red-700 text-white px-3 py-1 rounded"
>
Eliminar
-
+
|
)
diff --git a/diplomas/src/pages/diplomasVista.jsx b/diplomas/src/pages/diplomasVista.jsx
index 4539b60..c5d6b89 100644
--- a/diplomas/src/pages/diplomasVista.jsx
+++ b/diplomas/src/pages/diplomasVista.jsx
@@ -18,9 +18,23 @@ export default function DiplomasVista() {
const cargarAlumnos = async () => {
const { data, error } = await supabaseClient
.from("alumno")
- .select("id, nombre, correo, telefono, curso(id, nombre)")
+ .select(
+ `
+ id,
+ nombre,
+ correo,
+ telefono,
+ tipo_formacion,
+ curso_id,
+ curso(id, nombre),
+ inyeccion_id,
+ inyeccion(id, nombre),
+ pildoras_id,
+ pildoras(id, nombre)
+ `
+ )
.order("id", { ascending: true });
- if (!error) setAlumnos(data);
+ setAlumnos(data || []);
};
cargarAlumnos();
}, []);
@@ -37,16 +51,38 @@ export default function DiplomasVista() {
};
useEffect(() => {
- if (alumnoSeleccionado && alumnoSeleccionado.curso?.id) {
- supabaseClient
- .from("curso_competencia")
- .select("competencia(id, descripcion)")
- .eq("curso_id", alumnoSeleccionado.curso.id)
- .then(({ data }) => {
- const comps = data?.map((c) => c.competencia).filter(Boolean) || [];
- setCompetencias(comps);
- setCompetenciasAcreditadas(comps.map((c) => c.id)); // Opcional: selecciona todas por default
- });
+ if (alumnoSeleccionado) {
+ if (
+ alumnoSeleccionado.tipo_formacion === "curso" &&
+ alumnoSeleccionado.curso?.id
+ ) {
+ supabaseClient
+ .from("curso_competencia")
+ .select("competencia(id, descripcion)")
+ .eq("curso_id", alumnoSeleccionado.curso.id)
+ .then(({ data }) => {
+ const comps = data?.map((c) => c.competencia).filter(Boolean) || [];
+ setCompetencias(comps);
+ setCompetenciasAcreditadas(comps.map((c) => c.id));
+ });
+ } else if (
+ alumnoSeleccionado.tipo_formacion === "inyeccion" &&
+ alumnoSeleccionado.inyeccion?.id
+ ) {
+ supabaseClient
+ .from("inyeccion_competencia_inyeccion")
+ .select("competencia_inyeccion(id, descripcion)")
+ .eq("inyeccion_id", alumnoSeleccionado.inyeccion.id)
+ .then(({ data }) => {
+ const comps =
+ data?.map((c) => c.competencia_inyeccion).filter(Boolean) || [];
+ setCompetencias(comps);
+ setCompetenciasAcreditadas(comps.map((c) => c.id));
+ });
+ } else {
+ setCompetencias([]);
+ setCompetenciasAcreditadas([]);
+ }
}
}, [alumnoSeleccionado]);
@@ -62,7 +98,8 @@ export default function DiplomasVista() {
Nombre |
Correo |
Teléfono |
- Curso |
+ Tipo |
+ Formación |
Acciones |
@@ -74,7 +111,20 @@ export default function DiplomasVista() {
{alumno.correo} |
{alumno.telefono} |
- {alumno.curso?.nombre || "Sin curso"}
+ {alumno.tipo_formacion === "curso"
+ ? "Curso"
+ : alumno.tipo_formacion === "inyeccion"
+ ? "Inyección"
+ : alumno.tipo_formacion === "pildora"
+ ? "Píldora"
+ : ""}
+ |
+
+ {alumno.tipo_formacion === "curso" && alumno.curso?.nombre}
+ {alumno.tipo_formacion === "inyeccion" &&
+ alumno.inyeccion?.nombre}
+ {alumno.tipo_formacion === "pildora" &&
+ alumno.pildoras?.nombre}
|
{/* Dialog para crear diploma y vista previa juntos */}
{mostrarDialog && (
-
+
{
+ e.preventDefault();
+ const desc = getValues("nuevaCompetencia").trim();
+ if (!desc) return;
+ if (competencias.some((c) => c.descripcion === desc)) {
+ setDialogMsg("La competencia ya fue agregada.");
+ setShowDialog(true);
+ return;
+ }
+ try {
+ let { data: existente } = await supabaseClient
+ .from("competencia_inyeccion")
+ .select("id")
+ .eq("descripcion", desc)
+ .maybeSingle();
+ let id = existente?.id;
+ if (!id) {
+ const { data: insertada, error } = await supabaseClient
+ .from("competencia_inyeccion")
+ .insert([{ descripcion: desc }])
+ .select("id")
+ .single();
+ if (error) throw error;
+ id = insertada.id;
+ }
+ setCompetencias([...competencias, { id, descripcion: desc }]);
+ setAddCompetencia(false);
+ setValue("nuevaCompetencia", "");
+ setDialogMsg("¡La competencia fue agregada exitosamente!");
+ setShowDialog(true);
+ } catch (err) {
+ setDialogMsg("Error al guardar la competencia: " + (err.message || err));
+ setShowDialog(true);
+ }
+ };
+
+ // Eliminar competencia
+ const handleDeleteCompetencia = (index) => {
+ setCompetencias(competencias.filter((_, i) => i !== index));
+ };
+
+ // Guardar inyección y asociar competencias
const onSubmit = async (data) => {
setLoading(true);
try {
const { nombre, descripcion, horas } = data;
- const { error } = await supabaseClient
+ const { data: inyeccion, error: errorIny } = await supabaseClient
.from("inyeccion")
- .insert([{ nombre, descripcion, horas: parseInt(horas, 10) }]);
- if (error) throw error;
+ .insert([{ nombre, descripcion, horas: parseInt(horas, 10) }])
+ .select("id")
+ .single();
+ if (errorIny) throw errorIny;
+ if (competencias.length) {
+ const relaciones = competencias.map((c) => ({
+ inyeccion_id: inyeccion.id,
+ competencia_inyeccion_id: c.id,
+ }));
+ const { error: errorPivote } = await supabaseClient
+ .from("inyeccion_competencia_inyeccion")
+ .insert(relaciones);
+ if (errorPivote) throw errorPivote;
+ }
setDialogMsg("Inyección guardada exitosamente");
+ setCompetencias([]);
reset();
} catch (err) {
setDialogMsg("Error: " + (err.message || err));
@@ -57,9 +120,7 @@ export default function InyeccionesManual() {
return (
-
- Nueva inyección
-
+ Nueva inyección
|