From 70556b2fddb2e0eab9dbea58d6cdc41acba7ae1f Mon Sep 17 00:00:00 2001 From: Fernando Escobar Robles <zs22016116@estudiantes.uv.mx> Date: Wed, 26 Feb 2025 16:37:43 -0600 Subject: [PATCH] version 1.1 --- bd/bd.sql | 10 +- bd/tablas.sql | 63 ++++++ .../buscar_conciertos.php | 0 controladores/cerrar_sesion.php | 21 ++ controladores/conciertos.php | 55 +++++ controladores/conexion.php | 5 +- controladores/insertar_concierto.php | 66 ++++++ controladores/login.php | 2 +- css/botonRegreso.css | 19 ++ css/conciertos.css | 141 +++++++++++++ css/estilo.css | 67 ------- .../Frutiger Bold Italic.ttf | Bin 0 -> 41396 bytes css/fonts/Frutiger Bold Italic/readme.html | 188 ++++++++++++++++++ css/formulario.css | 50 +++++ css/login.css | 89 +++++++++ index.html | 5 +- js/botonRegreso.js | 9 + js/conciertos.js | 59 ++++++ js/crearConciertos.js | 86 ++++++++ js/login.js | 2 +- ventaBoletos.html | 52 +++++ ventanaConciertos.html | 31 +++ ventanaInsertarConcierto.html | 45 +++++ 23 files changed, 988 insertions(+), 77 deletions(-) create mode 100644 bd/tablas.sql rename ventanaPrincipal.html => controladores/buscar_conciertos.php (100%) create mode 100644 controladores/cerrar_sesion.php create mode 100644 controladores/conciertos.php create mode 100644 controladores/insertar_concierto.php create mode 100644 css/botonRegreso.css create mode 100644 css/conciertos.css create mode 100644 css/fonts/Frutiger Bold Italic/Frutiger Bold Italic.ttf create mode 100644 css/fonts/Frutiger Bold Italic/readme.html create mode 100644 css/formulario.css create mode 100644 css/login.css create mode 100644 js/botonRegreso.js create mode 100644 js/conciertos.js create mode 100644 js/crearConciertos.js create mode 100644 ventaBoletos.html create mode 100644 ventanaConciertos.html create mode 100644 ventanaInsertarConcierto.html 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 0000000000000000000000000000000000000000..a4e8024eb6a8f07431b5cb7ccc75553d3dd308d3 GIT binary patch literal 41396 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 Ee>bEJQUCw| literal 0 HcmV?d00001 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>