diff --git a/bd/tablas.sql b/bd/tablas.sql index 7e82cad..e10e6a0 100644 --- a/bd/tablas.sql +++ b/bd/tablas.sql @@ -61,3 +61,30 @@ FROM conciertos c JOIN zonas z ON c.id_concierto = z.id_concierto WHERE c.id_concierto = 1; +-- Tabla Asientos +CREATE TABLE asientos ( + id_asiento INT AUTO_INCREMENT PRIMARY KEY, + id_zona INT NOT NULL, + numero_asiento INT NOT NULL, + estado ENUM('disponible', 'ocupado') NOT NULL DEFAULT 'disponible', + FOREIGN KEY (id_zona) REFERENCES zonas(id_zona) ON DELETE CASCADE, + UNIQUE (id_zona, numero_asiento) -- Para evitar asientos duplicados en la misma zona +); +DROP TABLE asientos; + +-- Tabla Boletos +CREATE TABLE boletos ( + id_boleto INT AUTO_INCREMENT PRIMARY KEY, + id_concierto INT NOT NULL, + id_zona INT NOT NULL, + id_asiento INT NOT NULL, + nombre_comprador VARCHAR(255) NOT NULL, + precio DECIMAL(10,2) NOT NULL, + fecha_concierto DATE NOT NULL, + artista VARCHAR(255) NOT NULL, + FOREIGN KEY (id_concierto) REFERENCES conciertos(id_concierto) ON DELETE CASCADE, + FOREIGN KEY (id_zona) REFERENCES zonas(id_zona) ON DELETE CASCADE, + FOREIGN KEY (id_asiento) REFERENCES asientos(id_asiento) ON DELETE CASCADE, + UNIQUE (id_asiento) -- Evita que un asiento se venda dos veces +); +DROP TABLE boletos; \ No newline at end of file diff --git a/controladores/concierto_zonas.php b/controladores/concierto_zonas.php index 881d12d..5f0ec38 100644 --- a/controladores/concierto_zonas.php +++ b/controladores/concierto_zonas.php @@ -2,43 +2,27 @@ include 'conexion.php'; header('Content-Type: application/json'); -error_reporting(E_ALL); -ini_set('display_errors', 1); -if (!isset($_GET['id'])) { - echo json_encode(["error" => "No se proporcionó un ID de concierto"]); +if (!isset($_GET['id']) || !isset($_GET['zona'])) { + echo json_encode(["error" => "Faltan parámetros"]); exit; } $conciertoId = intval($_GET['id']); +$nombreZona = $_GET['zona']; -$consulta = "SELECT nombre_zona, capacidad, precio FROM zonas WHERE id_concierto = ? ORDER BY FIELD(nombre_zona, 'General', 'Plata', 'Oro', 'VIP')"; - +$consulta = "SELECT numero_asiento FROM boletos WHERE id_concierto = ? AND nombre_zona = ?"; $stmt = $conexionBD->prepare($consulta); -if (!$stmt) { - echo json_encode(["error" => "Error en la preparación de la consulta: " . $conexionBD->error]); - exit; -} - -$stmt->bind_param('i', $conciertoId); +$stmt->bind_param('is', $conciertoId, $nombreZona); $stmt->execute(); $resultado = $stmt->get_result(); -$zonas = []; +$asientosOcupados = []; while ($fila = $resultado->fetch_assoc()) { - $zonas[] = [ - 'nombre_zona' => $fila['nombre_zona'], - 'capacidad' => $fila['capacidad'], - 'precio' => $fila['precio'] - ]; -} - -if (empty($zonas)) { - echo json_encode(["error" => "No se encontraron zonas para este concierto"]); -} else { - echo json_encode($zonas, JSON_PRETTY_PRINT); + $asientosOcupados[] = intval($fila['numero_asiento']); } +echo json_encode($asientosOcupados); $stmt->close(); $conexionBD->close(); -?> \ No newline at end of file +?> diff --git a/controladores/insertar_concierto.php b/controladores/insertar_concierto.php index aafb6f2..b298ea4 100644 --- a/controladores/insertar_concierto.php +++ b/controladores/insertar_concierto.php @@ -44,16 +44,28 @@ try { $id_concierto = $conexionBD->insert_id; $stmt->close(); - // Insertar zonas + // Insertar zonas y sus asientos $consulta_zonas = "INSERT INTO zonas (id_concierto, nombre_zona, capacidad, precio) VALUES (?, ?, ?, ?)"; $stmt_zonas = $conexionBD->prepare($consulta_zonas); - + + $consulta_asientos = "INSERT INTO asientos (id_zona, numero_asiento, estado) VALUES (?, ?, 'disponible')"; + $stmt_asientos = $conexionBD->prepare($consulta_asientos); + foreach ($zonas as $zona) { $stmt_zonas->bind_param("isid", $id_concierto, $zona['nombre_zona'], $zona['capacidad'], $zona['precio']); $stmt_zonas->execute(); + + $id_zona = $conexionBD->insert_id; + + // Insertar asientos + for ($i = 1; $i <= $zona['capacidad']; $i++) { + $stmt_asientos->bind_param("ii", $id_zona, $i); + $stmt_asientos->execute(); + } } - + $stmt_zonas->close(); + $stmt_asientos->close(); $conexionBD->commit(); echo json_encode(['insercionCorrecta' => true, 'id_concierto' => $id_concierto]); @@ -64,3 +76,4 @@ try { } $conexionBD->close(); +?> diff --git a/css/modalEliminar.css b/css/modalEliminar.css index 591d4e8..7afa376 100644 --- a/css/modalEliminar.css +++ b/css/modalEliminar.css @@ -7,7 +7,6 @@ width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); - display: flex; justify-content: center; align-items: center; } diff --git a/css/zonas.css b/css/zonas.css index 6e2a65d..2dd17cb 100644 --- a/css/zonas.css +++ b/css/zonas.css @@ -1,101 +1,82 @@ -.mapa-estadio { - position: relative; - width: 600px; - height: 500px; - background-color: #f0f0f0; - border-radius: 50% 50% 0 0; - margin: auto; +/* Contenedor principal que divide la pantalla */ +.main-container { + display: flex; + height: 80vh; /* Ocupar 80% de la pantalla */ + gap: 20px; + padding: 20px; +} + +/* Lado izquierdo (imagen + botones) */ +.cardIzq { + flex: 2; /* Ocupar 2/3 del ancho */ display: flex; - justify-content: center; - align-items: flex-end; flex-direction: column; - overflow: hidden; -} - -.escenario { - position: absolute; - bottom: 0; - left: 50%; - transform: translateX(-50%); - width: 100%; - height: 140px; - background-color: black; - color: white; - text-align: center; - line-height: 60px; - font-weight: bold; - border-radius: 10px 10px 0 0; -} - -.zona { - position: absolute; - cursor: pointer; - text-align: center; - display: flex; - justify-content: center; align-items: center; - font-weight: bold; - color: white; - border-radius: 50% 50% 0 0; } -.general { - background-color: gray; +.cardIzq img { width: 100%; - height: 40%; - bottom: 10%; - left: 0; - border-radius: 50% 50% 0 0; + max-width: 600px; + height: 400px; } -.plata { - background-color: silver; - width: 80%; - height: 30%; - bottom: 20%; - left: 10%; - border-radius: 50% 50% 0 0; -} - -.oro { - background-color: gold; - width: 60%; - height: 25%; - bottom: 30%; - left: 20%; - border-radius: 50% 50% 0 0; -} - -.vip { - background-color: purple; - width: 40%; - height: 20%; - bottom: 10%; - left: 30%; - border-radius: 50% 50% 0 0; -} - -.selected { border: 3px solid red; } - -.asientos-container { - display: none; - margin-top: 20px; +.zones-container { display: flex; - flex-wrap: wrap; + gap: 10px; + margin-top: 15px; +} + +/* Lado derecho (tarjeta con info) */ +.cardDer { + flex: 1; /* Ocupar 1/3 del ancho */ + display: flex; + align-items: center; justify-content: center; } +.card { + background: #aab2b2; + border-radius: 12px; + padding: 20px; + width: 100%; + max-width: 300px; + box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.3); +} + +.zone-btn { + padding: 10px; + border-radius: 8px; + color: white; + font-weight: bold; + cursor: pointer; +} + +.vip-zone { background-color: #5e17eb; } +.oro-zone { background-color: #d5ce2d; } +.plata-zone { background-color: #737373; } +.general-zone { background-color: #725e2b; color: rgb(255, 255, 255); } + .asiento { - width: 30px; - height: 30px; - margin: 5px; display: inline-block; + width: 40px; + height: 40px; + margin: 5px; text-align: center; - line-height: 30px; - border-radius: 5px; + line-height: 40px; + font-size: 1.2em; + border: 1px solid #000; cursor: pointer; - background-color: green; + background-color: #f8f9fa; + border-radius: 5px; +} + +.asiento.seleccionado { + background-color: #28a745; color: white; } -.asiento.seleccionado { background-color: orange; } \ No newline at end of file +.asiento.ocupado { + background-color: #dc3545; + color: white; + cursor: not-allowed; +} diff --git a/editarConciertos.html b/editarConciertos.html index 1c5e935..eaf3589 100644 --- a/editarConciertos.html +++ b/editarConciertos.html @@ -12,7 +12,7 @@ <!-- Navbar --> <nav> - <a href="ventanaInsertarConcierto.html" class="navbar-brand">TicketFei</a> + <a href="ventanaConciertos.html" class="navbar-brand">TicketFei</a> <div class="nav-links"> <a href="ventanaInsertarConcierto.html">Crear Conciertos</a> <a href="ventanaConciertos.html">Ver Conciertos</a> diff --git a/img/mapa.png b/img/mapa.png new file mode 100644 index 0000000..69753b3 Binary files /dev/null and b/img/mapa.png differ diff --git a/js/login.js b/js/login.js index 72a7f56..fe93fe9 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 = 'ventanaInsertarConcierto.html'; + window.location.href = 'ventanaConciertos.html'; } else { notificacion.textContent ="Usuario o contraseña incorrecta"; notificacion.style.color='#ffffff'; diff --git a/js/ventaBoletos.js b/js/ventaBoletos.js index 6f859fc..9165ba9 100644 --- a/js/ventaBoletos.js +++ b/js/ventaBoletos.js @@ -5,20 +5,20 @@ document.addEventListener("DOMContentLoaded", async () => { alert("No se encontró el ID del concierto."); return; } - + try { const respuesta = await fetch(`controladores/concierto_zonas.php?id=${conciertoId}`); if (!respuesta.ok) throw new Error("Error al cargar las zonas del concierto"); - + const zonas = await respuesta.json(); - cargarZonas(zonas); + cargarZonas(zonas, conciertoId); } catch (error) { console.error(error); alert("Error al cargar los datos del concierto"); } }); -function cargarZonas(zonas) { +function cargarZonas(zonas, conciertoId) { const container = document.getElementById('zonas-container'); container.innerHTML = ""; @@ -26,28 +26,43 @@ function cargarZonas(zonas) { let div = document.createElement('div'); div.classList.add('zona', zona.nombre_zona.toLowerCase()); div.textContent = `${zona.nombre_zona} - ${zona.capacidad} asientos - $${zona.precio}`; - div.onclick = function() { + div.onclick = async function () { document.querySelectorAll('.zona').forEach(el => el.classList.remove('selected')); div.classList.add('selected'); - mostrarAsientos(zona.capacidad); + await mostrarAsientos(conciertoId, zona.nombre_zona, zona.capacidad); }; container.appendChild(div); }); } -function mostrarAsientos(capacidad) { +async function mostrarAsientos(conciertoId, nombreZona, capacidad) { const asientosContainer = document.getElementById('asientos-container'); asientosContainer.innerHTML = ""; asientosContainer.style.display = "flex"; - - for (let i = 0; i < capacidad; i++) { - let asiento = document.createElement('div'); - asiento.classList.add('asiento'); - asiento.textContent = i + 1; - asiento.onclick = function() { - asiento.classList.toggle('seleccionado'); - }; - asientosContainer.appendChild(asiento); + + try { + const respuesta = await fetch(`controladores/asientos_ocupados.php?id=${conciertoId}&zona=${nombreZona}`); + if (!respuesta.ok) throw new Error("Error al cargar los asientos ocupados"); + + const asientosOcupados = await respuesta.json(); + + for (let i = 1; i <= capacidad; i++) { + let asiento = document.createElement('div'); + asiento.classList.add('asiento'); + asiento.innerHTML = `<i class="bi bi-person-fill"></i> ${i}`; + + if (asientosOcupados.includes(i)) { + asiento.classList.add('ocupado'); + } else { + asiento.onclick = function () { + asiento.classList.toggle('seleccionado'); + }; + } + asientosContainer.appendChild(asiento); + } + } catch (error) { + console.error(error); + alert("Error al cargar los asientos"); } } @@ -57,11 +72,13 @@ document.getElementById("confirmarSeleccion").addEventListener("click", () => { alert("No has seleccionado ninguna zona."); return; } + let selectedAsientos = document.querySelectorAll('.asiento.seleccionado'); if (selectedAsientos.length === 0) { alert("No has seleccionado ningún asiento."); return; } - let asientosSeleccionados = Array.from(selectedAsientos).map(asiento => asiento.textContent); + + let asientosSeleccionados = Array.from(selectedAsientos).map(asiento => asiento.textContent.trim()); alert(`Zona seleccionada: ${selectedZona.textContent}\nAsientos: ${asientosSeleccionados.join(', ')}`); }); diff --git a/ventaBoletos.html b/ventaBoletos.html index 3450ec5..5f9de59 100644 --- a/ventaBoletos.html +++ b/ventaBoletos.html @@ -6,12 +6,10 @@ <title>Compra de Boletos</title> <script src="https://cdn.tailwindcss.com"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script> - <script defer src="js/ventaBoletos.js"></script> - <link rel="stylesheet" href="css/conciertos.css"> + <link rel="stylesheet" href="css/conciertos.css"> <!-- Aquí se incluye el CSS --> <link rel="stylesheet" href="css/zonas.css"> </head> <body> - <nav> <a href="ventanaInsertarConcierto.html" class="navbar-brand">TicketFei</a> <div class="nav-links"> @@ -19,29 +17,42 @@ <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 class="container mt-4 text-center"> - <h2>Selecciona tu zona</h2> - </div> - - <div class="mapa-estadio"> - <div class="escenario">ESCENARIO</div> - <div class="zona general" onclick="seleccionarZona('General')">General</div> - <div class="zona plata" onclick="seleccionarZona('Plata')">Plata</div> - <div class="zona oro" onclick="seleccionarZona('Oro')">Oro</div> - <div class="zona vip" onclick="seleccionarZona('VIP')">VIP</div> + <div class="main-container"> + + <div class="cardIzq"> + <h2>Zonas del Concierto</h2> + <img src="img/mapa.png" alt="Mapa de zonas del concierto"> + + <div class="zones-container"> + <button class="zone-btn vip-zone" onclick="seleccionarZona('vip')">Zona VIP</button> + <button class="zone-btn oro-zone" onclick="seleccionarZona('oro')">Zona ORO</button> + <button class="zone-btn plata-zone" onclick="seleccionarZona('plata')">Zona PLATA</button> + <button class="zone-btn general-zone" onclick="seleccionarZona('general')">Zona GENERAL</button> + </div> + + </div> + + <div class="cardDer"> + <div class="card"> + <h2 class="text-xl font-bold mb-4">Detalles de la Zona</h2> + <div id="zona-info" class="space-y-2"> + <p><strong>Zona:</strong> <span id="zona-nombre">-</span></p> + <p><strong>Capacidad:</strong> <span id="zona-capacidad">-</span></p> + <p><strong>Precio por asiento:</strong> $<span id="zona-precio">-</span></p> + </div> + </div> + </div> </div> + <div id="zonas-container"></div> <div id="asientos-container" class="asientos-container"></div> <div class="text-center mt-3"> <button class="btn btn-primary" id="confirmarSeleccion">Confirmar selección</button> </div> + <script defer src="js/ventaBoletos.js"></script> </body> -</html> \ No newline at end of file +</html> diff --git a/ventanaConciertos.html b/ventanaConciertos.html index ab16651..bed880f 100644 --- a/ventanaConciertos.html +++ b/ventanaConciertos.html @@ -12,7 +12,7 @@ <body> <nav> - <a href="ventanaInsertarConcierto.html" class="navbar-brand">TicketFei</a> + <a href="ventanaConciertos.html" class="navbar-brand">TicketFei</a> <div class="nav-links"> <a href="ventanaInsertarConcierto.html">Crear Conciertos</a> <a href="ventanaConciertos.html">Ver Conciertos</a>