Tul xxx Tul
User / IP
:
216.73.216.227
Host / Server
:
45.84.207.204 / aircan.me
System
:
Linux lt-bnk-web1726.main-hosting.eu 5.14.0-611.36.1.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Mar 3 11:23:52 EST 2026 x86_64
Command
|
Upload
|
Create
Mass Deface
|
Jumping
|
Symlink
|
Reverse Shell
Ping
|
Port Scan
|
DNS Lookup
|
Whois
|
Header
|
cURL
:
/
home
/
u931257429
/
domains
/
aircan.me
/
public_html
/
control
/
Viewing: index.html
<!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Control de Pagos</title> <link rel="icon" type="image/x-icon" href="logo.png" /> <link rel="manifest" href="manifest.json"> <meta name="theme-color" content="#ff9a00"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: linear-gradient(135deg, #ff9a00 0%, #ffcd3c 50%, #fff 100%); min-height: 100vh; position: relative; overflow-x: hidden; display: flex; flex-direction: column; } .bg-animation { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: -1; opacity: 0.1; } .floating-shape { position: absolute; background: rgba(255, 255, 255, 0.3); border-radius: 50%; animation: float 6s ease-in-out infinite; } .shape1 { width: 80px; height: 80px; top: 20%; left: 10%; animation-delay: 0s; } .shape2 { width: 60px; height: 60px; top: 60%; right: 10%; animation-delay: 2s; } .shape3 { width: 100px; height: 100px; bottom: 20%; left: 20%; animation-delay: 4s; } @keyframes float { 0%, 100% { transform: translateY(0px) rotate(0deg); } 50% { transform: translateY(-20px) rotate(180deg); } } .container { max-width: 1200px; margin: 0 auto; padding: 20px; position: relative; z-index: 1; flex: 1; width: 100%; } .header { text-align: center; margin-bottom: 40px; color: white; animation: slideDown 0.8s ease-out; } .header h1 { font-size: 3rem; font-weight: 700; margin-bottom: 10px; text-shadow: 2px 2px 4px rgba(0,0,0,0.3); color: #000000; display: flex; align-items: center; justify-content: center; gap: 15px; flex-wrap: wrap; } .header p { font-size: 1.2rem; opacity: 0.9; text-shadow: 1px 1px 2px rgba(0,0,0,0.3); } .bus-info { display: inline-flex; align-items: center; gap: 12px; flex-wrap: wrap; justify-content: center; margin-top: 10px; } .bus-number { background: rgba(255, 255, 255, 0.2); padding: 8px 20px; border-radius: 30px; font-size: 1.2rem; display: inline-flex; align-items: center; gap: 8px; backdrop-filter: blur(5px); } .install-btn { background: linear-gradient(135deg, #ffffff 0%, rgba(255,255,255,0.7) 100%); color: #ff8c00; border: none; padding: 10px 22px; border-radius: 24px; font-size: 1rem; font-weight: 600; display: inline-flex; align-items: center; gap: 10px; cursor: pointer; box-shadow: 0 10px 25px rgba(255, 154, 0, 0.25); transition: transform 0.3s ease, box-shadow 0.3s ease, background 0.3s ease; opacity: 0; pointer-events: none; } .install-btn.show { opacity: 1; pointer-events: auto; } .install-btn:hover { transform: translateY(-2px); box-shadow: 0 15px 30px rgba(255, 154, 0, 0.35); } .install-btn:active { transform: translateY(0); } .stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-bottom: 40px; } .stat-card { background: rgba(255, 255, 255, 0.25); backdrop-filter: blur(15px); border: 1px solid rgba(255, 255, 255, 0.4); border-radius: 20px; padding: 30px; text-align: center; color: #333; transition: all 0.3s ease; animation: slideUp 0.8s ease-out; position: relative; overflow: hidden; } .stat-card::before { content: ''; position: absolute; top: -50%; left: -50%; width: 200%; height: 200%; background: linear-gradient(45deg, transparent, rgba(255,154,0,0.2), transparent); transform: rotate(45deg); transition: all 0.6s; opacity: 0; } .stat-card:hover::before { animation: shine 0.8s ease-in-out; opacity: 1; } .stat-card:hover { transform: translateY(-10px) scale(1.02); background: rgba(255, 255, 255, 0.35); box-shadow: 0 20px 40px rgba(255,154,0,0.2); } .stat-number { font-size: 3rem; font-weight: 800; display: block; margin-bottom: 10px; color: #000000; text-shadow: 2px 2px 4px rgba(0,0,0,0.2); } #totalBolivares { color: #27ae60; } .stat-label { font-size: 1.1rem; opacity: 0.8; text-transform: uppercase; letter-spacing: 1px; color: #444; } .control-panel { background: rgba(255, 255, 255, 0.95); border-radius: 25px; padding: 40px; box-shadow: 0 20px 60px rgba(0,0,0,0.1); animation: slideUp 1s ease-out; backdrop-filter: blur(20px); border: 1px solid rgba(255, 255, 255, 0.3); margin-bottom: 40px; } .form-group { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 30px; width: 100%; } .input-wrapper { position: relative; } .form-input { width: 100%; padding: 15px 20px; border: 2px solid #e1e5e9; border-radius: 15px; font-size: 1rem; transition: all 0.3s ease; background: rgba(255, 255, 255, 0.8); } .form-input:focus { outline: none; border-color: #ff9a00; background: white; box-shadow: 0 0 20px rgba(255, 154, 0, 0.3); transform: translateY(-2px); } .form-select { width: 100%; padding: 15px 20px; border: 2px solid #e1e5e9; border-radius: 15px; font-size: 1rem; background: rgba(255, 255, 255, 0.8); transition: all 0.3s ease; cursor: pointer; } .form-select:focus { outline: none; border-color: #ff9a00; background: white; box-shadow: 0 0 20px rgba(255, 154, 0, 0.3); } .btn-primary { background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); color: white; border: none; padding: 18px 40px; border-radius: 25px; font-size: 1.1rem; font-weight: 600; cursor: pointer; transition: all 0.3s ease; text-transform: uppercase; letter-spacing: 1px; position: relative; overflow: hidden; text-shadow: 1px 1px 2px rgba(0,0,0,0.3); box-shadow: 0 4px 15px rgba(46, 204, 113, 0.3); } .btn-primary::before { content: ''; position: absolute; top: 50%; left: 50%; width: 0; height: 0; background: rgba(255, 255, 255, 0.2); border-radius: 50%; transform: translate(-50%, -50%); transition: all 0.3s ease; } .btn-primary:hover::before { width: 300px; height: 300px; } .btn-primary:hover { transform: translateY(-3px); box-shadow: 0 15px 35px rgba(46, 204, 113, 0.4); background: linear-gradient(135deg, #27ae60 0%, #2ecc71 100%); } .btn-primary:active { transform: translateY(-1px); } .transactions-table { margin-top: 30px; background: white; border-radius: 20px; overflow: hidden; box-shadow: 0 10px 30px rgba(0,0,0,0.1); } .table-header { background: linear-gradient(135deg, #ff9a00 0%, #ffcd3c 100%); color: white; padding: 20px; font-size: 1.2rem; font-weight: 600; text-align: center; text-shadow: 1px 1px 2px rgba(0,0,0,0.3); } .transaction-item { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr auto; gap: 20px; padding: 20px; border-bottom: 1px solid #f0f0f0; align-items: center; transition: all 0.3s ease; animation: fadeIn 0.5s ease-out; } .transaction-item:hover { background: rgba(255, 154, 0, 0.08); transform: translateX(5px); } .transaction-item:last-child { border-bottom: none; } .transaction-item > div { padding: 5px 0; } .transaction-time { font-weight: 600; color: #333; } .transaction-amount { font-weight: 700; color: #27ae60; font-size: 1.1rem; } .transaction-method { background: linear-gradient(135deg, #ff9a00, #ffcd3c); color: white; padding: 8px 15px; border-radius: 20px; font-size: 0.9rem; text-align: center; font-weight: 500; text-shadow: 1px 1px 2px rgba(0,0,0,0.2); } .delete-btn { background: #e74c3c; color: white; border: none; padding: 8px 15px; border-radius: 15px; cursor: pointer; transition: all 0.3s ease; font-size: 0.9rem; } .delete-btn:hover { background: #c0392b; transform: scale(1.05); } .empty-state { text-align: center; padding: 60px 20px; color: #666; } .empty-state h3 { font-size: 1.5rem; margin-bottom: 10px; color: #999; } .success-message { background: linear-gradient(135deg, #27ae60, #2ecc71); color: white; padding: 15px 20px; border-radius: 15px; margin-bottom: 20px; text-align: center; font-weight: 500; animation: slideDown 0.5s ease-out; box-shadow: 0 5px 15px rgba(39, 174, 96, 0.3); } .currency-badge { display: inline-block; background: linear-gradient(135deg, #ff9a00, #ffcd3c); color: white; padding: 4px 10px; border-radius: 12px; font-size: 0.8rem; font-weight: 600; margin-left: 8px; text-shadow: 1px 1px 2px rgba(0,0,0,0.2); } .history-panel { background: rgba(255, 255, 255, 0.95); border-radius: 25px; padding: 40px; box-shadow: 0 20px 60px rgba(0,0,0,0.1); animation: slideUp 1s ease-out; backdrop-filter: blur(20px); border: 1px solid rgba(255, 255, 255, 0.3); } .date-filter { display: flex; align-items: center; gap: 15px; margin-bottom: 30px; } .date-input { padding: 12px 15px; border: 2px solid #e1e5e9; border-radius: 15px; font-size: 1rem; background: rgba(255, 255, 255, 0.8); transition: all 0.3s ease; } .date-input:focus { outline: none; border-color: #ff9a00; background: white; box-shadow: 0 0 20px rgba(255, 154, 0, 0.3); } .filter-btn { background: linear-gradient(135deg, #3498db, #2980b9); color: white; border: none; padding: 12px 25px; border-radius: 15px; font-size: 1rem; font-weight: 600; cursor: pointer; transition: all 0.3s ease; } .filter-btn:hover { transform: translateY(-2px); box-shadow: 0 10px 20px rgba(52, 152, 219, 0.3); } .history-table { width: 100%; border-collapse: collapse; margin-top: 20px; background: white; border-radius: 15px; overflow: hidden; box-shadow: 0 5px 15px rgba(0,0,0,0.1); } .history-table th { background: linear-gradient(135deg, #3498db, #2980b9); color: white; padding: 15px; text-align: left; font-weight: 600; } .history-table td { padding: 12px 15px; border-bottom: 1px solid #f0f0f0; } .history-table tr:last-child td { border-bottom: none; } .history-table tr:hover { background-color: rgba(52, 152, 219, 0.05); } .footer { text-align: center; padding: 20px; background: rgba(255, 255, 255, 0.8); margin-top: 40px; font-size: 0.9rem; color: #555; width: 100%; position: relative; bottom: 0; } .footer a { color: #ff9a00; text-decoration: none; font-weight: 600; transition: all 0.3s ease; } .footer a:hover { color: #ff6600; text-decoration: underline; } @keyframes slideDown { from { transform: translateY(-30px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } @keyframes slideUp { from { transform: translateY(30px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } @keyframes fadeIn { from { opacity: 0; transform: translateX(-20px); } to { opacity: 1; transform: translateX(0); } } @keyframes shine { 0% { transform: translateX(-100%) translateY(-100%) rotate(45deg); } 100% { transform: translateX(100%) translateY(100%) rotate(45deg); } } @media (max-width: 768px) { .header h1 { font-size: 2rem; } .header p { font-size: 1rem; } .stats-grid { grid-template-columns: repeat(2, minmax(140px, 1fr)); gap: 12px; align-items: stretch; } .form-group { grid-template-columns: 1fr; gap: 15px; } .transaction-item { grid-template-columns: 1fr; text-align: center; gap: 10px; padding: 15px; border-bottom: 1px solid black; } .transaction-item:last-child { border-bottom: none; } .transaction-item > div { padding: 5px 0; } .control-panel, .history-panel { padding: 15px; } .date-filter { flex-direction: column; gap: 10px; } .date-filter input, .date-filter button { width: 100%; } .history-table { font-size: 0.9rem; } .history-table th, .history-table td { padding: 10px; } .btn-primary { width: 100%; padding: 15px; } .delete-btn { width: 100%; margin-top: 5px; } .form-input { font-size: 1.2rem; padding: 20px; height: 60px; margin-bottom: 10px; } .form-input::placeholder { font-size: 1.1rem; } .input-wrapper { margin-bottom: 15px; } #amount { font-size: 1.4rem; font-weight: 600; } #passengerRef { font-size: 1.2rem; } } @media (max-width: 480px) { .container { padding: 10px; } .header h1 { font-size: 1.8rem; } .bus-info { flex-direction: column; gap: 10px; } .stat-card { padding: 20px; } .stat-number { font-size: 2rem; } .table-header { font-size: 1rem; padding: 15px; } .footer { padding: 15px; font-size: 0.8rem; } } @media (min-width: 769px) and (max-width: 1024px) { .container { padding: 15px; } .header h1 { font-size: 2.5rem; } .stats-grid { grid-template-columns: repeat(2, 1fr); } .transaction-item { grid-template-columns: 1fr 1fr 1fr auto; } } </style> </head> <body> <div class="bg-animation"> <div class="floating-shape shape1"></div> <div class="floating-shape shape2"></div> <div class="floating-shape shape3"></div> </div> <div class="container"> <div class="header"> <h1><i class="fas fa-bus"></i> Línea Unión</h1> <div class="bus-info"> <div class="bus-number"> <i class="fas fa-bus"></i> Bus #42 </div> <button id="installButton" class="install-btn"> <i class="fas fa-download"></i> Instalar App </button> </div> </div> <div class="stats-grid"> <div class="stat-card"> <span class="stat-number" id="totalTransactions">0</span> <span class="stat-label">Transacciones Hoy</span> </div> <div class="stat-card"> <span class="stat-number" id="totalBolivares">Bs. 0</span> <span class="stat-label">Total Bolívares</span> </div> <!-- <div class="stat-card"> <span class="stat-number" id="totalDollars">$ 0</span> <span class="stat-label">Total Dólares</span> </div> <div class="stat-card"> <span class="stat-number" id="lastHourCount">0</span> <span class="stat-label">Última Hora</span> </div> --> </div> <div class="control-panel"> <div id="successMessage" class="success-message" style="display: none;"> ✅ Pago registrado exitosamente </div> <div class="form-group"> <div class="input-wrapper"> <input type="number" id="amount" class="form-input" placeholder="Monto del pago" step="0.01" min="0"> </div> <!-- <div class="input-wrapper"> <div id="currencyDisplay" class="form-input" style="display: flex; align-items: center; justify-content: center; background: rgba(255, 255, 255, 0.8); cursor: default;"> <span style="font-weight: 600; color: #333;">Bolívares (Bs.)</span> </div> </div> --> <div class="input-wrapper"> <input type="text" id="passengerRef" class="form-input" placeholder="Referencia del pasajero (opcional)"> </div> <button class="btn-primary" onclick="addPayment()"> <span>Registrar Pago</span> </button> </div> <div class="transactions-table"> <div class="table-header"> 📱 Registro de Pagos Móviles - Hoy </div> <div id="transactionsList"> <div class="empty-state"> <h3>No hay transacciones registradas</h3> <p>Los pagos aparecerán aquí una vez que comiences a registrarlos</p> </div> </div> </div> </div> <div class="history-panel"> <h2 style="margin-bottom: 20px; color: #333; text-align: center;">Historial de Pagos</h2> <div class="date-filter"> <input type="date" id="filterDate" class="date-input"> <button class="filter-btn" onclick="filterByDate()"> <i class="fas fa-search"></i> Buscar </button> <button class="filter-btn" style="background: linear-gradient(135deg, #2ecc71, #27ae60);" onclick="resetFilter()"> <i class="fas fa-sync-alt"></i> Restablecer </button> </div> <div style="overflow-x: auto;"> <table class="history-table"> <thead> <tr> <th>Fecha y Hora</th> <th>Monto</th> <!-- <th>Moneda</th> --> <!-- <th>Método</th> --> <th>Pasajero</th> <th>Acciones</th> </tr> </thead> <tbody id="historyTableBody"> <tr> <td colspan="4" style="text-align: center; padding: 30px;">Selecciona una fecha para ver los pagos</td> </tr> </tbody> </table> </div> <div style="display: flex; justify-content: center; margin-top: 20px;"> <div style="background: linear-gradient(135deg, #ff9a00, #ffcd3c); padding: 15px 30px; border-radius: 50px; color: white; font-weight: bold; box-shadow: 0 4px 15px rgba(255, 154, 0, 0.3);"> Total del día: <span id="historyTotal">Bs. 0.00</span> </div> </div> </div> </div> <footer class="footer"> <p>© 2025 Control de Pagos Móviles. Creado por <a href="https://aircan.me/" target="_blank">Aircan</a></p> </footer> <script> const API_URL = 'db.php'; let transactions = []; let deferredPrompt = null; const installButton = document.getElementById('installButton'); const pad = n => String(n).padStart(2, '0'); function isStandaloneMode() { return window.matchMedia('(display-mode: standalone)').matches || window.navigator.standalone === true; } function showInstallButton() { if (installButton) { installButton.classList.add('show'); } } function hideInstallButton() { if (installButton) { installButton.classList.remove('show'); } } function setupPWAInstall() { if (!installButton) { return; } hideInstallButton(); window.addEventListener('appinstalled', () => { deferredPrompt = null; hideInstallButton(); }); if (isStandaloneMode()) { return; } window.addEventListener('beforeinstallprompt', (event) => { event.preventDefault(); deferredPrompt = event; showInstallButton(); }); installButton.addEventListener('click', async () => { if (!deferredPrompt) { return; } installButton.disabled = true; hideInstallButton(); deferredPrompt.prompt(); const { outcome } = await deferredPrompt.userChoice; deferredPrompt = null; installButton.disabled = false; if (outcome !== 'accepted' && !isStandaloneMode()) { setTimeout(() => { showInstallButton(); }, 300); } }); } function registerServiceWorker() { if ('serviceWorker' in navigator) { navigator.serviceWorker.register('sw.js').catch(error => console.error('SW error:', error)); } } function getClientTimeString() { const now = new Date(); return `${now.getFullYear()}-${pad(now.getMonth()+1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`; } function formatTimeFromDateString(s) { const parts = (s || '').split(' '); const t = (parts[1] || parts[0] || '').split(':'); const h = parseInt(t[0] || '0', 10); const m = pad(parseInt(t[1] || '0', 10)); const hh = ((h + 11) % 12) + 1; const ampm = h >= 12 ? 'p. m.' : 'a. m.'; return `${pad(hh)}:${m} ${ampm}`; } function formatDateTimeForDisplay(s) { const parts = (s || '').split(' '); const dpart = parts[0] || ''; const tpart = (parts[1] || '00:00:00').split(':'); const segs = dpart.split('-'); const y = segs[0] || '0000'; const mo = segs[1] || '01'; const d = segs[2] || '01'; const h = parseInt(tpart[0] || '0', 10); const m = pad(parseInt(tpart[1] || '0', 10)); const hh = ((h + 11) % 12) + 1; const ampm = h >= 12 ? 'p. m.' : 'a. m.'; return `${pad(parseInt(d,10))}/${pad(parseInt(mo,10))}/${y} ${pad(hh)}:${m} ${ampm}`; } function timeAgoFromString(s) { const parts = (s || '').replace('T',' ').split(' '); const datePart = (parts[0] || '1970-01-01').split('-').map(Number); const timePart = (parts[1] || '00:00:00').split(':').map(Number); const dt = new Date(datePart[0] || 1970, (datePart[1] || 1) - 1, datePart[2] || 1, timePart[0] || 0, timePart[1] || 0, timePart[2] || 0); const diff = Math.floor((Date.now() - dt.getTime()) / 1000); if (!isFinite(diff)) return ''; if (diff < 60) return 'hace segundos'; const m = Math.floor(diff / 60); if (m < 60) return `hace ${m} min`; const h = Math.floor(m / 60); if (h < 24) return `hace ${h} h`; const d = Math.floor(h / 24); return `hace ${d} d`; } async function fetchData(url, method = 'GET', data = null) { const options = { method, headers: { 'Content-Type': 'application/json' } }; if (data) { options.body = JSON.stringify(data); } try { const response = await fetch(url, options); return await response.json(); } catch (error) { console.error('Error:', error); return { error: 'Error de conexión con el servidor' }; } } async function addPayment() { const amount = parseFloat(document.getElementById('amount').value); const currency = 'Bolivares'; // Valor fijo const method = 'Pago Móvil'; // Valor fijo const passengerRef = document.getElementById('passengerRef').value; if (!amount || amount <= 0) { alert('Por favor ingresa un monto válido'); return; } // Las validaciones de moneda y método ya no son necesarias porque los valores son fijos. const response = await fetchData(API_URL, 'POST', { amount, currency, method, passengerRef, clientTime: getClientTimeString(), clientTzOffset: new Date().getTimezoneOffset() }); if (response.error) { alert('Error al registrar el pago: ' + response.error); return; } clearForm(); showSuccessMessage(); loadTodayTransactions(); updateStats(); } async function deleteTransaction(id) { const confirmDelete = confirm('¿Estás seguro de eliminar esta transacción?'); if (!confirmDelete) return; const response = await fetchData(`${API_URL}?id=${id}`, 'DELETE'); if (response.error) { alert('Error al eliminar: ' + response.error); return; } loadTodayTransactions(); updateStats(); // Actualizar la tabla de historial si hay una fecha seleccionada const filterDate = document.getElementById('filterDate').value; if (filterDate) { const data = await fetchData(`${API_URL}?fecha=${filterDate}`); if (!data.error) { updateHistoryTable(data); } } } async function loadTodayTransactions() { const data = await fetchData(API_URL); if (data.error) { console.error(data.error); return; } transactions = data; updateTransactionsList(); } async function updateStats() { const data = await fetchData(`${API_URL}?estadisticas=true`); if (data.error) { console.error(data.error); return; } document.getElementById('totalTransactions').textContent = data.totalTransactions; document.getElementById('totalBolivares').textContent = `Bs. ${parseFloat(data.totalBolivares).toFixed(2)}`; const elDollars = document.getElementById('totalDollars'); if (elDollars) elDollars.textContent = `$ ${parseFloat(data.totalDollars).toFixed(2)}`; const elLastHour = document.getElementById('lastHourCount'); if (elLastHour) elLastHour.textContent = data.lastHourCount; } function updateTransactionsList() { const container = document.getElementById('transactionsList'); if (transactions.length === 0) { container.innerHTML = ` <div class="empty-state"> <h3>No hay transacciones registradas hoy</h3> <p>Los pagos aparecerán aquí una vez que comiences a registrarlos</p> </div> `; return; } container.innerHTML = transactions.map(transaction => { const timeString = formatTimeFromDateString(transaction.fecha_hora || ''); const rel = timeAgoFromString(transaction.fecha_hora || ''); return ` <div class="transaction-item"> <div class="transaction-time"> ${timeString} <div style="font-size: 0.8rem; color: #777;">${rel}</div> </div> <div class="transaction-amount"> ${transaction.moneda === 'Bolivares' ? 'Bs.' : '$'}${parseFloat(transaction.monto).toFixed(2)} <span class="currency-badge">${transaction.moneda === 'Bolivares' ? 'Bs' : 'USD'}</span> </div> <div class="transaction-method">${transaction.metodo_pago}</div> <div style="font-size: 0.9rem; color: #666;">${transaction.referencia_pasajero || 'Sin Referencia'}</div> <button class="delete-btn" onclick="deleteTransaction(${transaction.id})"> 🗑️ </button> </div> `}).join(''); } async function filterByDate() { const dateInput = document.getElementById('filterDate').value; if (!dateInput) { alert('Por favor selecciona una fecha'); return; } const data = await fetchData(`${API_URL}?fecha=${dateInput}`); if (data.error) { alert('Error al filtrar: ' + data.error); return; } updateHistoryTable(data); } function resetFilter() { document.getElementById('filterDate').value = ''; document.getElementById('historyTableBody').innerHTML = ` <tr> <td colspan="4" style="text-align: center; padding: 30px;">Selecciona una fecha para ver los pagos</td> </tr> `; } function updateHistoryTable(filteredTransactions) { const tableBody = document.getElementById('historyTableBody'); const historyTotal = document.getElementById('historyTotal'); if (filteredTransactions.length === 0) { tableBody.innerHTML = ` <tr> <td colspan="4" style="text-align: center; padding: 30px;">No hay transacciones para esta fecha</td> </tr> `; historyTotal.textContent = 'Bs. 0.00'; return; } // Calcular el total de Bolívares const total = filteredTransactions.reduce((sum, transaction) => { return sum + (transaction.moneda === 'Bolivares' ? parseFloat(transaction.monto) : 0); }, 0); // Actualizar el total historyTotal.textContent = `Bs. ${total.toFixed(2)}`; tableBody.innerHTML = filteredTransactions.map(transaction => { const dateString = formatDateTimeForDisplay(transaction.fecha_hora || ''); return ` <tr> <td>${dateString}</td> <td style="font-weight: 600; color: #27ae60;"> ${transaction.moneda === 'Bolivares' ? 'Bs.' : '$'}${parseFloat(transaction.monto).toFixed(2)} </td> <td>${transaction.referencia_pasajero || 'Sin Referencia'}</td> <td> <button class="delete-btn" onclick="deleteTransaction(${transaction.id})"> 🗑️ </button> </td> </tr> `}).join(''); } function clearForm() { document.getElementById('amount').value = ''; // Moneda y método de pago ya no necesitan ser reseteados ya que son fijos. document.getElementById('passengerRef').value = ''; } function showSuccessMessage() { const message = document.getElementById('successMessage'); message.style.display = 'block'; setTimeout(() => { message.style.display = 'none'; }, 3000); } // Cargar datos al iniciar document.addEventListener('DOMContentLoaded', () => { setupPWAInstall(); registerServiceWorker(); loadTodayTransactions(); updateStats(); }); </script> </body> </html>
Coded With 💗 by
0x6ick