Detalles finales y reporte de ventas

This commit is contained in:
alexis.palestina 2025-03-13 10:44:40 -06:00
parent cc71079a85
commit 2f4d1892f7
22 changed files with 295 additions and 76 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 {

50
css/reporte_ventas.css Normal file
View File

@ -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;
}

View File

@ -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;
}

BIN
img/1741881316_cerati.jpg Normal file

Binary file not shown.

After

(image error) Size: 159 KiB

Binary file not shown.

After

(image error) Size: 83 KiB

Binary file not shown.

After

(image error) Size: 52 KiB

Binary file not shown.

After

(image error) Size: 12 KiB

Binary file not shown.

After

(image error) Size: 31 KiB

View File

@ -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));
});

View File

@ -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
}

View File

@ -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";
});

43
js/reporte_ventas.js Normal file
View File

@ -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}`;
});

View File

@ -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));
});

33
php/exportar_csv.php Normal file
View File

@ -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);
?>

28
php/reporte_ventas.php Normal file
View File

@ -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);
?>

View File

@ -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>

View File

@ -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>

View File

@ -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">&#10094;</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">&#10095;</button>
</div>
</body>

47
views/reporte_ventas.html Normal file
View File

@ -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>

View File

@ -9,8 +9,6 @@
</head>
<body>
<a href="index.html" class="btn-volver">← Volver</a>
<div class="container">
<h1>Venta de Boletos</h1>