commit 2de036f40601f6d54e433371139d9a47ec4df7bb
Author: alexis.palestina <zs22016131@estudiantes.uv.mx>
Date:   Thu Mar 13 08:58:42 2025 -0600

    Proyecto BoleTC

diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..0aae3d2
Binary files /dev/null and b/.DS_Store differ
diff --git a/css/agregar_evento.css b/css/agregar_evento.css
new file mode 100644
index 0000000..15ea19a
--- /dev/null
+++ b/css/agregar_evento.css
@@ -0,0 +1,65 @@
+/* Estilos generales */
+body {
+    font-family: Arial, sans-serif;
+    margin: 0;
+    padding: 0;
+    background-color: #f4f4f4;
+    text-align: center;
+}
+
+h1 {
+    color: #333;
+    margin-top: 20px;
+}
+
+/* Contenedor del formulario */
+form {
+    background: white;
+    padding: 20px;
+    max-width: 400px;
+    margin: 20px auto;
+    border-radius: 10px;
+    box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.2);
+}
+
+/* Estilos de etiquetas */
+label {
+    display: block;
+    font-weight: bold;
+    margin: 10px 0 5px;
+}
+
+/* Estilos de los inputs y selects */
+input, select {
+    width: 100%;
+    padding: 8px;
+    margin-bottom: 10px;
+    border-radius: 5px;
+    border: 1px solid #ccc;
+    font-size: 16px;
+}
+
+/* Botón de agregar evento */
+button {
+    background-color: #008cba;
+    color: white;
+    padding: 10px 15px;
+    border: none;
+    border-radius: 5px;
+    font-weight: bold;
+    font-size: 16px;
+    cursor: pointer;
+    width: 100%;
+}
+
+button:hover {
+    background-color: #005f7f;
+}
+
+/* Mensaje de éxito o error */
+#mensaje {
+    margin-top: 15px;
+    font-size: 16px;
+    font-weight: bold;
+    color: #333;
+}
diff --git a/css/comprobante.css b/css/comprobante.css
new file mode 100644
index 0000000..afacc96
--- /dev/null
+++ b/css/comprobante.css
@@ -0,0 +1,60 @@
+/* Estilos generales */
+body {
+    font-family: 'Arial', sans-serif;
+    background-color: #f4f4f4;
+    color: #333;
+    margin: 0;
+    padding: 20px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+/* Contenedor principal */
+.comprobante-container {
+    background: white;
+    padding: 20px;
+    border-radius: 10px;
+    box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.2);
+    width: 50%;
+    text-align: center;
+}
+
+/* Título */
+h1 {
+    color: #4d4d4d;
+    font-size: 24px;
+    margin-bottom: 20px;
+}
+
+/* Información del boleto */
+.boleto {
+    background: #f9f9f9;
+    padding: 15px;
+    border-radius: 8px;
+    margin-bottom: 10px;
+}
+
+/* Separador entre boletos */
+hr {
+    border: none;
+    height: 1px;
+    background: #ccc;
+    margin: 20px 0;
+}
+
+/* Botón de volver */
+.boton-volver {
+    display: inline-block;
+    margin-top: 20px;
+    padding: 10px 15px;
+    background-color: #008cba;
+    color: white;
+    text-decoration: none;
+    font-weight: bold;
+    border-radius: 5px;
+}
+
+.boton-volver:hover {
+    background-color: #005f7f;
+}
diff --git a/css/editar_evento.css b/css/editar_evento.css
new file mode 100644
index 0000000..9e7546f
--- /dev/null
+++ b/css/editar_evento.css
@@ -0,0 +1,48 @@
+body {
+    font-family: Arial, sans-serif;
+    margin: 0;
+    padding: 0;
+    background-color: #f4f4f4;
+    text-align: center;
+}
+
+h1 {
+    color: #333;
+}
+
+form {
+    background: white;
+    padding: 20px;
+    max-width: 400px;
+    margin: 20px auto;
+    border-radius: 10px;
+    box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.2);
+}
+
+label {
+    display: block;
+    font-weight: bold;
+    margin: 10px 0 5px;
+}
+
+input, select {
+    width: 100%;
+    padding: 8px;
+    margin-bottom: 10px;
+    border-radius: 5px;
+    border: 1px solid #ccc;
+}
+
+button {
+    background-color: #008cba;
+    color: white;
+    padding: 10px 15px;
+    border: none;
+    border-radius: 5px;
+    font-weight: bold;
+    cursor: pointer;
+}
+
+button:hover {
+    background-color: #005f7f;
+}
diff --git a/css/estilos.css b/css/estilos.css
new file mode 100644
index 0000000..1a4fabe
--- /dev/null
+++ b/css/estilos.css
@@ -0,0 +1,76 @@
+/* Contenedor del carrusel */
+.carousel-container {
+    position: relative;
+    width: 100%;
+    overflow: hidden;
+    padding: 20px;
+    background: #f4f4f4;
+}
+
+/* Contenedor de conciertos con desplazamiento horizontal */
+.contenedor-conciertos {
+    display: flex;
+    overflow-x: auto;
+    scroll-behavior: smooth;
+    gap: 15px;
+    padding: 10px;
+    white-space: nowrap;
+}
+
+/* Ocultar scrollbar */
+.contenedor-conciertos::-webkit-scrollbar {
+    display: none;
+}
+
+/* Estilos para cada tarjeta de concierto */
+.concierto {
+    background: white;
+    padding: 15px;
+    border-radius: 10px;
+    box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.2);
+    text-align: center;
+    width: 250px;
+    flex-shrink: 0; /* Evita que se reduzcan de tamaño */
+}
+
+/* Botones de desplazamiento */
+.scroll-btn {
+    position: absolute;
+    top: 50%;
+    transform: translateY(-50%);
+    background-color: rgba(0, 0, 0, 0.5);
+    color: white;
+    border: none;
+    padding: 10px 15px;
+    cursor: pointer;
+    font-size: 20px;
+    border-radius: 50%;
+}
+
+.scroll-btn:hover {
+    background-color: rgba(0, 0, 0, 0.8);
+}
+
+.scroll-btn.left {
+    left: 10px;
+}
+
+.scroll-btn.right {
+    right: 10px;
+}
+
+.btn-volver {
+    display: inline-block;
+    background-color: #008cba;
+    color: white;
+    padding: 10px 15px;
+    text-decoration: none;
+    border-radius: 5px;
+    font-weight: bold;
+    margin-bottom: 15px;
+    transition: background 0.3s;
+}
+
+.btn-volver:hover {
+    background-color: #005f7f;
+}
diff --git a/css/venta_boletos.css b/css/venta_boletos.css
new file mode 100644
index 0000000..76040cb
--- /dev/null
+++ b/css/venta_boletos.css
@@ -0,0 +1,127 @@
+/* Estilos generales */
+body {
+    font-family: 'Arial', sans-serif;
+    margin: 0;
+    padding: 0;
+    background-color: #f4f4f4;
+    text-align: center;
+}
+
+/* Contenedor principal */
+.container {
+    width: 90%;
+    max-width: 800px;
+    margin: 20px auto;
+    background: white;
+    padding: 20px;
+    border-radius: 10px;
+    box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.2);
+}
+
+/* Título */
+h1 {
+    color: #4d4d4d;
+}
+
+/* Select de conciertos */
+select {
+    padding: 10px;
+    margin: 10px 0;
+    border-radius: 5px;
+    border: 1px solid #ccc;
+    font-size: 16px;
+}
+
+/* Contenedor de zonas */
+.zona-container {
+    margin-top: 20px;
+}
+
+/* Nombre de la zona */
+.zona-titulo {
+    font-size: 20px;
+    font-weight: bold;
+    color: #333;
+    margin-bottom: 10px;
+    text-align: center;
+}
+
+/* Contenedor de asientos */
+#asientosContainer {
+    display: flex;
+    flex-direction: column;
+    gap: 20px;
+    align-items: center;
+}
+
+/* Fila de asientos */
+.fila-asientos {
+    display: flex;
+    gap: 10px;
+    justify-content: center;
+    flex-wrap: wrap;
+}
+
+/* VIP: en una sola fila */
+#asientosVIP {
+    display: flex;
+    gap: 10px;
+    justify-content: center;
+}
+
+/* General: en 2 filas de 5 */
+#asientosGeneral {
+    display: grid;
+    grid-template-columns: repeat(5, 1fr);
+    gap: 10px;
+    justify-content: center;
+}
+
+/* Estilos de los asientos */
+.asiento {
+    width: 50px;
+    height: 50px;
+    line-height: 50px;
+    text-align: center;
+    border-radius: 5px;
+    font-weight: bold;
+    cursor: pointer;
+}
+
+/* Asientos disponibles */
+.asiento.disponible {
+    background-color: #4CAF50;
+    color: white;
+    border: 2px solid #3e8e41;
+}
+
+/* Asientos vendidos */
+.asiento.vendido {
+    background-color: #d9534f;
+    color: white;
+    border: 2px solid #a94442;
+    cursor: not-allowed;
+}
+
+/* Asientos seleccionados */
+.asiento.seleccionado {
+    background-color: #FFD700;
+    color: black;
+    border: 2px solid #DAA520;
+}
+
+/* Botón de compra */
+button {
+    background-color: #008cba;
+    color: white;
+    padding: 12px 20px;
+    border: none;
+    border-radius: 5px;
+    font-size: 16px;
+    cursor: pointer;
+    margin-top: 20px;
+}
+
+button:hover {
+    background-color: #005f7f;
+}
diff --git a/img/.DS_Store b/img/.DS_Store
new file mode 100644
index 0000000..109e1db
Binary files /dev/null and b/img/.DS_Store differ
diff --git a/img/default.jpg b/img/default.jpg
new file mode 100644
index 0000000..6b9f3fd
Binary files /dev/null and b/img/default.jpg differ
diff --git a/js/agregar_evento.js b/js/agregar_evento.js
new file mode 100644
index 0000000..b0057bc
--- /dev/null
+++ b/js/agregar_evento.js
@@ -0,0 +1,22 @@
+document.getElementById("formConcierto").addEventListener("submit", function(e) {
+    e.preventDefault();
+    
+    let formData = new FormData(this);
+
+    console.log("Datos enviados:");
+    for (let pair of formData.entries()) {
+        console.log(pair[0] + ": " + pair[1]); // Ver qué valores se están enviando
+    }
+
+    fetch("../php/insertar_concierto.php", {
+        method: "POST", // ✅ Asegurar que la solicitud es POST
+        body: formData
+    })
+    .then(response => response.text())
+    .then(data => {
+        console.log("Respuesta del servidor:", data);
+        alert(data); // Mensaje de éxito o error
+        this.reset();
+    })
+    .catch(error => console.error("Error:", error));
+});
diff --git a/js/conciertos.js b/js/conciertos.js
new file mode 100644
index 0000000..96cd770
--- /dev/null
+++ b/js/conciertos.js
@@ -0,0 +1,37 @@
+document.addEventListener("DOMContentLoaded", function() {
+    fetch("../php/conciertos.php")
+    .then(response => response.json())
+    .then(data => {
+        let div = document.getElementById("conciertos");
+        div.innerHTML = ""; // Limpiar contenido
+
+        data.forEach(concierto => {
+            let evento = document.createElement("div");
+            evento.classList.add("concierto");
+            evento.innerHTML = `
+                <img src="${concierto.imagen}" alt="${concierto.nombre}">
+                <h2>${concierto.nombre}</h2>
+                <p><strong>Artista:</strong> ${concierto.artista}</p>
+                <p><strong>Ubicación:</strong> ${concierto.direccion}</p>
+                <p><strong>Fecha:</strong> ${concierto.fecha} - ${concierto.hora}</p>
+                <button class="btn-comprar" onclick="comprarBoletos(${concierto.id})">COMPRAR</button>
+            `;
+            div.appendChild(evento);
+        });
+    })
+    .catch(error => console.error("Error cargando conciertos:", error));
+});
+
+function comprarBoletos(conciertoId) {
+    window.location.href = `venta_boletos.html?concierto_id=${conciertoId}`;
+}
+
+// Función para desplazar los conciertos
+function scrollConciertos(direction) {
+    const container = document.getElementById("conciertos");
+    const scrollAmount = 300; // Ajusta el valor para controlar la velocidad de desplazamiento
+    container.scrollBy({
+        left: direction * scrollAmount,
+        behavior: "smooth"
+    });
+}
diff --git a/js/editar_evento.js b/js/editar_evento.js
new file mode 100644
index 0000000..60af9be
--- /dev/null
+++ b/js/editar_evento.js
@@ -0,0 +1,93 @@
+document.addEventListener("DOMContentLoaded", function() {
+    cargarEventos();
+});
+
+// 🔹 Cargar eventos en el desplegable
+function cargarEventos() {
+    fetch("../php/obtener_conciertos.php")
+        .then(response => response.json())
+        .then(data => {
+            let select = document.getElementById("eventoSeleccionado");
+            select.innerHTML = '<option value="">Seleccione un evento</option>';
+
+            data.forEach(concierto => {
+                let option = document.createElement("option");
+                option.value = concierto.id;
+                option.textContent = concierto.nombre;
+                select.appendChild(option);
+            });
+
+            // Evento para cargar detalles cuando se seleccione un evento
+            select.addEventListener("change", function() {
+                cargarDatosEvento(select.value);
+            });
+        })
+        .catch(error => console.error("Error cargando conciertos:", error));
+}
+
+// 🔹 Cargar los detalles del evento seleccionado
+function cargarDatosEvento(eventoId) {
+    if (!eventoId) return;
+
+    fetch(`../php/obtener_detalle_concierto.php?id=${eventoId}`)
+        .then(response => response.json())
+        .then(data => {
+            document.querySelector("input[name='nombre']").value = data.nombre;
+            document.querySelector("input[name='artista']").value = data.artista;
+            document.querySelector("input[name='fecha']").value = data.fecha;
+            document.querySelector("input[name='hora']").value = data.hora;
+            document.querySelector("input[name='direccion']").value = data.direccion;
+            document.querySelector("input[name='precio_vip']").value = data.precio_vip;
+            document.querySelector("input[name='precio_general']").value = data.precio_general;
+        })
+        .catch(error => console.error("Error cargando detalles del evento:", error));
+}
+
+// 🔹 Guardar cambios al hacer submit
+document.getElementById("formEditarEvento").addEventListener("submit", function(e) {
+    e.preventDefault();
+    
+    let formData = new FormData(this);
+
+    fetch("../php/editar_concierto.php", {
+        method: "POST",
+        body: formData
+    })
+    .then(response => response.text())
+    .then(data => {
+        alert(data);
+        cargarEventos(); // Recargar la lista de eventos
+    })
+    .catch(error => console.error("Error:", error));
+});
+
+// 🔹 Eliminar evento
+document.getElementById("btnEliminar").addEventListener("click", function() {
+    let eventoId = document.getElementById("eventoSeleccionado").value;
+    
+    if (!eventoId) {
+        alert("Selecciona un evento para eliminar.");
+        return;
+    }
+
+    if (!confirm("¿Estás seguro de que quieres eliminar este evento?")) {
+        return;
+    }
+
+    fetch("../php/eliminar_concierto.php", {
+        method: "POST",
+        body: JSON.stringify({ id: eventoId }),
+        headers: { "Content-Type": "application/json" }
+    })
+    .then(response => response.text())
+    .then(data => {
+        alert(data);
+        cargarEventos(); // Recargar la lista de eventos
+    })
+    .catch(error => console.error("Error eliminando evento:", error));
+});
+
+// 🔹 Botón de volver al inicio
+document.getElementById("btnVolver").addEventListener("click", function() {
+    window.location.href = "../views/index.html";
+});
diff --git a/js/venta_boletos.js b/js/venta_boletos.js
new file mode 100644
index 0000000..fed4a0c
--- /dev/null
+++ b/js/venta_boletos.js
@@ -0,0 +1,105 @@
+document.addEventListener("DOMContentLoaded", function() {
+    cargarConciertos();
+});
+
+function cargarConciertos() {
+    fetch("../php/conciertos.php")
+        .then(response => response.json())
+        .then(data => {
+            let select = document.getElementById("concierto");
+            select.innerHTML = '<option value="">Selecciona un concierto</option>';
+            
+            data.forEach(concierto => {
+                let option = document.createElement("option");
+                option.value = concierto.id;
+                option.textContent = concierto.nombre;
+                select.appendChild(option);
+            });
+
+            select.addEventListener("change", function() {
+                cargarAsientos(select.value);
+            });
+        })
+        .catch(error => console.error("Error cargando conciertos:", error));
+}
+
+function cargarAsientos(conciertoId) {
+    fetch(`../php/asientos.php?concierto_id=${conciertoId}`)
+        .then(response => response.json())
+        .then(data => {
+            console.log("Asientos recibidos:", data);
+
+            // 💡 Verificamos que 'data' es un array antes de hacer forEach
+            if (!Array.isArray(data)) {
+                console.error("Error: La respuesta del servidor no es un array.", data);
+                return;
+            }
+
+            let containerVIP = document.getElementById("asientosVIP");
+            let containerGeneral = document.getElementById("asientosGeneral");
+
+            containerVIP.innerHTML = "";
+            containerGeneral.innerHTML = "";
+
+            if (data.length === 0) {
+                containerVIP.innerHTML = "<p>No hay asientos VIP disponibles.</p>";
+                containerGeneral.innerHTML = "<p>No hay asientos Generales disponibles.</p>";
+                return;
+            }
+
+            data.forEach(asiento => {
+                let div = document.createElement("div");
+                div.classList.add("asiento", asiento.estado);
+                div.textContent = `Asiento ${asiento.numero}`;
+
+                if (asiento.estado === "disponible") {
+                    div.addEventListener("click", () => seleccionarAsiento(div, asiento.id));
+                }
+
+                if (asiento.zona === "VIP") {
+                    containerVIP.appendChild(div);
+                } else {
+                    containerGeneral.appendChild(div);
+                }
+            });
+        })
+        .catch(error => console.error("Error cargando asientos:", error));
+}
+
+let asientosSeleccionados = [];
+
+function seleccionarAsiento(element, asientoId) {
+    if (asientosSeleccionados.includes(asientoId)) {
+        asientosSeleccionados = asientosSeleccionados.filter(id => id !== asientoId);
+        element.classList.remove("seleccionado");
+    } else {
+        asientosSeleccionados.push(asientoId);
+        element.classList.add("seleccionado");
+    }
+}
+
+document.getElementById("confirmarCompra").addEventListener("click", function() {
+    if (asientosSeleccionados.length === 0) {
+        alert("Selecciona al menos un asiento.");
+        return;
+    }
+
+    const conciertoId = document.getElementById("concierto").value;
+
+    fetch("../php/comprar_asiento.php", {
+        method: "POST",
+        body: JSON.stringify({ concierto_id: conciertoId, asientos: asientosSeleccionados }),
+        headers: { "Content-Type": "application/json" }
+    })
+    .then(response => response.json())
+    .then(data => {
+        if (data.error) {
+            alert("Error: " + data.error);
+        } else {
+            alert("Compra realizada con éxito.");
+            window.location.href = `../php/comprobante.php?transaction_id=${data.transaction_id}`;
+        }
+    })
+    .catch(error => console.error("Error al comprar boletos:", error));
+});
+
diff --git a/php/asientos.php b/php/asientos.php
new file mode 100644
index 0000000..e66555e
--- /dev/null
+++ b/php/asientos.php
@@ -0,0 +1,36 @@
+<?php
+include 'conexion.php';
+
+$concierto_id = $_GET['concierto_id'] ?? null;
+
+if (!$concierto_id) {
+    die(json_encode(["error" => "No se proporcionó un ID de concierto."]));
+}
+
+// Revisar si existen zonas para el concierto
+$sql_zonas = "SELECT id FROM zonas WHERE concierto_id = ?";
+$stmt_zonas = $conn->prepare($sql_zonas);
+$stmt_zonas->bind_param("i", $concierto_id);
+$stmt_zonas->execute();
+$result_zonas = $stmt_zonas->get_result();
+
+if ($result_zonas->num_rows === 0) {
+    die(json_encode(["error" => "No hay zonas registradas para este concierto."]));
+}
+
+$sql = "SELECT asientos.id, asientos.numero, asientos.estado, zonas.nombre AS zona 
+        FROM asientos 
+        JOIN zonas ON asientos.zona_id = zonas.id 
+        WHERE zonas.concierto_id = ?";
+$stmt = $conn->prepare($sql);
+$stmt->bind_param("i", $concierto_id);
+$stmt->execute();
+$result = $stmt->get_result();
+
+$asientos = [];
+while ($row = $result->fetch_assoc()) {
+    $asientos[] = $row;
+}
+
+echo json_encode($asientos);
+?>
diff --git a/php/comprar_asiento.php b/php/comprar_asiento.php
new file mode 100644
index 0000000..a6f4f19
--- /dev/null
+++ b/php/comprar_asiento.php
@@ -0,0 +1,57 @@
+<?php
+error_reporting(E_ALL);
+ini_set('display_errors', 1);
+
+include 'conexion.php';
+
+header("Content-Type: application/json");
+
+$data = json_decode(file_get_contents("php://input"), true);
+$asientos = $data['asientos'] ?? [];
+$concierto_id = $data['concierto_id'] ?? null;
+
+if (empty($asientos) || !$concierto_id) {
+    echo json_encode(["error" => "No se recibieron asientos para la compra."]);
+    exit;
+}
+
+$conn->begin_transaction();
+
+try {
+    // Generar un ID de transacción único
+    $transaction_id = uniqid("trx_");
+
+    foreach ($asientos as $asiento_id) {
+        // **Depuración**
+        error_log("Procesando asiento ID: $asiento_id para Concierto ID: $concierto_id");
+
+        // Marcar asiento como vendido
+        $sql = "UPDATE asientos SET estado = 'vendido' WHERE id = ?";
+        $stmt = $conn->prepare($sql);
+        if (!$stmt) {
+            throw new Exception("Error en la preparación del UPDATE: " . $conn->error);
+        }
+        $stmt->bind_param("i", $asiento_id);
+        $stmt->execute();
+
+        // Insertar en la tabla de boletos
+        $sql_boleto = "INSERT INTO boletos (asiento_id, concierto_id, transaction_id, fecha_venta, precio) 
+                       SELECT ?, ?, ?, NOW(), z.precio FROM asientos a 
+                       JOIN zonas z ON a.zona_id = z.id WHERE a.id = ?";
+        $stmt_boleto = $conn->prepare($sql_boleto);
+        if (!$stmt_boleto) {
+            throw new Exception("Error en la preparación del INSERT: " . $conn->error);
+        }
+        $stmt_boleto->bind_param("iisi", $asiento_id, $concierto_id, $transaction_id, $asiento_id);
+        $stmt_boleto->execute();
+    }
+
+    $conn->commit();
+    echo json_encode(["success" => "Compra realizada con éxito", "transaction_id" => $transaction_id]);
+
+} catch (Exception $e) {
+    $conn->rollback();
+    error_log("Error en la compra: " . $e->getMessage());
+    echo json_encode(["error" => "Error en la compra: " . $e->getMessage()]);
+}
+?>
diff --git a/php/comprobante.php b/php/comprobante.php
new file mode 100644
index 0000000..17705ea
--- /dev/null
+++ b/php/comprobante.php
@@ -0,0 +1,51 @@
+<?php
+include 'conexion.php';
+
+$transaction_id = $_GET['transaction_id'] ?? null;
+
+if (!$transaction_id) {
+    die("Error: No se proporcionó un ID de transacción.");
+}
+
+$sql = "SELECT b.id, c.nombre AS concierto, c.hora, a.numero, z.nombre AS zona, b.fecha_venta, b.precio 
+        FROM boletos b
+        JOIN asientos a ON b.asiento_id = a.id
+        JOIN zonas z ON a.zona_id = z.id
+        JOIN conciertos c ON z.concierto_id = c.id
+        WHERE b.transaction_id = ?";
+$stmt = $conn->prepare($sql);
+$stmt->bind_param("s", $transaction_id);
+$stmt->execute();
+$result = $stmt->get_result();
+$boletos = $result->fetch_all(MYSQLI_ASSOC);
+?>
+
+<!DOCTYPE html>
+<html lang="es">
+<head>
+    <meta charset="UTF-8">
+    <title>Comprobante de Compra</title>
+    <link rel="stylesheet" href="../css/comprobante.css">
+</head>
+<body>
+    <div class="comprobante-container">
+        <h1>Comprobante de Compra</h1>
+        <?php if (empty($boletos)): ?>
+            <p>No hay boletos registrados para esta compra.</p>
+        <?php else: ?>
+            <?php foreach ($boletos as $boleto): ?>
+                <div class="boleto">
+                    <p><strong>Concierto:</strong> <?= $boleto['concierto'] ?></p>
+                    <p><strong>Hora:</strong> <?= $boleto['hora'] ?></p>
+                    <p><strong>Zona:</strong> <?= $boleto['zona'] ?></p>
+                    <p><strong>Asiento:</strong> <?= $boleto['numero'] ?></p>
+                    <p><strong>Precio:</strong> $<?= number_format($boleto['precio'], 2) ?></p>
+                    <p><strong>Fecha de compra:</strong> <?= $boleto['fecha_venta'] ?></p>
+                </div>
+                <hr>
+            <?php endforeach; ?>
+        <?php endif; ?>
+        <a href="../views/venta_boletos.html" class="boton-volver">Volver</a>
+    </div>
+</body>
+</html>
diff --git a/php/conciertos.php b/php/conciertos.php
new file mode 100644
index 0000000..5973f29
--- /dev/null
+++ b/php/conciertos.php
@@ -0,0 +1,12 @@
+<?php
+include 'conexion.php';
+
+$sql = "SELECT * FROM conciertos";
+$result = $conn->query($sql);
+
+$conciertos = [];
+while ($row = $result->fetch_assoc()) {
+    $conciertos[] = $row;
+}
+echo json_encode($conciertos);
+?>
diff --git a/php/conexion.php b/php/conexion.php
new file mode 100644
index 0000000..0cb3f36
--- /dev/null
+++ b/php/conexion.php
@@ -0,0 +1,13 @@
+<?php
+$host = "127.0.0.1"; 
+$user = "root"; 
+$password = "root"; 
+$dbname = "BoleTC"; 
+$port = 8889; // Puerto de MySQL en MAMP
+
+$conn = new mysqli($host, $user, $password, $dbname, $port);
+
+if ($conn->connect_error) {
+    die("Error de conexión: " . $conn->connect_error);
+}
+?>
\ No newline at end of file
diff --git a/php/editar_concierto.php b/php/editar_concierto.php
new file mode 100644
index 0000000..b9db19b
--- /dev/null
+++ b/php/editar_concierto.php
@@ -0,0 +1,47 @@
+<?php
+include 'conexion.php';
+
+if ($_SERVER["REQUEST_METHOD"] == "POST") {
+    $id = $_POST['id'];
+    $nombre = $_POST['nombre'];
+    $artista = $_POST['artista'];
+    $fecha = $_POST['fecha'];
+    $hora = $_POST['hora'];
+    $direccion = $_POST['direccion'];
+    $precio_vip = $_POST['precio_vip'];
+    $precio_general = $_POST['precio_general'];
+
+    // Verificar si se subió una nueva imagen
+    if (!empty($_FILES["imagen"]["name"])) {
+        $imagenNombre = time() . "_" . $_FILES["imagen"]["name"];
+        $rutaImagen = "../img/" . $imagenNombre;
+        move_uploaded_file($_FILES["imagen"]["tmp_name"], $rutaImagen);
+
+        // Actualizar con nueva imagen
+        $sql = "UPDATE conciertos SET nombre=?, artista=?, fecha=?, hora=?, direccion=?, imagen=? WHERE id=?";
+        $stmt = $conn->prepare($sql);
+        $stmt->bind_param("ssssssi", $nombre, $artista, $fecha, $hora, $direccion, $imagenNombre, $id);
+    } else {
+        // Actualizar sin cambiar la imagen
+        $sql = "UPDATE conciertos SET nombre=?, artista=?, fecha=?, hora=?, direccion=? WHERE id=?";
+        $stmt = $conn->prepare($sql);
+        $stmt->bind_param("sssssi", $nombre, $artista, $fecha, $hora, $direccion, $id);
+    }
+
+    if ($stmt->execute()) {
+        // Actualizar precios de zonas
+        $sql_zonas = "UPDATE zonas SET precio = CASE 
+                      WHEN nombre = 'VIP' THEN ? 
+                      WHEN nombre = 'General' THEN ? 
+                      ELSE precio END
+                      WHERE concierto_id = ?";
+        $stmt_zonas = $conn->prepare($sql_zonas);
+        $stmt_zonas->bind_param("ddi", $precio_vip, $precio_general, $id);
+        $stmt_zonas->execute();
+
+        echo "Concierto actualizado correctamente";
+    } else {
+        echo "Error al actualizar concierto: " . $conn->error;
+    }
+}
+?>
diff --git a/php/eliminar_concierto.php b/php/eliminar_concierto.php
new file mode 100644
index 0000000..501f53b
--- /dev/null
+++ b/php/eliminar_concierto.php
@@ -0,0 +1,20 @@
+<?php
+include 'conexion.php';
+
+$data = json_decode(file_get_contents("php://input"), true);
+$id = $data['id'] ?? null;
+
+if (!$id) {
+    die("Error: No se recibió un ID válido.");
+}
+
+$sql = "DELETE FROM conciertos WHERE id = ?";
+$stmt = $conn->prepare($sql);
+$stmt->bind_param("i", $id);
+
+if ($stmt->execute()) {
+    echo "Concierto eliminado correctamente.";
+} else {
+    echo "Error al eliminar concierto: " . $conn->error;
+}
+?>
diff --git a/php/eliminar_conciertos_pasados.php b/php/eliminar_conciertos_pasados.php
new file mode 100644
index 0000000..d8aee80
--- /dev/null
+++ b/php/eliminar_conciertos_pasados.php
@@ -0,0 +1,18 @@
+<?php
+include 'conexion.php';
+
+// Obtener la fecha actual
+$fecha_actual = date("Y-m-d");
+
+// Eliminar conciertos cuya fecha ya pasó
+$sql = "DELETE FROM conciertos WHERE fecha < ?";
+$stmt = $conn->prepare($sql);
+$stmt->bind_param("s", $fecha_actual);
+$sql = "DELETE FROM conciertos WHERE CONCAT(fecha, ' ', hora) < NOW()";
+
+if ($stmt->execute()) {
+    echo "Conciertos pasados eliminados.";
+} else {
+    echo "Error al eliminar conciertos: " . $stmt->error;
+}
+?>
diff --git a/php/insertar_concierto.php b/php/insertar_concierto.php
new file mode 100644
index 0000000..78dbd24
--- /dev/null
+++ b/php/insertar_concierto.php
@@ -0,0 +1,83 @@
+<?php
+error_reporting(E_ALL);
+ini_set('display_errors', 1);
+
+include 'conexion.php';
+
+if ($_SERVER["REQUEST_METHOD"] !== "POST") {
+    die("Error: La solicitud no es POST.");
+}
+
+$nombre = $_POST['nombre'] ?? '';
+$artista = $_POST['artista'] ?? '';
+$fecha = $_POST['fecha'] ?? '';
+$hora = $_POST['hora'] ?? '';
+$direccion = $_POST['direccion'] ?? '';
+$precio_vip = $_POST['precio_vip'] ?? null;
+$precio_general = $_POST['precio_general'] ?? null;
+
+if (empty($nombre) || empty($artista) || empty($fecha) || empty($hora) || empty($direccion) || empty($precio_vip) || empty($precio_general)) {
+    die("Error: Todos los campos son obligatorios.");
+}
+
+// Manejo de imagen
+if (!empty($_FILES["imagen"]["name"])) {
+    $extension = pathinfo($_FILES["imagen"]["name"], PATHINFO_EXTENSION);
+    $imagenNombre = time() . "_" . uniqid() . "." . $extension;
+    $rutaImagen = __DIR__ . "/../img/" . $imagenNombre;
+
+    if (!move_uploaded_file($_FILES["imagen"]["tmp_name"], $rutaImagen)) {
+        die("Error: No se pudo mover la imagen.");
+    }
+} else {
+    $imagenNombre = "default.jpg"; 
+}
+
+$conn->begin_transaction();
+
+try {
+    // Insertar el concierto con hora
+    $sql = "INSERT INTO conciertos (nombre, artista, fecha, hora, direccion, imagen) VALUES (?, ?, ?, ?, ?, ?)";
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ssssss", $nombre, $artista, $fecha, $hora, $direccion, $imagenNombre);
+    $stmt->execute();
+    $concierto_id = $stmt->insert_id;
+
+    // Insertar las zonas (VIP y General)
+    $sql_zonas = "INSERT INTO zonas (concierto_id, nombre, capacidad, precio) VALUES 
+                  (?, 'VIP', 5, ?),
+                  (?, 'General', 10, ?)";
+    $stmt_zonas = $conn->prepare($sql_zonas);
+    $stmt_zonas->bind_param("idid", $concierto_id, $precio_vip, $concierto_id, $precio_general);
+    $stmt_zonas->execute();
+
+    // Obtener los IDs de las zonas insertadas
+    $zona_vip_id = $conn->insert_id;
+    $zona_general_id = $zona_vip_id + 1;
+
+    // Insertar los asientos (VIP y General)
+    $sql_asientos = "INSERT INTO asientos (zona_id, numero, estado) VALUES ";
+    $values = [];
+    $params = [];
+
+    for ($i = 1; $i <= 5; $i++) {
+        $values[] = "(?, ?, 'disponible')";
+        array_push($params, $zona_vip_id, $i);
+    }
+    for ($i = 1; $i <= 10; $i++) {
+        $values[] = "(?, ?, 'disponible')";
+        array_push($params, $zona_general_id, $i);
+    }
+
+    $sql_asientos .= implode(", ", $values);
+    $stmt_asientos = $conn->prepare($sql_asientos);
+    $stmt_asientos->bind_param(str_repeat("ii", count($params) / 2), ...$params);
+    $stmt_asientos->execute();
+
+    $conn->commit();
+    echo "Concierto agregado con éxito.";
+} catch (Exception $e) {
+    $conn->rollback();
+    die("Error en la transacción: " . $e->getMessage());
+}
+?>
diff --git a/php/obtener_conciertos.php b/php/obtener_conciertos.php
new file mode 100644
index 0000000..660e1d1
--- /dev/null
+++ b/php/obtener_conciertos.php
@@ -0,0 +1,13 @@
+<?php
+include 'conexion.php';
+
+$sql = "SELECT id, nombre FROM conciertos";
+$result = $conn->query($sql);
+
+$conciertos = [];
+while ($row = $result->fetch_assoc()) {
+    $conciertos[] = $row;
+}
+header('Content-Type: application/json');
+echo json_encode($conciertos);
+?>
diff --git a/php/obtener_detalle_concierto.php b/php/obtener_detalle_concierto.php
new file mode 100644
index 0000000..b6ec238
--- /dev/null
+++ b/php/obtener_detalle_concierto.php
@@ -0,0 +1,38 @@
+<?php
+include 'conexion.php';
+
+$id = $_GET['id'] ?? null;
+if (!$id) {
+    die(json_encode(["error" => "No se proporcionó un ID de evento."]));
+}
+
+// Obtener detalles básicos del concierto
+$sql = "SELECT nombre, artista, fecha, hora, direccion FROM conciertos WHERE id = ?";
+$stmt = $conn->prepare($sql);
+$stmt->bind_param("i", $id);
+$stmt->execute();
+$result = $stmt->get_result();
+$concierto = $result->fetch_assoc();
+
+if (!$concierto) {
+    die(json_encode(["error" => "Concierto no encontrado."]));
+}
+
+// Obtener precios de zonas
+$sql_zonas = "SELECT nombre, precio FROM zonas WHERE concierto_id = ?";
+$stmt = $conn->prepare($sql_zonas);
+$stmt->bind_param("i", $id);
+$stmt->execute();
+$result = $stmt->get_result();
+$zonas = $result->fetch_all(MYSQLI_ASSOC);
+
+foreach ($zonas as $zona) {
+    if ($zona['nombre'] === 'VIP') {
+        $concierto['precio_vip'] = $zona['precio'];
+    } else if ($zona['nombre'] === 'General') {
+        $concierto['precio_general'] = $zona['precio'];
+    }
+}
+
+echo json_encode($concierto);
+?>
diff --git a/views/agregar_evento.html b/views/agregar_evento.html
new file mode 100644
index 0000000..9e7bb34
--- /dev/null
+++ b/views/agregar_evento.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html lang="es">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Agregar Evento - BoleTC</title>
+    <link rel="stylesheet" href="../css/agregar_evento.css">
+</head>
+<body>
+
+    <a href="index.html" class="btn-volver">← Volver</a>
+
+    <h1>Agregar Nuevo Evento</h1>
+
+    <form id="formConcierto" action="../php/insertar_concierto.php" method="POST" enctype="multipart/form-data">
+        <label>Nombre del Concierto:</label>
+        <input type="text" name="nombre" required>
+
+        <label>Artista:</label>
+        <input type="text" name="artista" required>        
+
+        <label>Fecha del Concierto:</label>
+        <input type="date" name="fecha" required>
+
+        <label>Hora del Concierto:</label>
+        <input type="time" name="hora" required>
+
+        <label>Dirección:</label>
+        <input type="text" name="direccion" required>
+
+        <label>Imagen del Concierto:</label>
+        <input type="file" name="imagen" accept="image/*" required>
+
+        <h3>Zonas</h3>
+
+        <div class="zona-container">
+            <label>Zona: <strong>VIP</strong></label>
+            <input type="hidden" name="zona_vip" value="VIP">
+            <label>Capacidad:</label>
+            <input type="number" value="5" readonly> <!-- No editable -->
+            <label>Precio:</label>
+            <input type="number" name="precio_vip" min="1" required>
+        </div>
+
+        <div class="zona-container">
+            <label>Zona: <strong>General</strong></label>
+            <input type="hidden" name="zona_general" value="General">
+            <label>Capacidad:</label>
+            <input type="number" value="10" readonly> <!-- No editable -->
+            <label>Precio:</label>
+            <input type="number" name="precio_general" min="1" required>
+        </div>
+
+        <button type="submit">Agregar Concierto</button>
+    </form>
+
+    <div id="mensaje"></div>
+
+    <script src="../js/agregar_evento.js"></script>
+
+</body>
+</html>
diff --git a/views/editar_evento.html b/views/editar_evento.html
new file mode 100644
index 0000000..649e267
--- /dev/null
+++ b/views/editar_evento.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html lang="es">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Editar Evento - BoleTC</title>
+    <link rel="stylesheet" href="../css/editar_evento.css">
+</head>
+<body>
+
+    <a href="index.html" class="btn-volver">← Volver</a>
+
+    <h1>Editar Evento</h1>
+
+    <form id="formEditarEvento" enctype="multipart/form-data">
+        <label>Seleccionar Evento:</label>
+        <select id="eventoSeleccionado" name="id" required>
+            <option value="">Seleccione un evento</option>
+        </select>
+
+        <label>Nuevo Nombre:</label>
+        <input type="text" name="nombre">
+
+        <label>Nuevo Artista:</label>
+        <input type="text" name="artista">        
+
+        <label>Nueva Fecha:</label>
+        <input type="date" name="fecha">
+
+        <label>Nueva Hora:</label>
+        <input type="time" name="hora">
+
+        <label>Nueva Dirección:</label>
+        <input type="text" name="direccion">
+
+        <label>Precio VIP:</label>
+        <input type="number" name="precio_vip" min="0" step="0.01" required>
+
+        <label>Precio General:</label>
+        <input type="number" name="precio_general" min="0" step="0.01" required>
+
+        <label>Nueva Imagen (opcional):</label>
+        <input type="file" name="imagen" accept="image/*">
+
+        <button type="submit">Actualizar Concierto</button>
+        <button type="button" id="btnEliminar">Eliminar Concierto</button>
+    </form>
+
+    <div id="mensaje"></div>
+
+    <script src="../js/editar_evento.js"></script>
+
+</body>
+</html>
diff --git a/views/index.html b/views/index.html
new file mode 100644
index 0000000..8cb1127
--- /dev/null
+++ b/views/index.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="es">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>BoleTC - Inicio</title>
+    <link rel="stylesheet" href="../css/estilos.css">
+    <script src="../js/conciertos.js" defer></script>
+</head>
+<body>
+
+    <!-- Banner superior -->
+    <header>
+        <h1>BoleTC</h1>
+        <a href="agregar_evento.html" class="btn">Agregar Evento</a>
+        <a href="editar_evento.html" class="btn">Editar Evento</a>
+    </header>
+
+    <!-- Contenedor principal con botones de desplazamiento -->
+    <div class="carousel-container">
+        <button class="scroll-btn left" onclick="scrollConciertos(-1)">&#10094;</button>
+        <div class="contenedor-conciertos" id="conciertos"></div>
+        <button class="scroll-btn right" onclick="scrollConciertos(1)">&#10095;</button>
+    </div>
+
+</body>
+</html>
diff --git a/views/venta_boletos.html b/views/venta_boletos.html
new file mode 100644
index 0000000..91df5b1
--- /dev/null
+++ b/views/venta_boletos.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html lang="es">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Venta de Boletos - BoleTC</title>
+    <link rel="stylesheet" href="../css/venta_boletos.css">
+    <script src="../js/venta_boletos.js" defer></script>
+</head>
+<body>
+
+    <a href="index.html" class="btn-volver">← Volver</a>
+
+    <div class="container">
+        <h1>Venta de Boletos</h1>
+
+        <label for="concierto">Seleccionar Concierto:</label>
+        <select id="concierto"></select>
+
+        <div id="asientosContainer">
+            <div class="zona-container">
+                <div class="zona-titulo">VIP</div>
+                <div id="asientosVIP" class="fila-asientos"></div>
+            </div>
+
+            <div class="zona-container">
+                <div class="zona-titulo">General</div>
+                <div id="asientosGeneral" class="fila-asientos"></div>
+            </div>
+        </div>
+
+        <button id="confirmarCompra">Confirmar Compra</button>
+    </div>
+
+</body>
+</html>