{
+ e.preventDefault();
+ // 1. Insertar la inyección
+ const { data: inyeccion, error } = await supabaseClient
+ .from("inyeccion")
+ .insert([
+ {
+ nombre,
+ descripcion,
+ horas: horas ? parseInt(horas) : null,
+ },
+ ])
+ .select("id")
+ .single();
+
+ if (error) {
+ setMensaje("Error al registrar la inyección: " + error.message);
+ return;
+ }
+
+ // 2. Procesar competencias si hay
+ if (inyeccion && competencias.trim()) {
+ const competenciasArr = competencias
+ .split(",")
+ .map((c) => c.trim())
+ .filter(Boolean);
+ let competenciasIds = [];
+ for (const desc of competenciasArr) {
+ // Buscar si ya existe la competencia
+ let { data: existente } = await supabaseClient
+ .from("competencia_inyeccion")
+ .select("id")
+ .eq("descripcion", desc)
+ .maybeSingle();
+
+ let compId = existente?.id;
+ if (!compId) {
+ // Insertar si no existe
+ const { data: insertada, error: errorInsert } = await supabaseClient
+ .from("competencia_inyeccion")
+ .insert([{ descripcion: desc }])
+ .select("id")
+ .single();
+ if (errorInsert) continue;
+ compId = insertada.id;
+ }
+ competenciasIds.push(compId);
+ }
+ // Relacionar competencias con la inyección
+ if (competenciasIds.length > 0) {
+ const relaciones = competenciasIds.map((cid) => ({
+ inyeccion_id: inyeccion.id,
+ competencia_inyeccion_id: cid,
+ }));
+ await supabaseClient
+ .from("inyeccion_competencia_inyeccion")
+ .insert(relaciones);
+ }
+ }
+
+ setMensaje("¡Inyección registrada correctamente!");
+ setNombre("");
+ setDescripcion("");
+ setHoras("");
+ setCompetencias("");
+ };
+
+ return (
+
+ );
+}
\ No newline at end of file
diff --git a/diplomas/src/components/pildorasManualForm.jsx b/diplomas/src/components/pildorasManualForm.jsx
new file mode 100644
index 0000000..2b5291d
--- /dev/null
+++ b/diplomas/src/components/pildorasManualForm.jsx
@@ -0,0 +1,60 @@
+import React, { useState } from "react";
+import { supabaseClient } from "@/utils/supabase";
+import { Button } from "@/components/ui/button";
+
+export function PildoraManualForm({ nombreSugerido = "" }) {
+ const [nombre, setNombre] = useState(nombreSugerido);
+ const [descripcion, setDescripcion] = useState("");
+ const [horas, setHoras] = useState("");
+ const [mensaje, setMensaje] = useState("");
+
+ const handleSubmit = async (e) => {
+ e.preventDefault();
+ const { error } = await supabaseClient.from("pildoras").insert([
+ {
+ nombre,
+ descripcion,
+ horas: horas ? parseInt(horas) : null,
+ },
+ ]);
+ if (error) {
+ setMensaje("Error al registrar la píldora: " + error.message);
+ } else {
+ setMensaje("¡Píldora registrada correctamente!");
+ setNombre("");
+ setDescripcion("");
+ setHoras("");
+ }
+ };
+
+ return (
+
+ );
+}
\ No newline at end of file
diff --git a/diplomas/src/components/ui/sonner.jsx b/diplomas/src/components/ui/sonner.jsx
new file mode 100644
index 0000000..132fc2e
--- /dev/null
+++ b/diplomas/src/components/ui/sonner.jsx
@@ -0,0 +1,24 @@
+import { useTheme } from "next-themes"
+import { Toaster as Sonner } from "sonner";
+
+const Toaster = ({
+ ...props
+}) => {
+ const { theme = "system" } = useTheme()
+
+ return (
+ ()
+ );
+}
+
+export { Toaster }
diff --git a/diplomas/src/pages/_app.js b/diplomas/src/pages/_app.js
index b97e52f..79d88a9 100644
--- a/diplomas/src/pages/_app.js
+++ b/diplomas/src/pages/_app.js
@@ -1,5 +1,11 @@
import "@/styles/globals.css";
+import { Toaster } from "sonner";
export default function App({ Component, pageProps }) {
- return ;
+ return (
+ <>
+
+ ;
+ >
+ );
}
diff --git a/diplomas/src/pages/alumnosArchivo.jsx b/diplomas/src/pages/alumnosArchivo.jsx
index c201a0a..f5b4652 100644
--- a/diplomas/src/pages/alumnosArchivo.jsx
+++ b/diplomas/src/pages/alumnosArchivo.jsx
@@ -15,6 +15,8 @@ import {
import { CursosManualForm } from "@/components/cursosManualForm";
import { supabaseClient } from "@/utils/supabase";
import { useRouter } from "next/router";
+import { InyeccionManualForm } from "@/components/inyeccionesManualForm";
+import { PildoraManualForm } from "@/components/pildorasManualForm";
export default function AlumnosArchivo() {
const [archivo, setArchivo] = useState(null);
@@ -25,6 +27,8 @@ export default function AlumnosArchivo() {
const [cursoFaltante, setCursoFaltante] = useState("");
const [dialogoAdvertencia, setDialogoAdvertencia] = useState(false);
const [rutaPendiente, setRutaPendiente] = useState(null);
+ const [mostrarDialogFormacion, setMostrarDialogFormacion] = useState(false);
+ const [formacionFaltante, setFormacionFaltante] = useState(null);
const router = useRouter();
useEffect(() => {
@@ -55,40 +59,92 @@ export default function AlumnosArchivo() {
const errores = [];
for (const alumno of datos) {
- // 1. Verifica si el curso existe
- const { data: cursosEncontrados, error: errorCurso } =
- await supabaseClient
+ let formacionId = null;
+ let tipo = (alumno.tipo || "").toLowerCase();
+
+ if (tipo === "curso") {
+ const { data: curso, error } = await supabaseClient
.from("curso")
.select("id")
- .eq("nombre", alumno.nombreCurso)
+ .eq("nombre", alumno.formacion)
.maybeSingle();
-
- if (errorCurso) {
- errores.push({ alumno, error: "Error al buscar el curso" });
+ if (error) {
+ errores.push({ alumno, error: "Error al buscar el curso" });
+ continue;
+ }
+ if (!curso) {
+ setFormacionFaltante({ tipo: "curso", nombre: alumno.formacion });
+ setMostrarDialogFormacion(true);
+ setMensajeDialogo(
+ `El curso "${alumno.formacion}" no existe. Por favor, regístralo primero.`
+ );
+ setDialogoAbierto(true);
+ return;
+ }
+ formacionId = curso.id;
+ } else if (tipo === "inyeccion") {
+ const { data: inyeccion, error } = await supabaseClient
+ .from("inyeccion")
+ .select("id")
+ .eq("nombre", alumno.formacion)
+ .maybeSingle();
+ if (error) {
+ errores.push({ alumno, error: "Error al buscar la inyección" });
+ continue;
+ }
+ if (!inyeccion) {
+ setFormacionFaltante({ tipo: "inyeccion", nombre: alumno.formacion });
+ setMostrarDialogFormacion(true);
+ setMensajeDialogo(
+ `La inyección "${alumno.formacion}" no existe. Por favor, regístrala primero.`
+ );
+ setDialogoAbierto(true);
+ return;
+ }
+ formacionId = inyeccion.id;
+ } else if (tipo === "pildora") {
+ const { data: pildora, error } = await supabaseClient
+ .from("pildoras")
+ .select("id")
+ .eq("nombre", alumno.formacion)
+ .maybeSingle();
+ if (error) {
+ errores.push({ alumno, error: "Error al buscar la píldora" });
+ continue;
+ }
+ if (!pildora) {
+ setFormacionFaltante({ tipo: "pildora", nombre: alumno.formacion });
+ setMostrarDialogFormacion(true);
+ setMensajeDialogo(
+ `La píldora "${alumno.formacion}" no existe. Por favor, regístrala primero.`
+ );
+ setDialogoAbierto(true);
+ return;
+ }
+ formacionId = pildora.id;
+ } else {
+ errores.push({ alumno, error: "Tipo de formación no válido" });
continue;
}
- if (!cursosEncontrados) {
- // Si no existe el curso, muestra el dialog para registrar el curso
- setCursoFaltante(alumno.nombreCurso);
- setMostrarDialogCurso(true);
- setMensajeDialogo(
- `El curso "${alumno.nombreCurso}" no existe. Por favor, regístralo primero.`
- );
- setDialogoAbierto(true);
- return; // Detiene el registro de alumnos
- }
+ // Registrar alumno con el campo correcto según tipo
+ let body = {
+ nombre: alumno.nombre,
+ correo: alumno.correo,
+ telefono: alumno.telefono,
+ tipo_formacion: tipo,
+ curso_id: null,
+ inyeccion_id: null,
+ pildoras_id: null,
+ };
+ if (tipo === "curso") body.curso_id = formacionId;
+ if (tipo === "inyeccion") body.inyeccion_id = formacionId;
+ if (tipo === "pildora") body.pildoras_id = formacionId;
- // 2. Si existe, registra el alumno con el curso_id correcto
const res = await fetch("/api/alumno", {
method: "POST",
headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- nombre: alumno.nombre,
- correo: alumno.correo,
- telefono: alumno.telefono,
- curso_id: cursosEncontrados.id,
- }),
+ body: JSON.stringify(body),
});
const resultado = await res.json();
@@ -289,6 +345,38 @@ export default function AlumnosArchivo() {
+
+ {/* Dialog para formacion faltante */}
+
);
}
diff --git a/diplomas/src/pages/alumnosVista.jsx b/diplomas/src/pages/alumnosVista.jsx
index c7f607b..0fe726f 100644
--- a/diplomas/src/pages/alumnosVista.jsx
+++ b/diplomas/src/pages/alumnosVista.jsx
@@ -334,7 +334,7 @@ export default function AlumnosVista() {
{alumno.tipo_formacion === "pildora" &&
alumno.pildoras?.nombre}
-
+ |
|