From 447658ddc7c709f6f2ddc2736bc6cffb1b0bae99 Mon Sep 17 00:00:00 2001
From: Christian Julian Jimenez <zs22016079@estudiantes.uv.mx>
Date: Mon, 10 Mar 2025 00:16:32 -0600
Subject: [PATCH] =?UTF-8?q?feat:=20Corregi=C3=B3n=20de=20archivos?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 corregido/conf/bd.sql                        |  89 ++++++++
 corregido/controlador/VendedorController.php |  48 +++++
 corregido/controlador/asientos.php           |  38 ++++
 corregido/controlador/comprobante.php        |  17 ++
 corregido/controlador/venta.php              |  71 +++++++
 corregido/index.php                          |   5 +
 corregido/modelo/BaseDatos.php               |  94 +++++++++
 corregido/modelo/Boleto.php                  |  46 +++++
 corregido/modelo/Sala.php                    |  62 ++++++
 corregido/modelo/Venta.php                   |  69 +++++++
 corregido/vista/comprobante.html             |  76 +++++++
 corregido/vista/css/comprobante.css          | 103 ++++++++++
 corregido/vista/css/index.css                | 199 ++++++++++++++++++
 corregido/vista/images/icono.png             | Bin 0 -> 24097 bytes
 corregido/vista/index.html                   |  93 +++++++++
 corregido/vista/js/comprobante.js            | 110 ++++++++++
 corregido/vista/js/index.js                  | 206 +++++++++++++++++++
 17 files changed, 1326 insertions(+)
 create mode 100644 corregido/conf/bd.sql
 create mode 100644 corregido/controlador/VendedorController.php
 create mode 100644 corregido/controlador/asientos.php
 create mode 100644 corregido/controlador/comprobante.php
 create mode 100644 corregido/controlador/venta.php
 create mode 100644 corregido/index.php
 create mode 100644 corregido/modelo/BaseDatos.php
 create mode 100644 corregido/modelo/Boleto.php
 create mode 100644 corregido/modelo/Sala.php
 create mode 100644 corregido/modelo/Venta.php
 create mode 100644 corregido/vista/comprobante.html
 create mode 100644 corregido/vista/css/comprobante.css
 create mode 100644 corregido/vista/css/index.css
 create mode 100644 corregido/vista/images/icono.png
 create mode 100644 corregido/vista/index.html
 create mode 100644 corregido/vista/js/comprobante.js
 create mode 100644 corregido/vista/js/index.js

diff --git a/corregido/conf/bd.sql b/corregido/conf/bd.sql
new file mode 100644
index 0000000..fe44ff0
--- /dev/null
+++ b/corregido/conf/bd.sql
@@ -0,0 +1,89 @@
+-- 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 ;
\ No newline at end of file
diff --git a/corregido/controlador/VendedorController.php b/corregido/controlador/VendedorController.php
new file mode 100644
index 0000000..4d60fab
--- /dev/null
+++ b/corregido/controlador/VendedorController.php
@@ -0,0 +1,48 @@
+<?php
+
+require_once '../modelo/BaseDatos.php';
+require_once '../modelo/Sala.php';
+require_once '../modelo/Boleto.php';
+require_once '../modelo/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;
+    }
+}
\ No newline at end of file
diff --git a/corregido/controlador/asientos.php b/corregido/controlador/asientos.php
new file mode 100644
index 0000000..fd8c6e4
--- /dev/null
+++ b/corregido/controlador/asientos.php
@@ -0,0 +1,38 @@
+<?php
+// api/asientos.php - API para obtener el mapa de asientos
+session_start();
+
+require_once '../modelo/BaseDatos.php';
+require_once '../modelo/Sala.php';
+require_once '../modelo/Boleto.php';
+require_once '../modelo/Venta.php';
+require_once 'VendedorController.php';
+
+header('Content-Type: application/json');
+
+// 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
+}
+
+// Obtener mapa de asientos
+$mapaAsientos = $vendedorController->mostrarDisponibilidadAsientos();
+
+// Preparar respuesta
+$response = [
+    'success' => true,
+    'mapa' => $mapaAsientos,
+    'precio' => 50.00 // Agregamos el precio de los boletos a la respuesta
+];
+
+echo json_encode($response);
\ No newline at end of file
diff --git a/corregido/controlador/comprobante.php b/corregido/controlador/comprobante.php
new file mode 100644
index 0000000..7c544d9
--- /dev/null
+++ b/corregido/controlador/comprobante.php
@@ -0,0 +1,17 @@
+<?php
+// comprobante.php - Lógica de servidor para el comprobante de venta
+session_start();
+
+// Verificar si hay un comprobante en la sesión
+if (!isset($_SESSION['comprobante'])) {
+    header('Location: ../vista/index.html');
+    exit;
+}
+
+// Obtener el comprobante de la sesión
+$comprobante = $_SESSION['comprobante'];
+
+// Devolver datos en formato JSON para ser consumidos por JavaScript
+header('Content-Type: application/json');
+echo json_encode($comprobante);
+?>
\ No newline at end of file
diff --git a/corregido/controlador/venta.php b/corregido/controlador/venta.php
new file mode 100644
index 0000000..f976d92
--- /dev/null
+++ b/corregido/controlador/venta.php
@@ -0,0 +1,71 @@
+<?php
+// api/venta.php - API para procesar ventas
+session_start();
+
+require_once '../modelo/BaseDatos.php';
+require_once '../modelo/Sala.php';
+require_once '../modelo/Boleto.php';
+require_once '../modelo/Venta.php';
+require_once 'VendedorController.php';
+
+header('Content-Type: application/json');
+
+// Verificar método de solicitud
+if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
+    echo json_encode(['success' => false, 'mensaje' => 'Método no permitido']);
+    exit;
+}
+
+// Obtener datos JSON del cuerpo de la solicitud
+$data = json_decode(file_get_contents('php://input'), true);
+
+if (!$data || !isset($data['asientos']) || !isset($data['nombre_cliente'])) {
+    echo json_encode(['success' => false, 'mensaje' => 'Datos incompletos']);
+    exit;
+}
+
+// Extraer datos
+$idsBoletos = $data['asientos'];
+$nombreCliente = $data['nombre_cliente'];
+
+// Validar que haya asientos seleccionados
+if (empty($idsBoletos)) {
+    echo json_encode(['success' => false, 'mensaje' => 'No se han seleccionado asientos']);
+    exit;
+}
+
+// Conexión a base de datos
+$db = new BaseDatos('localhost:3306', 'root', '481037', 'boletos_db');
+
+// Inicializar el controlador
+$vendedorController = new VendedorController($db);
+
+// Cargar la sala (agregando esta línea)
+$vendedorController->cargarSala(1); // O el ID de sala correspondiente
+
+// Seleccionar boletos
+$boletosSeleccionados = $vendedorController->seleccionarBoletos($idsBoletos);
+
+if (count($boletosSeleccionados) == 0) {
+    echo json_encode(['success' => false, 'mensaje' => 'No se han seleccionado asientos disponibles']);
+    exit;
+}
+
+// Procesar venta
+$comprobante = $vendedorController->procesarVenta($boletosSeleccionados, $nombreCliente);
+
+if (!$comprobante) {
+    echo json_encode(['success' => false, 'mensaje' => 'Error al procesar la venta. Intente nuevamente']);
+    exit;
+}
+
+// Guardar comprobante en sesión
+$_SESSION['comprobante'] = $comprobante;
+
+// Respuesta exitosa
+echo json_encode([
+    'success' => true, 
+    'mensaje' => 'Venta procesada con éxito',
+    'redirect' => '../vista/comprobante.html',
+    'comprobante' => $comprobante
+]);
\ No newline at end of file
diff --git a/corregido/index.php b/corregido/index.php
new file mode 100644
index 0000000..968cc46
--- /dev/null
+++ b/corregido/index.php
@@ -0,0 +1,5 @@
+<?php
+// Redirigir a la página principal del sistema
+header("Location: vista/index.html");
+exit();
+?>
diff --git a/corregido/modelo/BaseDatos.php b/corregido/modelo/BaseDatos.php
new file mode 100644
index 0000000..c27b5a1
--- /dev/null
+++ b/corregido/modelo/BaseDatos.php
@@ -0,0 +1,94 @@
+<?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();
+    }
+}
\ No newline at end of file
diff --git a/corregido/modelo/Boleto.php b/corregido/modelo/Boleto.php
new file mode 100644
index 0000000..bec7a82
--- /dev/null
+++ b/corregido/modelo/Boleto.php
@@ -0,0 +1,46 @@
+<?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';
+    }
+}
\ No newline at end of file
diff --git a/corregido/modelo/Sala.php b/corregido/modelo/Sala.php
new file mode 100644
index 0000000..b1ea1af
--- /dev/null
+++ b/corregido/modelo/Sala.php
@@ -0,0 +1,62 @@
+<?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;
+    }
+}
\ No newline at end of file
diff --git a/corregido/modelo/Venta.php b/corregido/modelo/Venta.php
new file mode 100644
index 0000000..1df14ae
--- /dev/null
+++ b/corregido/modelo/Venta.php
@@ -0,0 +1,69 @@
+<?php
+require_once 'Boleto.php';
+
+class Venta {
+    private $id;
+    private $fecha;
+    private $boletos = [];
+    private $total;
+    private $nombreCliente;
+    
+    public function __construct($nombreCliente) {
+        $this->id = bin2hex(random_bytes(8));
+        date_default_timezone_set('America/Mexico_City');
+        $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;
+    }
+}
\ No newline at end of file
diff --git a/corregido/vista/comprobante.html b/corregido/vista/comprobante.html
new file mode 100644
index 0000000..b517579
--- /dev/null
+++ b/corregido/vista/comprobante.html
@@ -0,0 +1,76 @@
+<!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">Nº de Venta:</span>
+                        <span id="id-venta"></span>
+                    </div>
+                    <div class="info-item">
+                        <span class="info-label">Fecha:</span>
+                        <span id="fecha-venta"></span>
+                    </div>
+                </div>
+                <div>
+                    <div class="info-item">
+                        <span class="info-label">Cliente:</span>
+                        <span id="cliente-venta"></span>
+                    </div>
+                </div>
+            </div>
+            
+            <h3>Detalle de Boletos</h3>
+            <table>
+                <thead>
+                    <tr>
+                        <th>#</th>
+                        <th>Ubicación</th>
+                        <th>Precio</th>
+                    </tr>
+                </thead>
+                <tbody id="detalle-boletos">
+                    <!-- El contenido de la tabla se generará dinámicamente con JavaScript -->
+                </tbody>
+            </table>
+            
+            <div class="total">
+                Total: $<span id="total-venta"></span>
+            </div>
+            
+            <div class="qr-container">
+                <div id="qr-code"></div>
+                <p class="qr-info">Este QR contiene el número de venta para verificación</p>
+            </div>
+            
+            <div class="mensaje">
+                <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.html" class="btn">Volver a Ventas</a>
+            <button class="btn btn-print" onclick="imprimirComprobante()">Imprimir Comprobante</button>
+        </div>
+    </div>
+    
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
+    <script src="js/comprobante.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/corregido/vista/css/comprobante.css b/corregido/vista/css/comprobante.css
new file mode 100644
index 0000000..fcf94c0
--- /dev/null
+++ b/corregido/vista/css/comprobante.css
@@ -0,0 +1,103 @@
+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;
+}
+
+.qr-container {
+    text-align: center;
+    margin: 30px 0;
+    padding: 10px;
+    border-top: 1px dashed #ccc;
+    padding-top: 20px;
+}
+#qr-code {
+    display: inline-block;
+    margin: 0 auto;
+}
+.qr-info {
+    font-size: 14px;
+    margin-top: 10px;
+}
+
+.mensaje {
+    margin-top: 40px; 
+    font-size: 14px; 
+    text-align: center;
+}
\ No newline at end of file
diff --git a/corregido/vista/css/index.css b/corregido/vista/css/index.css
new file mode 100644
index 0000000..bb656a5
--- /dev/null
+++ b/corregido/vista/css/index.css
@@ -0,0 +1,199 @@
+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);
+}
+
+.main-content {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20px;
+    margin-top: 20px;
+}
+
+.sala {
+    flex: 1;
+    min-width: 300px;
+    margin: 20px 0;
+    text-align: center;
+}
+
+.sidebar {
+    flex: 0 0 350px;
+}
+
+h1, h2 {
+    color: #333;
+}
+
+.mensaje {
+    background-color: #f8d7da;
+    color: #721c24;
+    padding: 10px;
+    margin-bottom: 20px;
+    border-radius: 4px;
+    display: none;
+}
+
+.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, .concierto-detalles, #formularioVenta {
+    background-color: #f8f9fa;
+    border-radius: 4px;
+}
+
+.resumen {
+    margin-top: 20px;
+    padding: 15px;
+}
+
+.concierto-detalles {
+    border-left: 4px solid #6c757d;
+}
+
+#formularioVenta {
+    padding: 20px;
+    border: 1px solid #ddd;
+    height: fit-content;
+}
+
+.concierto-detalles i {
+    color: #6c757d;
+    margin-right: 5px;
+    width: 20px;
+    text-align: center;
+}
+
+#formularioVenta i {
+    color: #495057;
+    margin-right: 5px;
+}
+
+.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;
+}
+
+@media (max-width: 992px) {
+    .main-content {
+        flex-direction: column;
+    }
+    
+    .sidebar {
+        width: 100%;
+    }
+}
\ No newline at end of file
diff --git a/corregido/vista/images/icono.png b/corregido/vista/images/icono.png
new file mode 100644
index 0000000000000000000000000000000000000000..b7d11e951f10559c3f2c07aae868aabab8f646ff
GIT binary patch
literal 24097
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

literal 0
HcmV?d00001

diff --git a/corregido/vista/index.html b/corregido/vista/index.html
new file mode 100644
index 0000000..973f533
--- /dev/null
+++ b/corregido/vista/index.html
@@ -0,0 +1,93 @@
+<!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 href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
+    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
+    <link rel="stylesheet" href="css/index.css">
+    <style>
+        .app-title {
+            display: flex;
+            align-items: center;
+            gap: 15px;
+        }
+        
+        .app-icon {
+            height: 40px;
+            width: auto;
+        }
+    </style>
+</head>
+<body>
+    <div class="container">
+        <div class="app-title">
+            <img src="images/icono.png" alt="TicketFlow Logo" class="app-icon">
+            <h1>TicketFlow</h1>
+        </div>
+        
+        <div id="mensajeAlerta" class="alert alert-warning d-none" role="alert"></div>
+        
+        <div class="main-content">
+            <div class="sala">
+                <h2>Selección de Asientos - Sala Principal</h2>
+                <div class="escenario">ESCENARIO</div>
+                
+                <div class="filas" id="mapaAsientos">
+                    <!-- El mapa de asientos se cargará dinámicamente con JavaScript -->
+                </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="sidebar">
+                <div class="concierto-detalles mb-4 p-3 bg-light border rounded">
+                    <h3 class="mb-3"><i class="bi bi-music-note-beamed"></i> Detalles del Concierto</h3>
+                    <ul class="list-unstyled">
+                        <li class="mb-2"><i class="bi bi-person-circle"></i> <strong>Artista:</strong> Nombre del Artista</li>
+                        <li class="mb-2"><i class="bi bi-calendar-event"></i> <strong>Fecha:</strong> 15 de abril, 2025</li>
+                        <li class="mb-2"><i class="bi bi-clock"></i> <strong>Hora:</strong> 20:00 hrs</li>
+                        <li class="mb-2"><i class="bi bi-geo-alt"></i> <strong>Lugar:</strong> Arena Principal</li>
+                        <li class="mb-2"><i class="bi bi-hourglass-split"></i> <strong>Duración:</strong> 2 horas</li>
+                        <li class="mb-2"><i class="bi bi-door-open"></i> <strong>Apertura:</strong> 18:30 hrs</li>
+                    </ul>
+                </div>
+                
+                <form id="formularioVenta">
+                    <h3><i class="bi bi-cart"></i> Datos de Venta</h3>
+                    <div class="form-group mb-3">
+                        <label for="nombre_cliente"><i class="bi bi-person"></i> Nombre del Cliente:</label>
+                        <input type="text" id="nombre_cliente" name="nombre_cliente" class="form-control" required>
+                    </div>
+                    
+                    <div class="resumen" id="resumen">
+                        <h3><i class="bi bi-ticket-perforated"></i> Resumen de Selección</h3>
+                        <p><i class="bi bi-seat"></i> Asientos seleccionados: <span id="asientosSeleccionados">Ninguno</span></p>
+                        <p><i class="bi bi-cash"></i> Total: $<span id="totalVenta">0.00</span></p>
+                        <button type="submit" id="btnVender" class="btn btn-primary"><i class="bi bi-check-circle"></i> Confirmar Venta</button>
+                    </div>
+                    
+                    <!-- Campo oculto para almacenar IDs de asientos seleccionados -->
+                    <div id="asientosSeleccionadosInput"></div>
+                </form>
+            </div>
+        </div>
+    </div>
+    
+    <script src="js/index.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/corregido/vista/js/comprobante.js b/corregido/vista/js/comprobante.js
new file mode 100644
index 0000000..0978029
--- /dev/null
+++ b/corregido/vista/js/comprobante.js
@@ -0,0 +1,110 @@
+// comprobante.js - Maneja la comunicación entre el PHP y el HTML
+
+// Cuando el documento esté listo, cargar los datos del comprobante
+document.addEventListener('DOMContentLoaded', cargarComprobante);
+
+// Función para cargar los datos del comprobante desde el servidor
+function cargarComprobante() {
+    fetch('../controlador/comprobante.php')
+        .then(response => {
+            if (!response.ok) {
+                throw new Error('Error al obtener los datos del comprobante');
+            }
+            return response.json();
+        })
+        .then(comprobante => {
+            // Llenar los datos básicos del comprobante
+            document.getElementById('id-venta').textContent = comprobante.id_venta;
+            document.getElementById('fecha-venta').textContent = comprobante.fecha;
+            document.getElementById('cliente-venta').textContent = comprobante.cliente;
+            document.getElementById('total-venta').textContent = formatearNumero(comprobante.total);
+            
+            // Generar las filas de la tabla de boletos
+            const tablaBoletos = document.getElementById('detalle-boletos');
+            let contenidoTabla = '';
+            
+            comprobante.boletos.forEach((boleto, index) => {
+                contenidoTabla += `
+                    <tr>
+                        <td>${index + 1}</td>
+                        <td>Fila ${boleto.fila}, Asiento ${boleto.numero}</td>
+                        <td>$${formatearNumero(boleto.precio)}</td>
+                    </tr>
+                `;
+            });
+            
+            tablaBoletos.innerHTML = contenidoTabla;
+            
+            // Generar código QR con el ID de la venta
+            generarQR(comprobante.id_venta);
+        })
+        .catch(error => {
+            console.error('Error:', error);
+            alert('No se pudo cargar el comprobante. Por favor, inténtelo de nuevo.');
+            window.location.href = 'index.html';
+        });
+}
+
+// Función para generar el código QR
+function generarQR(idVenta) {
+    // Verificar si existe el elemento donde se mostrará el QR
+    const qrContainer = document.getElementById('qr-code');
+    if (!qrContainer) {
+        console.error('No se encontró el elemento para mostrar el código QR');
+        return;
+    }
+    
+    // Limpiar el contenedor por si ya tiene contenido
+    qrContainer.innerHTML = '';
+    
+    // Crear una nueva instancia de QRCode
+    new QRCode(qrContainer, {
+        text: idVenta.toString(),
+        width: 128,
+        height: 128,
+        colorDark: "#000000",
+        colorLight: "#ffffff",
+        correctLevel: QRCode.CorrectLevel.H // Alta corrección de errores
+    });
+}
+
+// Función para imprimir el comprobante
+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; }
+                .qr-container { text-align: center; margin: 20px 0; border-top: 1px dashed #ccc; padding-top: 20px;}
+                #qr-code { display: inline-block; margin: 0 auto; }
+                .qr-info { font-size: 14px; margin-top: 10px; }
+                .mensaje { margin-top: 40px; font-size: 14px; text-align: center;}
+            </style>
+        </head>
+        <body>
+            ${contenido}
+        </body>
+        </html>
+    `);
+    
+    ventanaImpresion.document.close();
+    ventanaImpresion.focus();
+    ventanaImpresion.print();
+}
+
+// Función auxiliar para formatear números con dos decimales
+function formatearNumero(numero) {
+    return Number(numero).toFixed(2);
+}
\ No newline at end of file
diff --git a/corregido/vista/js/index.js b/corregido/vista/js/index.js
new file mode 100644
index 0000000..ce74209
--- /dev/null
+++ b/corregido/vista/js/index.js
@@ -0,0 +1,206 @@
+// js/index.js - Script para manejar la interfaz de usuario y la comunicación con el backend
+
+document.addEventListener('DOMContentLoaded', function() {
+    let seleccionados = [];
+    const precioBoleto = 50.00; // Precio por boleto
+    
+    // Cargar el mapa de asientos al iniciar
+    cargarMapaAsientos();
+    
+    // Agregar manejador para el formulario
+    const formulario = document.getElementById('formularioVenta');
+    formulario.addEventListener('submit', validarYEnviarFormulario);
+    
+    // Función para cargar el mapa de asientos desde la API
+    async function cargarMapaAsientos() {
+        try {
+            const response = await fetch('../controlador/asientos.php');
+            const data = await response.json();
+            
+            if (!data.success) {
+                mostrarMensaje('Error al cargar el mapa de asientos', 'error');
+                return;
+            }
+            
+            renderizarMapaAsientos(data.mapa);
+        } catch (error) {
+            console.error('Error al cargar el mapa de asientos:', error);
+            mostrarMensaje('Error de conexión con el servidor', 'error');
+        }
+    }
+    
+    // Función para renderizar el mapa de asientos
+    function renderizarMapaAsientos(mapa) {
+        const contenedor = document.getElementById('mapaAsientos');
+        contenedor.innerHTML = '';
+        
+        Object.entries(mapa).forEach(([numeroFila, asientosEnFila]) => {
+            const filaElement = document.createElement('div');
+            filaElement.className = 'fila';
+            
+            // Crear elemento para el número de fila
+            const numeroFilaElement = document.createElement('div');
+            numeroFilaElement.className = 'numero-fila';
+            numeroFilaElement.textContent = `F${numeroFila}`;
+            filaElement.appendChild(numeroFilaElement);
+            
+            // Crear contenedor para los asientos
+            const asientosContainer = document.createElement('div');
+            asientosContainer.className = 'asientos';
+            
+            // Crear cada asiento
+            Object.entries(asientosEnFila).forEach(([numeroAsiento, estado]) => {
+                const idBoleto = ((parseInt(numeroFila) - 1) * Object.keys(asientosEnFila).length) + parseInt(numeroAsiento);
+                const asiento = document.createElement('div');
+                
+                // Determinar la clase según el estado
+                asiento.className = `asiento ${estado === 'disponible' ? 'disponible' : 'vendido'}`;
+                asiento.dataset.id = idBoleto;
+                asiento.textContent = numeroAsiento;
+                
+                asientosContainer.appendChild(asiento);
+            });
+            
+            filaElement.appendChild(asientosContainer);
+            contenedor.appendChild(filaElement);
+        });
+        
+        // Una vez que se ha renderizado, añadir los eventos
+        configurarEventosAsientos();
+    }
+    
+    // Configurar eventos para los asientos
+    function configurarEventosAsientos() {
+        const asientos = document.querySelectorAll('.asiento.disponible');
+        
+        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();
+            });
+        });
+    }
+    
+    // Función para actualizar el resumen de venta
+    function actualizarResumen() {
+        const resumenAsientos = document.getElementById('asientosSeleccionados');
+        const resumenTotal = document.getElementById('totalVenta');
+        const asientosInput = document.getElementById('asientosSeleccionadosInput');
+        
+        if (seleccionados.length === 0) {
+            resumenAsientos.textContent = 'Ninguno';
+            resumenTotal.textContent = '0.00';
+            
+            // Limpiar los inputs ocultos
+            if (asientosInput) {
+                asientosInput.innerHTML = '';
+            }
+        } 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
+            if (asientosInput) {
+                asientosInput.innerHTML = '';
+                seleccionados.forEach(asiento => {
+                    const input = document.createElement('input');
+                    input.type = 'hidden';
+                    input.name = 'asientos[]';
+                    input.value = asiento.id;
+                    asientosInput.appendChild(input);
+                });
+            }
+        }
+    }
+    
+    // Función para validar y enviar el formulario
+    function validarYEnviarFormulario(e) {
+        e.preventDefault();
+        
+        if (seleccionados.length === 0) {
+            mostrarMensaje('Por favor, seleccione al menos un asiento.');
+            return false;
+        }
+        
+        const nombreCliente = document.getElementById('nombre_cliente').value.trim();
+        if (nombreCliente === '') {
+            mostrarMensaje('Por favor, ingrese el nombre del cliente.');
+            return false;
+        }
+        
+        // Preparar los datos para enviar
+        const asientosIds = seleccionados.map(asiento => asiento.id);
+        const datos = {
+            asientos: asientosIds,
+            nombre_cliente: nombreCliente
+        };
+        
+        // Enviar los datos mediante fetch
+        fetch('../controlador/venta.php', {
+            method: 'POST',
+            headers: {
+                'Content-Type': 'application/json'
+            },
+            body: JSON.stringify(datos)
+        })
+        .then(response => response.json())
+        .then(result => {
+            if (result.success) {
+                // Redireccionar a la página de comprobante
+                window.location.href = result.redirect || 'comprobante.php';
+            } else {
+                mostrarMensaje(result.mensaje || 'Error al procesar la venta', 'error');
+            }
+        })
+        .catch(error => {
+            console.error('Error:', error);
+            mostrarMensaje('Error de conexión con el servidor', 'error');
+        });
+        
+        return false;
+    }
+    
+    // Función para mostrar mensajes
+    function mostrarMensaje(texto, tipo = 'warning') {
+        const mensajeElement = document.getElementById('mensajeAlerta');
+        if (mensajeElement) {
+            mensajeElement.textContent = texto;
+            mensajeElement.className = `alert alert-${tipo === 'error' ? 'danger' : 'warning'}`;
+            mensajeElement.classList.remove('d-none');
+            
+            // Ocultar después de 5 segundos
+            setTimeout(() => {
+                mensajeElement.classList.add('d-none');
+            }, 5000);
+        } else {
+            // Si no existe el elemento, usar alert
+            alert(texto);
+        }
+    }
+});
\ No newline at end of file