Compra de Boletos

This commit is contained in:
Jorge Luis Ortega Zenteno 2025-03-06 11:30:20 -06:00
parent 4aa177c5c5
commit ce5c75fff4
11 changed files with 181 additions and 149 deletions

View File

@ -61,3 +61,30 @@ FROM conciertos c
JOIN zonas z ON c.id_concierto = z.id_concierto JOIN zonas z ON c.id_concierto = z.id_concierto
WHERE c.id_concierto = 1; 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;

View File

@ -2,43 +2,27 @@
include 'conexion.php'; include 'conexion.php';
header('Content-Type: application/json'); header('Content-Type: application/json');
error_reporting(E_ALL);
ini_set('display_errors', 1);
if (!isset($_GET['id'])) { if (!isset($_GET['id']) || !isset($_GET['zona'])) {
echo json_encode(["error" => "No se proporcionó un ID de concierto"]); echo json_encode(["error" => "Faltan parámetros"]);
exit; exit;
} }
$conciertoId = intval($_GET['id']); $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); $stmt = $conexionBD->prepare($consulta);
if (!$stmt) { $stmt->bind_param('is', $conciertoId, $nombreZona);
echo json_encode(["error" => "Error en la preparación de la consulta: " . $conexionBD->error]);
exit;
}
$stmt->bind_param('i', $conciertoId);
$stmt->execute(); $stmt->execute();
$resultado = $stmt->get_result(); $resultado = $stmt->get_result();
$zonas = []; $asientosOcupados = [];
while ($fila = $resultado->fetch_assoc()) { while ($fila = $resultado->fetch_assoc()) {
$zonas[] = [ $asientosOcupados[] = intval($fila['numero_asiento']);
'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);
} }
echo json_encode($asientosOcupados);
$stmt->close(); $stmt->close();
$conexionBD->close(); $conexionBD->close();
?> ?>

View File

@ -44,16 +44,28 @@ try {
$id_concierto = $conexionBD->insert_id; $id_concierto = $conexionBD->insert_id;
$stmt->close(); $stmt->close();
// Insertar zonas // Insertar zonas y sus asientos
$consulta_zonas = "INSERT INTO zonas (id_concierto, nombre_zona, capacidad, precio) VALUES (?, ?, ?, ?)"; $consulta_zonas = "INSERT INTO zonas (id_concierto, nombre_zona, capacidad, precio) VALUES (?, ?, ?, ?)";
$stmt_zonas = $conexionBD->prepare($consulta_zonas); $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) { foreach ($zonas as $zona) {
$stmt_zonas->bind_param("isid", $id_concierto, $zona['nombre_zona'], $zona['capacidad'], $zona['precio']); $stmt_zonas->bind_param("isid", $id_concierto, $zona['nombre_zona'], $zona['capacidad'], $zona['precio']);
$stmt_zonas->execute(); $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_zonas->close();
$stmt_asientos->close();
$conexionBD->commit(); $conexionBD->commit();
echo json_encode(['insercionCorrecta' => true, 'id_concierto' => $id_concierto]); echo json_encode(['insercionCorrecta' => true, 'id_concierto' => $id_concierto]);
@ -64,3 +76,4 @@ try {
} }
$conexionBD->close(); $conexionBD->close();
?>

View File

@ -7,7 +7,6 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
background-color: rgba(0, 0, 0, 0.5); background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }

View File

@ -1,101 +1,82 @@
.mapa-estadio { /* Contenedor principal que divide la pantalla */
position: relative; .main-container {
width: 600px; display: flex;
height: 500px; height: 80vh; /* Ocupar 80% de la pantalla */
background-color: #f0f0f0; gap: 20px;
border-radius: 50% 50% 0 0; padding: 20px;
margin: auto; }
/* Lado izquierdo (imagen + botones) */
.cardIzq {
flex: 2; /* Ocupar 2/3 del ancho */
display: flex; display: flex;
justify-content: center;
align-items: flex-end;
flex-direction: column; 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; align-items: center;
font-weight: bold;
color: white;
border-radius: 50% 50% 0 0;
} }
.general { .cardIzq img {
background-color: gray;
width: 100%; width: 100%;
height: 40%; max-width: 600px;
bottom: 10%; height: 400px;
left: 0;
border-radius: 50% 50% 0 0;
} }
.plata { .zones-container {
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;
display: flex; 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; 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 { .asiento {
width: 30px;
height: 30px;
margin: 5px;
display: inline-block; display: inline-block;
width: 40px;
height: 40px;
margin: 5px;
text-align: center; text-align: center;
line-height: 30px; line-height: 40px;
border-radius: 5px; font-size: 1.2em;
border: 1px solid #000;
cursor: pointer; cursor: pointer;
background-color: green; background-color: #f8f9fa;
border-radius: 5px;
}
.asiento.seleccionado {
background-color: #28a745;
color: white; color: white;
} }
.asiento.seleccionado { background-color: orange; } .asiento.ocupado {
background-color: #dc3545;
color: white;
cursor: not-allowed;
}

View File

@ -12,7 +12,7 @@
<!-- Navbar --> <!-- Navbar -->
<nav> <nav>
<a href="ventanaInsertarConcierto.html" class="navbar-brand">TicketFei</a> <a href="ventanaConciertos.html" class="navbar-brand">TicketFei</a>
<div class="nav-links"> <div class="nav-links">
<a href="ventanaInsertarConcierto.html">Crear Conciertos</a> <a href="ventanaInsertarConcierto.html">Crear Conciertos</a>
<a href="ventanaConciertos.html">Ver Conciertos</a> <a href="ventanaConciertos.html">Ver Conciertos</a>

BIN
img/mapa.png Normal file

Binary file not shown.

After

(image error) Size: 62 KiB

View File

@ -19,7 +19,7 @@ formulario.addEventListener('submit', async (event) => {
}); });
const verificarCredenciales = await respuestaPeticion.json(); const verificarCredenciales = await respuestaPeticion.json();
if (verificarCredenciales.loginExitoso) { if (verificarCredenciales.loginExitoso) {
window.location.href = 'ventanaInsertarConcierto.html'; window.location.href = 'ventanaConciertos.html';
} else { } else {
notificacion.textContent ="Usuario o contraseña incorrecta"; notificacion.textContent ="Usuario o contraseña incorrecta";
notificacion.style.color='#ffffff'; notificacion.style.color='#ffffff';

View File

@ -5,20 +5,20 @@ document.addEventListener("DOMContentLoaded", async () => {
alert("No se encontró el ID del concierto."); alert("No se encontró el ID del concierto.");
return; return;
} }
try { try {
const respuesta = await fetch(`controladores/concierto_zonas.php?id=${conciertoId}`); const respuesta = await fetch(`controladores/concierto_zonas.php?id=${conciertoId}`);
if (!respuesta.ok) throw new Error("Error al cargar las zonas del concierto"); if (!respuesta.ok) throw new Error("Error al cargar las zonas del concierto");
const zonas = await respuesta.json(); const zonas = await respuesta.json();
cargarZonas(zonas); cargarZonas(zonas, conciertoId);
} catch (error) { } catch (error) {
console.error(error); console.error(error);
alert("Error al cargar los datos del concierto"); alert("Error al cargar los datos del concierto");
} }
}); });
function cargarZonas(zonas) { function cargarZonas(zonas, conciertoId) {
const container = document.getElementById('zonas-container'); const container = document.getElementById('zonas-container');
container.innerHTML = ""; container.innerHTML = "";
@ -26,28 +26,43 @@ function cargarZonas(zonas) {
let div = document.createElement('div'); let div = document.createElement('div');
div.classList.add('zona', zona.nombre_zona.toLowerCase()); div.classList.add('zona', zona.nombre_zona.toLowerCase());
div.textContent = `${zona.nombre_zona} - ${zona.capacidad} asientos - $${zona.precio}`; 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')); document.querySelectorAll('.zona').forEach(el => el.classList.remove('selected'));
div.classList.add('selected'); div.classList.add('selected');
mostrarAsientos(zona.capacidad); await mostrarAsientos(conciertoId, zona.nombre_zona, zona.capacidad);
}; };
container.appendChild(div); container.appendChild(div);
}); });
} }
function mostrarAsientos(capacidad) { async function mostrarAsientos(conciertoId, nombreZona, capacidad) {
const asientosContainer = document.getElementById('asientos-container'); const asientosContainer = document.getElementById('asientos-container');
asientosContainer.innerHTML = ""; asientosContainer.innerHTML = "";
asientosContainer.style.display = "flex"; asientosContainer.style.display = "flex";
for (let i = 0; i < capacidad; i++) { try {
let asiento = document.createElement('div'); const respuesta = await fetch(`controladores/asientos_ocupados.php?id=${conciertoId}&zona=${nombreZona}`);
asiento.classList.add('asiento'); if (!respuesta.ok) throw new Error("Error al cargar los asientos ocupados");
asiento.textContent = i + 1;
asiento.onclick = function() { const asientosOcupados = await respuesta.json();
asiento.classList.toggle('seleccionado');
}; for (let i = 1; i <= capacidad; i++) {
asientosContainer.appendChild(asiento); 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."); alert("No has seleccionado ninguna zona.");
return; return;
} }
let selectedAsientos = document.querySelectorAll('.asiento.seleccionado'); let selectedAsientos = document.querySelectorAll('.asiento.seleccionado');
if (selectedAsientos.length === 0) { if (selectedAsientos.length === 0) {
alert("No has seleccionado ningún asiento."); alert("No has seleccionado ningún asiento.");
return; 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(', ')}`); alert(`Zona seleccionada: ${selectedZona.textContent}\nAsientos: ${asientosSeleccionados.join(', ')}`);
}); });

View File

@ -6,12 +6,10 @@
<title>Compra de Boletos</title> <title>Compra de Boletos</title>
<script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></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"> <!-- Aquí se incluye el CSS -->
<link rel="stylesheet" href="css/conciertos.css">
<link rel="stylesheet" href="css/zonas.css"> <link rel="stylesheet" href="css/zonas.css">
</head> </head>
<body> <body>
<nav> <nav>
<a href="ventanaInsertarConcierto.html" class="navbar-brand">TicketFei</a> <a href="ventanaInsertarConcierto.html" class="navbar-brand">TicketFei</a>
<div class="nav-links"> <div class="nav-links">
@ -19,29 +17,42 @@
<a href="ventanaConciertos.html">Ver Conciertos</a> <a href="ventanaConciertos.html">Ver Conciertos</a>
<a href="#">Reporte Ventas</a> <a href="#">Reporte Ventas</a>
</div> </div>
<div class="search-container">
<input type="search" id="buscadorColaborador" placeholder="Buscar...">
<button id="buscadorBoton">Buscar</button>
</div>
</nav> </nav>
<div class="container mt-4 text-center"> <div class="main-container">
<h2>Selecciona tu zona</h2>
</div> <div class="cardIzq">
<h2>Zonas del Concierto</h2>
<div class="mapa-estadio"> <img src="img/mapa.png" alt="Mapa de zonas del concierto">
<div class="escenario">ESCENARIO</div>
<div class="zona general" onclick="seleccionarZona('General')">General</div> <div class="zones-container">
<div class="zona plata" onclick="seleccionarZona('Plata')">Plata</div> <button class="zone-btn vip-zone" onclick="seleccionarZona('vip')">Zona VIP</button>
<div class="zona oro" onclick="seleccionarZona('Oro')">Oro</div> <button class="zone-btn oro-zone" onclick="seleccionarZona('oro')">Zona ORO</button>
<div class="zona vip" onclick="seleccionarZona('VIP')">VIP</div> <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>
<div id="zonas-container"></div>
<div id="asientos-container" class="asientos-container"></div> <div id="asientos-container" class="asientos-container"></div>
<div class="text-center mt-3"> <div class="text-center mt-3">
<button class="btn btn-primary" id="confirmarSeleccion">Confirmar selección</button> <button class="btn btn-primary" id="confirmarSeleccion">Confirmar selección</button>
</div> </div>
<script defer src="js/ventaBoletos.js"></script>
</body> </body>
</html> </html>

View File

@ -12,7 +12,7 @@
<body> <body>
<nav> <nav>
<a href="ventanaInsertarConcierto.html" class="navbar-brand">TicketFei</a> <a href="ventanaConciertos.html" class="navbar-brand">TicketFei</a>
<div class="nav-links"> <div class="nav-links">
<a href="ventanaInsertarConcierto.html">Crear Conciertos</a> <a href="ventanaInsertarConcierto.html">Crear Conciertos</a>
<a href="ventanaConciertos.html">Ver Conciertos</a> <a href="ventanaConciertos.html">Ver Conciertos</a>