526 lines
23 KiB
PHP
526 lines
23 KiB
PHP
<?php
|
|
include("../db.php");
|
|
|
|
if (!isset($_SESSION['rol']) || $_SESSION['rol'] !== 'admin') {
|
|
header("Location: ../login.php?error=acceso_denegado");
|
|
exit();
|
|
}
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['cambiar_pago'])) {
|
|
$id_p = (int)$_POST['id_pedido'];
|
|
$nuevo_pago = mysqli_real_escape_string($conexion, $_POST['nuevo_pago']);
|
|
$query_pago = "UPDATE pedidos SET pago_estado = '$nuevo_pago' WHERE id_pedido = $id_p";
|
|
if (mysqli_query($conexion, $query_pago)) {
|
|
$nombre_admin = $_SESSION['usuario'] ?? 'Admin ID: ' . ($_SESSION['id_usuario'] ?? 'Desconocido');
|
|
escribir_log("[CAJA] Pedido #$id_p actualizó su estado de pago a '$nuevo_pago' por el Administrador: $nombre_admin");
|
|
header("Location: pedidos.php?status=updated");
|
|
} else {
|
|
escribir_log("[ERROR SQL] Fallo al intentar cambiar pago del pedido #$id_p. Error: " . mysqli_error($conexion));
|
|
header("Location: pedidos.php?status=error");
|
|
}
|
|
exit();
|
|
}
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['cambiar_estado'])) {
|
|
$id_p = (int)$_POST['id_pedido'];
|
|
$nuevo_est = mysqli_real_escape_string($conexion, $_POST['nuevo_estado']);
|
|
$query_cliente = "SELECT p.telefono_contacto, u.nombre, p.total
|
|
FROM pedidos p
|
|
JOIN usuarios u ON p.id_usuario = u.id_usuario
|
|
WHERE p.id_pedido = $id_p";
|
|
$res_c = mysqli_query($conexion, $query_cliente);
|
|
$data_c = mysqli_fetch_assoc($res_c);
|
|
$query_update = "UPDATE pedidos SET estado = '$nuevo_est' WHERE id_pedido = $id_p";
|
|
if (mysqli_query($conexion, $query_update)) {
|
|
$nombre_admin = $_SESSION['usuario'] ?? 'Admin ID: ' . ($_SESSION['id_usuario'] ?? 'Desconocido');
|
|
$nombre_cliente = $data_c['nombre'] ?? 'Desconocido';
|
|
if ($nuevo_est === 'Cancelado') {
|
|
$motivo = $_POST['motivo_cancelacion'] ?? 'No especificado o directo desde monitor';
|
|
escribir_log("[🚨 CANCELACIÓN] Pedido ID #$id_p fue CANCELADO por Admin: $nombre_admin. Motivo: $motivo");
|
|
} else {
|
|
escribir_log("[CAJA/COCINA] Pedido #$id_p (Cliente: $nombre_cliente) cambio a estado '$nuevo_est' por el Administrador: $nombre_admin");
|
|
}
|
|
if ($nuevo_est !== 'Cancelado' && !empty($data_c['telefono_contacto']) && ($nuevo_est === 'En camino' || $nuevo_est === 'Listo para retirar')) {
|
|
if ($nuevo_est === 'En camino') {
|
|
$texto = "¡Hola " . $data_c['nombre'] . "! Tu pedido de *La Pecosa* ya está en camino. 🛵 ¡Prepárate para recibirlo! Total a pagar: $" . number_format($data_c['total'], 2, ',', '.');
|
|
} else {
|
|
$texto = "¡Hola " . $data_c['nombre'] . "! Tu pedido de *La Pecosa* ya está listo para ser retirado. 🛍️ ¡Te esperamos! Total: $" . number_format($data_c['total'], 2, ',', '.');
|
|
}
|
|
$mensaje_ws = urlencode($texto);
|
|
$telefono_limpio = preg_replace('/[^0-9]/', '', $data_c['telefono_contacto']);
|
|
if (substr($telefono_limpio, 0, 2) !== '54') {
|
|
$telefono_limpio = '54' . $telefono_limpio;
|
|
}
|
|
$_SESSION['url_whatsapp'] = "https://api.whatsapp.com/send?phone=$telefono_limpio&text=$mensaje_ws";
|
|
}
|
|
header("Location: pedidos.php?status=updated");
|
|
} else {
|
|
escribir_log("[ERROR SQL] Fallo al intentar cambiar el estado del pedido #$id_p a '$nuevo_est'. Error: " . mysqli_error($conexion));
|
|
header("Location: pedidos.php?status=error");
|
|
}
|
|
exit();
|
|
}
|
|
|
|
$query_activos = "SELECT p.id_pedido, p.fecha, p.total, p.estado, p.pago_estado, p.comprobante, u.nombre AS cliente
|
|
FROM pedidos p
|
|
JOIN usuarios u ON p.id_usuario = u.id_usuario
|
|
WHERE p.estado IN ('Pendiente', 'En cocina', 'Listo para retirar', 'En camino')
|
|
ORDER BY p.fecha DESC";
|
|
$res_activos = mysqli_query($conexion, $query_activos);
|
|
|
|
$query_historial = "SELECT p.id_pedido, p.fecha, p.total, p.estado, p.pago_estado, p.comprobante, u.nombre AS cliente
|
|
FROM pedidos p
|
|
JOIN usuarios u ON p.id_usuario = u.id_usuario
|
|
WHERE p.estado IN ('Entregado', 'Cancelado')
|
|
ORDER BY p.fecha DESC
|
|
LIMIT 50";
|
|
$res_historial = mysqli_query($conexion, $query_historial);
|
|
?>
|
|
|
|
<!DOCTYPE html>
|
|
<html lang="es">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Pedidos Activos - La Pecosa</title>
|
|
<link rel="stylesheet" href="../css/all.min.css">
|
|
<link rel="stylesheet" href="admin_style.css">
|
|
<style>
|
|
/* ── TOAST ── */
|
|
.toast-ok {
|
|
background: #f0fdf4;
|
|
border: 1px solid #bbf7d0;
|
|
color: #166534;
|
|
border-radius: 8px;
|
|
padding: 12px 16px;
|
|
margin-bottom: 20px;
|
|
font-size: 0.875rem;
|
|
font-weight: 600;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
/* ── BUSCADOR ── */
|
|
.search-bar {
|
|
background: #fff;
|
|
border: 1px solid #e5e7eb;
|
|
border-radius: 10px;
|
|
padding: 16px 20px;
|
|
margin-bottom: 24px;
|
|
display: flex;
|
|
gap: 10px;
|
|
align-items: center;
|
|
}
|
|
.search-bar .search-wrap {
|
|
position: relative;
|
|
flex: 1;
|
|
}
|
|
.search-bar .search-wrap i {
|
|
position: absolute;
|
|
left: 14px;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
color: #9ca3af;
|
|
font-size: 0.9rem;
|
|
}
|
|
.search-bar input {
|
|
width: 100%;
|
|
padding: 10px 12px 10px 40px;
|
|
border: 1px solid #e5e7eb;
|
|
border-radius: 7px;
|
|
font-size: 0.9rem;
|
|
outline: none;
|
|
transition: border-color 0.2s;
|
|
box-sizing: border-box;
|
|
}
|
|
.search-bar input:focus { border-color: #e02828; }
|
|
.search-bar .btn-buscar {
|
|
background: #e02828;
|
|
color: #fff;
|
|
border: none;
|
|
padding: 10px 20px;
|
|
border-radius: 7px;
|
|
font-weight: 700;
|
|
font-size: 0.875rem;
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
transition: opacity 0.15s;
|
|
}
|
|
.search-bar .btn-buscar:hover { opacity: 0.88; }
|
|
|
|
/* ── SECTION CARD ── */
|
|
.section-card {
|
|
background: #fff;
|
|
border: 1px solid #e5e7eb;
|
|
border-radius: 12px;
|
|
overflow: hidden;
|
|
margin-bottom: 20px;
|
|
}
|
|
.section-card-header {
|
|
padding: 16px 22px;
|
|
border-bottom: 1px solid #f3f4f6;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
.section-card-header h2 {
|
|
font-size: 1rem;
|
|
font-weight: 700;
|
|
color: #111827;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
margin: 0;
|
|
}
|
|
.section-card-body { overflow-x: auto; }
|
|
|
|
/* ── PULSO ── */
|
|
@keyframes pulse {
|
|
0% { opacity: 0.6; transform: scale(0.9); }
|
|
50% { opacity: 1; transform: scale(1.1); }
|
|
100% { opacity: 0.6; transform: scale(0.9); }
|
|
}
|
|
.dot-live {
|
|
width: 9px;
|
|
height: 9px;
|
|
border-radius: 50%;
|
|
background: #e02828;
|
|
display: inline-block;
|
|
animation: pulse 1.6s infinite;
|
|
}
|
|
|
|
/* ── TABLA ── */
|
|
.admin-table td { font-size: 0.875rem; vertical-align: middle; }
|
|
.admin-table tr:last-child td { border-bottom: none; }
|
|
|
|
/* ── CELDA ESTADO+PAGO (columna "Estado actual") ── */
|
|
.estado-cell { display: flex; flex-direction: column; gap: 5px; }
|
|
|
|
/* ── PAGO ── */
|
|
.pago-ok {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
font-size: 0.75rem;
|
|
font-weight: 700;
|
|
color: #166534;
|
|
}
|
|
.pago-pendiente-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
font-size: 0.75rem;
|
|
font-weight: 700;
|
|
color: #9d174d;
|
|
background: #fdf2f8;
|
|
border: 1px dashed #fbcfe8;
|
|
border-radius: 5px;
|
|
padding: 3px 8px;
|
|
cursor: pointer;
|
|
transition: background 0.15s;
|
|
}
|
|
.pago-pendiente-btn:hover { background: #fce7f3; }
|
|
.pago-pendiente-tag {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
font-size: 0.75rem;
|
|
font-weight: 700;
|
|
color: #9d174d;
|
|
background: #fdf2f8;
|
|
border-radius: 5px;
|
|
padding: 3px 8px;
|
|
}
|
|
|
|
/* ── COMPROBANTE ── */
|
|
.btn-comprobante {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
font-size: 0.72rem;
|
|
font-weight: 600;
|
|
color: #475569;
|
|
background: #f8fafc;
|
|
border: 1px solid #e2e8f0;
|
|
border-radius: 5px;
|
|
padding: 3px 8px;
|
|
text-decoration: none;
|
|
transition: border-color 0.15s, color 0.15s;
|
|
}
|
|
.btn-comprobante:hover { border-color: #e02828; color: #e02828; }
|
|
|
|
/* ── VER DETALLE ── */
|
|
.btn-detalle {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
font-size: 0.8rem;
|
|
font-weight: 600;
|
|
color: #475569;
|
|
background: #f1f5f9;
|
|
border-radius: 20px;
|
|
padding: 6px 12px;
|
|
text-decoration: none;
|
|
transition: background 0.15s, color 0.15s;
|
|
}
|
|
.btn-detalle:hover { background: #e2e8f0; color: #111827; }
|
|
|
|
/* ── FORM ESTADO ── */
|
|
.form-estado { display: flex; align-items: center; gap: 6px; }
|
|
.btn-confirmar {
|
|
background: #1f2937;
|
|
color: #fff;
|
|
border: none;
|
|
width: 30px;
|
|
height: 30px;
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 0.75rem;
|
|
flex-shrink: 0;
|
|
transition: background 0.15s;
|
|
}
|
|
.btn-confirmar:hover { background: #e02828; }
|
|
|
|
/* ── HISTORIAL COLAPSABLE ── */
|
|
.historial-toggle {
|
|
width: 100%;
|
|
background: #f9fafb;
|
|
border: 1px solid #e5e7eb;
|
|
border-radius: 10px;
|
|
padding: 14px 22px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
cursor: pointer;
|
|
font-size: 0.9rem;
|
|
font-weight: 700;
|
|
color: #374151;
|
|
transition: background 0.15s;
|
|
margin-bottom: 0;
|
|
}
|
|
.historial-toggle:hover { background: #f3f4f6; }
|
|
.historial-toggle .toggle-left { display: flex; align-items: center; gap: 8px; }
|
|
.historial-toggle .chevron {
|
|
font-size: 0.8rem;
|
|
color: #9ca3af;
|
|
transition: transform 0.25s;
|
|
}
|
|
.historial-toggle.open .chevron { transform: rotate(180deg); }
|
|
|
|
.historial-body {
|
|
display: none;
|
|
margin-top: 8px;
|
|
}
|
|
.historial-body.open { display: block; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<?php include("sidebar.php"); ?>
|
|
|
|
<div class="main-content">
|
|
|
|
<div class="page-header">
|
|
<h1><i class="fa-solid fa-fire-burner"></i> Monitor operativo de pedidos</h1>
|
|
</div>
|
|
|
|
<?php if (isset($_GET['status']) && $_GET['status'] === 'updated'): ?>
|
|
<div class="toast-ok">
|
|
<i class="fa-solid fa-circle-check"></i> Panel actualizado correctamente.
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<!-- BUSCADOR -->
|
|
<div class="search-bar">
|
|
<form action="buscar_clientes.php" method="GET" style="display:contents;">
|
|
<div class="search-wrap">
|
|
<i class="fa-solid fa-magnifying-glass"></i>
|
|
<input type="text" name="query" required placeholder="Buscar por #ID de pedido, nombre de cliente o ID de usuario...">
|
|
</div>
|
|
<button type="submit" class="btn-buscar">
|
|
<i class="fa-solid fa-filter"></i> Buscar
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- COMANDAS ACTIVAS -->
|
|
<div class="section-card">
|
|
<div class="section-card-header">
|
|
<h2><span class="dot-live"></span> Comandas activas — cocina y despacho</h2>
|
|
</div>
|
|
<div class="section-card-body">
|
|
<table class="admin-table">
|
|
<thead>
|
|
<tr>
|
|
<th>N° Pedido</th>
|
|
<th>Fecha / Hora</th>
|
|
<th>Cliente</th>
|
|
<th>Total</th>
|
|
<th>Estado actual</th>
|
|
<th>Ver detalle</th>
|
|
<th>Cambiar estado</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if (mysqli_num_rows($res_activos) == 0): ?>
|
|
<tr>
|
|
<td colspan="7" style="text-align:center; color:#9ca3af; padding:36px 14px;">
|
|
<i class="fa-solid fa-mug-hot" style="font-size:1.4rem; display:block; margin-bottom:6px;"></i>
|
|
No hay pedidos activos en este momento.
|
|
</td>
|
|
</tr>
|
|
<?php else: ?>
|
|
<?php while ($ped = mysqli_fetch_assoc($res_activos)):
|
|
$en = strtolower($ped['estado']);
|
|
$badge = 'badge-pendiente';
|
|
if ($en === 'en cocina') $badge = 'badge-cocina';
|
|
if ($en === 'listo para retirar') $badge = 'badge-listo';
|
|
if ($en === 'en camino') $badge = 'badge-camino';
|
|
?>
|
|
<tr>
|
|
<td><strong>#<?php echo $ped['id_pedido']; ?></strong></td>
|
|
<td style="color:#6b7280;"><?php echo date('d/m/Y H:i', strtotime($ped['fecha'])); ?> hs</td>
|
|
<td><?php echo htmlspecialchars($ped['cliente']); ?></td>
|
|
<td><strong>$<?php echo number_format($ped['total'], 2, ',', '.'); ?></strong></td>
|
|
<td>
|
|
<div class="estado-cell">
|
|
<span class="badge <?php echo $badge; ?>"><?php echo htmlspecialchars($ped['estado']); ?></span>
|
|
|
|
<?php if ($ped['pago_estado'] === 'Aprobado'): ?>
|
|
<span class="pago-ok"><i class="fa-solid fa-circle-dollar-to-slot"></i> Pago aprobado</span>
|
|
<?php else: ?>
|
|
<form action="pedidos.php" method="POST" style="display:inline;">
|
|
<input type="hidden" name="id_pedido" value="<?php echo $ped['id_pedido']; ?>">
|
|
<input type="hidden" name="nuevo_pago" value="Aprobado">
|
|
<button type="submit" name="cambiar_pago" class="pago-pendiente-btn" title="Clic para registrar pago recibido">
|
|
<i class="fa-solid fa-hand-holding-dollar"></i> Pago pendiente
|
|
</button>
|
|
</form>
|
|
<?php endif; ?>
|
|
|
|
<?php if (!empty($ped['comprobante'])): ?>
|
|
<a href="imprimir_ticket.php?file=<?php echo urlencode($ped['comprobante']); ?>" target="_blank" class="btn-comprobante">
|
|
<i class="fa-solid fa-receipt"></i> Ver comprobante
|
|
</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<a href="ver_detalle.php?id=<?php echo $ped['id_pedido']; ?>&desde=pedidos" class="btn-detalle">
|
|
<i class="fa-solid fa-list-ul"></i> Ver detalle
|
|
</a>
|
|
</td>
|
|
<td>
|
|
<form action="pedidos.php" method="POST" class="form-estado">
|
|
<input type="hidden" name="id_pedido" value="<?php echo $ped['id_pedido']; ?>">
|
|
<input type="hidden" name="cambiar_estado" value="1">
|
|
<select name="nuevo_estado" class="select-status" required>
|
|
<option value="Pendiente" <?php echo $ped['estado'] === 'Pendiente' ? 'selected' : ''; ?>>Pendiente</option>
|
|
<option value="En cocina" <?php echo $ped['estado'] === 'En cocina' ? 'selected' : ''; ?>>En cocina</option>
|
|
<option value="Listo para retirar" <?php echo $ped['estado'] === 'Listo para retirar' ? 'selected' : ''; ?>>Listo para retirar</option>
|
|
<option value="En camino" <?php echo $ped['estado'] === 'En camino' ? 'selected' : ''; ?>>En camino</option>
|
|
<option value="Entregado">Entregado (Finalizar)</option>
|
|
<option value="Cancelado">Cancelado</option>
|
|
</select>
|
|
<button type="submit" class="btn-confirmar" title="Confirmar cambio">
|
|
<i class="fa-solid fa-check"></i>
|
|
</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
<?php endwhile; ?>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- HISTORIAL COLAPSABLE -->
|
|
<button class="historial-toggle" onclick="toggleHistorial(this)">
|
|
<span class="toggle-left">
|
|
<i class="fa-solid fa-clock-rotate-left" style="color:#6b7280;"></i>
|
|
Historial de pedidos finalizados
|
|
</span>
|
|
<i class="fa-solid fa-chevron-down chevron"></i>
|
|
</button>
|
|
|
|
<div class="historial-body" id="historialBody">
|
|
<div class="section-card">
|
|
<div class="section-card-body">
|
|
<table class="admin-table">
|
|
<thead>
|
|
<tr>
|
|
<th>N° Pedido</th>
|
|
<th>Fecha / Hora</th>
|
|
<th>Cliente</th>
|
|
<th>Total cobrado</th>
|
|
<th>Resolución</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if (mysqli_num_rows($res_historial) == 0): ?>
|
|
<tr>
|
|
<td colspan="5" style="text-align:center; color:#9ca3af; padding:36px 14px;">
|
|
<i class="fa-solid fa-box-open" style="font-size:1.4rem; display:block; margin-bottom:6px;"></i>
|
|
Todavía no hay pedidos finalizados.
|
|
</td>
|
|
</tr>
|
|
<?php else: ?>
|
|
<?php while ($hist = mysqli_fetch_assoc($res_historial)):
|
|
$badge_h = ($hist['estado'] === 'Entregado') ? 'badge-entregado' : 'badge-cancelado';
|
|
?>
|
|
<tr>
|
|
<td><strong>#<?php echo $hist['id_pedido']; ?></strong></td>
|
|
<td style="color:#6b7280;"><?php echo date('d/m/Y H:i', strtotime($hist['fecha'])); ?> hs</td>
|
|
<td><?php echo htmlspecialchars($hist['cliente']); ?></td>
|
|
<td>$<?php echo number_format($hist['total'], 2, ',', '.'); ?></td>
|
|
<td>
|
|
<div class="estado-cell">
|
|
<span class="badge <?php echo $badge_h; ?>"><?php echo htmlspecialchars($hist['estado']); ?></span>
|
|
|
|
<?php if ($hist['pago_estado'] === 'Aprobado'): ?>
|
|
<span class="pago-ok"><i class="fa-solid fa-circle-dollar-to-slot"></i> Pago aprobado</span>
|
|
<?php else: ?>
|
|
<span class="pago-pendiente-tag"><i class="fa-solid fa-hand-holding-dollar"></i> Pago pendiente</span>
|
|
<?php endif; ?>
|
|
|
|
<?php if (!empty($hist['comprobante'])): ?>
|
|
<a href="imprimir_ticket.php?file=<?php echo urlencode($hist['comprobante']); ?>" target="_blank" class="btn-comprobante">
|
|
<i class="fa-solid fa-receipt"></i> Ver comprobante
|
|
</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<?php endwhile; ?>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<script>
|
|
function toggleHistorial(btn) {
|
|
btn.classList.toggle('open');
|
|
document.getElementById('historialBody').classList.toggle('open');
|
|
}
|
|
</script>
|
|
|
|
<?php if (isset($_SESSION['url_whatsapp'])): ?>
|
|
<script>
|
|
window.open("<?php echo $_SESSION['url_whatsapp']; ?>", "_blank");
|
|
</script>
|
|
<?php unset($_SESSION['url_whatsapp']); ?>
|
|
<?php endif; ?>
|
|
|
|
</body>
|
|
</html>
|