diff --git a/backend/routes/api.js b/backend/routes/api.js index c789a49..aeba6a1 100644 --- a/backend/routes/api.js +++ b/backend/routes/api.js @@ -4,49 +4,54 @@ const pool = require("../db"); const router = express.Router(); // LISTAR (con filtros opcionales) -router.get("/tareas", async (req, res) => { - const { materia, estado } = req.query; +router.get("/polls", async (req, res) => { + const { categoria, estado } = req.query; const where = []; const params = []; - if (materia) { where.push("materia = ?"); params.push(materia); } + if (categoria) { where.push("categoria = ?"); params.push(categoria); } if (estado) { where.push("estado = ?"); params.push(estado); } - const sql = `SELECT * FROM tareas ${where.length ? "WHERE " + where.join(" AND ") : ""} ORDER BY id DESC`; + const sql = `SELECT * FROM encuestas ${where.length ? "WHERE " + where.join(" AND ") : ""} ORDER BY id DESC`; const [rows] = await pool.query(sql, params); res.json(rows); }); -router.post("/tareas", async (req, res) => { - const { materia, titulo, descripcion } = req.body; - if (!materia || !titulo) return res.status(400).json({ error: "materia y titulo son obligatorios" }); +router.post("/polls", async (req, res) => { + const { categoria, pregunta, opciones } = req.body; + if (!categoria || !pregunta) + return res.status(400).json({ error: "categoria y pregunta son obligatorios" }); const [r] = await pool.query( - "INSERT INTO tareas (materia, titulo, descripcion) VALUES (?,?,?)", - [materia.trim(), titulo.trim(), (descripcion || "").trim() || null] + "INSERT INTO encuestas (categoria, pregunta, opciones) VALUES (?,?,?)", + [categoria.trim(), pregunta.trim(), (opciones || "").trim() || null] ); res.status(201).json({ id: r.insertId }); }); -router.put("/tareas/:id", async (req, res) => { +router.put("/polls/:id", async (req, res) => { const id = Number(req.params.id); - const { materia, titulo, descripcion, estado } = req.body; + const { categoria, pregunta, opciones, estado } = req.body; const [r] = await pool.query( - `UPDATE tareas - SET materia = ?, titulo = ?, descripcion = ?, estado = ? + `UPDATE encuestas + SET categoria = ?, pregunta = ?, opciones = ?, estado = ? WHERE id = ?`, - [materia, titulo, descripcion || null, estado, id] + [categoria, pregunta, opciones || null, estado, id] ); - if (r.affectedRows === 0) return res.status(404).json({ error: "No existe" }); + if (r.affectedRows === 0) + return res.status(404).json({ error: "No existe" }); + res.json({ ok: true }); }); -router.delete("/tareas/:id", async (req, res) => { +router.delete("/polls/:id", async (req, res) => { const id = Number(req.params.id); - const [r] = await pool.query("DELETE FROM tareas WHERE id = ?", [id]); - if (r.affectedRows === 0) return res.status(404).json({ error: "No existe" }); + const [r] = await pool.query("DELETE FROM encuestas WHERE id = ?", [id]); + if (r.affectedRows === 0) + return res.status(404).json({ error: "No existe" }); + res.json({ ok: true }); }); diff --git a/backend/sql/schema.sql b/backend/sql/schema.sql index 63e345f..813bb4d 100644 --- a/backend/sql/schema.sql +++ b/backend/sql/schema.sql @@ -1,4 +1,4 @@ -CREATE TABLE IF NOT EXISTS tareas ( +CREATE TABLE IF NOT EXISTS encuestas ( id INT AUTO_INCREMENT PRIMARY KEY, materia VARCHAR(80) NOT NULL, titulo VARCHAR(120) NOT NULL, diff --git a/frontend/app.js b/frontend/app.js index 0d1167c..f86c8dc 100644 --- a/frontend/app.js +++ b/frontend/app.js @@ -1,79 +1,107 @@ -const tbody = document.querySelector("#tbody"); -const frm = document.querySelector("#frm"); -const fMateria = document.querySelector("#fMateria"); -const fEstado = document.querySelector("#fEstado"); - -async function load() { - const qs = new URLSearchParams(); - if (fMateria.value.trim()) qs.set("materia", fMateria.value.trim()); - if (fEstado.value) qs.set("estado", fEstado.value); - - const res = await fetch("/api/tareas?" + qs.toString()); - const data = await res.json(); - - tbody.innerHTML = data.map(t => ` - - ${t.id} - ${escapeHtml(t.materia)} - ${escapeHtml(t.titulo)} - - - - - - - - `).join(""); - - document.querySelectorAll(".estado").forEach(sel => { - sel.addEventListener("change", async (e) => { - const id = e.target.dataset.id; - const estado = e.target.value; - const row = data.find(x => x.id == id); - await fetch("/api/tareas/" + id, { - method: "PUT", - headers: {"Content-Type":"application/json"}, - body: JSON.stringify({ ...row, estado }) - }); - load(); +document.addEventListener("DOMContentLoaded", () => { + + let votos = { + excelente: 0, + bueno: 0, + regular: 0, + malo: 0 + }; + + const formEncuesta = document.getElementById("formEncuesta"); + const btnVotar = document.getElementById("btnVotar"); + const btnNuevaEncuesta = document.getElementById("btnNuevaEncuesta"); + const btnReiniciarVotos = document.getElementById("btnReiniciarVotos"); + + const barras = { + excelente: document.querySelector(".progreso.excelente"), + bueno: document.querySelector(".progreso.bueno"), + regular: document.querySelector(".progreso.regular"), + malo: document.querySelector(".progreso.malo") + }; + + actualizarBarras(); + + // CREAR NUEVA ENCUESTA + btnNuevaEncuesta.addEventListener("click", () => { + + const preguntas = [ + document.getElementById("preg1").value, + document.getElementById("preg2").value, + document.getElementById("preg3").value + ]; + + if (preguntas.some(p => p.trim() === "")) { + alert("Debes escribir todas las preguntas"); + return; + } + + // Limpiar SOLO preguntas, no el botón + const botonVotar = btnVotar; + formEncuesta.innerHTML = ""; + formEncuesta.appendChild(botonVotar); + + preguntas.forEach((texto, index) => { + const bloque = document.createElement("div"); + bloque.innerHTML = ` +

${texto}

+ + + + + `; + formEncuesta.insertBefore(bloque, botonVotar); + }); + + reiniciarVotos(); }); - }); - document.querySelectorAll("button[data-del]").forEach(btn => { - btn.addEventListener("click", async () => { - await fetch("/api/tareas/" + btn.dataset.del, { method: "DELETE" }); - load(); + // VOTAR + btnVotar.addEventListener("click", () => { + + const seleccionados = document.querySelectorAll("input[type='radio']:checked"); + + if (seleccionados.length === 0) { + alert("Debes seleccionar al menos una opción"); + return; + } + + seleccionados.forEach(radio => { + votos[radio.value]++; + }); + + actualizarBarras(); + limpiarFormulario(); }); - }); -} - -frm.addEventListener("submit", async (e) => { - e.preventDefault(); - const materia = document.querySelector("#materia").value; - const titulo = document.querySelector("#titulo").value; - const descripcion = document.querySelector("#descripcion").value; - - await fetch("/api/tareas", { - method: "POST", - headers: {"Content-Type":"application/json"}, - body: JSON.stringify({ materia, titulo, descripcion }) - }); - frm.reset(); - load(); -}); -document.querySelector("#btnFiltrar").addEventListener("click", load); -document.querySelector("#btnReset").addEventListener("click", () => { - fMateria.value = ""; - fEstado.value = ""; - load(); -}); + // REINICIAR VOTOS + btnReiniciarVotos.addEventListener("click", () => { + reiniciarVotos(); + }); + + function reiniciarVotos() { + votos = { + excelente: 0, + bueno: 0, + regular: 0, + malo: 0 + }; + actualizarBarras(); + limpiarFormulario(); + } + + function actualizarBarras() { + const total = Object.values(votos).reduce((a, b) => a + b, 0); -function escapeHtml(s) { - return String(s).replaceAll("&","&").replaceAll("<","<").replaceAll(">",">"); -} + for (let opcion in votos) { + const porcentaje = total === 0 ? 0 : Math.round((votos[opcion] / total) * 100); + barras[opcion].style.width = porcentaje + "%"; + barras[opcion].textContent = porcentaje + "%"; + } + } -load(); + function limpiarFormulario() { + document.querySelectorAll("input[type='radio']") + .forEach(r => r.checked = false); + } + +}); diff --git a/frontend/index.html b/frontend/index.html index 218437b..d9ac44a 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -1,47 +1,79 @@ - + - - - Grupo 1 - Tareas - + + + Encuesta y Resultados - Grupo 5 + -
-

Gestor de Tareas (Grupo 1)

- -
-

Nueva tarea

-
- - - - -
-
- -
-

Listado

-
- - - - -
- - - - - - -
IDMateriaTítuloEstadoAcciones
-
-
- - + +
+

Encuesta y Resultados - Grupo 5

+ +
+ +

¿Cómo calificarías nuestra encuesta?

+ + + + + +

¿Qué le pareció nuestra encuesta sencilla?

+ + + + + +

¿Qué calificación nos darían por esta encuesta?

+ + + + + + +
+ +

Resultados de la Encuesta

+ +
+ Excelente +
60%
+
+ +
+ Bueno +
25%
+
+ +
+ Regular +
10%
+
+ +
+ Malo +
5%
+
+ + + + +
+

Nueva encuesta

+ + + + + + +
+ + +
+ + diff --git a/frontend/style.css b/frontend/style.css index 5682d55..af42d66 100644 --- a/frontend/style.css +++ b/frontend/style.css @@ -1,9 +1,85 @@ -body { font-family: system-ui, Arial, sans-serif; margin: 0; background: #0f172a; color: #e2e8f0; } -.container { max-width: 980px; margin: 0 auto; padding: 20px; } -.card { background: #111c36; padding: 16px; border-radius: 12px; margin: 14px 0; } -input, select, button { padding: 10px; border-radius: 10px; border: 1px solid #24304b; background: #0b1224; color: #e2e8f0; } -button { cursor: pointer; } -table { width: 100%; border-collapse: collapse; margin-top: 10px; } -th, td { border-bottom: 1px solid #24304b; padding: 10px; text-align: left; } -.filters { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; } -form { display: flex; gap: 10px; flex-wrap: wrap; } +body { + font-family: Arial, sans-serif; + background: #063d74; + display: flex; + justify-content: center; + padding: 20px; +} + +.encuesta { + background: #ffffff; + width: 400px; + padding: 25px; + border-radius: 10px; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); +} + +.encuesta h2 { + text-align: center; + margin-bottom: 10px; +} + +.pregunta { + font-weight: bold; + margin-bottom: 10px; +} + +form label { + display: block; + margin-bottom: 8px; + cursor: pointer; +} + +button { + width: 100%; + margin-top: 15px; + padding: 10px 0; + background: #007bff; + color: white; + font-size: 16px; + border-radius: 6px; + cursor: pointer; +} + +button:hover { + background: #0056b3; +} + +h3 { + margin-top: 25px; +} + +.resultados { + margin-bottom: 12px; +} + +.barra { + background: #ddd; + border-radius: 20px; + overflow: hidden; + height: 22px; +} + +.Exelente { + width: 60%; + background: #007bff; +} + +.Exelente { + width: 25% y 30; + background: #536f8d; +} + +.Exelente { + width: 10% y 20%; + background: #572828; +} + +.Malo { + width: 5%; + background: #ff0000; +} + + + +