Conecctado Alumno y Curso con Supabase (agregado manualmente)

This commit is contained in:
BenitoBB 2025-04-25 18:16:30 -06:00
parent 567efccc06
commit b658bf9496
5 changed files with 225 additions and 36 deletions

View File

@ -15,6 +15,7 @@
"@radix-ui/react-slot": "^1.2.0",
"@radix-ui/react-tabs": "^1.1.9",
"@radix-ui/react-tooltip": "^1.2.4",
"@supabase/supabase-js": "^2.49.4",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"diplomas": "file:",
@ -1958,6 +1959,73 @@
"integrity": "sha512-zxnHvoMQVqewTJr/W4pKjF0bMGiKJv1WX7bSrkl46Hg0QjESbzBROWK0Wg4RphzSOS5Jiy7eFimmM3UgMrMZbQ==",
"dev": true
},
"node_modules/@supabase/auth-js": {
"version": "2.69.1",
"resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.69.1.tgz",
"integrity": "sha512-FILtt5WjCNzmReeRLq5wRs3iShwmnWgBvxHfqapC/VoljJl+W8hDAyFmf1NVw3zH+ZjZ05AKxiKxVeb0HNWRMQ==",
"dependencies": {
"@supabase/node-fetch": "^2.6.14"
}
},
"node_modules/@supabase/functions-js": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.4.4.tgz",
"integrity": "sha512-WL2p6r4AXNGwop7iwvul2BvOtuJ1YQy8EbOd0dhG1oN1q8el/BIRSFCFnWAMM/vJJlHWLi4ad22sKbKr9mvjoA==",
"dependencies": {
"@supabase/node-fetch": "^2.6.14"
}
},
"node_modules/@supabase/node-fetch": {
"version": "2.6.15",
"resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz",
"integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
}
},
"node_modules/@supabase/postgrest-js": {
"version": "1.19.4",
"resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.19.4.tgz",
"integrity": "sha512-O4soKqKtZIW3olqmbXXbKugUtByD2jPa8kL2m2c1oozAO11uCcGrRhkZL0kVxjBLrXHE0mdSkFsMj7jDSfyNpw==",
"dependencies": {
"@supabase/node-fetch": "^2.6.14"
}
},
"node_modules/@supabase/realtime-js": {
"version": "2.11.2",
"resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.11.2.tgz",
"integrity": "sha512-u/XeuL2Y0QEhXSoIPZZwR6wMXgB+RQbJzG9VErA3VghVt7uRfSVsjeqd7m5GhX3JR6dM/WRmLbVR8URpDWG4+w==",
"dependencies": {
"@supabase/node-fetch": "^2.6.14",
"@types/phoenix": "^1.5.4",
"@types/ws": "^8.5.10",
"ws": "^8.18.0"
}
},
"node_modules/@supabase/storage-js": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.7.1.tgz",
"integrity": "sha512-asYHcyDR1fKqrMpytAS1zjyEfvxuOIp1CIXX7ji4lHHcJKqyk+sLl/Vxgm4sN6u8zvuUtae9e4kDxQP2qrwWBA==",
"dependencies": {
"@supabase/node-fetch": "^2.6.14"
}
},
"node_modules/@supabase/supabase-js": {
"version": "2.49.4",
"resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.49.4.tgz",
"integrity": "sha512-jUF0uRUmS8BKt37t01qaZ88H9yV1mbGYnqLeuFWLcdV+x1P4fl0yP9DGtaEhFPZcwSom7u16GkLEH9QJZOqOkw==",
"dependencies": {
"@supabase/auth-js": "2.69.1",
"@supabase/functions-js": "2.4.4",
"@supabase/node-fetch": "2.6.15",
"@supabase/postgrest-js": "1.19.4",
"@supabase/realtime-js": "2.11.2",
"@supabase/storage-js": "2.7.1"
}
},
"node_modules/@swc/counter": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
@ -2252,6 +2320,27 @@
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
"dev": true
},
"node_modules/@types/node": {
"version": "22.15.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.2.tgz",
"integrity": "sha512-uKXqKN9beGoMdBfcaTY1ecwz6ctxuJAcUlwE55938g0ZJ8lRxwAZqRz2AJ4pzpt5dHdTPMB863UZ0ESiFUcP7A==",
"dependencies": {
"undici-types": "~6.21.0"
}
},
"node_modules/@types/phoenix": {
"version": "1.6.6",
"resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.6.tgz",
"integrity": "sha512-PIzZZlEppgrpoT2QgbnDU+MMzuR6BbCjllj0bM70lWoejMeNJAxCchxnv7J3XFkI8MpygtRpzXrIlmWUBclP5A=="
},
"node_modules/@types/ws": {
"version": "8.18.1",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
"integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.30.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.30.1.tgz",
@ -6370,6 +6459,11 @@
"node": ">=8.0"
}
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"node_modules/ts-api-utils": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
@ -6525,6 +6619,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="
},
"node_modules/unrs-resolver": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.5.0.tgz",
@ -6602,6 +6701,20 @@
}
}
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@ -6711,6 +6824,26 @@
"node": ">=0.10.0"
}
},
"node_modules/ws": {
"version": "8.18.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz",
"integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",

View File

@ -16,6 +16,7 @@
"@radix-ui/react-slot": "^1.2.0",
"@radix-ui/react-tabs": "^1.1.9",
"@radix-ui/react-tooltip": "^1.2.4",
"@supabase/supabase-js": "^2.49.4",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"diplomas": "file:",

View File

@ -1,23 +1,65 @@
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import Layout from "@/components/layout/Layout";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
Select,
SelectTrigger,
SelectValue,
SelectContent,
SelectItem,
} from "@/components/ui/select";
import { supabase } from "@/lib/supabaseClient";
export default function AlumnosManual() {
const [nombre, setNombre] = useState("");
const [email, setEmail] = useState("");
const [curso, setCurso] = useState("");
const manejarGuardar = () => {
console.log({ nombre, email, curso });
const [cursoSeleccionado, setCursoSeleccionado] = useState("");
const [cursos, setCursos] = useState([]);
// Cargar cursos al iniciar el componente
useEffect(() => {
const cargarCursos = async () => {
const { data, error } = await supabase.from("curso").select("id, nombre");
if (error) {
console.error("Error al cargar cursos:", error.message);
} else {
setCursos(data);
}
};
cargarCursos();
}, []);
// Guardar alumno
const manejarGuardar = async () => {
try {
const { data, error } = await supabase.from("alumno").insert([
{
nombre: nombre,
correo: email,
},
]);
if (error) {
console.error("Error al guardar:", error.message);
alert("Error al guardar: " + error.message);
} else {
console.log("Alumno guardado:", data);
alert("Alumno guardado con éxito");
setNombre("");
setEmail("");
setCursoSeleccionado("");
}
} catch (err) {
console.error("Error inesperado:", err);
}
};
return (
<Layout>
<div className="w-[60vw] pt-10 flex flex-col items-end justify-center">
<div className="bg-white p-8 font-sans text-center w-[70%]">
<h1 className="text-xl font-semibold mb-4 text-black">
Nuevo alumno
</h1>
<h1 className="text-xl font-semibold mb-4 text-black">Nuevo alumno</h1>
<Input
type="text"
placeholder="Nombre"
@ -32,13 +74,22 @@ export default function AlumnosManual() {
onChange={(e) => setEmail(e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-md mb-3"
/>
<Input
type="text"
placeholder="Curso"
value={curso}
onChange={(e) => setCurso(e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-md mb-3"
/>
<Select
onValueChange={(value) => setCursoSeleccionado(value)}
value={cursoSeleccionado}
>
<SelectTrigger className="w-full px-3 py-2 border border-gray-300 rounded-md mb-4">
<SelectValue placeholder="Selecciona un curso" />
</SelectTrigger>
<SelectContent>
{cursos.map((curso) => (
<SelectItem key={curso.id} value={curso.id.toString()}>
{curso.nombre}
</SelectItem>
))}
</SelectContent>
</Select>
<Button
onClick={manejarGuardar}
className="bg-green-400 hover:bg-green-500 text-white font-bold py-2 px-4 rounded-md"

View File

@ -10,13 +10,34 @@ import {
} from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import React, { useState } from "react";
import { supabase } from "@/lib/supabaseClient";
const CursosManual = () => {
const [nombre, setNombre] = useState("");
const [descripcion, setDescripcion] = useState("");
const [descripcion, setDescripcion] = useState("");
const [competencia, setCompetencia] = useState("");
const manejarGuardar = () => {
console.log({ nombre, descripcion, competencia });
const [loading, setLoading] = useState(false);
const manejarGuardar = async () => {
setLoading(true);
const { error } = await supabase.from("curso").insert([
{
nombre,
descripcion,
horas: 10, // o usa otro input para personalizar
competencias: [competencia], // si es una sola, usa string. Si son varias, un array.
},
]);
setLoading(false);
if (error) {
alert("Error al guardar: " + error.message);
} else {
alert("Curso guardado correctamente");
setNombre("");
setDescripcion("");
setCompetencia("");
}
};
return (
@ -49,8 +70,9 @@ const CursosManual = () => {
<Button
onClick={manejarGuardar}
className="bg-green-400 hover:bg-green-500 text-white font-bold py-2 px-4 rounded-md"
disabled={loading}
>
Guardar
{loading ? "Guardando..." : "Guardar"}
</Button>
</div>
</div>

View File

@ -1,20 +1,3 @@
<<<<<<< HEAD
import Link from 'next/link';
import React from 'react';
export default function Home() {
return (
<div>
<h1>Welcome to the Diploma Generator</h1>
<Link href="/alumnos" className="text-blue-500 hover:underline">
Go to Alumnos Page
</Link>
<br></br>
<Link href="/diplomas" className="text-blue-500 hover:underline">
Go to Diplomas Page
</Link>
</div>
=======
import Layout from "@/components/layout/Layout";
export default function Home() {
@ -24,6 +7,5 @@ export default function Home() {
<h1 className="text-3xl font-bold text-black">¡Bienvenido a SIDAC!</h1>
</div>
</Layout>
>>>>>>> 493b05750bcfa46ff9d030c3f0a85d596f403d28
);
}