// Estado global de la reserva let estadoReserva = { tipoCancha: null, fecha: null, horario: null, numeroCancha: null, quincho: false, descuento: 0, cuponeado: false, reservasRestantes: null, cantidadReservas: 0, umbral: 0 }; // Obtener datos de las canchas al cargar let datoscCanchas = { futbol: null, padel: null, quincho: null }; // Variable global para guardar el código de WhatsApp temporalmente let codigoCorrecto = null; // Cargar datos de las canchas desde la base de datos async function cargarDatosCanchas() { try { const response = await fetch('../php/Obtener_Canchas.php'); const data = await response.json(); console.log('Datos recibidos de Obtener_Canchas.php:', data); const canchas = Array.isArray(data) ? data : (data && Array.isArray(data.canchas) ? data.canchas : []); if (!canchas.length) { console.warn('No se recibieron canchas válidas desde el servidor:', data); return; } canchas.forEach(cancha => { const rawTipo = String(cancha.Tipo ?? cancha.tipo ?? '').trim().toUpperCase(); const tipo = rawTipo === 'F' || rawTipo === 'FUTBOL' ? 'F' : rawTipo === 'P' || rawTipo === 'PADEL' ? 'P' : rawTipo === 'Q' || rawTipo === 'QUINCHO' ? 'Q' : null; if (!tipo) { console.warn('Tipo de cancha desconocido en la respuesta:', rawTipo, cancha); return; } const duracion = parseInt(cancha.Duracion ?? cancha.duracion, 10) || 0; const precio = parseFloat(cancha.Precio ?? cancha.precio_venta ?? cancha.precio) || 0; const apertura = cancha.Hora_Apertura ?? cancha.apertura ?? null; const cierre = cancha.Hora_Cierre ?? cancha.cierre ?? null; const cantidad = parseInt(cancha.Cant_Canchas ?? cancha.cantidad, 10) || 0; const reservas = parseInt(cancha.Cant_Reservas_Cupon ?? cancha.reservas, 10) || 0; const descuento = parseFloat(cancha.Descuento_Cupon ?? cancha.descuento_cupon) || 0; const maxFaltas = parseInt(cancha.Cant_Faltas ?? cancha.cant_faltas, 10) || 0; const duracionCupon = parseInt(cancha.Duracion_Cupon ?? cancha.duracion_cupon, 10) || 0; if (tipo === 'F') { datoscCanchas.futbol = { duracion, precio, apertura, cierre, cantidad, reservasParaCupon: reservas, descuentoCupon: descuento, maxFaltas, duracionCupon }; } else if (tipo === 'P') { datoscCanchas.padel = { duracion, precio, apertura, cierre, cantidad, reservasParaCupon: reservas, descuentoCupon: descuento, maxFaltas, duracionCupon }; } else if (tipo === 'Q') { datoscCanchas.quincho = { precio, reservasMax: reservas }; } }); console.log('Datos de canchas cargados:', datoscCanchas); } catch (error) { console.error('Error al cargar datos de canchas desde BD:', error); } } // Inicializar la interfaz function inicializarReserva() { const botonesCancha = document.querySelectorAll('.btn-cancha-tipo'); botonesCancha.forEach(btn => { btn.addEventListener('click', (e) => { botonesCancha.forEach(b => b.classList.remove('activo')); btn.classList.add('activo'); estadoReserva.tipoCancha = btn.dataset.tipo; estadoReserva.fecha = null; estadoReserva.horario = null; document.querySelector('.selector-fecha').style.display = 'block'; document.querySelector('.selector-horario').style.display = 'none'; document.querySelector('.datos-cliente').style.display = 'none'; document.querySelector('.resumen-reserva').style.display = 'none'; generarDiasDisponibles(); }); }); // Botón volver document.querySelector('.btn-volver').addEventListener('click', () => { document.querySelector('.resumen-reserva').style.display = 'none'; }); // --- LÓGICA DE DATOS DEL CLIENTE --- document.querySelector('.btn-verificar').addEventListener('click', async () => { const nombre = document.getElementById('cliente-nombre').value.trim(); const telefono = document.getElementById('cliente-telefono').value.trim(); const dni = document.getElementById('cliente-dni').value.trim(); if (!nombre || !telefono || !dni) { alert('Por favor completa todos tus datos antes de continuar'); return; } if (!estadoReserva.numeroCancha) { alert('Selecciona primero el número de cancha disponible.'); return; } await obtenerEstadoCupon(dni, estadoReserva.tipoCancha); actualizarResumen(); document.querySelector('.resumen-reserva').style.display = 'block'; }); // Botón "Confirmar Reserva" (Pide el código) const btnSolicitar = document.getElementById('btn-solicitar-reserva'); if (btnSolicitar) { btnSolicitar.addEventListener('click', async () => { await solicitarCodigoWhatsApp(); }); } // Botón "Validar y Reservar" (Verifica el código) const btnVerificarWA = document.getElementById('btn-verificar-codigo'); if (btnVerificarWA) { btnVerificarWA.addEventListener('click', async () => { const codigoIngresado = document.getElementById('codigo-verificacion').value; if (codigoIngresado === codigoCorrecto) { await guardarReservaFinal(); } else { alert("Código incorrecto. Por favor, inténtelo de nuevo."); } }); } // Checkbox quincho document.getElementById('incluir-quincho').addEventListener('change', (e) => { estadoReserva.quincho = e.target.checked; const precioQuincho = datoscCanchas.quincho?.precio || 0; if (e.target.checked && precioQuincho > 0) { document.querySelector('.precio-quincho').style.display = 'inline-block'; document.getElementById('quincho-reservas').style.display = 'block'; document.getElementById('precio-quincho-val').textContent = precioQuincho.toFixed(2); } else { estadoReserva.quincho = false; document.querySelector('.precio-quincho').style.display = 'none'; document.getElementById('quincho-reservas').style.display = 'none'; e.target.checked = false; } actualizarPrecioTotal(); }); const formComprobante = document.getElementById('form-comprobante'); if (formComprobante) { formComprobante.addEventListener('submit', async (e) => { e.preventDefault(); await enviarComprobantePago(); }); } } // Generar días disponibles function generarDiasDisponibles() { const contenedor = document.getElementById('dias-disponibles'); contenedor.innerHTML = ''; const hoy = new Date(); const diasSemana = ['Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sab']; for (let i = 0; i < 7; i++) { const fecha = new Date(hoy); fecha.setDate(fecha.getDate() + i); const btn = document.createElement('button'); btn.type = 'button'; btn.className = 'btn-dia'; btn.innerHTML = `
${diasSemana[fecha.getDay()]}
${fecha.getDate()}/${fecha.getMonth() + 1}
`; btn.dataset.fecha = fecha.toISOString().split('T')[0]; btn.addEventListener('click', async () => { document.querySelectorAll('.btn-dia').forEach(b => b.classList.remove('activo')); btn.classList.add('activo'); estadoReserva.fecha = btn.dataset.fecha; estadoReserva.horario = null; generarHorarios(); await actualizarDisponibilidadQuincho(btn.dataset.fecha); document.querySelector('.selector-horario').style.display = 'block'; document.querySelector('.datos-cliente').style.display = 'none'; document.querySelector('.resumen-reserva').style.display = 'none'; }); contenedor.appendChild(btn); } } // Obtener disponibilidad de quinchos async function obtenerDisponibilidadQuincho(fecha) { try { const response = await fetch(`../php/Obtener_Disponibilidad_Quincho.php?fecha=${fecha}`); const data = await response.json(); return data.success ? data.disponibles : 0; } catch (error) { return 0; } } // Actualizar disponibilidad de quincho en UI async function actualizarDisponibilidadQuincho(fecha) { const disponibles = await obtenerDisponibilidadQuincho(fecha); const checkboxQuincho = document.getElementById('incluir-quincho'); const quinchoInfo = document.getElementById('quincho-reservas'); const quinchoAlerta = document.getElementById('quincho-no-disponible'); document.getElementById('quincho-disp').textContent = disponibles; if (disponibles === 0) { checkboxQuincho.disabled = true; checkboxQuincho.checked = false; estadoReserva.quincho = false; quinchoInfo.style.display = 'none'; quinchoAlerta.style.display = 'block'; document.querySelector('.precio-quincho').style.display = 'none'; } else { checkboxQuincho.disabled = false; quinchoAlerta.style.display = 'none'; quinchoInfo.style.display = 'block'; } actualizarPrecioTotal(); } // Obtener disponibilidad de cancha async function obtenerDisponibilidadCancha(fecha, horario, duracion, tipo) { try { const response = await fetch(`../php/Obtener_Disponibilidad_Cancha.php?fecha=${fecha}&horario=${horario}&duracion=${duracion}&tipo=${tipo === 'futbol' ? 'F' : 'P'}`); const data = await response.json(); return data.success ? data.disponibles : 0; } catch (error) { return 0; } } // Obtener números de canchas async function obtenerNumerosCanchas(fecha, horario, duracion, tipo) { try { const response = await fetch(`../php/Obtener_Canchas_Numeros.php?fecha=${fecha}&horario=${horario}&duracion=${duracion}&tipo=${tipo === 'futbol' ? 'F' : 'P'}`); const data = await response.json(); return data.success ? data.canchas : []; } catch (error) { return []; } } // Generar selección de número de cancha async function generarSeleccionNumeroCancha(horarioInicio) { const contenedor = document.getElementById('botones-canchas-numeros'); contenedor.innerHTML = ''; const tipo = estadoReserva.tipoCancha; const canchas = await obtenerNumerosCanchas(estadoReserva.fecha, horarioInicio, datoscCanchas[tipo].duracion, tipo); canchas.forEach(cancha => { const btn = document.createElement('button'); btn.type = 'button'; btn.className = 'btn-numero-cancha'; btn.textContent = `Cancha ${cancha.numero}`; btn.dataset.numero = cancha.numero; if (!cancha.disponible) { btn.disabled = true; btn.classList.add('no-disponible'); btn.style.opacity = '0.5'; btn.style.cursor = 'not-allowed'; } else { btn.addEventListener('click', () => { document.querySelectorAll('.btn-numero-cancha').forEach(b => b.classList.remove('activo')); btn.classList.add('activo'); estadoReserva.numeroCancha = cancha.numero; document.querySelector('.datos-cliente').style.display = 'block'; }); } contenedor.appendChild(btn); }); } // Generar horarios async function generarHorarios() { const contenedor = document.getElementById('grid-horarios'); contenedor.innerHTML = ''; const tipo = estadoReserva.tipoCancha; const datos = datoscCanchas[tipo]; if (!datos || typeof datos.duracion !== 'number' || !datos.apertura || !datos.cierre) { console.error('No hay datos de configuración válidos para la cancha seleccionada:', tipo, datos); alert('Error al cargar los horarios. Revisa la configuración de la cancha.'); return; } const duracion = datos.duracion; const [aperturaH, aperturaM] = datos.apertura.split(':').map(Number); const [cierreH, cierreM] = datos.cierre.split(':').map(Number); const aperturaTotalMin = aperturaH * 60 + aperturaM; const cierreTotalMin = cierreH * 60 + cierreM; const ahora = new Date(); const [selYear, selMonth, selDay] = estadoReserva.fecha.split('-').map(Number); const fechaSeleccionada = new Date(selYear, selMonth - 1, selDay); const hoy = new Date(ahora.getFullYear(), ahora.getMonth(), ahora.getDate()); const fechaSelSoloFecha = new Date(fechaSeleccionada.getFullYear(), fechaSeleccionada.getMonth(), fechaSeleccionada.getDate()); const esHoy = fechaSelSoloFecha.getTime() === hoy.getTime(); const minutoActual = ahora.getHours() * 60 + ahora.getMinutes(); let horaActualMin = aperturaTotalMin; const horarios = []; while (horaActualMin + duracion <= cierreTotalMin) { const horas = Math.floor(horaActualMin / 60); const minutos = horaActualMin % 60; const horaFin = Math.floor((horaActualMin + duracion) / 60); const minutesFin = (horaActualMin + duracion) % 60; horarios.push({ inicio: `${String(horas).padStart(2, '0')}:${String(minutos).padStart(2, '0')}`, fin: `${String(horaFin).padStart(2, '0')}:${String(minutesFin).padStart(2, '0')}`, minutos: horaActualMin }); horaActualMin += duracion; } for (const horario of horarios) { const btn = document.createElement('button'); btn.type = 'button'; btn.className = 'horario-slot'; btn.textContent = `${horario.inicio}\n-\n${horario.fin}`; const inicioArr = horario.inicio.split(':').map(Number); const inicioMin = inicioArr[0] * 60 + inicioArr[1]; const esPasado = fechaSelSoloFecha.getTime() < hoy.getTime() || (esHoy && inicioMin < minutoActual); let disponibles = 0; if (!esPasado) { disponibles = await obtenerDisponibilidadCancha(estadoReserva.fecha, genericNormalizeTipo(horario.inicio), duracion, tipo); } if (esPasado || disponibles === 0) { btn.disabled = true; btn.classList.add('no-disponible'); btn.style.opacity = '0.5'; btn.style.cursor = 'not-allowed'; } else { btn.addEventListener('click', async () => { document.querySelectorAll('.horario-slot').forEach(b => b.classList.remove('activo')); btn.classList.add('activo'); estadoReserva.horario = `${horario.inicio} - ${horario.fin}`; estadoReserva.numeroCancha = null; document.getElementById('incluir-quincho').checked = false; estadoReserva.quincho = false; document.querySelector('.precio-quincho').style.display = 'none'; document.getElementById('quincho-reservas').style.display = 'none'; await generarSeleccionNumeroCancha(horario.inicio); document.querySelector('.selector-numero-cancha').style.display = 'block'; document.querySelector('.datos-cliente').style.display = 'none'; document.querySelector('.resumen-reserva').style.display = 'none'; }); } contenedor.appendChild(btn); } } function genericNormalizeTipo(inicio) { return inicio; } // Actualizar resumen function actualizarResumen() { const tipo = estadoReserva.tipoCancha; const datos = datoscCanchas[tipo]; document.getElementById('res-cancha').textContent = `${tipo === 'futbol' ? 'Fútbol' : 'Pádel'} - Cancha ${estadoReserva.numeroCancha}`; document.getElementById('res-fecha').textContent = new Date(estadoReserva.fecha).toLocaleDateString('es-AR', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }); document.getElementById('res-horario').textContent = estadoReserva.horario; const duracionHoras = Math.floor(datos.duracion / 60); const duracionMinutos = datos.duracion % 60; document.getElementById('res-duracion').textContent = duracionHoras > 0 ? (duracionMinutos > 0 ? `${duracionHoras}h ${duracionMinutos}m` : `${duracionHoras}h`) : `${duracionMinutos}m`; if (estadoReserva.cuponeado) { document.getElementById('res-cupon').textContent = `Cupón activo: ${(estadoReserva.descuento * 100).toFixed(0)}% aplicado`; } else if (estadoReserva.reservasRestantes !== null) { document.getElementById('res-cupon').textContent = estadoReserva.reservasRestantes > 0 ? `Faltan ${estadoReserva.reservasRestantes} reserva(s) para cupón` : 'Sin cupón activo'; } else { document.getElementById('res-cupon').textContent = '-'; } actualizarPrecioTotal(); } function actualizarPrecioTotal() { const tipo = estadoReserva.tipoCancha; const datos = datoscCanchas[tipo]; if (!datos || typeof datos.precio !== 'number') { console.error('No se puede actualizar el precio porque no se cargaron los datos de cancha:', tipo, datos); return; } const basePrecio = datos.precio; const descuentoMonto = basePrecio * (estadoReserva.descuento || 0); const precioCancha = basePrecio - descuentoMonto; const totalPrecio = precioCancha + (estadoReserva.quincho ? (datoscCanchas.quincho?.precio || 0) : 0); const precioOriginalElement = document.getElementById('precio-original'); const precioOriginalValor = document.getElementById('res-precio-original'); const labelPrecio = document.getElementById('label-precio'); if (estadoReserva.descuento > 0) { // Mostrar precio original tachado precioOriginalValor.textContent = `$${basePrecio.toFixed(2)}`; precioOriginalElement.style.display = 'block'; labelPrecio.textContent = 'Precio Final:'; } else { // Ocultar precio original precioOriginalElement.style.display = 'none'; labelPrecio.textContent = 'Precio:'; } document.getElementById('res-precio').textContent = `$${totalPrecio.toFixed(2)}`; } async function obtenerEstadoCupon(dni, tipo) { try { const response = await fetch(`../php/Obtener_Cupon.php?dni=${encodeURIComponent(dni)}&tipo=${encodeURIComponent(tipo)}`); const data = await response.json(); if (!data.success) { throw new Error(data.message || 'No se pudo obtener el estado del cupón'); } estadoReserva.cuponeado = data.aplicarDescuento; estadoReserva.descuento = data.aplicarDescuento ? parseFloat(data.descuentoCanchas) : 0; estadoReserva.cantidadReservas = data.cantidadReservas; estadoReserva.umbral = data.umbral; estadoReserva.reservasRestantes = data.reservasRestantes; if (!estadoReserva.cuponeado && data.reservasRestantes === 0 && data.umbral === 0) { estadoReserva.reservasRestantes = null; } return data; } catch (error) { console.error('Error al obtener estado de cupón:', error); alert('No se pudo determinar el estado del cupón. Intenta nuevamente.'); estadoReserva.cuponeado = false; estadoReserva.descuento = 0; estadoReserva.reservasRestantes = null; return null; } } // --- FUNCIONES DE WHATSAPP Y GUARDADO --- async function solicitarCodigoWhatsApp() { const nombre = document.getElementById('cliente-nombre').value.trim(); const telefono = document.getElementById('cliente-telefono').value.trim(); const btnSolicitar = document.getElementById('btn-solicitar-reserva'); btnSolicitar.disabled = true; btnSolicitar.textContent = 'Enviando código...'; try { const response = await fetch('../php/Enviar_Codigo_WSP.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ telefono: telefono, nombre: nombre }) }); const data = await response.json(); if (data.success) { codigoCorrecto = data.codigo; // Ocultar botones de Confirmar/Volver y mostrar campo de validación document.querySelector('.botones-reserva').style.display = 'none'; document.getElementById('lbl-telefono').textContent = telefono; document.getElementById('seccion-verificacion').style.display = 'block'; console.log('Código enviado a Selenium:', data.codigo); } else { alert('Error al enviar el mensaje de WhatsApp.'); btnSolicitar.disabled = false; btnSolicitar.textContent = 'Confirmar Reserva'; } } catch (error) { console.error('Error:', error); alert('Error de conexión con el servidor.'); btnSolicitar.disabled = false; btnSolicitar.textContent = 'Confirmar Reserva'; } } async function guardarReservaFinal() { const tipo = estadoReserva.tipoCancha; const datos = { nombre: document.getElementById('cliente-nombre').value.trim(), telefono: document.getElementById('cliente-telefono').value.trim(), dni: document.getElementById('cliente-dni').value.trim(), fecha: estadoReserva.fecha, horario: estadoReserva.horario.split(' - ')[0], tipo: tipo === 'futbol' ? 'F' : 'P', numeroCancha: estadoReserva.numeroCancha, monto: datoscCanchas[tipo].precio, incluirQuincho: estadoReserva.quincho, montoQuincho: estadoReserva.quincho ? datoscCanchas.quincho.precio : 0 }; try { const response = await fetch('../php/Guardar_Reserva.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(datos) }); const result = await response.json(); if (result.success) { alert('¡Reserva confirmada exitosamente!'); // ADAPTACIÓN: Ocultamos la sección de reserva en vez de refrescar la pantalla document.getElementById('seccion-verificacion').style.display = 'none'; document.querySelector('.resumen-reserva').style.display = 'none'; // Cargamos el ID retornado por tu servidor en el input oculto del formulario // Nota: Tu php/Guardar_Reserva.php debe retornar un campo id_reserva (ej: result.id_reserva) const idNuevaReserva = result.id_reserva || result.id || 0; document.getElementById('comprobante-id-reserva').value = idNuevaReserva; // Hacemos visible la ventana de carga para la imagen document.getElementById('seccion-comprobante').style.display = 'block'; } else { alert('Error al guardar: ' + result.message); } } catch (error) { console.error('Error:', error); alert('Ocurrió un error crítico al intentar guardar la reserva.'); } } // --- FUNCIÓN ASÍNCRONA PARA SUBIR EL COMPROBANTE DE PAGO --- async function enviarComprobantePago() { const idReserva = document.getElementById('comprobante-id-reserva').value; const fileInput = document.getElementById('input-file-comprobante'); const btnSubir = document.querySelector('#form-comprobante button[type="submit"]'); if (fileInput.files.length === 0) { alert("Por favor, selecciona una foto de tu comprobante."); return; } btnSubir.disabled = true; btnSubir.textContent = "Subiendo archivo..."; // Construimos el FormData binario const formData = new FormData(); formData.append('id_reserva', idReserva); formData.append('comprobante', fileInput.files[0]); try { const response = await fetch('../php/Subir_Comprobante.php', { method: 'POST', body: formData // El navegador setea automáticamente el multipart/form-data }); const data = await response.json(); if (data.success) { alert("¡Comprobante enviado con éxito! El administrador verificará su pago en la brevedad."); location.reload(); // Ahora sí, reiniciamos la vista limpia del complejo } else { alert("Error: " + data.error); btnSubir.disabled = false; btnSubir.textContent = "Enviar Comprobante"; } } catch (error) { console.error("Error al subir el comprobante:", error); alert("Error de conexión al procesar el archivo."); btnSubir.disabled = false; btnSubir.textContent = "Enviar Comprobante"; } } // Inicializar cuando el DOM esté listo document.addEventListener('DOMContentLoaded', async () => { await cargarDatosCanchas(); inicializarReserva(); });