diff --git a/bd/bd.sql b/bd/bd.sql index 9ed1dfe..c28cd61 100644 --- a/bd/bd.sql +++ b/bd/bd.sql @@ -1,5 +1,5 @@ -create database DeliveryFast; -CREATE USER 'proyectoSistemas'@'localhost' IDENTIFIED BY 'password'; -GRANT CREATE,ALTER,DROP,INSERT,UPDATE,DELETE,SELECT,CREATE VIEW,REFERENCES on DeliveryFast.* to 'proyectoSistemas'@'localhost'; -GRANT LOCK TABLES, PROCESS ON *.* TO 'proyectoSistemas'@'localhost'; -FLUSH PRIVILEGES; \ No newline at end of file +create database TicketFei; +CREATE USER 'desarrolloTicketFei'@'localhost' IDENTIFIED BY 'password'; +GRANT CREATE,ALTER,DROP,INSERT,UPDATE,DELETE,SELECT,CREATE VIEW,REFERENCES on TicketFei.* to 'desarrolloTicketFei'@'localhost'; +GRANT LOCK TABLES, PROCESS ON *.* TO 'desarrolloTicketFei'@'localhost'; +FLUSH PRIVILEGES; diff --git a/bd/tablas.sql b/bd/tablas.sql new file mode 100644 index 0000000..7e82cad --- /dev/null +++ b/bd/tablas.sql @@ -0,0 +1,63 @@ +USE TicketFei; + +CREATE TABLE usuarios ( + id INT AUTO_INCREMENT PRIMARY KEY, + nombre VARCHAR(255) NOT NULL, + apellidoPaterno VARCHAR(255) NOT NULL, + apellidoMaterno VARCHAR(255) NOT NULL, + usuario VARCHAR(255) NOT NULL, + contraseña VARCHAR(255) NOT NULL +); +INSERT INTO usuarios (nombre, apellidoPaterno, apellidoMaterno, usuario, contraseña) VALUES +('Aaron', 'Bonilla', 'Gonzalez', 's22', '123'), +('Carlos', 'Palestina', 'Alducin', 's23', '123'), +('Miguel', 'Diaz', 'Villa', 's24', '123'); + +SELECT * FROM usuarios; +DROP TABLE usuarios; + +-- concierto +CREATE TABLE conciertos ( + id_concierto INT AUTO_INCREMENT PRIMARY KEY, + nombre_concierto VARCHAR(255) NOT NULL, + artista VARCHAR(255) NOT NULL, + fecha DATE NOT NULL, + calle VARCHAR(255) NOT NULL, + colonia VARCHAR(255) NOT NULL, + numero_direccion VARCHAR(255) NOT NULL, + codigo_postal VARCHAR(10) NOT NULL, + estado VARCHAR(255) NOT NULL, + capacidad_total INT NOT NULL +); +INSERT INTO conciertos (nombre_concierto, artista, fecha, calle, colonia, numero_direccion, codigo_postal, estado, capacidad_total) +VALUES ('Linux Fest', 'Junior H', '2025-06-15', 'Av. Xalapa', 'Obrero Campesina', 's/n', '91020', 'Veracruz', 5000); +SELECT * FROM conciertos; +DROP TABLE conciertos; +-- Zona +CREATE TABLE zonas ( + id_zona INT AUTO_INCREMENT PRIMARY KEY, + id_concierto INT NOT NULL, + nombre_zona ENUM('General', 'Plata', 'Oro', 'VIP') NOT NULL, + capacidad INT NOT NULL, + precio DECIMAL(10,2) NOT NULL, + FOREIGN KEY (id_concierto) REFERENCES conciertos(id_concierto) ON DELETE CASCADE +); +INSERT INTO zonas (id_concierto, nombre_zona, capacidad, precio) VALUES +(1, 'General', 20000, 800.00), +(1, 'Plata', 15000, 1500.00), +(1, 'Oro', 10000, 2500.00), +(1, 'VIP', 5000, 5000.00); +DROP TABLE zonas; +-- Obtener todos los conciertos con sus zonas y precios +SELECT c.id_concierto, c.nombre_concierto, c.artista, c.fecha, + z.nombre_zona, z.capacidad, z.precio +FROM conciertos c +JOIN zonas z ON c.id_concierto = z.id_concierto; + +-- Consultar un concierto específico con sus zonas +SELECT c.nombre_concierto, c.artista, c.fecha, + z.nombre_zona, z.capacidad, z.precio +FROM conciertos c +JOIN zonas z ON c.id_concierto = z.id_concierto +WHERE c.id_concierto = 1; + diff --git a/ventanaPrincipal.html b/controladores/buscar_conciertos.php similarity index 100% rename from ventanaPrincipal.html rename to controladores/buscar_conciertos.php diff --git a/controladores/cerrar_sesion.php b/controladores/cerrar_sesion.php new file mode 100644 index 0000000..6675094 --- /dev/null +++ b/controladores/cerrar_sesion.php @@ -0,0 +1,21 @@ +<?php + + include 'conexion.php'; + + if ($_SERVER['REQUEST_METHOD'] === 'POST') { + session_start(); + + session_unset(); + session_destroy(); + + echo json_encode(['success' => true]); + } else { + http_response_code(405); + echo json_encode(['success' => false, 'message' => 'Método no permitido']); + } + + if (isset($conexionBD)) { + $conexionBD->close(); + } + +?> diff --git a/controladores/conciertos.php b/controladores/conciertos.php new file mode 100644 index 0000000..d625eee --- /dev/null +++ b/controladores/conciertos.php @@ -0,0 +1,55 @@ +<?php +include 'conexion.php'; + +// Configurar respuesta como JSON +header('Content-Type: application/json'); +error_reporting(E_ALL); +ini_set('display_errors', 1); + +$consulta = "SELECT c.id_concierto, c.nombre_concierto, c.artista, c.fecha, c.calle, c.colonia, + c.numero_direccion, c.codigo_postal, c.estado, c.capacidad_total, + z.nombre_zona, z.capacidad AS capacidad_zona, z.precio + FROM conciertos c + LEFT JOIN zonas z ON c.id_concierto = z.id_concierto + ORDER BY c.id_concierto, FIELD(z.nombre_zona, 'General', 'Plata', 'Oro', 'VIP')"; + +$resultado = $conexionBD->query($consulta); + +$conciertos = []; + +if ($resultado->num_rows > 0) { + while ($fila = $resultado->fetch_assoc()) { + $id_concierto = $fila['id_concierto']; + + if (!isset($conciertos[$id_concierto])) { + $direccion = trim("{$fila['calle']}, {$fila['colonia']}, #{$fila['numero_direccion']}, CP: {$fila['codigo_postal']}, {$fila['estado']}"); + if ($direccion === ", , #, CP: , ") { + $direccion = "Dirección no definida"; + } + + $conciertos[$id_concierto] = [ + 'id' => $id_concierto, + 'nombre_concierto' => $fila['nombre_concierto'], + 'artista' => $fila['artista'], + 'fecha' => $fila['fecha'], + 'direccion' => $direccion, + 'capacidad_total' => $fila['capacidad_total'], + 'zonas' => [] + ]; + } + + if (!empty($fila['nombre_zona'])) { + $conciertos[$id_concierto]['zonas'][] = [ + 'nombre_zona' => $fila['nombre_zona'], + 'capacidad' => $fila['capacidad_zona'], + 'precio' => $fila['precio'] + ]; + } + } +} + +// Enviar JSON +echo json_encode(array_values($conciertos), JSON_PRETTY_PRINT); + +$conexionBD->close(); +?> diff --git a/controladores/conexion.php b/controladores/conexion.php index 93a603e..710c5ae 100644 --- a/controladores/conexion.php +++ b/controladores/conexion.php @@ -1,4 +1,7 @@ <?php + error_reporting(E_ALL); + ini_set('display_errors', 1); + // Valores para la conexión $direccion = "localhost:3306"; $nombreBD = "TicketFei"; @@ -10,6 +13,6 @@ // Verificar si hay un error en la conexión if ($conexionBD->connect_error) { - die("Error en la conexión: " . $conexionBD->connect_error); + die(json_encode(["error" => "Error en la conexión: " . $conexionBD->connect_error])); } ?> diff --git a/controladores/insertar_concierto.php b/controladores/insertar_concierto.php new file mode 100644 index 0000000..aafb6f2 --- /dev/null +++ b/controladores/insertar_concierto.php @@ -0,0 +1,66 @@ +<?php +include 'conexion.php'; + +header('Content-Type: application/json'); +error_reporting(E_ALL); +ini_set('display_errors', 1); + +// Leer el JSON enviado +$datos = json_decode(file_get_contents("php://input"), true); + +if ($datos === null) { + echo json_encode(['insercionCorrecta' => false, 'error' => 'Error al decodificar JSON']); + exit; +} + +// Verificar que los datos requeridos estén presentes +if (!isset($datos['nombre_concierto'], $datos['zonas'])) { + echo json_encode(['insercionCorrecta' => false, 'error' => 'Faltan datos requeridos']); + exit; +} + +// Extraer valores +$nombre_concierto = $datos['nombre_concierto']; +$artista = $datos['artista']; +$fecha = $datos['fecha']; +$calle = $datos['calle']; +$colonia = $datos['colonia']; +$numero_direccion = $datos['numero_direccion']; +$codigo_postal = $datos['codigo_postal']; +$estado = $datos['estado']; +$capacidad_total = $datos['capacidad_total']; +$zonas = $datos['zonas']; + +$conexionBD->begin_transaction(); + +try { + // Insertar el concierto + $consulta = "INSERT INTO conciertos (nombre_concierto, artista, fecha, calle, colonia, numero_direccion, codigo_postal, estado, capacidad_total) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; + $stmt = $conexionBD->prepare($consulta); + $stmt->bind_param("ssssssssi", $nombre_concierto, $artista, $fecha, $calle, $colonia, $numero_direccion, $codigo_postal, $estado, $capacidad_total); + $stmt->execute(); + + $id_concierto = $conexionBD->insert_id; + $stmt->close(); + + // Insertar zonas + $consulta_zonas = "INSERT INTO zonas (id_concierto, nombre_zona, capacidad, precio) VALUES (?, ?, ?, ?)"; + $stmt_zonas = $conexionBD->prepare($consulta_zonas); + + foreach ($zonas as $zona) { + $stmt_zonas->bind_param("isid", $id_concierto, $zona['nombre_zona'], $zona['capacidad'], $zona['precio']); + $stmt_zonas->execute(); + } + + $stmt_zonas->close(); + $conexionBD->commit(); + + echo json_encode(['insercionCorrecta' => true, 'id_concierto' => $id_concierto]); + +} catch (Exception $e) { + $conexionBD->rollback(); + echo json_encode(['insercionCorrecta' => false, 'error' => $e->getMessage()]); +} + +$conexionBD->close(); diff --git a/controladores/login.php b/controladores/login.php index 0de8b92..7ca46cd 100644 --- a/controladores/login.php +++ b/controladores/login.php @@ -6,7 +6,7 @@ $password = $_POST['password']; // Prepara la consulta - $consulta = "SELECT id, nombre, apellidoPaterno, apellidoMaterno, usuario FROM usuarios WHERE usuario = ? AND contraseña = ?"; + $consulta = "SELECT id, nombre, apellidoPaterno, apellidoMaterno, usuario FROM usuarios WHERE usuario = ? AND password = ?"; $consultaPreparada = $conexionBD->prepare($consulta); $consultaPreparada->bind_param("ss", $usuario, $password); diff --git a/css/botonRegreso.css b/css/botonRegreso.css new file mode 100644 index 0000000..bdf1a57 --- /dev/null +++ b/css/botonRegreso.css @@ -0,0 +1,19 @@ +#btnRegresar { + position: absolute; + top: 20px; + left: 20px; + background-color: #6c757d; + color: white; + padding: 10px 15px; + border-radius: 8px; + border: none; + cursor: pointer; + font-size: 16px; + font-weight: bold; + transition: background 0.3s, transform 0.2s; +} + +#btnRegresar:hover { + background-color: #5a6268; + transform: scale(1.05); +} diff --git a/css/conciertos.css b/css/conciertos.css new file mode 100644 index 0000000..23afe23 --- /dev/null +++ b/css/conciertos.css @@ -0,0 +1,141 @@ +body { + background-color: #12122B; + font-family: 'Poppins', sans-serif; + color: #E3E3E3; + margin: 0; + padding: 0; +} + +nav { + background-color: #12122B; + padding: 1rem 2rem; + display: flex; + align-items: center; + justify-content: space-between; + box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.3); + position: sticky; + top: 0; + z-index: 1000; +} + +.navbar-brand { + font-size: 1.8rem; + font-weight: bold; + color: #E3E3E3; + text-decoration: none; +} + +.nav-links { + display: flex; + gap: 25px; +} + +.nav-links a { + color: #E3E3E3; + text-decoration: none; + font-size: 1.1rem; + font-weight: 500; + transition: color 0.3s; + padding-bottom: 5px; +} + +.nav-links a:hover { + color: #AAAA91; + border-bottom: 3px solid #AAAA91; +} + +.search-container { + display: flex; + background: #383845; + padding: 10px; + border-radius: 6px; + align-items: center; +} + +.search-container input { + border: none; + background: transparent; + color: #E3E3E3; + outline: none; + padding: 8px; + flex-grow: 1; +} + +.search-container button { + background: #AAAA91; + border: none; + padding: 8px 12px; + color: #12122B; + font-weight: bold; + cursor: pointer; + border-radius: 6px; +} + +.search-container button:hover { + background: #848478; +} + +#listaConciertos { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); + gap: 24px; + padding: 40px; + max-width: 1300px; + margin: auto; +} + +.concierto-card { + background-color: #383845; + border-radius: 12px; + overflow: hidden; + box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.3); + transition: transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out; + display: flex; + flex-direction: column; + height: 100%; +} + +.concierto-card:hover { + transform: translateY(-6px); + box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.4); +} + +.concierto-card img { + width: 100%; + height: 180px; + object-fit: cover; +} + +.card-body { + padding: 16px; + flex-grow: 1; +} + +.card-title { + font-size: 1.3rem; + font-weight: bold; + color: #E3E3E3; +} + +.card-text { + font-size: 1rem; + color: #C4C4C4; +} + +.btn-comprar { + width: 100%; + background: #AAAA91; + color: #12122B; + font-weight: bold; + padding: 12px; + border-radius: 8px; + transition: background 0.3s; + text-align: center; + display: block; + margin-top: auto; +} + +.btn-comprar:hover { + background: #848478; +} + diff --git a/css/estilo.css b/css/estilo.css index 653bde3..e69de29 100644 --- a/css/estilo.css +++ b/css/estilo.css @@ -1,67 +0,0 @@ -body { - background-color: #212529; - min-height: 100vh; - display: flex; - align-items: center; - justify-content: center; - font-family: Arial, sans-serif; -} - -.container { - text-align: center; -} - -h1 { - color: #ffffff; - font-size: 24px; - margin-bottom: 20px; -} - -.card { - background-color: #2d3238; - padding: 30px; - border-radius: 10px; - box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); - width: 300px; -} - -.datos { - display: flex; - flex-direction: column; - text-align: left; - margin-bottom: 15px; -} - -.datos label { - font-size: 14px; - color: #ffffff; - margin-bottom: 5px; -} - -.datos input { - padding: 10px; - border: 1px solid #495057; - border-radius: 5px; - background-color: #343a40; - color: white; -} - -.boton { - text-align: center; - margin-top: 15px; -} - -#btnIniciarSesion { - padding: 10px; - border-radius: 5px; - background-color: #007bff; - border: none; - color: white; - font-size: 16px; - cursor: pointer; - width: 100%; -} - -#btnIniciarSesion:hover { - background-color: #0056b3; -} diff --git a/css/fonts/Frutiger Bold Italic/Frutiger Bold Italic.ttf b/css/fonts/Frutiger Bold Italic/Frutiger Bold Italic.ttf new file mode 100644 index 0000000..a4e8024 Binary files /dev/null and b/css/fonts/Frutiger Bold Italic/Frutiger Bold Italic.ttf differ diff --git a/css/fonts/Frutiger Bold Italic/readme.html b/css/fonts/Frutiger Bold Italic/readme.html new file mode 100644 index 0000000..8dbdb1c --- /dev/null +++ b/css/fonts/Frutiger Bold Italic/readme.html @@ -0,0 +1,188 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta name="viewport" content="width=device-width" /> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="refresh" content="5;url=http://fontsgeek.com/fonts/frutiger-bold-italic?ref=readme"> + <title>Frutiger Bold ItalicFontsgeek</title> + <style> +/* ------------------------------------- + GLOBAL + ------------------------------------- */ + * { + margin:0; + padding:0; + font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; + font-size: 100%; + line-height: 1.6; + } + + img { + max-width: 100%; + } + + body { + -webkit-font-smoothing:antialiased; + -webkit-text-size-adjust:none; + width: 100%!important; + height: 100%; + background:#DDD; + } + + + /* ------------------------------------- + ELEMENTS + ------------------------------------- */ + a { + color: #348eda; + } + + .btn-primary, .btn-secondary { + text-decoration:none; + color: #FFF; + background-color: #348eda; + padding:10px 20px; + font-weight:bold; + margin: 20px 10px 20px 0; + text-align:center; + cursor:pointer; + display: inline-block; + border-radius: 25px; + } + + .btn-secondary{ + background: #aaa; + } + + .last { + margin-bottom: 0; + } + + .first{ + margin-top: 0; + } + + + /* ------------------------------------- + BODY + ------------------------------------- */ + table.body-wrap { + width: 100%; + padding: 20px; + } + + table.body-wrap .container{ + border: 1px solid #f0f0f0; + } + + + /* ------------------------------------- + FOOTER + ------------------------------------- */ + table.footer-wrap { + width: 100%; + clear:both!important; + } + + .footer-wrap .container p { + font-size:12px; + color:#666; + + } + + table.footer-wrap a{ + color: #999; + } + + + /* ------------------------------------- + TYPOGRAPHY + ------------------------------------- */ + h1,h2,h3{ + font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; color:#000; + margin: 40px 0 10px; + line-height: 1.2; + font-weight:200; + } + + h1 { + font-size: 36px; + } + h2 { + font-size: 28px; + } + h3 { + font-size: 22px; + } + + p, ul { + margin-bottom: 10px; + font-weight: normal; + font-size:14px; + } + + ul li { + margin-left:5px; + list-style-position: inside; + } + + /* --------------------------------------------------- + RESPONSIVENESS + Nuke it from orbit. It's the only way to be sure. + ------------------------------------------------------ */ + + /* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */ + .container { + display:block!important; + max-width:600px!important; + margin:0 auto!important; /* makes it centered */ + clear:both!important; + } + + /* This should also be a block element, so that it will fill 100% of the .container */ + .content { + padding:20px; + max-width:600px; + margin:0 auto; + display:block; + } + + /* Let's make sure tables in the content area are 100% wide */ + .content table { + width: 100%; + } + + </style> + </head> + + <body bgcolor="#f6f6f6"> + + <!-- body --> + <table class="body-wrap"> + <tr> + <td></td> + <td class="container" bgcolor="#FFFFFF"> + + <!-- content --> + <div class="content"> + <table> + <tr> + <td> + <h1>Frutiger Bold Italic</h1> + <p>This font was downloaded from <a href="http://fontsgeek.com?ref=readme">fontsgeek.com</a> . You can visit <a href="http://fontsgeek.com?ref=readme">fontsgeek.com</a> for thousands of free fonts.</p> + <p><a href="http://fontsgeek.com/fonts/frutiger-bold-italic?ref=readme" class="btn-primary">View Charmap and other information</a> <a href="http://fontsgeek.com?ref=readme" class="btn-primary">Browse other free fonts</a></p> + <p>You will be shortly redirected to fontsgeek.</p> + </td> + </tr> + </table> + </div> + <!-- /content --> + + </td> + <td></td> + </tr> + </table> + <!-- /body --> + + </body> +</html> diff --git a/css/formulario.css b/css/formulario.css new file mode 100644 index 0000000..eaaae2b --- /dev/null +++ b/css/formulario.css @@ -0,0 +1,50 @@ +/* Estilo del formulario */ +.form-container { + width: 400px; + background-color: #383845; + padding: 20px; + border-radius: 12px; + box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.3); + text-align: center; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.form-container h2 { + color: #E3E3E3; + margin-bottom: 20px; +} + +.form-container label { + display: block; + text-align: left; + color: #C4C4C4; + margin-bottom: 5px; + font-size: 14px; +} + +.form-container input { + width: 100%; + padding: 10px; + margin-bottom: 15px; + border-radius: 6px; + border: none; + background-color: #282828; + color: #E3E3E3; +} + +.form-container button { + width: 100%; + background: #AAAA91; + color: #12122B; + font-weight: bold; + padding: 12px; + border-radius: 8px; + transition: background 0.3s; +} + +.form-container button:hover { + background: #848478; +} diff --git a/css/login.css b/css/login.css new file mode 100644 index 0000000..893cb4b --- /dev/null +++ b/css/login.css @@ -0,0 +1,89 @@ +body { + background-color: #212529; + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + font-family: Arial, sans-serif; +} + +.container { + text-align: center; +} + +@font-face { + font-family: 'Frutiger'; + src: url('fonts/Frutiger Bold Italic/Frutiger Bold Italic.ttf') format('truetype'); + font-weight: bold; + font-style: italic; +} + +h1 { + font-family: 'Frutiger', sans-serif; + color: #ffffff; + font-size: 100px; + margin-bottom: 20px; +} + +h1 { + font-family: 'Frutiger', sans-serif; + color: #ffffff; + font-size: 24px; + margin-bottom: 20px; +} + +h2 { + color: #ffffff; + font-size: 24px; + margin-bottom: 20px; +} + + +.card { + background-color: #2d3238; + padding: 30px; + border-radius: 10px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); + width: 300px; +} + +.datos { + display: flex; + flex-direction: column; + text-align: left; + margin-bottom: 15px; +} + +.datos label { + font-size: 14px; + color: #ffffff; + margin-bottom: 5px; +} + +.datos input { + padding: 10px; + border: 1px solid #495057; + border-radius: 5px; + background-color: #343a40; + color: white; +} + +.boton { + text-align: center; + margin-top: 15px; +} + +#btnIniciarSesion { + padding: 10px; + border-radius: 5px; + background-color: #007bff; + border: none; + color: white; + font-size: 16px; + cursor: pointer; + width: 100%; +} + +#btnIniciarSesion:hover { + background-color: #0056b3; +} diff --git a/index.html b/index.html index e979bec..ccefe86 100644 --- a/index.html +++ b/index.html @@ -4,11 +4,12 @@ <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Login</title> - <link rel="stylesheet" href="css/estilo.css"> + <link rel="stylesheet" href="css/login.css"> </head> <body> <div class="container"> - <h1>Inicio de sesión</h1> + <h1>TicketFei</h1> + <h2>Inicio de sesión</h2> <div class="card"> <form id="formularioLogin"> <div class="datos"> diff --git a/js/botonRegreso.js b/js/botonRegreso.js new file mode 100644 index 0000000..d2f2b09 --- /dev/null +++ b/js/botonRegreso.js @@ -0,0 +1,9 @@ +document.addEventListener("DOMContentLoaded", () => { + const btnRegresar = document.getElementById("btnRegresar"); + + if (btnRegresar) { + btnRegresar.addEventListener("click", () => { + window.history.back(); // Regresa a la página anterior + }); + } +}); diff --git a/js/conciertos.js b/js/conciertos.js new file mode 100644 index 0000000..e8d3923 --- /dev/null +++ b/js/conciertos.js @@ -0,0 +1,59 @@ +document.addEventListener("DOMContentLoaded", () => { + cargarConciertos(); +}); + +const listaConciertos = document.getElementById("listaConciertos"); + +// Función para cargar conciertos +async function cargarConciertos() { + try { + const respuesta = await fetch('controladores/conciertos.php'); + if (!respuesta.ok) throw new Error("Error al cargar conciertos"); + + const conciertos = await respuesta.json(); + listaConciertos.innerHTML = ""; // Limpiar la lista antes de agregar nuevos + + let tarjetas = []; + + conciertos.forEach(concierto => { + const tarjeta = document.createElement("div"); + tarjeta.classList.add("concierto-card"); + + let zonasHTML = ""; + if (concierto.zonas.length > 0) { + zonasHTML = `<ul class="text-sm card-text">`; + concierto.zonas.forEach(zona => { + zonasHTML += `<li>🔹 ${zona.nombre_zona}: <b>${zona.capacidad} asientos</b> - $${zona.precio}</li>`; + }); + zonasHTML += `</ul>`; + } + + tarjeta.innerHTML = ` + <img src="img/concierto_${concierto.id}.jpg" alt="Concierto"> + <div class="card-body"> + <h3 class="card-title">${concierto.nombre_concierto}</h3> + <p class="card-text">🎤 ${concierto.artista}</p> + <p class="card-text">📅 ${concierto.fecha}</p> + <p class="card-text">📍 ${concierto.direccion || 'No definida'}</p> + <p class="card-text">🎟 ${concierto.capacidad_total} Asistentes</p> + ${zonasHTML} + </div> + <button class="btn-comprar">Comprar Boletos</button> + `; + + listaConciertos.appendChild(tarjeta); + tarjetas.push(tarjeta); + }); + + // Aplicar animación GSAP + gsap.fromTo( + tarjetas, + { opacity: 0, scale: 0.9 }, + { opacity: 1, scale: 1, duration: 0.6, stagger: 0.2, ease: "power3.out" } + ); + + } catch (error) { + console.error(error); + listaConciertos.innerHTML = `<p class="text-red-500">No se pudieron cargar los conciertos.</p>`; + } +} diff --git a/js/crearConciertos.js b/js/crearConciertos.js new file mode 100644 index 0000000..bfe0d2a --- /dev/null +++ b/js/crearConciertos.js @@ -0,0 +1,86 @@ +const formulario = document.getElementById("formulario"); +const mensajeDiv = document.getElementById("mensaje"); +const buscadorBoton = document.getElementById("buscadorBoton"); +const buscadorInput = document.getElementById("buscadorColaborador"); +const cerrarSesion = document.getElementById("cerrarSesion"); + +// Función para cambiar de paso en el formulario +function siguientePaso (paso) { + paso = Number(paso); // Asegurar que sea número + const pasos = document.querySelectorAll("[id^='paso']"); + + // Ocultar todos los pasos + pasos.forEach(p => p.classList.add("d-none")); + + // Mostrar el paso seleccionado + document.getElementById(`paso${paso}`).classList.remove("d-none"); +} + +// Enviar formulario +formulario.addEventListener("submit", async (event) => { + event.preventDefault(); + + const capacidadTotal = parseInt(document.getElementById("capacidad_total").value, 10); + if (isNaN(capacidadTotal) || capacidadTotal <= 0) { + mensajeDiv.innerHTML = '<div class="alert alert-danger">Error: La capacidad total debe ser un número mayor a 0.</div>'; + return; + } + + const datosConcierto = { + nombre_concierto: document.getElementById("nombre_concierto").value.trim(), + artista: document.getElementById("artista").value.trim(), + fecha: document.getElementById("fecha").value, + calle: document.getElementById("calle").value.trim(), + colonia: document.getElementById("colonia").value.trim(), + numero_direccion: document.getElementById("numero_direccion").value.trim(), + codigo_postal: document.getElementById("codigo_postal").value.trim(), + estado: document.getElementById("estado").value.trim(), + capacidad_total: capacidadTotal, + zonas: [ + { nombre_zona: "General", capacidad: parseInt(document.getElementById("capacidad_general").value, 10) || 0, precio: parseFloat(document.getElementById("precio_general").value) || 0 }, + { nombre_zona: "Plata", capacidad: parseInt(document.getElementById("capacidad_plata").value, 10) || 0, precio: parseFloat(document.getElementById("precio_plata").value) || 0 }, + { nombre_zona: "Oro", capacidad: parseInt(document.getElementById("capacidad_oro").value, 10) || 0, precio: parseFloat(document.getElementById("precio_oro").value) || 0 }, + { nombre_zona: "VIP", capacidad: parseInt(document.getElementById("capacidad_vip").value, 10) || 0, precio: parseFloat(document.getElementById("precio_vip").value) || 0 } + ] + }; + + const sumaCapacidades = datosConcierto.zonas.reduce((total, zona) => total + zona.capacidad, 0); + + if (sumaCapacidades > capacidadTotal) { + mensajeDiv.innerHTML = '<div class="alert alert-danger">La suma de las capacidades de las zonas no puede superar la capacidad total.</div>'; + return; + } else if (sumaCapacidades < capacidadTotal){ + mensajeDiv.innerHTML = '<div class="alert alert-danger">La suma de las capacidades de las zonas no puede ser menor a la capacidad total.</div>'; + return; + } + + try { + const respuesta = await fetch("controladores/insertar_concierto.php", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(datosConcierto) + }); + + if (!respuesta.ok) { + throw new Error(`HTTP Error: ${respuesta.status}`); + } + + const data = await respuesta.json(); + + if (data.insercionCorrecta) { + formulario.reset(); + siguientePaso(1); + mensajeDiv.innerHTML = '<div class="alert alert-success">Concierto registrado correctamente.</div>'; + } else { + mensajeDiv.innerHTML = `<div class="alert alert-danger">Error: ${data.error || "No se pudo registrar el concierto."}</div>`; + } + } catch (error) { + mensajeDiv.innerHTML = `<div class="alert alert-danger">Error en la solicitud: ${error.message}</div>`; + console.error("Error:", error); + } +}); + +// Cerrar sesión +cerrarSesion.addEventListener("click", () => { + window.location.href = "logout.php"; +}); \ No newline at end of file diff --git a/js/login.js b/js/login.js index 275ebed..1574cae 100644 --- a/js/login.js +++ b/js/login.js @@ -19,7 +19,7 @@ formulario.addEventListener('submit', async (event) => { }); const verificarCredenciales = await respuestaPeticion.json(); if (verificarCredenciales.loginExitoso) { - window.location.href = 'ventanaPrincipal.html'; + window.location.href = 'ventanaInsertarConcierto.html'; } else { notificacion.textContent ="Usuario o contraseña incorrecta"; notificacion.style.color='#ffffff'; diff --git a/ventaBoletos.html b/ventaBoletos.html new file mode 100644 index 0000000..5319ea7 --- /dev/null +++ b/ventaBoletos.html @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<html lang="es"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Registro de Conciertos</title> + <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"> + <link rel="stylesheet" href="css/ventanaPrincipal.css"> +</head> +<body> + + <!-- Navbar --> + <nav class="navbar navbar-expand-lg navbar-dark bg-dark"> + <div class="container-fluid"> + <a class="navbar-brand" href="ventanaPrincipal.html">TicketFei</a> + <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"> + <span class="navbar-toggler-icon"></span> + </button> + <div class="collapse navbar-collapse" id="navbarNav"> + <ul class="navbar-nav me-auto"> + <li class="nav-item"> + <a class="nav-link active" href="ventanaPrincipal.html">Conciertos</a> + </li> + <li class="nav-item"> + <a class="nav-link" href="#">Reporte Ventas</a> + </li> + <li class="nav-item"> + <form class="d-flex"> + <input class="form-control me-2" type="search" id="buscadorColaborador" placeholder="Buscar concierto" aria-label="Buscar"> + <button class="btn btn-outline-light" type="submit" id="buscadorBoton"> + <i class="bi bi-search"></i> + </button> + </form> + </li> + + </ul> + <button class="btn btn-danger" id="cerrarSesion">Cerrar Sesión</button> + + </div> + </div> + </nav> + + <!-- Contenedor Principal --> + <div class="container mt-5"> + + + </div> + + <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script> + <script src="js/conciertos.js"></script> +</body> +</html> diff --git a/ventanaConciertos.html b/ventanaConciertos.html new file mode 100644 index 0000000..11952e8 --- /dev/null +++ b/ventanaConciertos.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html lang="es"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Registro de Conciertos</title> + <script src="https://cdn.tailwindcss.com"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script> + <link rel="stylesheet" href="css/conciertos.css"> +</head> +<body> + + <nav> + <a href="ventanaInsertarConcierto.html" class="navbar-brand">TicketFei</a> + <div class="nav-links"> + <a href="ventanaInsertarConcierto.html">Crear Conciertos</a> + <a href="ventanaConciertos.html">Ver Conciertos</a> + <a href="#">Reporte Ventas</a> + </div> + <div class="search-container"> + <input type="search" id="buscadorColaborador" placeholder="Buscar..."> + <button id="buscadorBoton">Buscar</button> + </div> + </nav> + + <div id="listaConciertos"></div> + + <script src="js/conciertos.js"></script> + +</body> +</html> diff --git a/ventanaInsertarConcierto.html b/ventanaInsertarConcierto.html new file mode 100644 index 0000000..0ad4572 --- /dev/null +++ b/ventanaInsertarConcierto.html @@ -0,0 +1,45 @@ +<!DOCTYPE html> +<html lang="es"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Registrar Concierto</title> + + <!-- CSS de diseño --> + <link rel="stylesheet" href="css/conciertos.css"> + <link rel="stylesheet" href="css/formulario.css"> +</head> +<body> + + <!-- Navbar --> + <nav> + <a class="navbar-brand" href="#">TicketFei</a> + <div class="nav-links"> + <a href="ventanaInsertarConcierto.html">Crear Conciertos</a> + <a href="ventanaConciertos.html">Ver Conciertos</a> + <a href="#">Reporte Ventas</a> + </div> + </nav> + + <!-- Contenedor del formulario --> + <div class="form-container"> + <h2>Registrar Concierto</h2> + <form id="formulario"> + <label for="nombre_concierto">Nombre del Concierto:</label> + <input type="text" id="nombre_concierto" required> + + <label for="artista">Artista:</label> + <input type="text" id="artista" required> + + <label for="fecha">Fecha del Concierto:</label> + <input type="date" id="fecha" required> + + <button type="submit">Registrar</button> + </form> + </div> + + <!-- JavaScript --> + <script src="js/crearConciertos.js"></script> + +</body> +</html>