diff --git a/css/agregar_evento.css b/css/agregar_evento.css index 15ea19a..5aa9140 100644 --- a/css/agregar_evento.css +++ b/css/agregar_evento.css @@ -63,3 +63,19 @@ button:hover { font-weight: bold; color: #333; } + +/* 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 index 9e7546f..ada67a5 100644 --- a/css/editar_evento.css +++ b/css/editar_evento.css @@ -46,3 +46,19 @@ button { button:hover { background-color: #005f7f; } + +/* 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/estilos.css b/css/estilos.css index 1756232..99eed55 100644 --- a/css/estilos.css +++ b/css/estilos.css @@ -4,6 +4,7 @@ body { margin: 0; padding: 0; background-color: #f4f4f4; + overflow-x: hidden; } /* Estilos del encabezado */ @@ -35,44 +36,36 @@ nav a:hover { /* Carrusel de conciertos */ .contenedor-principal { display: flex; - align-items: center; justify-content: center; - position: relative; - width: 90%; - margin: 20px auto; - background-color: #eeeeee; + width: 100%; + background: #eeeeee; padding: 20px; border-radius: 10px; } -/* Botones de desplazamiento */ -.flecha-izquierda, .flecha-derecha { - background-color: rgba(0, 0, 0, 0.5); - color: white; - border: none; - padding: 10px; - font-size: 20px; - cursor: pointer; - position: absolute; - top: 50%; - transform: translateY(-50%); -} - -.flecha-izquierda { left: 10px; } -.flecha-derecha { right: 10px; } - -.flecha-izquierda:hover, .flecha-derecha:hover { - background-color: rgba(0, 0, 0, 0.8); -} - -/* Contenedor de conciertos */ +/* Contenedor de conciertos con scroll horizontal */ .contenedor-conciertos { display: flex; - overflow-x: auto; - white-space: nowrap; + gap: 20px; + overflow-x: auto; /* Habilitar desplazamiento horizontal */ scroll-behavior: smooth; + white-space: nowrap; /* Evitar que los conciertos se apilen verticalmente */ padding: 10px; - width: 80%; + width: 90%; +} + +/* Estilo del scrollbar en navegadores modernos */ +.contenedor-conciertos::-webkit-scrollbar { + height: 8px; +} + +.contenedor-conciertos::-webkit-scrollbar-thumb { + background: #008cba; + border-radius: 5px; +} + +.contenedor-conciertos::-webkit-scrollbar-track { + background: #f4f4f4; } /* Tarjetas de concierto */ @@ -82,7 +75,6 @@ nav a:hover { box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.2); text-align: center; width: 250px; - margin: 0 10px; display: inline-block; padding: 15px; } @@ -90,8 +82,8 @@ nav a:hover { .concierto img { width: 100%; height: 150px; - border-radius: 10px; object-fit: cover; + border-radius: 5px; } .concierto h2 { @@ -109,7 +101,6 @@ nav a:hover { background-color: #008cba; color: white; padding: 10px 15px; - text-decoration: none; border: none; border-radius: 5px; font-weight: bold; @@ -120,7 +111,7 @@ nav a:hover { background-color: #005f7f; } -/* Botón Volver */ +/* Botón de volver */ .boton-volver { display: inline-block; margin-top: 20px; @@ -130,7 +121,6 @@ nav a:hover { text-decoration: none; font-weight: bold; border-radius: 5px; - transition: background 0.3s ease; } .boton-volver:hover { diff --git a/css/reporte_ventas.css b/css/reporte_ventas.css new file mode 100644 index 0000000..82ceb56 --- /dev/null +++ b/css/reporte_ventas.css @@ -0,0 +1,50 @@ +body { + font-family: Arial, sans-serif; + background-color: #f4f4f4; + text-align: center; +} + +h1 { + color: #333; +} + +table { + width: 90%; + margin: 20px auto; + border-collapse: collapse; +} + +th, td { + border: 1px solid #ddd; + padding: 10px; + text-align: center; +} + +th { + background-color: #008cba; + color: white; +} + +button { + padding: 10px 15px; + background: #008cba; + color: white; + border: none; + cursor: pointer; +} + +/* 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/venta_boletos.css b/css/venta_boletos.css index 76040cb..66ed72b 100644 --- a/css/venta_boletos.css +++ b/css/venta_boletos.css @@ -125,3 +125,19 @@ button { button:hover { background-color: #005f7f; } + +/* 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/img/1741881316_cerati.jpg b/img/1741881316_cerati.jpg new file mode 100644 index 0000000..d8c7fbb Binary files /dev/null and b/img/1741881316_cerati.jpg differ diff --git a/img/1741882321_67d303d1bc254.jpeg b/img/1741882321_67d303d1bc254.jpeg new file mode 100644 index 0000000..54ddd91 Binary files /dev/null and b/img/1741882321_67d303d1bc254.jpeg differ diff --git a/img/1741882562_67d304c22bf7e.jpg b/img/1741882562_67d304c22bf7e.jpg new file mode 100644 index 0000000..e9fe137 Binary files /dev/null and b/img/1741882562_67d304c22bf7e.jpg differ diff --git a/img/1741882756_67d305841fb3b.jpeg b/img/1741882756_67d305841fb3b.jpeg new file mode 100644 index 0000000..714e071 Binary files /dev/null and b/img/1741882756_67d305841fb3b.jpeg differ diff --git a/img/1741884055_67d30a97eac0e.jpeg b/img/1741884055_67d30a97eac0e.jpeg new file mode 100644 index 0000000..5a17580 Binary files /dev/null and b/img/1741884055_67d30a97eac0e.jpeg differ diff --git a/js/agregar_evento.js b/js/agregar_evento.js index b0057bc..42309aa 100644 --- a/js/agregar_evento.js +++ b/js/agregar_evento.js @@ -3,20 +3,15 @@ document.getElementById("formConcierto").addEventListener("submit", function(e) 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 + method: "POST", body: formData }) .then(response => response.text()) .then(data => { console.log("Respuesta del servidor:", data); - alert(data); // Mensaje de éxito o error this.reset(); + window.location.href = "../views/index.html"; // Redirigir al inicio sin alert }) .catch(error => console.error("Error:", error)); }); diff --git a/js/conciertos.js b/js/conciertos.js index 7f733ac..4767f1a 100644 --- a/js/conciertos.js +++ b/js/conciertos.js @@ -23,6 +23,8 @@ document.addEventListener("DOMContentLoaded", function() { `; div.appendChild(evento); }); + + configurarScroll(); }) .catch(error => console.error("Error cargando conciertos:", error)); }); @@ -31,3 +33,10 @@ document.addEventListener("DOMContentLoaded", function() { function comprarBoletos(conciertoId) { window.location.href = `venta_boletos.html?concierto_id=${conciertoId}`; } + +// Configurar la barra de desplazamiento +function configurarScroll() { + const container = document.getElementById("conciertos"); + container.style.overflowX = "auto"; // Habilitar desplazamiento horizontal + container.style.whiteSpace = "nowrap"; // Asegurar que los elementos estén en línea +} diff --git a/js/editar_evento.js b/js/editar_evento.js index 60af9be..82d57a0 100644 --- a/js/editar_evento.js +++ b/js/editar_evento.js @@ -2,7 +2,6 @@ document.addEventListener("DOMContentLoaded", function() { cargarEventos(); }); -// 🔹 Cargar eventos en el desplegable function cargarEventos() { fetch("../php/obtener_conciertos.php") .then(response => response.json()) @@ -17,7 +16,6 @@ function cargarEventos() { select.appendChild(option); }); - // Evento para cargar detalles cuando se seleccione un evento select.addEventListener("change", function() { cargarDatosEvento(select.value); }); @@ -25,7 +23,6 @@ function cargarEventos() { .catch(error => console.error("Error cargando conciertos:", error)); } -// 🔹 Cargar los detalles del evento seleccionado function cargarDatosEvento(eventoId) { if (!eventoId) return; @@ -43,7 +40,6 @@ function cargarDatosEvento(eventoId) { .catch(error => console.error("Error cargando detalles del evento:", error)); } -// 🔹 Guardar cambios al hacer submit document.getElementById("formEditarEvento").addEventListener("submit", function(e) { e.preventDefault(); @@ -54,14 +50,12 @@ document.getElementById("formEditarEvento").addEventListener("submit", function( body: formData }) .then(response => response.text()) - .then(data => { - alert(data); - cargarEventos(); // Recargar la lista de eventos + .then(() => { + window.location.href = "../views/index.html"; // Redirigir sin alert }) .catch(error => console.error("Error:", error)); }); -// 🔹 Eliminar evento document.getElementById("btnEliminar").addEventListener("click", function() { let eventoId = document.getElementById("eventoSeleccionado").value; @@ -80,14 +74,12 @@ document.getElementById("btnEliminar").addEventListener("click", function() { headers: { "Content-Type": "application/json" } }) .then(response => response.text()) - .then(data => { - alert(data); - cargarEventos(); // Recargar la lista de eventos + .then(() => { + window.location.href = "../views/index.html"; // Redirigir sin alert }) .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/reporte_ventas.js b/js/reporte_ventas.js new file mode 100644 index 0000000..c4ab0fa --- /dev/null +++ b/js/reporte_ventas.js @@ -0,0 +1,43 @@ +document.getElementById("generarReporte").addEventListener("click", function() { + let fechaInicio = document.getElementById("fechaInicio").value; + let fechaFin = document.getElementById("fechaFin").value; + + if (!fechaInicio || !fechaFin) { + alert("Por favor, selecciona un período de fechas."); + return; + } + + fetch(`../php/reporte_ventas.php?fechaInicio=${fechaInicio}&fechaFin=${fechaFin}`) + .then(response => response.json()) + .then(data => { + let tabla = document.getElementById("tablaReporte"); + tabla.innerHTML = ""; // Limpiar datos previos + + data.forEach(venta => { + let row = `<tr> + <td>${venta.id}</td> + <td>${venta.concierto}</td> + <td>${venta.fecha}</td> + <td>${venta.hora}</td> + <td>${venta.zona}</td> + <td>${venta.asiento}</td> + <td>$${parseFloat(venta.precio).toFixed(2)}</td> + <td>${venta.fecha_venta}</td> + </tr>`; + tabla.innerHTML += row; + }); + }) + .catch(error => console.error("Error cargando el reporte:", error)); +}); + +document.getElementById("exportarCSV").addEventListener("click", function() { + let fechaInicio = document.getElementById("fechaInicio").value; + let fechaFin = document.getElementById("fechaFin").value; + + if (!fechaInicio || !fechaFin) { + alert("Por favor, selecciona un período de fechas."); + return; + } + + window.location.href = `../php/exportar_csv.php?fechaInicio=${fechaInicio}&fechaFin=${fechaFin}`; +}); diff --git a/js/venta_boletos.js b/js/venta_boletos.js index fed4a0c..f0d6452 100644 --- a/js/venta_boletos.js +++ b/js/venta_boletos.js @@ -27,9 +27,6 @@ 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; @@ -93,13 +90,9 @@ document.getElementById("confirmarCompra").addEventListener("click", function() }) .then(response => response.json()) .then(data => { - if (data.error) { - alert("Error: " + data.error); - } else { - alert("Compra realizada con éxito."); + if (!data.error) { window.location.href = `../php/comprobante.php?transaction_id=${data.transaction_id}`; } }) .catch(error => console.error("Error al comprar boletos:", error)); }); - diff --git a/php/exportar_csv.php b/php/exportar_csv.php new file mode 100644 index 0000000..5336960 --- /dev/null +++ b/php/exportar_csv.php @@ -0,0 +1,33 @@ +<?php +include 'conexion.php'; + +$fechaInicio = $_GET['fechaInicio'] ?? null; +$fechaFin = $_GET['fechaFin'] ?? null; + +if (!$fechaInicio || !$fechaFin) { + die("Debe seleccionar un período de fechas."); +} + +header('Content-Type: text/csv; charset=utf-8'); +header('Content-Disposition: attachment; filename=reporte_ventas.csv'); + +$output = fopen("php://output", "w"); +fputcsv($output, ['ID', 'Concierto', 'Fecha', 'Hora', 'Zona', 'Asiento', 'Precio', 'Fecha Venta']); + +$sql = "SELECT b.id, c.nombre AS concierto, c.fecha, c.hora, z.nombre AS zona, a.numero AS asiento, b.precio, b.fecha_venta + 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 DATE(b.fecha_venta) BETWEEN ? AND ?"; +$stmt = $conn->prepare($sql); +$stmt->bind_param("ss", $fechaInicio, $fechaFin); +$stmt->execute(); +$result = $stmt->get_result(); + +while ($row = $result->fetch_assoc()) { + fputcsv($output, $row); +} + +fclose($output); +?> diff --git a/php/reporte_ventas.php b/php/reporte_ventas.php new file mode 100644 index 0000000..3ea9ead --- /dev/null +++ b/php/reporte_ventas.php @@ -0,0 +1,28 @@ +<?php +include 'conexion.php'; + +$fechaInicio = $_GET['fechaInicio'] ?? null; +$fechaFin = $_GET['fechaFin'] ?? null; + +if (!$fechaInicio || !$fechaFin) { + die(json_encode(["error" => "Debe seleccionar un período de fechas."])); +} + +$sql = "SELECT b.id, c.nombre AS concierto, c.fecha, c.hora, z.nombre AS zona, a.numero AS asiento, b.precio, b.fecha_venta + 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 DATE(b.fecha_venta) BETWEEN ? AND ?"; +$stmt = $conn->prepare($sql); +$stmt->bind_param("ss", $fechaInicio, $fechaFin); +$stmt->execute(); +$result = $stmt->get_result(); + +$ventas = []; +while ($row = $result->fetch_assoc()) { + $ventas[] = $row; +} + +echo json_encode($ventas); +?> diff --git a/views/agregar_evento.html b/views/agregar_evento.html index 5f8e933..b5c8a02 100644 --- a/views/agregar_evento.html +++ b/views/agregar_evento.html @@ -50,14 +50,12 @@ </div> <button type="submit">Agregar Concierto</button> + <a href="../views/index.html" class="boton-volver">Volver</a> </form> <div id="mensaje"></div> <script src="../js/agregar_evento.js"></script> - - <a href="../views/index.html" class="boton-volver">Volver</a> - </body> </html> diff --git a/views/editar_evento.html b/views/editar_evento.html index 255e4cb..eb76038 100644 --- a/views/editar_evento.html +++ b/views/editar_evento.html @@ -8,8 +8,6 @@ </head> <body> - <a href="index.html" class="btn-volver">← Volver</a> - <h1>Editar Evento</h1> <form id="formEditarEvento" enctype="multipart/form-data"> @@ -39,18 +37,17 @@ <label>Precio General:</label> <input type="number" name="precio_general" min="0" step="0.01" required> - <label>Nueva Imagen (opcional):</label> + <label>Nueva Imagen:</label> <input type="file" name="imagen" accept="image/*"> <button type="submit">Actualizar Concierto</button> <button type="button" id="btnEliminar">Eliminar Concierto</button> + <a href="../views/index.html" class="boton-volver">Volver</a> </form> <div id="mensaje"></div> <script src="../js/editar_evento.js"></script> - <a href="../views/index.html" class="boton-volver">Volver</a> - </body> </html> diff --git a/views/index.html b/views/index.html index 8f97f4a..e480ecc 100644 --- a/views/index.html +++ b/views/index.html @@ -12,19 +12,17 @@ <header> <h1>BoleTC</h1> <nav> + <a href="venta_boletos.html">Comprar Boletos</a> <a href="agregar_evento.html">Agregar Evento</a> <a href="editar_evento.html">Editar Evento</a> + <a href="reporte_ventas.html">Reporte Ventas</a> </nav> </header> <div class="contenedor-principal"> - <button class="flecha-izquierda">❮</button> - <div class="contenedor-conciertos" id="conciertos"> - <!-- Aquí se cargarán los conciertos dinámicamente --> + <!-- Los conciertos se cargarán aquí dinámicamente --> </div> - - <button class="flecha-derecha">❯</button> </div> </body> diff --git a/views/reporte_ventas.html b/views/reporte_ventas.html new file mode 100644 index 0000000..77c3524 --- /dev/null +++ b/views/reporte_ventas.html @@ -0,0 +1,47 @@ +<!DOCTYPE html> +<html lang="es"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Reporte de Ventas - BoleTC</title> + <link rel="stylesheet" href="../css/reporte_ventas.css"> +</head> +<body> + + <h1>Reporte de Ventas</h1> + + <label for="fechaInicio">Fecha de Inicio:</label> + <input type="date" id="fechaInicio"> + + <label for="fechaFin">Fecha Fin:</label> + <input type="date" id="fechaFin"> + + <button id="generarReporte">Generar Reporte</button> + <button id="exportarCSV">Exportar a CSV</button> + + <div id="reporteContainer"> + <table> + <thead> + <tr> + <th>ID</th> + <th>Concierto</th> + <th>Fecha</th> + <th>Hora</th> + <th>Zona</th> + <th>Asiento</th> + <th>Precio</th> + <th>Fecha Venta</th> + </tr> + </thead> + <tbody id="tablaReporte"> + <!-- Los datos se insertarán aquí con JavaScript --> + </tbody> + </table> + </div> + + <button onclick="window.location.href='index.html'">Volver</button> + + <script src="../js/reporte_ventas.js"></script> + +</body> +</html> diff --git a/views/venta_boletos.html b/views/venta_boletos.html index fc5d8b2..2988aed 100644 --- a/views/venta_boletos.html +++ b/views/venta_boletos.html @@ -9,8 +9,6 @@ </head> <body> - <a href="index.html" class="btn-volver">← Volver</a> - <div class="container"> <h1>Venta de Boletos</h1>