commit 437aa1ef068c48dbada9a11d80b99f394d0b8809
Author: Fernando Escobar Robles <zs22016116@estudiantes.uv.mx>
Date:   Sun Mar 9 23:02:14 2025 -0600

    version 09/03/25

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..699142a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+# ---> NetBeans
+**/nbproject/private/
+**/nbproject/Makefile-*.mk
+**/nbproject/Package-*.bash
+build/
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..4732d8c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,28 @@
+
+# Proyecto TicketFei
+
+Descripcion del Proyecto a realizar:
+
+Para el desarrollo de la aplicación de venta de boletos, se utilizarán HTML, CSS, JavaScript y PHP, ya que permiten construir una solución web eficiente, accesible y fácil de gestionar.Esta combinación de tecnologías garantiza una aplicación funcional, dinámica y escalable, cumpliendo con los requisitos del proyecto. 
+
+Funcionalidades:
+HU01: Selección y Venta de Boletos 
+
+HU02: Generación de Reporte de Ventas 
+
+HU03: Gestión de Eventos y Conciertos 
+
+HU04: Cancelación de Venta de Boletos 
+
+HU05: Edición de Boletos Vendidos o Reservados
+
+HU06: Búsqueda y Filtrado de Boletos
+## Autores
+
+- [@FernandoEscobar](https://git.gumoio.com/fernando.escobar)
+- [@AxelVasquez](https://git.gumoio.com/axel.vasquez)
+- [@JorgeOrtega](https://git.gumoio.com/jorge.ortega)
+
+
+
+
diff --git a/bd/bd.sql b/bd/bd.sql
new file mode 100644
index 0000000..c28cd61
--- /dev/null
+++ b/bd/bd.sql
@@ -0,0 +1,5 @@
+create database TicketFei;
+CREATE USER 'desarrolloTicketFei'@'localhost' IDENTIFIED BY 'password';
+GRANT CREATE,ALTER,DROP,INSERT,UPDATE,DELETE,SELECT,CREATE VIEW,REFERENCES on TicketFei.* to 'desarrolloTicketFei'@'localhost';
+GRANT LOCK TABLES, PROCESS ON *.* TO 'desarrolloTicketFei'@'localhost';
+FLUSH PRIVILEGES;
diff --git a/bd/tablas.sql b/bd/tablas.sql
new file mode 100644
index 0000000..6ac4921
--- /dev/null
+++ b/bd/tablas.sql
@@ -0,0 +1,85 @@
+USE TicketFei;
+
+CREATE TABLE usuarios (
+    id INT AUTO_INCREMENT PRIMARY KEY,
+	nombre VARCHAR(255) NOT NULL,
+    apellidoPaterno VARCHAR(255) NOT NULL,
+	apellidoMaterno VARCHAR(255) NOT NULL,
+    usuario VARCHAR(255) NOT NULL,
+    contraseña VARCHAR(255) NOT NULL
+);
+INSERT INTO usuarios (nombre, apellidoPaterno, apellidoMaterno, usuario, contraseña) VALUES 
+('Aaron', 'Bonilla', 'Gonzalez', 's22', '123'),
+('Carlos', 'Palestina', 'Alducin', 's23', '123'),
+('Miguel', 'Diaz', 'Villa', 's24', '123');
+
+SELECT * FROM usuarios;
+DROP TABLE usuarios;
+
+-- concierto
+CREATE TABLE conciertos (
+    id_concierto INT AUTO_INCREMENT PRIMARY KEY,
+    nombre_concierto VARCHAR(255) NOT NULL,
+    artista VARCHAR(255) NOT NULL,
+    fecha DATE NOT NULL,
+    calle VARCHAR(255) NOT NULL,
+    colonia VARCHAR(255) NOT NULL,
+    numero_direccion VARCHAR(255) NOT NULL,
+    codigo_postal VARCHAR(10) NOT NULL,
+    estado VARCHAR(255) NOT NULL,
+    capacidad_total INT NOT NULL
+);
+INSERT INTO conciertos (nombre_concierto, artista, fecha, calle, colonia, numero_direccion, codigo_postal, estado, capacidad_total)  
+SELECT * FROM conciertos;
+DROP TABLE conciertos;
+-- Zona
+CREATE TABLE zonas (
+    id_zona INT AUTO_INCREMENT PRIMARY KEY,
+    id_concierto INT NOT NULL,
+    nombre_zona ENUM('General', 'Plata', 'Oro', 'VIP') NOT NULL,
+    capacidad INT NOT NULL,
+    precio DECIMAL(10,2) NOT NULL,
+    FOREIGN KEY (id_concierto) REFERENCES conciertos(id_concierto) ON DELETE CASCADE
+);
+
+DROP TABLE zonas;
+-- Obtener todos los conciertos con sus zonas y precios
+SELECT c.id_concierto, c.nombre_concierto, c.artista, c.fecha, 
+       z.nombre_zona, z.capacidad, z.precio
+FROM conciertos c
+JOIN zonas z ON c.id_concierto = z.id_concierto;
+
+-- Consultar un concierto específico con sus zonas
+SELECT c.nombre_concierto, c.artista, c.fecha, 
+       z.nombre_zona, z.capacidad, z.precio
+FROM conciertos c
+JOIN zonas z ON c.id_concierto = z.id_concierto
+WHERE c.id_concierto = 1;
+
+-- Tabla Asientos
+CREATE TABLE asientos (
+    id_asiento INT AUTO_INCREMENT PRIMARY KEY,
+    id_zona INT NOT NULL,
+    numero_asiento INT NOT NULL,
+    estado ENUM('disponible', 'ocupado') NOT NULL DEFAULT 'disponible',
+    FOREIGN KEY (id_zona) REFERENCES zonas(id_zona) ON DELETE CASCADE,
+    UNIQUE (id_zona, numero_asiento) -- Para evitar asientos duplicados en la misma zona
+);
+DROP TABLE asientos;
+
+-- Tabla Boletos
+CREATE TABLE boletos (
+    id_boleto INT AUTO_INCREMENT PRIMARY KEY,
+    id_concierto INT NOT NULL,
+    id_zona INT NOT NULL,
+    id_asiento INT NOT NULL,
+    nombre_comprador VARCHAR(255) NOT NULL,
+    precio DECIMAL(10,2) NOT NULL,
+    fecha_concierto DATE NOT NULL,
+    artista VARCHAR(255) NOT NULL,
+    FOREIGN KEY (id_concierto) REFERENCES conciertos(id_concierto) ON DELETE CASCADE,
+    FOREIGN KEY (id_zona) REFERENCES zonas(id_zona) ON DELETE CASCADE,
+    FOREIGN KEY (id_asiento) REFERENCES asientos(id_asiento) ON DELETE CASCADE,
+    UNIQUE (id_asiento) -- Evita que un asiento se venda dos veces
+);
+DROP TABLE boletos;
\ No newline at end of file
diff --git a/bd/ticket_fei.sql b/bd/ticket_fei.sql
new file mode 100644
index 0000000..7faa400
--- /dev/null
+++ b/bd/ticket_fei.sql
@@ -0,0 +1,55 @@
+-- MySQL dump 10.13  Distrib 8.0.34, for Win64 (x86_64)
+--
+-- Host: 127.0.0.1    Database: ticketfei
+-- ------------------------------------------------------
+-- Server version	8.0.34
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!50503 SET NAMES utf8 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Table structure for table `usuarios`
+--
+
+DROP TABLE IF EXISTS `usuarios`;
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `usuarios` (
+  `id` int NOT NULL AUTO_INCREMENT,
+  `nombre` varchar(255) NOT NULL,
+  `apellidoPaterno` varchar(255) NOT NULL,
+  `apellidoMaterno` varchar(255) NOT NULL,
+  `usuario` varchar(255) NOT NULL,
+  `contraseña` varchar(255) NOT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `usuarios`
+--
+
+LOCK TABLES `usuarios` WRITE;
+/*!40000 ALTER TABLE `usuarios` DISABLE KEYS */;
+INSERT INTO `usuarios` VALUES (1,'Aaron','Bonilla','Gonzalez','s22','123'),(2,'Carlos','Palestina','Alducin','s23','123'),(3,'Miguel','Diaz','Villa','s24','123');
+/*!40000 ALTER TABLE `usuarios` ENABLE KEYS */;
+UNLOCK TABLES;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+-- Dump completed on 2025-02-19 10:38:05
diff --git a/controladores/actualizar_concierto.php b/controladores/actualizar_concierto.php
new file mode 100644
index 0000000..411b69b
--- /dev/null
+++ b/controladores/actualizar_concierto.php
@@ -0,0 +1,68 @@
+<?php
+include 'conexion.php';
+
+if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['id'])) {
+    $id = intval($_GET['id']);
+    $consulta = "SELECT * FROM conciertos WHERE id_concierto = ?";
+    $stmt = $conexionBD->prepare($consulta);
+    $stmt->bind_param("i", $id);
+    $stmt->execute();
+    $resultado = $stmt->get_result();
+    $concierto = $resultado->fetch_assoc();
+    
+    if ($concierto) {
+        $consulta_zonas = "SELECT * FROM zonas WHERE id_concierto = ?";
+        $stmt_zonas = $conexionBD->prepare($consulta_zonas);
+        $stmt_zonas->bind_param("i", $id);
+        $stmt_zonas->execute();
+        $resultado_zonas = $stmt_zonas->get_result();
+        while ($zona = $resultado_zonas->fetch_assoc()) {
+            $concierto['zonas'][] = $zona;
+        }
+        echo json_encode($concierto);
+    } else {
+        echo json_encode(["error" => "Concierto no encontrado"]);
+    }
+    exit;
+}
+
+if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+    $datos = json_decode(file_get_contents("php://input"), true);
+    if (!$datos || !isset($datos['id'])) {
+        echo json_encode(["actualizacionCorrecta" => false, "error" => "Datos incompletos"]);
+        exit;
+    }
+
+    // Actualizar la información del concierto
+    $consulta = "UPDATE conciertos SET nombre_concierto=?, artista=?, fecha=?, calle=?, colonia=?, numero_direccion=?, codigo_postal=?, estado=?, capacidad_total=? WHERE id_concierto=?";
+    $stmt = $conexionBD->prepare($consulta);
+    $stmt->bind_param("ssssssissi",
+        $datos['nombre_concierto'],
+        $datos['artista'],
+        $datos['fecha'],
+        $datos['calle'],
+        $datos['colonia'],
+        $datos['numero_direccion'],
+        $datos['codigo_postal'],
+        $datos['estado'],
+        $datos['capacidad_total'],
+        $datos['id']
+    );
+    $stmt->execute();
+
+    // Actualizar la información de las zonas
+    foreach ($datos['zonas'] as $zona) {
+        $consulta_zonas = "UPDATE zonas SET capacidad=?, precio=? WHERE id_concierto=? AND nombre_zona=?";
+        $stmt_zona = $conexionBD->prepare($consulta_zonas);
+        $stmt_zona->bind_param("idis",
+            $zona['capacidad'],
+            $zona['precio'],
+            $datos['id'],
+            $zona['nombre_zona']
+        );
+        $stmt_zona->execute();
+    }
+    
+    echo json_encode(["actualizacionCorrecta" => true]);
+    exit;
+}
\ No newline at end of file
diff --git a/controladores/cerrar_sesion.php b/controladores/cerrar_sesion.php
new file mode 100644
index 0000000..6675094
--- /dev/null
+++ b/controladores/cerrar_sesion.php
@@ -0,0 +1,21 @@
+<?php
+
+    include 'conexion.php';
+
+    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+        session_start();
+
+        session_unset(); 
+        session_destroy(); 
+
+        echo json_encode(['success' => true]);
+    } else {
+        http_response_code(405); 
+        echo json_encode(['success' => false, 'message' => 'Método no permitido']);
+    }
+
+    if (isset($conexionBD)) {
+        $conexionBD->close();
+    }
+
+?>
diff --git a/controladores/comprar_asiento.php b/controladores/comprar_asiento.php
new file mode 100644
index 0000000..c1327c3
--- /dev/null
+++ b/controladores/comprar_asiento.php
@@ -0,0 +1,41 @@
+<?php
+include 'conexion.php';
+
+header('Content-Type: application/json');
+
+$rawData = file_get_contents("php://input");
+$data = json_decode($rawData, true);
+
+if (!isset($data['asientos']) || !is_array($data['asientos'])) {
+    echo json_encode(["error" => "Datos inválidos"]);
+    exit;
+}
+
+$conexionBD->begin_transaction();
+
+try {
+    foreach ($data['asientos'] as $idAsiento) {
+        // Verificar si el asiento sigue disponible
+        $stmtVerificar = $conexionBD->prepare("SELECT estado FROM asientos WHERE id_asiento = ?");
+        $stmtVerificar->bind_param("i", $idAsiento);
+        $stmtVerificar->execute();
+        $resultado = $stmtVerificar->get_result()->fetch_assoc();
+
+        if (!$resultado || $resultado['estado'] !== 'disponible') {
+            throw new Exception("El asiento ID $idAsiento ya está ocupado o no existe.");
+        }
+
+        // Marcar el asiento como ocupado
+        $stmtActualizar = $conexionBD->prepare("UPDATE asientos SET estado = 'ocupado' WHERE id_asiento = ?");
+        $stmtActualizar->bind_param("i", $idAsiento);
+        $stmtActualizar->execute();
+    }
+
+    $conexionBD->commit();
+    echo json_encode(["success" => true]);
+} catch (Exception $e) {
+    $conexionBD->rollback();
+    echo json_encode(["error" => $e->getMessage()]);
+}
+exit;
+?>
diff --git a/controladores/concierto_zonas.php b/controladores/concierto_zonas.php
new file mode 100644
index 0000000..f7458c1
--- /dev/null
+++ b/controladores/concierto_zonas.php
@@ -0,0 +1,111 @@
+<?php
+include 'conexion.php';
+
+header('Content-Type: application/json');
+
+if ($_SERVER['REQUEST_METHOD'] === 'GET') {
+    // Verificar si es solicitud de concierto
+    if (isset($_GET['id_concierto'])) {
+        $idConcierto = intval($_GET['id_concierto']);
+
+        // Obtener la información del concierto
+        $consultaConcierto = "SELECT * FROM conciertos WHERE id_concierto = ?";
+        $stmt = $conexionBD->prepare($consultaConcierto);
+        $stmt->bind_param("i", $idConcierto);
+        $stmt->execute();
+        $resultadoConcierto = $stmt->get_result();
+        $concierto = $resultadoConcierto->fetch_assoc();
+
+        if (!$concierto) {
+            echo json_encode(["error" => "Concierto no encontrado"]);
+            exit;
+        }
+
+        // Obtener zonas del concierto
+        $consultaZonas = "SELECT * FROM zonas WHERE id_concierto = ?";
+        $stmtZonas = $conexionBD->prepare($consultaZonas);
+        $stmtZonas->bind_param("i", $idConcierto);
+        $stmtZonas->execute();
+        $resultadoZonas = $stmtZonas->get_result();
+
+        $zonas = [];
+        while ($zona = $resultadoZonas->fetch_assoc()) {
+            // Contar asientos disponibles y ocupados
+            $consultaAsientos = "SELECT estado FROM asientos WHERE id_zona = ?";
+            $stmtAsientos = $conexionBD->prepare($consultaAsientos);
+            $stmtAsientos->bind_param("i", $zona['id_zona']);
+            $stmtAsientos->execute();
+            $resultadoAsientos = $stmtAsientos->get_result();
+
+            $asientos_disponibles = 0;
+            $asientos_ocupados = 0;
+
+            while ($asiento = $resultadoAsientos->fetch_assoc()) {
+                if ($asiento['estado'] === 'disponible') {
+                    $asientos_disponibles++;
+                } else {
+                    $asientos_ocupados++;
+                }
+            }
+
+            // Agregar datos de asientos a la zona
+            $zona['asientos_disponibles'] = $asientos_disponibles;
+            $zona['asientos_ocupados'] = $asientos_ocupados;
+            
+            $zonas[] = $zona;
+        }
+
+        // Agregar las zonas al concierto
+        $concierto['zonas'] = $zonas;
+
+        echo json_encode($concierto);
+        exit;
+    }
+
+    // Verificar si es solicitud de zona
+    if (isset($_GET['id_zona'])) {
+        $idZona = intval($_GET['id_zona']);
+
+        // Obtener la información de la zona específica
+        $consultaZona = "SELECT * FROM zonas WHERE id_zona = ?";
+        $stmtZona = $conexionBD->prepare($consultaZona);
+        $stmtZona->bind_param("i", $idZona);
+        $stmtZona->execute();
+        $resultadoZona = $stmtZona->get_result();
+        $zona = $resultadoZona->fetch_assoc();
+
+        if (!$zona) {
+            echo json_encode(["error" => "Zona no encontrada"]);
+            exit;
+        }
+
+        // Obtener asientos de la zona
+        $consultaAsientos = "SELECT estado FROM asientos WHERE id_zona = ?";
+        $stmtAsientos = $conexionBD->prepare($consultaAsientos);
+        $stmtAsientos->bind_param("i", $idZona);
+        $stmtAsientos->execute();
+        $resultadoAsientos = $stmtAsientos->get_result();
+
+        $asientos_disponibles = 0;
+        $asientos_ocupados = 0;
+
+        while ($asiento = $resultadoAsientos->fetch_assoc()) {
+            if ($asiento['estado'] === 'disponible') {
+                $asientos_disponibles++;
+            } else {
+                $asientos_ocupados++;
+            }
+        }
+
+        // Agregar información de asientos a la zona
+        $zona['asientos_disponibles'] = $asientos_disponibles;
+        $zona['asientos_ocupados'] = $asientos_ocupados;
+
+        echo json_encode($zona);
+        exit;
+    }
+
+    echo json_encode(["error" => "Solicitud incorrecta"]);
+    exit;
+}
+?>
diff --git a/controladores/conciertos.php b/controladores/conciertos.php
new file mode 100644
index 0000000..2d7ad36
--- /dev/null
+++ b/controladores/conciertos.php
@@ -0,0 +1,51 @@
+<?php
+include 'conexion.php';
+
+header('Content-Type: application/json'); // Asegurar que el contenido es JSON
+error_reporting(E_ALL);
+ini_set('display_errors', 1);
+
+$consulta = "SELECT c.id_concierto, c.nombre_concierto, c.artista, c.fecha, c.calle, c.colonia, c.numero_direccion, c.codigo_postal, c.estado, c.capacidad_total, 
+                    z.nombre_zona, z.capacidad AS capacidad_zona, z.precio 
+             FROM conciertos c 
+             LEFT JOIN zonas z ON c.id_concierto = z.id_concierto
+             ORDER BY c.id_concierto, 
+                      FIELD(z.nombre_zona, 'General', 'Plata', 'Oro', 'VIP')";
+
+$resultado = $conexionBD->query($consulta);
+
+if (!$resultado) {
+    echo json_encode(["error" => "Error en la consulta SQL: " . $conexionBD->error]);
+    exit;
+}
+
+$conciertos = [];
+
+while ($fila = $resultado->fetch_assoc()) {
+    $id_concierto = $fila['id_concierto'];
+    if (!isset($conciertos[$id_concierto])) {
+        $conciertos[$id_concierto] = [
+            'id' => $id_concierto,
+            'nombre_concierto' => $fila['nombre_concierto'],
+            'artista' => $fila['artista'],
+            'fecha' => $fila['fecha'],
+            'direccion' => $fila['calle'] . ', ' . $fila['colonia'] . ', ' . $fila['numero_direccion'] . ', CP: ' . $fila['codigo_postal'] . ', ' . $fila['estado'],
+            'capacidad_total' => $fila['capacidad_total'],
+            'zonas' => []
+        ];
+    }
+
+    if (!empty($fila['nombre_zona'])) {
+        $conciertos[$id_concierto]['zonas'][] = [
+            'nombre_zona' => $fila['nombre_zona'],
+            'capacidad' => $fila['capacidad_zona'],
+            'precio' => $fila['precio']
+        ];
+    }
+}
+
+// Convertir el array a JSON y enviarlo
+echo json_encode(array_values($conciertos), JSON_PRETTY_PRINT);
+
+$conexionBD->close();
+?>
diff --git a/controladores/conexion.php b/controladores/conexion.php
new file mode 100644
index 0000000..710c5ae
--- /dev/null
+++ b/controladores/conexion.php
@@ -0,0 +1,18 @@
+<?php
+  error_reporting(E_ALL);
+  ini_set('display_errors', 1);
+
+  // Valores para la conexión
+  $direccion = "localhost:3306";
+  $nombreBD = "TicketFei";
+  $usuario = "desarrolloTicketFei"; 
+  $password = "password";
+
+  // Obtener conexión
+  $conexionBD = new mysqli($direccion, $usuario, $password, $nombreBD);
+
+  // Verificar si hay un error en la conexión
+  if ($conexionBD->connect_error) {
+    die(json_encode(["error" => "Error en la conexión: " . $conexionBD->connect_error]));
+  }
+?>
diff --git a/controladores/eliminar_concierto.php b/controladores/eliminar_concierto.php
new file mode 100644
index 0000000..b1553d3
--- /dev/null
+++ b/controladores/eliminar_concierto.php
@@ -0,0 +1,35 @@
+<?php
+include 'conexion.php';
+
+if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+    $datos = json_decode(file_get_contents("php://input"), true);
+    
+    if (!isset($datos['id'])) {
+        echo json_encode(["eliminacionCorrecta" => false, "error" => "ID de concierto no proporcionado"]);
+        exit;
+    }
+
+    $id = intval($datos['id']);
+    
+    // Eliminar las zonas relacionadas con el concierto
+    $consulta_zonas = "DELETE FROM zonas WHERE id_concierto = ?";
+    $stmt_zonas = $conexionBD->prepare($consulta_zonas);
+    $stmt_zonas->bind_param("i", $id);
+    $stmt_zonas->execute();
+    
+    // Eliminar el concierto
+    $consulta = "DELETE FROM conciertos WHERE id_concierto = ?";
+    $stmt = $conexionBD->prepare($consulta);
+    $stmt->bind_param("i", $id);
+    $stmt->execute();
+    
+    if ($stmt->affected_rows > 0) {
+        echo json_encode(["eliminacionCorrecta" => true]);
+    } else {
+        echo json_encode(["eliminacionCorrecta" => false, "error" => "No se pudo eliminar el concierto"]);
+    }
+    exit;
+} else {
+    echo json_encode(["error" => "Método no permitido"]);
+    exit;
+}
diff --git a/controladores/insertar_concierto.php b/controladores/insertar_concierto.php
new file mode 100644
index 0000000..b298ea4
--- /dev/null
+++ b/controladores/insertar_concierto.php
@@ -0,0 +1,79 @@
+<?php
+include 'conexion.php';
+
+header('Content-Type: application/json');
+error_reporting(E_ALL);
+ini_set('display_errors', 1);
+
+// Leer el JSON enviado
+$datos = json_decode(file_get_contents("php://input"), true);
+
+if ($datos === null) {
+    echo json_encode(['insercionCorrecta' => false, 'error' => 'Error al decodificar JSON']);
+    exit;
+}
+
+// Verificar que los datos requeridos estén presentes
+if (!isset($datos['nombre_concierto'], $datos['zonas'])) {
+    echo json_encode(['insercionCorrecta' => false, 'error' => 'Faltan datos requeridos']);
+    exit;
+}
+
+// Extraer valores
+$nombre_concierto = $datos['nombre_concierto'];
+$artista = $datos['artista'];
+$fecha = $datos['fecha'];
+$calle = $datos['calle'];
+$colonia = $datos['colonia'];
+$numero_direccion = $datos['numero_direccion'];
+$codigo_postal = $datos['codigo_postal'];
+$estado = $datos['estado'];
+$capacidad_total = $datos['capacidad_total'];
+$zonas = $datos['zonas'];
+
+$conexionBD->begin_transaction();
+
+try {
+    // Insertar el concierto
+    $consulta = "INSERT INTO conciertos (nombre_concierto, artista, fecha, calle, colonia, numero_direccion, codigo_postal, estado, capacidad_total) 
+                 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
+    $stmt = $conexionBD->prepare($consulta);
+    $stmt->bind_param("ssssssssi", $nombre_concierto, $artista, $fecha, $calle, $colonia, $numero_direccion, $codigo_postal, $estado, $capacidad_total);
+    $stmt->execute();
+
+    $id_concierto = $conexionBD->insert_id;
+    $stmt->close();
+
+    // Insertar zonas y sus asientos
+    $consulta_zonas = "INSERT INTO zonas (id_concierto, nombre_zona, capacidad, precio) VALUES (?, ?, ?, ?)";
+    $stmt_zonas = $conexionBD->prepare($consulta_zonas);
+    
+    $consulta_asientos = "INSERT INTO asientos (id_zona, numero_asiento, estado) VALUES (?, ?, 'disponible')";
+    $stmt_asientos = $conexionBD->prepare($consulta_asientos);
+    
+    foreach ($zonas as $zona) {
+        $stmt_zonas->bind_param("isid", $id_concierto, $zona['nombre_zona'], $zona['capacidad'], $zona['precio']);
+        $stmt_zonas->execute();
+        
+        $id_zona = $conexionBD->insert_id;
+        
+        // Insertar asientos
+        for ($i = 1; $i <= $zona['capacidad']; $i++) {
+            $stmt_asientos->bind_param("ii", $id_zona, $i);
+            $stmt_asientos->execute();
+        }
+    }
+    
+    $stmt_zonas->close();
+    $stmt_asientos->close();
+    $conexionBD->commit();
+    
+    echo json_encode(['insercionCorrecta' => true, 'id_concierto' => $id_concierto]);
+
+} catch (Exception $e) {
+    $conexionBD->rollback();
+    echo json_encode(['insercionCorrecta' => false, 'error' => $e->getMessage()]);
+}
+
+$conexionBD->close();
+?>
diff --git a/controladores/login.php b/controladores/login.php
new file mode 100644
index 0000000..0de8b92
--- /dev/null
+++ b/controladores/login.php
@@ -0,0 +1,32 @@
+<?php
+    session_start(); 
+    include 'conexion.php';
+
+    $usuario = $_POST['usuario'];
+    $password = $_POST['password'];
+    
+    // Prepara la consulta 
+    $consulta = "SELECT id, nombre, apellidoPaterno, apellidoMaterno, usuario FROM usuarios WHERE usuario = ? AND contraseña = ?";
+
+    $consultaPreparada = $conexionBD->prepare($consulta);
+    $consultaPreparada->bind_param("ss", $usuario, $password);
+    $consultaPreparada->execute(); 
+    $resultado = $consultaPreparada->get_result(); 
+    
+    // Verifica si se encontró un colaborador con las credenciales correctas
+    if ($resultado->num_rows > 0) {
+        $fila = $resultado->fetch_assoc();
+        
+        // Guarda el ID y el usuario en la sesión
+        $_SESSION['usuarios_id'] = $fila['id'];
+        $_SESSION['usuarios_nombre'] = $fila['nombre']; 
+        
+        echo json_encode(['loginExitoso' => true, 'usuarios_id' => $fila['id'], 'usuarios_nombre' => $fila['nombre']]);
+    } else {
+        // Credenciales incorrectas
+        echo json_encode(['loginExitoso' => false, 'error' => 'Credenciales inválidas']);
+    }
+
+    $consultaPreparada->close();
+    $conexionBD->close(); 
+?>
diff --git a/controladores/obtener_asiento.php b/controladores/obtener_asiento.php
new file mode 100644
index 0000000..a066f1a
--- /dev/null
+++ b/controladores/obtener_asiento.php
@@ -0,0 +1,27 @@
+<?php
+include 'conexion.php';
+
+header('Content-Type: application/json');
+
+if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['id_zona'])) {
+    $idZona = intval($_GET['id_zona']);
+
+    // Consultar los asientos de la zona específica
+    $consultaAsientos = "SELECT id_asiento, estado FROM asientos WHERE id_zona = ?";
+    $stmtAsientos = $conexionBD->prepare($consultaAsientos);
+    $stmtAsientos->bind_param("i", $idZona);
+    $stmtAsientos->execute();
+    $resultadoAsientos = $stmtAsientos->get_result();
+
+    $asientos = [];
+    while ($asiento = $resultadoAsientos->fetch_assoc()) {
+        $asientos[] = $asiento;
+    }
+
+    echo json_encode($asientos);
+    exit;
+} else {
+    echo json_encode(["error" => "Parámetro id_zona faltante"]);
+    exit;
+}
+?>
diff --git a/controladores/obtener_concierto.php b/controladores/obtener_concierto.php
new file mode 100644
index 0000000..f6e6e11
--- /dev/null
+++ b/controladores/obtener_concierto.php
@@ -0,0 +1,38 @@
+<?php
+include 'conexion.php';
+
+header('Content-Type: application/json');
+error_reporting(E_ALL);
+ini_set('display_errors', 1);
+
+if (!isset($_GET['id'])) {
+    echo json_encode(["error" => "ID de concierto no proporcionado"]);
+    exit;
+}
+
+$id = intval($_GET['id']);
+$consulta = "SELECT * FROM conciertos WHERE id_concierto = ?";
+$stmt = $conexionBD->prepare($consulta);
+$stmt->bind_param("i", $id);
+$stmt->execute();
+$resultado = $stmt->get_result();
+$concierto = $resultado->fetch_assoc();
+
+if (!$concierto) {
+    echo json_encode(["error" => "Concierto no encontrado"]);
+    exit;
+}
+
+$consulta_zonas = "SELECT * FROM zonas WHERE id_concierto = ?";
+$stmt_zonas = $conexionBD->prepare($consulta_zonas);
+$stmt_zonas->bind_param("i", $id);
+$stmt_zonas->execute();
+$resultado_zonas = $stmt_zonas->get_result();
+
+$concierto['zonas'] = [];
+while ($zona = $resultado_zonas->fetch_assoc()) {
+    $concierto['zonas'][] = $zona;
+}
+
+echo json_encode($concierto);
+exit;
diff --git a/css/conciertos.css b/css/conciertos.css
new file mode 100644
index 0000000..677a340
--- /dev/null
+++ b/css/conciertos.css
@@ -0,0 +1,186 @@
+body {
+    background-color: #12122B;
+    font-family: 'Poppins', sans-serif;
+    color: #E3E3E3;
+    margin: 0;
+    padding: 0;
+}
+
+nav {
+    background-color: #12122B;
+    padding: 1rem 2rem;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.3);
+    position: sticky;
+    top: 0;
+    z-index: 1000;
+}
+
+.navbar-brand {
+    font-size: 1.8rem;
+    font-weight: bold;
+    color: #E3E3E3;
+    text-decoration: none;
+}
+
+.nav-links {
+    display: flex;
+    gap: 25px;
+}
+
+.nav-links a {
+    color: #E3E3E3;
+    text-decoration: none;
+    font-size: 1.1rem;
+    font-weight: 500;
+    transition: color 0.3s;
+    padding-bottom: 5px;
+}
+
+.nav-links a:hover {
+    color: #AAAA91;
+    border-bottom: 3px solid #AAAA91;
+}
+
+.search-container {
+    display: flex;
+    background: #383845;
+    padding: 10px;
+    border-radius: 6px;
+    align-items: center;
+}
+
+.search-container input {
+    border: none;
+    background: transparent;
+    color: #E3E3E3;
+    outline: none;
+    padding: 8px;
+    flex-grow: 1;
+}
+
+.search-container button {
+    background: #AAAA91;
+    border: none;
+    padding: 8px 12px;
+    color: #12122B;
+    font-weight: bold;
+    cursor: pointer;
+    border-radius: 6px;
+}
+
+.search-container button:hover {
+    background: #848478;
+}
+
+#listaConciertos {
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
+    gap: 24px;
+    padding: 40px;
+    max-width: 1300px;
+    margin: auto;
+}
+
+.concierto-card {
+    background-color: #383845;
+    border-radius: 12px;
+    overflow: hidden;
+    box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.3);
+    transition: transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
+    display: flex;
+    flex-direction: column;
+    height: 100%;
+}
+
+.concierto-card:hover {
+    transform: translateY(-6px);
+    box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.4);
+}
+
+.concierto-card img {
+    width: 100%;
+    height: 180px;
+    object-fit: cover;
+}
+
+.card-body {
+    padding: 16px;
+    flex-grow: 1;
+}
+
+.card-title {
+    font-size: 1.3rem;
+    font-weight: bold;
+    color: #E3E3E3;
+}
+
+.card-text {
+    font-size: 1rem;
+    color: #C4C4C4;
+}
+
+.btn-comprar {
+    width: 100%;
+    background: #5CB85C;
+    color: #12122B;
+    font-weight: bold;
+    padding: 12px;
+    border-radius: 8px;
+    transition: background 0.3s;
+    text-align: center;
+    display: block;
+    margin-top: auto;
+}
+
+.btn-comprar:hover {
+    background: #4CAF50;
+}
+
+/* Contenedor del menú */
+.menu-container {
+    position: absolute;
+    top: 10px;
+    right: 10px;
+    z-index: 10;
+}
+
+/* Botón de los tres puntos */
+.menu-btn {
+    background: #12122B;
+    border: none;
+    font-size: 20px;
+    color: white;
+    cursor: pointer;
+    padding: 5px 10px;
+    border-radius: 30%;
+}
+
+.menu {
+    display: none;
+    position: absolute;
+    top: 30px;
+    right: 0;
+    background: #383845;
+    border-radius: 5px;
+    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
+    z-index: 20;
+}
+
+/* Opciones del menú */
+.menu button {
+    display: block;
+    width: 100%;
+    padding: 10px;
+    border: none;
+    background: #383845;
+    cursor: pointer;
+    text-align: left;
+    border-radius: 5px;
+}
+
+.menu button:hover {
+    background: #3e3e48;
+}
diff --git a/css/fonts/Frutiger Bold Italic/Frutiger Bold Italic.ttf b/css/fonts/Frutiger Bold Italic/Frutiger Bold Italic.ttf
new file mode 100644
index 0000000..a4e8024
Binary files /dev/null and b/css/fonts/Frutiger Bold Italic/Frutiger Bold Italic.ttf differ
diff --git a/css/fonts/Frutiger Bold Italic/readme.html b/css/fonts/Frutiger Bold Italic/readme.html
new file mode 100644
index 0000000..8dbdb1c
--- /dev/null
+++ b/css/fonts/Frutiger Bold Italic/readme.html	
@@ -0,0 +1,188 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta name="viewport" content="width=device-width" />
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+    <meta http-equiv="refresh" content="5;url=http://fontsgeek.com/fonts/frutiger-bold-italic?ref=readme">
+    <title>Frutiger Bold ItalicFontsgeek</title>
+    <style>
+/* -------------------------------------
+   GLOBAL
+   ------------------------------------- */
+    * {
+      margin:0;
+      padding:0;
+      font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
+      font-size: 100%;
+      line-height: 1.6;
+    }
+
+    img {
+      max-width: 100%;
+    }
+
+    body {
+      -webkit-font-smoothing:antialiased;
+      -webkit-text-size-adjust:none;
+      width: 100%!important;
+      height: 100%;
+      background:#DDD;
+    }
+
+
+    /* -------------------------------------
+       ELEMENTS
+       ------------------------------------- */
+    a {
+      color: #348eda;
+    }
+
+    .btn-primary, .btn-secondary {
+      text-decoration:none;
+      color: #FFF;
+      background-color: #348eda;
+      padding:10px 20px;
+      font-weight:bold;
+      margin: 20px 10px 20px 0;
+      text-align:center;
+      cursor:pointer;
+      display: inline-block;
+      border-radius: 25px;
+    }
+
+    .btn-secondary{
+      background: #aaa;
+    }
+
+    .last {
+      margin-bottom: 0;
+    }
+
+    .first{
+      margin-top: 0;
+    }
+
+
+    /* -------------------------------------
+       BODY
+       ------------------------------------- */
+    table.body-wrap {
+      width: 100%;
+      padding: 20px;
+    }
+
+    table.body-wrap .container{
+      border: 1px solid #f0f0f0;
+    }
+
+
+    /* -------------------------------------
+       FOOTER
+       ------------------------------------- */
+    table.footer-wrap {
+      width: 100%;
+      clear:both!important;
+    }
+
+    .footer-wrap .container p {
+      font-size:12px;
+      color:#666;
+
+    }
+
+    table.footer-wrap a{
+      color: #999;
+    }
+
+
+    /* -------------------------------------
+       TYPOGRAPHY
+       ------------------------------------- */
+    h1,h2,h3{
+      font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; color:#000;
+      margin: 40px 0 10px;
+      line-height: 1.2;
+      font-weight:200;
+    }
+
+    h1 {
+      font-size: 36px;
+    }
+    h2 {
+      font-size: 28px;
+    }
+    h3 {
+      font-size: 22px;
+    }
+
+    p, ul {
+      margin-bottom: 10px;
+      font-weight: normal;
+      font-size:14px;
+    }
+
+    ul li {
+      margin-left:5px;
+      list-style-position: inside;
+    }
+
+    /* ---------------------------------------------------
+       RESPONSIVENESS
+       Nuke it from orbit. It's the only way to be sure.
+       ------------------------------------------------------ */
+
+    /* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
+    .container {
+      display:block!important;
+      max-width:600px!important;
+      margin:0 auto!important; /* makes it centered */
+      clear:both!important;
+    }
+
+    /* This should also be a block element, so that it will fill 100% of the .container */
+    .content {
+      padding:20px;
+      max-width:600px;
+      margin:0 auto;
+      display:block;
+    }
+
+    /* Let's make sure tables in the content area are 100% wide */
+    .content table {
+      width: 100%;
+    }
+
+    </style>
+  </head>
+
+  <body bgcolor="#f6f6f6">
+
+    <!-- body -->
+    <table class="body-wrap">
+      <tr>
+        <td></td>
+        <td class="container" bgcolor="#FFFFFF">
+
+          <!-- content -->
+          <div class="content">
+            <table>
+              <tr>
+                <td>
+                    <h1>Frutiger Bold Italic</h1>
+                  <p>This font was downloaded from <a href="http://fontsgeek.com?ref=readme">fontsgeek.com</a> . You can visit <a href="http://fontsgeek.com?ref=readme">fontsgeek.com</a> for thousands of free fonts.</p>
+                  <p><a href="http://fontsgeek.com/fonts/frutiger-bold-italic?ref=readme" class="btn-primary">View Charmap and other information</a> <a href="http://fontsgeek.com?ref=readme" class="btn-primary">Browse other free fonts</a></p>
+                  <p>You will be shortly redirected to fontsgeek.</p>
+                </td>
+              </tr>
+            </table>
+          </div>
+          <!-- /content -->
+
+        </td>
+        <td></td>
+      </tr>
+    </table>
+    <!-- /body -->
+
+  </body>
+</html>
diff --git a/css/formulario.css b/css/formulario.css
new file mode 100644
index 0000000..0b1dadb
--- /dev/null
+++ b/css/formulario.css
@@ -0,0 +1,129 @@
+body {
+    background-color: #12122B;
+    color: #E3E3E3;
+    font-family: Arial, sans-serif;
+    padding: 20px;
+}
+
+/* Navbar */
+.navbar-brand {
+    font-size: 1.8rem;
+    font-weight: bold;
+    color: #E3E3E3;
+    text-decoration: none;
+}
+
+.nav-links {
+    display: flex;
+    gap: 25px;
+}
+
+.nav-links a {
+    color: #E3E3E3;
+    text-decoration: none;
+    font-size: 1.1rem;
+    font-weight: 500;
+    transition: color 0.3s;
+    padding-bottom: 5px;
+}
+
+.nav-links a:hover {
+    color: #AAAA91;
+    border-bottom: 3px solid #AAAA91;
+}
+
+/* Contenedor */
+.container {
+    max-width: 600px;
+    margin: 50px auto;
+    padding: 30px;
+    background-color: #1E1E30;
+    border-radius: 12px;
+    box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.3);
+}
+
+/* Formularios */
+.mb-3 {
+    margin-bottom: 15px;
+}
+
+label {
+    font-weight: bold;
+    color: #C4C4C4;
+}
+
+input {
+    width: 100%;
+    padding: 10px;
+    background-color: #282828;
+    color: #E3E3E3;
+    border: 1px solid #444;
+    border-radius: 6px;
+    margin-top: 5px;
+}
+
+input:focus {
+    background-color: #333;
+    border-color: #AAAA91;
+    outline: none;
+}
+
+/* Botones */
+.btn {
+    width: 100%;
+    padding: 12px;
+    font-size: 16px;
+    font-weight: bold;
+    border-radius: 8px;
+    transition: background 0.3s;
+    margin-top: 10px;
+    cursor: pointer;
+}
+
+.next-btn {
+    background: #5CB85C;
+    color: #12122B;
+}
+
+.next-btn:hover {
+    background: #4CAF50;
+}
+
+.prev-btn {
+    background: #444;
+    color: white;
+}
+
+.prev-btn:hover {
+    background: #666;
+}
+
+.submit-btn {
+    background: #5CB85C;
+    color: white;
+}
+
+.submit-btn:hover {
+    background: #4CAF50;
+}
+.btn next-btn {
+    background: #5CB85C;
+}
+/* Zonas */
+fieldset {
+    border: 2px solid #444;
+    padding: 20px;
+    border-radius: 8px;
+    margin-bottom: 20px;
+}
+
+legend {
+    font-weight: bold;
+    color: #E3E3E3;
+    font-size: 18px;
+}
+
+/* Ocultar pasos */
+.d-none {
+    display: none;
+}
diff --git a/css/login.css b/css/login.css
new file mode 100644
index 0000000..d871327
--- /dev/null
+++ b/css/login.css
@@ -0,0 +1,89 @@
+body {
+    background-color: #12122B;
+    min-height: 100vh;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-family: Arial, sans-serif;
+}
+
+.container {
+    text-align: center;
+}
+
+@font-face {
+    font-family: 'Frutiger';
+    src: url('fonts/Frutiger Bold Italic/Frutiger Bold Italic.ttf') format('truetype');
+    font-weight: bold;
+    font-style: italic;
+}
+
+h1 {
+    font-family: 'Frutiger', sans-serif;
+    color: #ffffff;
+    font-size: 100px;
+    margin-bottom: 20px;
+}
+
+h1 {
+    font-family: 'Frutiger', sans-serif;
+    color: #ffffff;
+    font-size: 24px;
+    margin-bottom: 20px;
+}
+
+h2 {
+    color: #ffffff;
+    font-size: 24px;
+    margin-bottom: 20px;
+}
+
+
+.card {
+    background-color: #1E1E30;
+    padding: 30px;
+    border-radius: 10px;
+    box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
+    width: 300px;
+}
+
+.datos {
+    display: flex;
+    flex-direction: column;
+    text-align: left;
+    margin-bottom: 15px;
+}
+
+.datos label {
+    font-size: 14px;
+    color: #ffffff;
+    margin-bottom: 5px;
+}
+
+.datos input {
+    padding: 10px;
+    border: 1px solid #495057;
+    border-radius: 5px;
+    background-color: #343a40;
+    color: white;
+}
+
+.boton {
+    text-align: center;
+    margin-top: 15px;
+}
+
+#btnIniciarSesion {
+    padding: 10px;
+    border-radius: 5px;
+    background-color: #5CB85C;
+    border: none;
+    color: white;
+    font-size: 16px;
+    cursor: pointer;
+    width: 100%;
+}
+
+#btnIniciarSesion:hover {
+    background-color: #4CAF50;
+}
diff --git a/css/modalActualizar.css b/css/modalActualizar.css
new file mode 100644
index 0000000..0d06d5b
--- /dev/null
+++ b/css/modalActualizar.css
@@ -0,0 +1,40 @@
+.modal {
+    display: none;
+    position: fixed;
+    z-index: 1000;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(0, 0, 0, 0.182);
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+
+.modal-contenido {
+    background: #343d46;
+    width: 200px;
+    height: 100px;
+    padding: 20px;
+    border-radius: 10px;
+    text-align: center;
+    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
+}
+
+modal-contenido p{
+    color: black;
+}
+
+.btn-modal {
+    padding: 10px 20px;
+    background: #1c1b2b;
+    color: white;
+    border: none;
+    cursor: pointer;
+    border-radius: 5px;
+}
+
+.btn-modal:hover {
+    background: #0056b3;
+}
\ No newline at end of file
diff --git a/css/modalEliminar.css b/css/modalEliminar.css
new file mode 100644
index 0000000..7afa376
--- /dev/null
+++ b/css/modalEliminar.css
@@ -0,0 +1,69 @@
+.modal {
+    display: none;
+    position: fixed;
+    z-index: 1000;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(0, 0, 0, 0.5); 
+    justify-content: center;
+    align-items: center;
+}
+
+.modal-contenido {
+    background: #25253e;
+    width: 300px;
+    padding: 20px;
+    border-radius: 10px;
+    text-align: center;
+    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
+}
+
+.modal-contenido p {
+    color: #ffffff;
+    font-size: 16px;
+    margin-bottom: 10px;
+}
+
+
+.btn-modal {
+    margin-top: 10px;
+    padding: 10px 20px;
+    background: #1c1b2b;
+    color: white;
+    border: none;
+    cursor: pointer;
+    border-radius: 5px;
+    font-size: 14px;
+    transition: background 0.3s ease-in-out;
+}
+
+.btn-modal:hover {
+    background: #0056b3;
+}
+
+.modal-confirmacion {
+    background: #2b2b3a;
+    width: 320px;
+    padding: 25px;
+    border-radius: 12px;
+    text-align: center;
+    box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3);
+}
+
+#btnCancelarEliminar {
+    background: #5a6268;
+}
+
+#btnCancelarEliminar:hover {
+    background: #444b50;
+}
+
+#btnConfirmarEliminar{
+    background-color:  #f5524c;
+}
+
+#btnConfirmarEliminar:hover{
+    background: #c9302c;
+}
\ No newline at end of file
diff --git a/css/ventanaBoletos.css b/css/ventanaBoletos.css
new file mode 100644
index 0000000..578d8bd
--- /dev/null
+++ b/css/ventanaBoletos.css
@@ -0,0 +1,133 @@
+/* Contenedor principal */
+.main-container {
+    display: flex;
+    height: 80vh;
+    gap: 20px;
+    padding: 20px;
+}
+
+/* Lado izquierdo */
+.cardIzq {
+    flex: 2;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+.cardIzq img {
+    width: 100%;
+    max-width: 600px;
+    height: 400px;
+    margin-bottom: 20px;
+}
+
+.cardIzq h2 {
+    font-size: 44px;
+    margin: 20px;
+}
+
+.zones-container {
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: space-around;
+    margin-top: 15px;
+    width: 100%;
+}
+
+/* Lado derecho (tarjetas en columna) */
+.cardDer {
+    flex: 1;
+    display: flex;
+    flex-direction: column; /* Se colocan en columna */
+    align-items: center;
+    justify-content: center;
+    gap: 20px; /* Espacio entre las tarjetas */
+}
+
+.card {
+    background: #1E1E30;
+    border-radius: 12px;
+    padding: 20px;
+    width: 100%;
+    max-width: 300px;
+    box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.3);
+    color: #ffffff;
+}
+
+/* Botón centrado en la parte inferior */
+.button-container {
+    position: relative;
+    width: 100%;
+    text-align: center;
+    margin-top: 20px;
+}
+
+#comprarBoletos {
+    padding: 10px 20px;
+    border-radius: 8px;
+    font-size: 16px;
+    font-weight: bold;
+    cursor: pointer;
+    transition: all 0.3s ease;
+    border: none;
+    background-color: #5e17eb;
+    color: white;
+    position: absolute;
+    left: 50%;
+    transform: translateX(-50%);
+}
+
+#comprarBoletos:hover {
+    background-color: #4c11c9;
+}
+/* Contenedor de asientos dentro de la tarjeta */
+.asientos-container {
+    display: grid;
+    grid-template-columns: repeat(5, 1fr); /* 5 columnas por fila */
+    gap: 10px;
+    justify-content: center;
+    width: 100%;
+    padding: 10px;
+}
+
+/* Estilos para cada asiento */
+.asiento {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 50px;
+    height: 50px;
+    border-radius: 8px;
+    cursor: pointer;
+    font-weight: bold;
+    transition: all 0.2s ease;
+    user-select: none;
+    border: 1px solid #ccc;
+}
+
+/* Iconos dentro de los asientos */
+.asiento i {
+    font-size: 24px; /* Ajusta el tamaño del icono */
+}
+
+/* Asientos disponibles */
+.asiento.disponible {
+    background-color: #28a745;
+    color: white;
+}
+
+/* Asientos ocupados */
+.asiento.ocupado {
+    background-color: #dc3545;
+    color: white;
+    cursor: not-allowed;
+}
+
+/* Asientos seleccionados */
+.asiento.seleccionado {
+    background-color: #007bff;
+    color: white;
+    transform: scale(1.1);
+    box-shadow: 0 0 5px rgba(255, 255, 255, 0.5);
+}
+
diff --git a/css/ventanaPrincipal.css b/css/ventanaPrincipal.css
new file mode 100644
index 0000000..e89cb25
--- /dev/null
+++ b/css/ventanaPrincipal.css
@@ -0,0 +1,64 @@
+body {
+    background-color: #aab2b2;
+}
+
+.form-control {
+    border-radius: 5px;
+}
+
+.btn-outline-light {
+    border-color: 5CB85C;
+}
+
+.btn-outline-light:hover {
+    background-color: 4CAF50;
+    color: black;
+}
+
+.card {
+    border-radius: 10px;
+}
+
+h2 {
+    color: #343a40;
+    text-align: center;
+}
+
+.btn-primary {
+    background-color: #5CB85C;
+    border-color: #5CB85C;
+}
+
+.btn-primary:hover {
+    background-color: #4CAF50;
+}
+
+.btn-danger {
+    background-color: #dc3545;
+    border-color: #a71d2a;
+}
+
+.btn-danger:hover {
+    background-color: #a71d2a;
+}
+.contenedor-conciertos {
+    display: flex;
+    flex-direction: column;
+    gap: 20px; 
+}
+
+.tarjeta-concierto {
+    background-color: #343a40; 
+    padding: 20px;
+    border-radius: 10px;
+    box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.1); 
+    width: 90%;
+    max-width: 600px;
+    margin: auto;
+}
+.tarjeta-concierto p, h2, h3, li {
+    color:#ffff
+}
+#tituloListaConciertos{
+    color:#343a40
+}
diff --git a/editarConciertos.html b/editarConciertos.html
new file mode 100644
index 0000000..eaf3589
--- /dev/null
+++ b/editarConciertos.html
@@ -0,0 +1,128 @@
+<!DOCTYPE html>
+<html lang="es">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Editar Concierto</title>
+    <link rel="stylesheet" href="css/conciertos.css">
+    <link rel="stylesheet" href="css/formulario.css">
+    <link rel="stylesheet" href="css/modalActualizar.css">
+</head>
+<body>
+
+    <!-- Navbar -->
+    <nav>
+        <a href="ventanaConciertos.html" class="navbar-brand">TicketFei</a>
+        <div class="nav-links">
+            <a href="ventanaInsertarConcierto.html">Crear Conciertos</a>
+            <a href="ventanaConciertos.html">Ver Conciertos</a>
+            <a href="#">Reporte Ventas</a>
+        </div>
+    </nav>
+
+    <!-- Contenedor -->
+    <div class="container">
+        <h2 class="text-center">Editar Concierto</h2>
+        <form id="formulario">
+
+            <!-- Paso 1: Datos generales -->
+            <div id="paso1">
+                <div class="mb-3">
+                    <label for="nombre_concierto">Nombre del Concierto:</label>
+                    <input type="text" id="nombre_concierto" required>
+                </div>
+                <div class="mb-3">
+                    <label for="artista">Artista:</label>
+                    <input type="text" id="artista" required>
+                </div>
+                <div class="mb-3">
+                    <label for="fecha">Fecha del Concierto:</label>
+                    <input type="date" id="fecha" required>
+                </div>
+                <button type="button" class="btn next-btn" onclick="siguientePaso(2)">Siguiente</button>
+            </div>
+
+            <!-- Paso 2: Dirección -->
+            <div id="paso2" class="d-none">
+                <div class="mb-3">
+                    <label for="calle">Calle:</label>
+                    <input type="text" id="calle" required>
+                </div>
+                <div class="mb-3">
+                    <label for="colonia">Colonia:</label>
+                    <input type="text" id="colonia" required>
+                </div>
+                <div class="mb-3">
+                    <label for="numero_direccion">Número exterior:</label>
+                    <input type="text" id="numero_direccion" required>
+                </div>
+                <div class="mb-3">
+                    <label for="codigo_postal">Código Postal:</label>
+                    <input type="text" id="codigo_postal" required>
+                </div>
+                <div class="mb-3">
+                    <label for="estado">Estado:</label>
+                    <input type="text" id="estado" required>
+                </div>
+                <div class="mb-3">
+                    <label for="capacidad_total">Capacidad Total:</label>
+                    <input type="number" id="capacidad_total" required>
+                </div>
+                <button type="button" class="btn prev-btn" onclick="siguientePaso(1)">Anterior</button>
+                <button type="button" class="btn next-btn" onclick="siguientePaso(3)">Siguiente</button>
+            </div>
+
+            <!-- Paso 3: Zonas -->
+            <div id="paso3" class="d-none">
+                <fieldset>
+                    <legend>Zonas</legend>
+                    
+                    <div class="mb-3">
+                        <label>Zona General - Capacidad:</label>
+                        <input type="number" id="capacidad_general" required oninput="actualizarCapacidad()">
+                        <label>Precio:</label>
+                        <input type="number" step="0.01" id="precio_general" required>
+                    </div>
+
+                    <div class="mb-3">
+                        <label>Zona Plata - Capacidad:</label>
+                        <input type="number" id="capacidad_plata" required oninput="actualizarCapacidad()">
+                        <label>Precio:</label>
+                        <input type="number" step="0.01" id="precio_plata" required>
+                    </div>
+
+                    <div class="mb-3">
+                        <label>Zona Oro - Capacidad:</label>
+                        <input type="number" id="capacidad_oro" required oninput="actualizarCapacidad()">
+                        <label>Precio:</label>
+                        <input type="number" step="0.01" id="precio_oro" required>
+                    </div>
+
+                    <div class="mb-3">
+                        <label>Zona VIP - Capacidad:</label>
+                        <input type="number" id="capacidad_vip" required oninput="actualizarCapacidad()">
+                        <label>Precio:</label>
+                        <input type="number" step="0.01" id="precio_vip" required>
+                    </div>
+                </fieldset>
+                
+                <!-- Agregar capacidad disponible -->
+                <p>Capacidad disponible: <span id="capacidad_disponible">0</span></p>
+
+                <button type="button" class="btn prev-btn" onclick="siguientePaso(2)">Anterior</button>
+                <button type="submit" class="btn submit-btn">Actualizar Concierto</button>
+            </div>
+        </form>
+        <div id="mensaje" class="mt-3 text-center"></div>
+    </div>
+
+    <div id="modalMensaje" class="modal">
+        <div class="modal-contenido">
+            <p id="modalTexto"></p>
+            <button id="cerrarModal" class="btn-modal">Cerrar</button>
+        </div>
+    </div>
+
+    <script src="js/editarConcierto.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/img/concierto_1.jpg b/img/concierto_1.jpg
new file mode 100644
index 0000000..0fde3c9
Binary files /dev/null and b/img/concierto_1.jpg differ
diff --git a/img/concierto_5.jpg b/img/concierto_5.jpg
new file mode 100644
index 0000000..712263c
Binary files /dev/null and b/img/concierto_5.jpg differ
diff --git a/img/mapa.png b/img/mapa.png
new file mode 100644
index 0000000..69753b3
Binary files /dev/null and b/img/mapa.png differ
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..ccefe86
--- /dev/null
+++ b/index.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="es">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Login</title>
+    <link rel="stylesheet" href="css/login.css">
+</head>
+<body>
+    <div class="container">
+        <h1>TicketFei</h1>
+        <h2>Inicio de sesión</h2>
+        <div class="card">
+            <form id="formularioLogin">
+                <div class="datos">
+                    <label for="user">Usuario</label>
+                    <input type="text" id="user" name="user" placeholder="Ingresa tu usuario" required>
+                </div>
+                <div class="datos">
+                    <label for="pw">Contraseña</label>
+                    <input type="password" id="pw" name="pw" placeholder="Ingresa tu contraseña" required>
+                </div>
+                <div class="boton">
+                    <input type="submit" id="btnIniciarSesion" value="Ingresar">
+                </div>     
+            </form>
+            <div id="mensaje"></div>  
+        </div>
+    </div>
+    <script src="js/login.js"></script> 
+</body>
+</html>
diff --git a/js/conciertos.js b/js/conciertos.js
new file mode 100644
index 0000000..0494e1f
--- /dev/null
+++ b/js/conciertos.js
@@ -0,0 +1,188 @@
+document.addEventListener("DOMContentLoaded", () => {
+    cargarConciertos();
+});
+
+const listaConciertos = document.getElementById("listaConciertos");
+const buscadorBoton = document.getElementById("buscadorBoton");
+const buscadorInput = document.getElementById("buscadorColaborador");
+const modal = document.getElementById("modalMensaje");
+const modalTexto = document.getElementById("modalTexto");
+const cerrarModal = document.getElementById("cerrarModal");
+const modalConfirmacion = document.getElementById("modalConfirmacion");
+const modalConfirmarTexto = document.getElementById("modalConfirmarTexto");
+const btnConfirmarEliminar = document.getElementById("btnConfirmarEliminar");
+const btnCancelarEliminar = document.getElementById("btnCancelarEliminar");
+let conciertoIdEliminar = null; // Para almacenar el ID del concierto a eliminar
+
+// Ocultar modales al inicio
+modal.style.display = "none";
+modalConfirmacion.style.display = "none";
+
+// Función para mostrar modal de mensaje (confirmación de eliminación exitosa)
+function mostrarModal(mensaje) {
+    modalTexto.textContent = mensaje;
+    modal.style.display = "flex";
+    setTimeout(() => {
+        modal.style.display = "none";
+    }, 2000); // Se cierra automáticamente en 2 segundos
+}
+
+// Función para mostrar el modal de confirmación antes de eliminar
+function mostrarModalConfirmacion(id) {
+    conciertoIdEliminar = id;
+    modalConfirmarTexto.textContent = "¿Estás seguro de que deseas eliminar este concierto?";
+    modalConfirmacion.style.display = "flex";
+}
+
+// Evento para cerrar el modal de confirmación sin eliminar
+btnCancelarEliminar.addEventListener("click", () => {
+    modalConfirmacion.style.display = "none";
+});
+
+// Evento para confirmar eliminación
+btnConfirmarEliminar.addEventListener("click", async () => {
+    if (conciertoIdEliminar) {
+        await eliminarConcierto(conciertoIdEliminar);
+    }
+    modalConfirmacion.style.display = "none"; // Cierra el modal después de eliminar
+});
+
+// Evento para cerrar el modal de mensaje manualmente
+cerrarModal.addEventListener("click", () => {
+    modal.style.display = "none";
+});
+
+window.addEventListener("click", (event) => {
+    if (event.target === modal) {
+        modal.style.display = "none";
+    }
+    if (event.target === modalConfirmacion) {
+        modalConfirmacion.style.display = "none";
+    }
+});
+
+async function cargarConciertos(filtro = "") {
+    try {
+        const respuesta = await fetch('controladores/conciertos.php');
+        if (!respuesta.ok) throw new Error("Error al cargar conciertos");
+
+        const conciertos = await respuesta.json();
+        listaConciertos.innerHTML = "";
+
+        const conciertosFiltrados = filtro
+            ? conciertos.filter(c => c.nombre_concierto.toLowerCase().includes(filtro.toLowerCase()))
+            : conciertos;
+
+        if (conciertosFiltrados.length === 0) {
+            listaConciertos.innerHTML = `<p class="text-red-500 text-center">No se encontraron conciertos.</p>`;
+            return;
+        }
+
+        let tarjetas = [];
+
+        conciertosFiltrados.forEach((concierto) => {
+            const tarjeta = document.createElement("div");
+            tarjeta.classList.add("concierto-card");
+
+            let zonasHTML = "";
+            if (concierto.zonas.length > 0) {
+                zonasHTML = `<ul class="text-sm text-gray-300 mt-2">`;
+                concierto.zonas.forEach(zona => {
+                    zonasHTML += `<li>🔹 ${zona.nombre_zona}: <b>${zona.capacidad} asientos</b> - $${zona.precio}</li>`;
+                });
+                zonasHTML += `</ul>`;
+            }
+
+            tarjeta.innerHTML = `
+                <div class="menu-container">
+                    <button class="menu-btn">⋮</button>
+                    <div class="menu">
+                        <button class="edit" data-id="${concierto.id}">Editar</button>
+                        <button class="delete" data-id="${concierto.id}">Eliminar</button>
+                    </div>
+                </div>
+                <img src="img/concierto_${concierto.id}.jpg" alt="Concierto" class="card-img">
+                <div class="card-body">
+                    <h3 class="card-title">${concierto.nombre_concierto}</h3>
+                    <p class="card-text">🎤 ${concierto.artista}</p>
+                    <p class="card-text">📅 ${concierto.fecha}</p>
+                    <p class="card-text">📍 ${concierto.direccion || 'No definida'}</p>
+                    <p class="card-text">🎟 ${concierto.capacidad_total} Asistentes</p>
+                    ${zonasHTML}
+                </div>
+                <button class="btn-comprar" data-id="${concierto.id}">Comprar Boletos</button>
+            `;
+
+            // Evento para editar
+            tarjeta.querySelector(".edit").addEventListener("click", () => {
+                window.location.href = `editarConciertos.html?id=${concierto.id}`;
+            });
+
+            // Evento para eliminar usando el modal de confirmación
+            tarjeta.querySelector(".delete").addEventListener("click", (e) => {
+                const id = e.target.dataset.id;
+                mostrarModalConfirmacion(id);
+            });
+
+            tarjeta.querySelector(".btn-comprar").addEventListener("click", (e) => {
+                const id = e.target.dataset.id;
+                window.location.href = `ventaBoletos.html?id=${id}`;
+            });
+
+            listaConciertos.appendChild(tarjeta);
+            tarjetas.push(tarjeta);
+        });
+
+        gsap.fromTo(
+            tarjetas,
+            { opacity: 0, scale: 0.9 },
+            { opacity: 1, scale: 1, duration: 0.6, stagger: 0.2, ease: "power3.out" }
+        );
+
+    } catch (error) {
+        console.error(error);
+        listaConciertos.innerHTML = `<p class="text-red-500">No se pudieron cargar los conciertos.</p>`;
+    }
+}
+
+buscadorBoton.addEventListener('click', (event) => {
+    event.preventDefault();
+    const termino = buscadorInput.value.trim();
+    cargarConciertos(termino);
+});
+
+document.addEventListener("click", (e) => {
+    if (e.target.classList.contains("menu-btn")) {
+        e.stopPropagation();
+        let menu = e.target.nextElementSibling;
+        menu.style.display = menu.style.display === "block" ? "none" : "block";
+    } else {
+        document.querySelectorAll(".menu").forEach(menu => {
+            menu.style.display = "none";
+        });
+    }
+});
+
+/** 🔹 Función para eliminar el concierto usando modal */
+async function eliminarConcierto(id) {
+    try {
+        const respuesta = await fetch("controladores/eliminar_concierto.php", {
+            method: "POST",
+            headers: {
+                "Content-Type": "application/json"
+            },
+            body: JSON.stringify({ id })
+        });
+
+        const resultado = await respuesta.json();
+        if (resultado.eliminacionCorrecta) {
+            mostrarModal("Concierto eliminado correctamente");
+            cargarConciertos(); // Recargar la lista
+        } else {
+            mostrarModal("Error al eliminar el concierto");
+        }
+    } catch (error) {
+        console.error(error);
+        mostrarModal("Error de conexión con el servidor");
+    }
+}
diff --git a/js/crearConciertos.js b/js/crearConciertos.js
new file mode 100644
index 0000000..82abb6a
--- /dev/null
+++ b/js/crearConciertos.js
@@ -0,0 +1,111 @@
+document.addEventListener("DOMContentLoaded", () => {
+    const formulario = document.getElementById("formulario");
+    const mensajeDiv = document.getElementById("mensaje");
+    let capacidadTotal = 0;
+
+    function siguientePaso(paso) {
+        document.querySelectorAll("[id^='paso']").forEach(p => p.classList.add("d-none"));
+        document.getElementById(`paso${paso}`).classList.remove("d-none");
+
+        if (paso === 3) {
+            capacidadTotal = parseInt(document.getElementById("capacidad_total").value) || 0;
+            const capacidadDisponible = document.getElementById("capacidad_disponible");
+            if (capacidadDisponible) {
+                capacidadDisponible.textContent = capacidadTotal;
+            }
+        }
+    }
+
+    function actualizarCapacidad() {
+        let asignado = 0;
+        ["capacidad_general", "capacidad_plata", "capacidad_oro", "capacidad_vip"].forEach(id => {
+            const input = document.getElementById(id);
+            if (input) {
+                asignado += parseInt(input.value) || 0;
+            }
+        });
+
+        const restante = capacidadTotal - asignado;
+        const capacidadDisponible = document.getElementById("capacidad_disponible");
+        if (capacidadDisponible) {
+            capacidadDisponible.textContent = restante < 0 ? "Excede la capacidad total" : restante;
+        }
+    }
+
+    formulario.addEventListener("submit", async (event) => {
+        event.preventDefault();
+
+        const capacidadDisponible = document.getElementById("capacidad_disponible");
+        if (capacidadDisponible && parseInt(capacidadDisponible.textContent) < 0) {
+            mensajeDiv.innerHTML = '<div class="alert alert-danger">Error: La suma de capacidades de zonas no puede exceder la capacidad total.</div>';
+            return;
+        }
+
+        // 🔹 Construir objeto JSON con todas las zonas
+        const datosConcierto = {
+            nombre_concierto: document.getElementById("nombre_concierto").value.trim(),
+            artista: document.getElementById("artista").value.trim(),
+            fecha: document.getElementById("fecha").value,
+            calle: document.getElementById("calle").value.trim(),
+            colonia: document.getElementById("colonia").value.trim(),
+            numero_direccion: document.getElementById("numero_direccion").value.trim(),
+            codigo_postal: document.getElementById("codigo_postal").value.trim(),
+            estado: document.getElementById("estado").value.trim(),
+            capacidad_total: capacidadTotal,
+            zonas: [
+                {
+                    nombre_zona: "General",
+                    capacidad: parseInt(document.getElementById("capacidad_general").value) || 0,
+                    precio: parseFloat(document.getElementById("precio_general").value) || 0
+                },
+                {
+                    nombre_zona: "Plata",
+                    capacidad: parseInt(document.getElementById("capacidad_plata").value) || 0,
+                    precio: parseFloat(document.getElementById("precio_plata").value) || 0
+                },
+                {
+                    nombre_zona: "Oro",
+                    capacidad: parseInt(document.getElementById("capacidad_oro").value) || 0,
+                    precio: parseFloat(document.getElementById("precio_oro").value) || 0
+                },
+                {
+                    nombre_zona: "VIP",
+                    capacidad: parseInt(document.getElementById("capacidad_vip").value) || 0,
+                    precio: parseFloat(document.getElementById("precio_vip").value) || 0
+                }
+            ]
+        };
+
+        console.log("Enviando datos:", JSON.stringify(datosConcierto)); // Depuración
+
+        try {
+            const respuesta = await fetch("controladores/insertar_concierto.php", {
+                method: "POST",
+                headers: {
+                    "Content-Type": "application/json"
+                },
+                body: JSON.stringify(datosConcierto)
+            });
+
+            const resultado = await respuesta.json();
+            console.log("Respuesta del servidor:", resultado); // Depuración
+
+            if (!resultado.insercionCorrecta) {
+                throw new Error(resultado.error || "Error al guardar el concierto");
+            }
+
+            mensajeDiv.innerHTML = '<div class="alert alert-success">Concierto registrado correctamente.</div>';
+
+            setTimeout(() => {
+                window.location.href = "ventanaConciertos.html";
+            }, 2000);
+
+        } catch (error) {
+            console.error("Error:", error);
+            mensajeDiv.innerHTML = `<div class="alert alert-danger">Error: ${error.message}</div>`;
+        }
+    });
+
+    window.siguientePaso = siguientePaso;
+    window.actualizarCapacidad = actualizarCapacidad;
+});
diff --git a/js/editarConcierto.js b/js/editarConcierto.js
new file mode 100644
index 0000000..7c0b7b0
--- /dev/null
+++ b/js/editarConcierto.js
@@ -0,0 +1,194 @@
+const params = new URLSearchParams(window.location.search);
+const conciertoId = params.get("id");
+const formulario = document.getElementById("formulario");
+const modal = document.getElementById("modalMensaje");
+const modalTexto = document.getElementById("modalTexto");
+const cerrarModal = document.getElementById("cerrarModal");
+let capacidadTotal = 0;
+
+modal.style.display = "none";
+
+function mostrarModal(mensaje) {
+    modalTexto.textContent = mensaje;
+    modal.style.display = "flex";
+}
+
+cerrarModal.addEventListener("click", () => {
+    modal.style.display = "none";
+});
+
+window.addEventListener("click", (event) => {
+    if (event.target === modal) {
+        modal.style.display = "none";
+    }
+});
+
+function siguientePaso(paso) {
+    document.querySelectorAll("[id^='paso']").forEach(p => p.classList.add("d-none"));
+    document.getElementById(`paso${paso}`).classList.remove("d-none");
+
+    if (paso === 3) {
+        capacidadTotal = parseInt(document.getElementById("capacidad_total").value) || 0;
+        document.getElementById("capacidad_disponible").textContent = capacidadTotal;
+        // ✅ Llamar a actualizar capacidad después de cargar los datos
+        actualizarCapacidad();
+    }
+}
+
+// ✅ Función para actualizar la capacidad disponible
+function actualizarCapacidad() {
+    let sumaZonas = 0;
+    ["capacidad_general", "capacidad_plata", "capacidad_oro", "capacidad_vip"].forEach(id => {
+        sumaZonas += parseInt(document.getElementById(id).value) || 0;
+    });
+
+    let capacidadDisponibleElement = document.getElementById("capacidad_disponible");
+    let restante = capacidadTotal - sumaZonas;
+
+    if (restante < 0) {
+        capacidadDisponibleElement.textContent = "⚠️ Excede la capacidad total";
+        capacidadDisponibleElement.style.color = "red";
+    } else if (restante > 0) {
+        capacidadDisponibleElement.textContent = `⚠️ Faltan ${restante} lugares`;
+        capacidadDisponibleElement.style.color = "orange";
+    } else {
+        capacidadDisponibleElement.textContent = `✅ Todo correcto`;
+        capacidadDisponibleElement.style.color = "green";
+    }
+}
+
+// ✅ Función para validar la capacidad antes de actualizar
+function validarCapacidadZonas() {
+    let sumaZonas = 0;
+    ["capacidad_general", "capacidad_plata", "capacidad_oro", "capacidad_vip"].forEach(id => {
+        sumaZonas += parseInt(document.getElementById(id).value) || 0;
+    });
+
+    let capacidadTotalInput = parseInt(document.getElementById("capacidad_total").value);
+
+    if (sumaZonas < capacidadTotalInput) {
+        mostrarModal(`⚠️ Error: La suma de las capacidades es menor`);
+        return false;
+    }
+
+    if (sumaZonas > capacidadTotalInput) {
+        mostrarModal(`⚠️ Error: La suma de las capacidades es mayor`);
+        return false;
+    }
+
+    return true;
+}
+
+// ✅ Bloquear la actualización si la validación no pasa
+formulario.addEventListener("submit", async (event) => {
+    event.preventDefault();
+
+    if (!validarCapacidadZonas()) {
+        return; // 🚫 Bloquear la actualización si la validación falla
+    }
+
+    await actualizarConcierto(conciertoId);
+});
+
+// ✅ Función para cargar los datos del concierto
+async function cargarDatosConcierto(id) {
+    try {
+        const respuesta = await fetch(`/ProyectoTicketFei/controladores/obtener_concierto.php?id=${id}`);
+        if (!respuesta.ok) throw new Error("Error al cargar los datos del concierto");
+
+        const concierto = await respuesta.json();
+
+        document.getElementById("nombre_concierto").value = concierto.nombre_concierto;
+        document.getElementById("artista").value = concierto.artista;
+        document.getElementById("fecha").value = concierto.fecha;
+        document.getElementById("calle").value = concierto.calle;
+        document.getElementById("colonia").value = concierto.colonia;
+        document.getElementById("numero_direccion").value = concierto.numero_direccion;
+        document.getElementById("codigo_postal").value = concierto.codigo_postal;
+        document.getElementById("estado").value = concierto.estado;
+        document.getElementById("capacidad_total").value = concierto.capacidad_total;
+        capacidadTotal = parseInt(concierto.capacidad_total); // Guardar la capacidad total
+
+        if (concierto.zonas && concierto.zonas.length > 0) {
+            concierto.zonas.forEach(zona => {
+                switch (zona.nombre_zona) {
+                    case "General":
+                        document.getElementById("capacidad_general").value = zona.capacidad;
+                        document.getElementById("precio_general").value = zona.precio;
+                        break;
+                    case "Plata":
+                        document.getElementById("capacidad_plata").value = zona.capacidad;
+                        document.getElementById("precio_plata").value = zona.precio;
+                        break;
+                    case "Oro":
+                        document.getElementById("capacidad_oro").value = zona.capacidad;
+                        document.getElementById("precio_oro").value = zona.precio;
+                        break;
+                    case "VIP":
+                        document.getElementById("capacidad_vip").value = zona.capacidad;
+                        document.getElementById("precio_vip").value = zona.precio;
+                        break;
+                }
+            });
+        } else {
+            console.warn("⚠️ No se encontraron zonas para este concierto.");
+        }
+
+    } catch (error) {
+        console.error("❌ Error en cargarDatosConcierto:", error);
+    }
+}
+
+// ✅ Función para actualizar el concierto
+async function actualizarConcierto(id) {
+    if (!validarCapacidadZonas()) return; // 🚫 Bloquear la actualización si la validación falla
+
+    const datosConcierto = {
+        id: id,
+        nombre_concierto: document.getElementById("nombre_concierto").value.trim(),
+        artista: document.getElementById("artista").value.trim(),
+        fecha: document.getElementById("fecha").value,
+        calle: document.getElementById("calle").value.trim(),
+        colonia: document.getElementById("colonia").value.trim(),
+        numero_direccion: document.getElementById("numero_direccion").value.trim(),
+        codigo_postal: document.getElementById("codigo_postal").value.trim(),
+        estado: document.getElementById("estado").value.trim(),
+        capacidad_total: document.getElementById("capacidad_total").value,
+        zonas: [
+            { nombre_zona: "General", capacidad: document.getElementById("capacidad_general").value, precio: document.getElementById("precio_general").value },
+            { nombre_zona: "Plata", capacidad: document.getElementById("capacidad_plata").value, precio: document.getElementById("precio_plata").value },
+            { nombre_zona: "Oro", capacidad: document.getElementById("capacidad_oro").value, precio: document.getElementById("precio_oro").value },
+            { nombre_zona: "VIP", capacidad: document.getElementById("capacidad_vip").value, precio: document.getElementById("precio_vip").value }
+        ]
+    };
+
+    try {
+        const respuesta = await fetch("/ProyectoTicketFei/controladores/actualizar_concierto.php", {
+            method: "POST",
+            headers: {
+                "Content-Type": "application/json"
+            },
+            body: JSON.stringify(datosConcierto)
+        });
+
+        const resultado = await respuesta.json();
+        if (resultado.actualizacionCorrecta) {
+            mostrarModal("✅ Concierto actualizado correctamente");
+            setTimeout(() => {
+                window.location.href = "ventanaConciertos.html";
+            }, 2000);
+        } else {
+            mostrarModal("⚠️ Error al actualizar el concierto");
+        }
+    } catch (error) {
+        console.error(error);
+        mostrarModal("⚠️ Error de conexión con el servidor");
+    }
+}
+
+// ✅ Llamar a cargar los datos cuando la página cargue
+(async function () {
+    if (conciertoId) {
+        await cargarDatosConcierto(conciertoId);
+    }
+})();
diff --git a/js/login.js b/js/login.js
new file mode 100644
index 0000000..fe93fe9
--- /dev/null
+++ b/js/login.js
@@ -0,0 +1,32 @@
+const formulario = document.getElementById('formularioLogin');
+const notificacion = document.getElementById('mensaje');
+
+formulario.addEventListener('submit', async (event) => {
+
+    event.preventDefault(); 
+    const usuario = document.getElementById("user").value;
+    const password = document.getElementById("pw").value;
+
+    const data = new FormData(); 
+    data.append('usuario', usuario);
+    data.append('password', password);
+
+    try {
+        
+        const respuestaPeticion = await fetch('controladores/login.php', {
+            method: 'POST',
+            body: data
+        });
+        const verificarCredenciales = await respuestaPeticion.json();
+        if (verificarCredenciales.loginExitoso) {
+            window.location.href = 'ventanaConciertos.html';
+        } else {
+            notificacion.textContent ="Usuario o contraseña incorrecta"; 
+            notificacion.style.color='#ffffff';
+        }
+    } catch (error) {
+        console.error(error);
+        notificacion.textContent = 'Lo sentimos, el servicio no está disponible por el momento.';
+        notificacion.style.color = '#ff0000';
+    }
+});
diff --git a/js/ventaBoletos.js b/js/ventaBoletos.js
new file mode 100644
index 0000000..957d44d
--- /dev/null
+++ b/js/ventaBoletos.js
@@ -0,0 +1,137 @@
+document.addEventListener("DOMContentLoaded", async () => {
+    const params = new URLSearchParams(window.location.search);
+    const conciertoId = params.get("id");
+
+    if (!conciertoId) {
+        console.error("Error: No se proporcionó un ID de concierto en la URL.");
+        return;
+    }
+
+    try {
+        const respuesta = await fetch(`controladores/concierto_zonas.php?id_concierto=${conciertoId}`);
+        if (!respuesta.ok) throw new Error("Error al cargar los datos del concierto");
+
+        const concierto = await respuesta.json();
+
+        if (concierto.error) {
+            console.error(`Error: ${concierto.error}`);
+            return;
+        }
+
+        // Mostrar información del concierto
+        document.getElementById("nombre_concierto").textContent = concierto.nombre_concierto;
+        document.getElementById("artista").textContent = `Artista: ${concierto.artista}`;
+        document.getElementById("fecha").textContent = `Fecha: ${concierto.fecha}`;
+
+        // Mostrar zonas del concierto
+        const zonasContainer = document.getElementById("zonas-container");
+        zonasContainer.innerHTML = "";
+
+        if (!concierto.zonas || concierto.zonas.length === 0) {
+            console.error("No se encontraron zonas para este concierto.");
+            return;
+        }
+
+        concierto.zonas.forEach(zona => {
+            const zonaBtn = document.createElement("button");
+            zonaBtn.classList.add("boton-zona");
+            zonaBtn.textContent = `Ver Zona ${zona.nombre_zona}`;
+            zonaBtn.dataset.idZona = zona.id_zona;
+
+            zonaBtn.addEventListener("click", () => cargarDatosZona(zona));
+
+            zonasContainer.appendChild(zonaBtn);
+        });
+
+    } catch (error) {
+        console.error("Error al obtener los datos del concierto:", error);
+    }
+});
+
+async function cargarDatosZona(zona) {
+    if (!zona) {
+        console.error("Error: Datos de zona no disponibles");
+        return;
+    }
+
+    // Mostrar información de la zona
+    document.getElementById("zonaNombre").textContent = `Zona: ${zona.nombre_zona || 'N/A'}`;
+    document.getElementById("zonaCapacidad").textContent = `Capacidad: ${zona.capacidad || 'N/A'}`;
+    document.getElementById("zonaPrecio").textContent = `Precio: $${zona.precio || 'N/A'}`;
+    document.getElementById("asientosDisponibles").textContent = `Disponibles: ${zona.asientos_disponibles ?? 0}`;
+    document.getElementById("asientosOcupados").textContent = `Ocupados: ${zona.asientos_ocupados ?? 0}`;
+
+    // Cargar los asientos disponibles
+    await cargarAsientos(zona.id_zona);
+}
+
+async function cargarAsientos(idZona) {
+    try {
+        const respuesta = await fetch(`controladores/obtener_asiento.php?id_zona=${idZona}`);
+        if (!respuesta.ok) throw new Error("Error al cargar los asientos");
+
+        const asientos = await respuesta.json();
+
+        const asientosContainer = document.getElementById("asientos-container");
+        asientosContainer.innerHTML = ""; // Limpiar antes de agregar nuevos
+
+        asientos.forEach(asiento => {
+            const asientoDiv = document.createElement("div");
+            asientoDiv.classList.add("asiento", asiento.estado);
+            asientoDiv.dataset.idAsiento = asiento.id_asiento;
+            asientoDiv.setAttribute("title", `Asiento #${asiento.id_asiento}`);
+
+            const icono = document.createElement("i");
+            icono.classList.add("bi", "bi-person-fill");
+
+            if (asiento.estado === "disponible") {
+                asientoDiv.appendChild(icono);
+                asientoDiv.addEventListener("click", () => seleccionarAsiento(asientoDiv, asiento.id_asiento));
+            } else {
+                icono.style.opacity = "0.3"; // Opacidad para los asientos ocupados
+                asientoDiv.appendChild(icono);
+            }
+
+            asientosContainer.appendChild(asientoDiv);
+        });
+
+    } catch (error) {
+        console.error("Error al obtener los asientos:", error);
+    }
+}
+
+const asientosSeleccionados = new Set();
+
+function seleccionarAsiento(elemento, idAsiento) {
+    if (asientosSeleccionados.has(idAsiento)) {
+        asientosSeleccionados.delete(idAsiento);
+        elemento.classList.remove("seleccionado");
+    } else {
+        asientosSeleccionados.add(idAsiento);
+        elemento.classList.add("seleccionado");
+    }
+
+    document.getElementById("comprarBoletos").disabled = asientosSeleccionados.size === 0;
+}
+
+document.getElementById("comprarBoletos").addEventListener("click", async () => {
+    if (asientosSeleccionados.size === 0) return;
+
+    try {
+        const respuesta = await fetch("controladores/comprar_asiento.php", {
+            method: "POST",
+            headers: { "Content-Type": "application/json" },
+            body: JSON.stringify({ asientos: Array.from(asientosSeleccionados) })
+        });
+
+        const resultado = await respuesta.json();
+        if (resultado.success) {
+            alert("Compra realizada con éxito.");
+            location.reload();
+        } else {
+            alert("Error al realizar la compra.");
+        }
+    } catch (error) {
+        console.error("Error al comprar boletos:", error);
+    }
+});
diff --git a/ventaBoletos.html b/ventaBoletos.html
new file mode 100644
index 0000000..33e5958
--- /dev/null
+++ b/ventaBoletos.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html lang="es">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Compra de Boletos</title>
+    <script src="https://cdn.tailwindcss.com"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
+    <link rel="stylesheet" href="css/conciertos.css"> 
+    <link rel="stylesheet" href="css/ventanaBoletos.css">
+    <link rel="stylesheet" 
+          href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css">
+</head>
+<body>
+    <nav>
+        <a href="ventanaInsertarConcierto.html" class="navbar-brand">TicketFei</a>
+        <div class="nav-links">
+            <a href="ventanaInsertarConcierto.html">Crear Conciertos</a>
+            <a href="ventanaConciertos.html">Ver Conciertos</a>
+            <a href="#">Reporte Ventas</a>
+        </div>
+    </nav>
+
+    <!-- Contenedor principal -->
+    <div class="main-container">
+        <div class="cardIzq">
+            <h2>Zonas del Concierto</h2>
+            <img src="img/mapa.png" alt="Mapa de zonas del concierto">
+            <div id="zonas-container" class="zones-container"></div>  
+        </div>
+
+        <!-- Lado derecho con tarjetas -->
+        <div class="cardDer">
+            <div class="card">
+                <h2 class="text-xl font-bold mb-4">Detalles del concierto</h2>
+                <div id="zona-info" class="space-y-2">
+                    <h2 id="nombre_concierto">Nombre del Concierto</h2>
+                    <p id="artista">Artista: </p>
+                    <p id="fecha">Fecha: </p>
+                    <h2 id="zonaNombre">Zona</h2>
+                    <p id="zonaCapacidad">Capacidad: </p>
+                    <p id="zonaPrecio">Precio: </p>
+                    <p id="asientosDisponibles">Disponibles: </p>
+                    <p id="asientosOcupados">Ocupados: </p>
+                </div>
+            </div>
+            <!-- Tarjeta para los asientos dentro de la columna derecha -->
+            <div class="card">  
+                <h2 class="text-xl font-bold mb-4">Asientos</h2>
+                <div id="asientos-container" class="asientos-container"></div> 
+            </div>
+
+        </div>
+    </div>
+
+    <!-- Contenedor del botón centrado en la parte inferior -->
+    <div class="button-container">
+        <button id="comprarBoletos" class="btn btn-primary" disabled>Comprar Asientos</button>
+    </div>
+
+    <script defer src="js/ventaBoletos.js"></script>
+</body>
+</html>
diff --git a/ventanaConciertos.html b/ventanaConciertos.html
new file mode 100644
index 0000000..bed880f
--- /dev/null
+++ b/ventanaConciertos.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html lang="es">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Registro de Conciertos</title>
+    <script src="https://cdn.tailwindcss.com"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
+    <link rel="stylesheet" href="css/conciertos.css">
+    <link rel="stylesheet" href="css/modalEliminar.css">
+</head>
+<body>
+
+    <nav>
+        <a href="ventanaConciertos.html" class="navbar-brand">TicketFei</a>
+        <div class="nav-links">
+            <a href="ventanaInsertarConcierto.html">Crear Conciertos</a>
+            <a href="ventanaConciertos.html">Ver Conciertos</a>
+            <a href="#">Reporte Ventas</a>
+        </div>
+        <div class="search-container">
+            <input type="search" id="buscadorColaborador" placeholder="Buscar...">
+            <button id="buscadorBoton">Buscar</button>
+        </div>
+    </nav>
+
+    <div id="listaConciertos"></div>
+
+    <!-- Modal de mensaje -->
+    <div id="modalMensaje" class="modal">
+        <div id="modalPanel" class="modal-contenido">
+            <p id="modalTexto"></p>
+            <button id="cerrarModal" class="btn-modal">Cerrar</button>
+        </div>
+    </div>
+
+    <!-- Modal de confirmación -->
+    <div id="modalConfirmacion" class="modal">
+        <div class="modal-contenido">
+            <p id="modalConfirmarTexto"></p>
+            <button id="btnCancelarEliminar" class="btn-modal">Cancelar</button>
+            <button id="btnConfirmarEliminar" class="btn-modal">Eliminar</button>
+        </div>
+    </div>
+
+    <script src="js/conciertos.js"></script>
+
+</body>
+</html>
diff --git a/ventanaInsertarConcierto.html b/ventanaInsertarConcierto.html
new file mode 100644
index 0000000..9685751
--- /dev/null
+++ b/ventanaInsertarConcierto.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<html lang="es">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Registrar Concierto</title>
+    <link rel="stylesheet" href="css/conciertos.css">
+    <link rel="stylesheet" href="css/formulario.css">
+</head>
+<body>
+
+    <!-- Navbar -->
+    <nav>
+        <a href="ventanaInsertarConcierto.html" class="navbar-brand">TicketFei</a>
+        <div class="nav-links">
+            <a href="ventanaInsertarConcierto.html">Crear Conciertos</a>
+            <a href="ventanaConciertos.html">Ver Conciertos</a>
+            <a href="#">Reporte Ventas</a>
+        </div>
+    </nav>
+
+    <!-- Contenedor -->
+    <div class="container">
+        <h2 class="text-center">Registrar Concierto</h2>
+        <form id="formulario">
+
+            <!-- Paso 1: Datos generales -->
+            <div id="paso1">
+                <div class="mb-3">
+                    <label for="nombre_concierto">Nombre del Concierto:</label>
+                    <input type="text" id="nombre_concierto" required>
+                </div>
+                <div class="mb-3">
+                    <label for="artista">Artista:</label>
+                    <input type="text" id="artista" required>
+                </div>
+                <div class="mb-3">
+                    <label for="fecha">Fecha del Concierto:</label>
+                    <input type="date" id="fecha" required>
+                </div>
+                <button type="button" class="btn next-btn" onclick="siguientePaso(2)">Siguiente</button>
+            </div>
+
+            <!-- Paso 2: Dirección -->
+            <div id="paso2" class="d-none">
+                <div class="mb-3">
+                    <label for="calle">Calle:</label>
+                    <input type="text" id="calle" required>
+                </div>
+                <div class="mb-3">
+                    <label for="colonia">Colonia:</label>
+                    <input type="text" id="colonia" required>
+                </div>
+                <div class="mb-3">
+                    <label for="numero_direccion">Número exterior:</label>
+                    <input type="text" id="numero_direccion" required>
+                </div>
+                <div class="mb-3">
+                    <label for="codigo_postal">Código Postal:</label>
+                    <input type="text" id="codigo_postal" required>
+                </div>
+                <div class="mb-3">
+                    <label for="estado">Estado:</label>
+                    <input type="text" id="estado" required>
+                </div>
+                <div class="mb-3">
+                    <label for="capacidad_total">Capacidad Total:</label>
+                    <input type="number" id="capacidad_total" required>
+                </div>
+                <button type="button" class="btn prev-btn" onclick="siguientePaso(1)">Anterior</button>
+                <button type="button" class="btn next-btn" onclick="siguientePaso(3)">Siguiente</button>
+            </div>
+
+            <!-- Paso 3: Zonas -->
+            <div id="paso3" class="d-none">
+                <fieldset>
+                    <legend>Zonas</legend>
+                    
+
+                    <div class="mb-3">
+                        <label>Zona General - Capacidad:</label>
+                        <input type="number" id="capacidad_general" required oninput="actualizarCapacidad()">
+                        <label>Precio:</label>
+                        <input type="number" step="0.01" id="precio_general" required>
+                    </div>
+
+                    <div class="mb-3">
+                        <label>Zona Plata - Capacidad:</label>
+                        <input type="number" id="capacidad_plata" required oninput="actualizarCapacidad()">
+                        <label>Precio:</label>
+                        <input type="number" step="0.01" id="precio_plata" required>
+                    </div>
+
+                    <div class="mb-3">
+                        <label>Zona Oro - Capacidad:</label>
+                        <input type="number" id="capacidad_oro" required oninput="actualizarCapacidad()">
+                        <label>Precio:</label>
+                        <input type="number" step="0.01" id="precio_oro" required>
+                    </div>
+
+                    <div class="mb-3">
+                        <label>Zona VIP - Capacidad:</label>
+                        <input type="number" id="capacidad_vip" required oninput="actualizarCapacidad()">
+                        <label>Precio:</label>
+                        <input type="number" step="0.01" id="precio_vip" required>
+                    </div>
+                </fieldset>
+                <button type="button" class="btn prev-btn" onclick="siguientePaso(2)">Anterior</button>
+                <button type="submit" class="btn submit-btn">Crear Concierto</button>
+            </div>
+        </form>
+        <div id="mensaje" class="mt-3 text-center"></div>
+    </div>
+
+    <script src="js/crearConciertos.js"></script>
+</body>
+</html>