refactor: reestructurar carpetas del proyecto

This commit is contained in:
Christian Julian Jimenez 2025-03-08 20:11:23 -06:00
parent 32c0a2c6a5
commit 37931b8cca
12 changed files with 0 additions and 961 deletions

89
bd.sql
View File

@ -1,89 +0,0 @@
-- Creación de la base de datos
CREATE DATABASE IF NOT EXISTS boletos_db;
USE boletos_db;
-- Tabla de salas
CREATE TABLE IF NOT EXISTS salas (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(100) NOT NULL,
filas INT NOT NULL,
asientos_por_fila INT NOT NULL
);
-- Tabla de boletos
CREATE TABLE IF NOT EXISTS boletos (
id INT AUTO_INCREMENT PRIMARY KEY,
id_sala INT NOT NULL,
fila INT NOT NULL,
numero INT NOT NULL,
precio DECIMAL(10,2) NOT NULL,
estado ENUM('disponible', 'vendido') DEFAULT 'disponible',
FOREIGN KEY (id_sala) REFERENCES salas(id),
UNIQUE KEY unique_asiento (id_sala, fila, numero)
);
-- Tabla de ventas
CREATE TABLE IF NOT EXISTS ventas (
id VARCHAR(36) PRIMARY KEY,
fecha DATETIME NOT NULL,
nombre_cliente VARCHAR(100) NOT NULL,
total DECIMAL(10,2) NOT NULL
);
select * from ventas;
select * from venta_boletos;
select * from boletos;
-- Tabla relacional venta-boletos
CREATE TABLE IF NOT EXISTS venta_boletos (
id INT AUTO_INCREMENT PRIMARY KEY,
id_venta VARCHAR(36) NOT NULL,
id_boleto INT NOT NULL,
FOREIGN KEY (id_venta) REFERENCES ventas(id),
FOREIGN KEY (id_boleto) REFERENCES boletos(id),
UNIQUE KEY unique_venta_boleto (id_venta, id_boleto)
);
-- Insertar una sala de ejemplo
INSERT INTO salas (id, nombre, filas, asientos_por_fila)
VALUES (1, 'Sala Principal', 10, 15);
-- Procedimiento para inicializar boletos
DELIMITER //
CREATE PROCEDURE InicializaBoletos(IN sala_id INT, IN precio DECIMAL(10,2))
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE j INT DEFAULT 1;
DECLARE total_filas INT DEFAULT 0;
DECLARE total_asientos INT DEFAULT 0;
-- Obtener dimensiones de la sala
SELECT filas, asientos_por_fila INTO total_filas, total_asientos
FROM salas WHERE id = sala_id;
-- Depuración: Verificar valores obtenidos
SELECT CONCAT('Filas:', total_filas, ' Asientos:', total_asientos) AS Debug_Info;
-- Si no se encuentran filas/asientos, salir del procedimiento
IF total_filas = 0 OR total_asientos = 0 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Sala no encontrada o sin dimensiones definidas';
END IF;
-- Eliminar boletos existentes de la sala
DELETE FROM boletos WHERE id_sala = sala_id;
-- Crear nuevos boletos
SET i = 1;
WHILE i <= total_filas DO
SET j = 1;
WHILE j <= total_asientos DO
INSERT INTO boletos (id_sala, fila, numero, precio, estado)
VALUES (sala_id, i, j, precio, 'disponible');
SET j = j + 1;
END WHILE;
SET i = i + 1;
END WHILE;
END //
DELIMITER ;

View File

@ -1,94 +0,0 @@
<?php
require_once 'Sala.php';
require_once 'Boleto.php';
require_once 'Venta.php';
class BaseDatos {
private $conexion;
public function __construct($host, $usuario, $password, $nombreBD) {
$this->conexion = new mysqli($host, $usuario, $password, $nombreBD);
if ($this->conexion->connect_error) {
die("Error de conexión: " . $this->conexion->connect_error);
}
}
public function cargarSala($idSala) {
$sala = null;
$query = "SELECT id, nombre FROM salas WHERE id = ?";
$stmt = $this->conexion->prepare($query);
$stmt->bind_param("i", $idSala);
$stmt->execute();
$result = $stmt->get_result();
if ($fila = $result->fetch_assoc()) {
$sala = new Sala($fila['id'], $fila['nombre']);
// Cargar boletos de la sala
$queryBoletos = "SELECT id, fila, numero, precio, estado FROM boletos WHERE id_sala = ?";
$stmtBoletos = $this->conexion->prepare($queryBoletos);
$stmtBoletos->bind_param("i", $idSala);
$stmtBoletos->execute();
$resultBoletos = $stmtBoletos->get_result();
$boletos = [];
while ($filaBoleto = $resultBoletos->fetch_assoc()) {
$boleto = new Boleto($filaBoleto['id'], $filaBoleto['fila'], $filaBoleto['numero'], $filaBoleto['precio']);
if ($filaBoleto['estado'] === 'vendido') {
$boleto->marcarComoVendido();
}
$boletos[] = $boleto;
}
// Asignar boletos a la sala
$sala->setBoletos($boletos);
}
return $sala;
}
public function guardarVenta($venta) {
// Iniciar transacción
$this->conexion->begin_transaction();
try {
// Insertar venta
$query = "INSERT INTO ventas (id, fecha, nombre_cliente, total) VALUES (?, ?, ?, ?)";
$stmt = $this->conexion->prepare($query);
$id = $venta->getId();
$fecha = $venta->getFecha();
$nombreCliente = $venta->getNombreCliente();
$total = $venta->getTotal();
$stmt->bind_param("sssd", $id, $fecha, $nombreCliente, $total);
$stmt->execute();
// Actualizar estado de boletos
foreach ($venta->getBoletos() as $boleto) {
$queryBoleto = "UPDATE boletos SET estado = 'vendido' WHERE id = ?";
$stmtBoleto = $this->conexion->prepare($queryBoleto);
$idBoleto = $boleto->getId();
$stmtBoleto->bind_param("i", $idBoleto);
$stmtBoleto->execute();
// Insertar relación venta-boleto
$queryRelacion = "INSERT INTO venta_boletos (id_venta, id_boleto) VALUES (?, ?)";
$stmtRelacion = $this->conexion->prepare($queryRelacion);
$stmtRelacion->bind_param("si", $id, $idBoleto);
$stmtRelacion->execute();
}
// Confirmar transacción
$this->conexion->commit();
return true;
} catch (Exception $e) {
// Revertir transacción en caso de error
$this->conexion->rollback();
return false;
}
}
public function cerrarConexion() {
$this->conexion->close();
}
}

View File

@ -1,46 +0,0 @@
<?php
class Boleto {
private $id;
private $fila;
private $numero;
private $precio;
private $estado; // 'disponible' o 'vendido'
public function __construct($id, $fila, $numero, $precio) {
$this->id = $id;
$this->fila = $fila;
$this->numero = $numero;
$this->precio = $precio;
$this->estado = 'disponible';
}
// Getters y setters
public function getId() {
return $this->id;
}
public function getFila() {
return $this->fila;
}
public function getNumero() {
return $this->numero;
}
public function getPrecio() {
return $this->precio;
}
public function getEstado() {
return $this->estado;
}
public function marcarComoVendido() {
$this->estado = 'vendido';
return true;
}
public function estaDisponible() {
return $this->estado === 'disponible';
}
}

View File

@ -1,62 +0,0 @@
<?php
require_once 'Boleto.php';
class Sala {
private $id;
private $nombre;
private $boletos = [];
public function __construct($id, $nombre) {
$this->id = $id;
$this->nombre = $nombre;
}
public function getId() {
return $this->id;
}
public function getNombre() {
return $this->nombre;
}
public function inicializarBoletos($filas, $asientosPorFila, $precio) {
$this->boletos = [];
$contador = 1;
for ($i = 1; $i <= $filas; $i++) {
for ($j = 1; $j <= $asientosPorFila; $j++) {
$this->boletos[] = new Boleto($contador, $i, $j, $precio);
$contador++;
}
}
}
public function obtenerBoletos() {
return $this->boletos;
}
public function obtenerBoletosPorEstado($estado) {
return array_filter($this->boletos, function($boleto) use ($estado) {
return $boleto->getEstado() === $estado;
});
}
public function obtenerBoletosPorId($ids) {
return array_filter($this->boletos, function($boleto) use ($ids) {
return in_array($boleto->getId(), $ids);
});
}
public function disponibilidadAsientos() {
$mapa = [];
foreach ($this->boletos as $boleto) {
$mapa[$boleto->getFila()][$boleto->getNumero()] = $boleto->getEstado();
}
return $mapa;
}
// Setter para asignar boletos desde la base de datos
public function setBoletos($boletos) {
$this->boletos = $boletos;
}
}

View File

@ -1,47 +0,0 @@
<?php
require_once 'BaseDatos.php';
require_once 'Sala.php';
require_once 'Boleto.php';
require_once 'Venta.php';
class VendedorController {
private $baseDatos;
private $sala;
public function __construct($baseDatos) {
$this->baseDatos = $baseDatos;
}
public function cargarSala($idSala) {
$this->sala = $this->baseDatos->cargarSala($idSala);
return $this->sala;
}
public function mostrarDisponibilidadAsientos() {
if ($this->sala) {
return $this->sala->disponibilidadAsientos();
}
return null;
}
public function seleccionarBoletos($idsBoletos) {
if ($this->sala) {
return $this->sala->obtenerBoletosPorId($idsBoletos);
}
return [];
}
public function procesarVenta($boletos, $nombreCliente) {
$venta = new Venta($nombreCliente);
$venta->agregarBoletos($boletos);
if (count($venta->getBoletos()) > 0) {
$resultado = $this->baseDatos->guardarVenta($venta);
if ($resultado) {
return $venta->generarComprobante();
}
}
return null;
}
}

View File

@ -1,68 +0,0 @@
<?php
require_once 'Boleto.php';
class Venta {
private $id;
private $fecha;
private $boletos = [];
private $total;
private $nombreCliente;
public function __construct($nombreCliente) {
$this->id = uniqid();
$this->fecha = date('Y-m-d H:i:s');
$this->nombreCliente = $nombreCliente;
$this->total = 0;
}
public function getId() {
return $this->id;
}
public function getFecha() {
return $this->fecha;
}
public function getNombreCliente() {
return $this->nombreCliente;
}
public function agregarBoletos($boletos) {
foreach ($boletos as $boleto) {
if ($boleto->estaDisponible()) {
$this->boletos[] = $boleto;
$this->total += $boleto->getPrecio();
$boleto->marcarComoVendido();
}
}
}
public function generarComprobante() {
$comprobante = [
'id_venta' => $this->id,
'fecha' => $this->fecha,
'cliente' => $this->nombreCliente,
'boletos' => [],
'total' => $this->total
];
foreach ($this->boletos as $boleto) {
$comprobante['boletos'][] = [
'id' => $boleto->getId(),
'fila' => $boleto->getFila(),
'numero' => $boleto->getNumero(),
'precio' => $boleto->getPrecio()
];
}
return $comprobante;
}
public function getTotal() {
return $this->total;
}
public function getBoletos() {
return $this->boletos;
}
}

View File

@ -1,89 +0,0 @@
<?php
// comprobante.php - Página de comprobante de venta
session_start();
// Verificar si hay un comprobante en la sesión
if (!isset($_SESSION['comprobante'])) {
header('Location: index.php');
exit;
}
$comprobante = $_SESSION['comprobante'];
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Comprobante de Venta</title>
<link rel="stylesheet" href="css/comprobante.css">
</head>
<body>
<div class="container">
<h1>Comprobante de Venta</h1>
<div class="comprobante" id="comprobante-imprimible">
<div class="header">
<h2>Boletos para Concierto - Sala Principal</h2>
</div>
<div class="info-venta">
<div>
<div class="info-item">
<span class="info-label"> de Venta:</span>
<span><?php echo $comprobante['id_venta']; ?></span>
</div>
<div class="info-item">
<span class="info-label">Fecha:</span>
<span><?php echo $comprobante['fecha']; ?></span>
</div>
</div>
<div>
<div class="info-item">
<span class="info-label">Cliente:</span>
<span><?php echo $comprobante['cliente']; ?></span>
</div>
</div>
</div>
<h3>Detalle de Boletos</h3>
<table>
<thead>
<tr>
<th>#</th>
<th>Ubicación</th>
<th>Precio</th>
</tr>
</thead>
<tbody>
<?php foreach ($comprobante['boletos'] as $index => $boleto): ?>
<tr>
<td><?php echo $index + 1; ?></td>
<td>Fila <?php echo $boleto['fila']; ?>, Asiento <?php echo $boleto['numero']; ?></td>
<td>$<?php echo number_format($boleto['precio'], 2); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="total">
Total: $<?php echo number_format($comprobante['total'], 2); ?>
</div>
<div style="margin-top: 40px; font-size: 14px; text-align: center;">
<p>¡Gracias por su compra!</p>
<p>Este comprobante es su entrada oficial para el evento.</p>
<p>Por favor, preséntelo en la entrada del concierto.</p>
</div>
</div>
<div class="acciones">
<a href="index.php" class="btn">Volver a Ventas</a>
<button class="btn btn-print" onclick="imprimirComprobante()">Imprimir Comprobante</button>
</div>
</div>
<script src="js/comprobante.js"></script>
</body>
</html>

View File

@ -1,81 +0,0 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
background-color: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
h1, h2 {
color: #333;
}
.comprobante {
border: 1px solid #ddd;
padding: 20px;
border-radius: 4px;
margin: 20px 0;
}
.header {
border-bottom: 2px solid #333;
padding-bottom: 10px;
margin-bottom: 20px;
}
.info-venta {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
}
.info-item {
margin-bottom: 10px;
}
.info-label {
font-weight: bold;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f8f9fa;
}
.total {
font-size: 18px;
font-weight: bold;
text-align: right;
margin-top: 20px;
padding-top: 10px;
border-top: 1px solid #ddd;
}
.acciones {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
.btn {
background-color: #007bff;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
text-decoration: none;
cursor: pointer;
display: inline-block;
}
.btn-print {
background-color: #6c757d;
}
.btn:hover {
opacity: 0.9;
}

View File

@ -1,131 +0,0 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
background-color: #f5f5f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
h1, h2 {
color: #333;
}
.mensaje {
background-color: #f8d7da;
color: #721c24;
padding: 10px;
margin-bottom: 20px;
border-radius: 4px;
display: none;
}
.sala {
margin: 20px 0;
text-align: center;
}
.escenario {
background-color: #ddd;
padding: 10px;
margin-bottom: 30px;
border-radius: 4px;
text-align: center;
font-weight: bold;
}
.filas {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
.fila {
display: flex;
gap: 10px;
align-items: center;
}
.numero-fila {
width: 30px;
text-align: center;
font-weight: bold;
}
.asientos {
display: flex;
gap: 5px;
}
.asiento {
width: 35px;
height: 35px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 5px;
cursor: pointer;
user-select: none;
font-size: 12px;
}
.disponible {
background-color: #28a745;
color: white;
}
.vendido {
background-color: #dc3545;
color: white;
cursor: not-allowed;
}
.seleccionado {
background-color: #007bff;
color: white;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
input[type="text"] {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
}
.btn {
background-color: #007bff;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
}
.btn:hover {
background-color: #0069d9;
}
.resumen {
margin-top: 20px;
padding: 15px;
background-color: #f8f9fa;
border-radius: 4px;
}
.leyenda {
display: flex;
gap: 15px;
margin-top: 20px;
justify-content: center;
}
.leyenda-item {
display: flex;
align-items: center;
gap: 5px;
}
.leyenda-color {
width: 20px;
height: 20px;
border-radius: 3px;
}

141
index.php
View File

@ -1,141 +0,0 @@
<?php
// index.php - Página principal del sistema
session_start();
require_once 'clases/BaseDatos.php';
require_once 'clases/Sala.php';
require_once 'clases/Boleto.php';
require_once 'clases/Venta.php';
require_once 'clases/VendedorController.php';
// Conexión a base de datos
$db = new BaseDatos('localhost:3306', 'root', '481037', 'boletos_db');
// Inicializar el controlador
$vendedorController = new VendedorController($db);
// Cargar sala (solo hay una sala con id=1)
$sala = $vendedorController->cargarSala(1);
// Si no hay sala, podríamos inicializarla para desarrollo
if (!$sala) {
$sala = new Sala(1, 'Sala Principal');
$sala->inicializarBoletos(10, 15, 50.00); // 10 filas, 15 asientos por fila, $50 cada uno
}
// Variable para almacenar mensajes de confirmación
$mensaje = '';
// Procesar formulario de venta
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['vender'])) {
if (isset($_POST['asientos']) && isset($_POST['nombre_cliente'])) {
$idsBoletos = $_POST['asientos'];
$nombreCliente = $_POST['nombre_cliente'];
$boletosSeleccionados = $vendedorController->seleccionarBoletos($idsBoletos);
if (count($boletosSeleccionados) > 0) {
$comprobante = $vendedorController->procesarVenta($boletosSeleccionados, $nombreCliente);
if ($comprobante) {
// Guardar comprobante en sesión para mostrarlo
$_SESSION['comprobante'] = $comprobante;
// Redireccionar a página de comprobante
header('Location: comprobante.php');
exit;
} else {
$mensaje = 'Error al procesar la venta. Intente nuevamente.';
}
} else {
$mensaje = 'No se han seleccionado asientos disponibles.';
}
} else {
$mensaje = 'Por favor, seleccione al menos un asiento y proporcione el nombre del cliente.';
}
}
// Obtener mapa de asientos
$mapaAsientos = $vendedorController->mostrarDisponibilidadAsientos();
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sistema de Venta de Boletos</title>
<link rel="stylesheet" href="css/index.css">
<style>
</style>
</head>
<body>
<div class="container">
<h1>Sistema de Venta de Boletos para Concierto</h1>
<?php if (!empty($mensaje)): ?>
<div class="mensaje"><?php echo $mensaje; ?></div>
<?php endif; ?>
<form method="post" id="formularioVenta">
<div class="sala">
<h2>Selección de Asientos - Sala Principal</h2>
<div class="escenario">ESCENARIO</div>
<div class="filas">
<?php foreach ($mapaAsientos as $numeroFila => $asientosEnFila): ?>
<div class="fila">
<div class="numero-fila">F<?php echo $numeroFila; ?></div>
<div class="asientos">
<?php foreach ($asientosEnFila as $numeroAsiento => $estado): ?>
<?php
$idBoleto = (($numeroFila - 1) * count($asientosEnFila)) + $numeroAsiento;
$clase = ($estado === 'disponible') ? 'asiento disponible' : 'asiento vendido';
$disabled = ($estado === 'disponible') ? '' : 'disabled';
?>
<div class="<?php echo $clase; ?>"
data-id="<?php echo $idBoleto; ?>"
<?php echo $disabled; ?>>
<?php echo $numeroAsiento; ?>
</div>
<?php endforeach; ?>
</div>
</div>
<?php endforeach; ?>
</div>
<div class="leyenda">
<div class="leyenda-item">
<div class="leyenda-color" style="background-color: #28a745;"></div>
<span>Disponible</span>
</div>
<div class="leyenda-item">
<div class="leyenda-color" style="background-color: #007bff;"></div>
<span>Seleccionado</span>
</div>
<div class="leyenda-item">
<div class="leyenda-color" style="background-color: #dc3545;"></div>
<span>Vendido</span>
</div>
</div>
</div>
<div class="form-group">
<label for="nombre_cliente">Nombre del Cliente:</label>
<input type="text" id="nombre_cliente" name="nombre_cliente" required>
</div>
<div class="resumen" id="resumen">
<h3>Resumen de Selección</h3>
<p>Asientos seleccionados: <span id="asientosSeleccionados">Ninguno</span></p>
<p>Total: $<span id="totalVenta">0.00</span></p>
<button type="submit" name="vender" class="btn">Confirmar Venta</button>
</div>
<!-- Campo oculto para almacenar IDs de asientos seleccionados -->
<div id="asientosSeleccionadosInput"></div>
</form>
</div>
<script src="js/index.js"></script>
</body>
</html>

View File

@ -1,30 +0,0 @@
function imprimirComprobante() {
const contenido = document.getElementById('comprobante-imprimible').innerHTML;
const ventanaImpresion = window.open('', '_blank');
ventanaImpresion.document.write(`
<html>
<head>
<title>Comprobante de Venta</title>
<style>
body { font-family: Arial, sans-serif; }
.header { border-bottom: 2px solid #333; padding-bottom: 10px; margin-bottom: 20px; }
.info-venta { display: flex; justify-content: space-between; margin-bottom: 20px; }
.info-item { margin-bottom: 10px; }
.info-label { font-weight: bold; }
table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f8f9fa; }
.total { font-size: 18px; font-weight: bold; text-align: right; margin-top: 20px; padding-top: 10px; border-top: 1px solid #ddd; }
</style>
</head>
<body>
${contenido}
</body>
</html>
`);
ventanaImpresion.document.close();
ventanaImpresion.focus();
ventanaImpresion.print();
}

View File

@ -1,83 +0,0 @@
document.addEventListener('DOMContentLoaded', function() {
const asientos = document.querySelectorAll('.asiento.disponible');
const resumenAsientos = document.getElementById('asientosSeleccionados');
const resumenTotal = document.getElementById('totalVenta');
const asientosInput = document.getElementById('asientosSeleccionadosInput');
const formulario = document.getElementById('formularioVenta');
let seleccionados = [];
const precioBoleto = 50.00; // Precio por boleto
// Función para actualizar el resumen
function actualizarResumen() {
if (seleccionados.length === 0) {
resumenAsientos.textContent = 'Ninguno';
resumenTotal.textContent = '0.00';
} else {
// Mostrar los asientos seleccionados
const detalles = seleccionados.map(asiento => {
const fila = Math.floor((asiento.id - 1) / 15) + 1;
const numero = ((asiento.id - 1) % 15) + 1;
return `F${fila}-${numero}`;
});
resumenAsientos.textContent = detalles.join(', ');
resumenTotal.textContent = (seleccionados.length * precioBoleto).toFixed(2);
// Actualizar campo oculto para el envío del formulario
asientosInput.innerHTML = '';
seleccionados.forEach(asiento => {
const input = document.createElement('input');
input.type = 'hidden';
input.name = 'asientos[]';
input.value = asiento.id;
asientosInput.appendChild(input);
});
}
}
// Escuchar clics en los asientos
asientos.forEach(asiento => {
asiento.addEventListener('click', function() {
const asientoId = parseInt(this.getAttribute('data-id'));
// Verificar si ya está seleccionado
const indice = seleccionados.findIndex(a => a.id === asientoId);
if (indice === -1) {
// Agregar a seleccionados
seleccionados.push({
id: asientoId,
elemento: this
});
this.classList.remove('disponible');
this.classList.add('seleccionado');
} else {
// Quitar de seleccionados
seleccionados.splice(indice, 1);
this.classList.remove('seleccionado');
this.classList.add('disponible');
}
actualizarResumen();
});
});
// Validar formulario antes de enviar
formulario.addEventListener('submit', function(e) {
if (seleccionados.length === 0) {
e.preventDefault();
alert('Por favor, seleccione al menos un asiento.');
return false;
}
const nombreCliente = document.getElementById('nombre_cliente').value.trim();
if (nombreCliente === '') {
e.preventDefault();
alert('Por favor, ingrese el nombre del cliente.');
return false;
}
return true;
});
});