Files
bot_palmas/admin/Layout.php
T
Lizandro GuarnizoandClaude Sonnet 4.6 332c808bf2 remove: drop Pendientes from nav menu
Pending-approval flow is no longer used. Remove the nav link so the
page is no longer reachable from the sidebar (routes and backend logic
left intact in case they're needed later).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 17:42:51 -05:00

151 lines
7.2 KiB
PHP

<?php
declare(strict_types=1);
class Layout
{
private static function h(string $v): string
{
return htmlspecialchars($v, ENT_QUOTES, 'UTF-8');
}
private static function icon(string $name): string
{
$s = 'width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"';
$icons = [
'dashboard' => '<svg '.$s.'><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/></svg>',
'live' => '<svg '.$s.'><circle cx="12" cy="12" r="2"/><path d="M16.24 7.76a6 6 0 0 1 0 8.49M7.76 16.24a6 6 0 0 1 0-8.49"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14M4.93 19.07a10 10 0 0 1 0-14.14"/></svg>',
'chat' => '<svg '.$s.'><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>',
'pending' => '<svg '.$s.'><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>',
'companies' => '<svg '.$s.'><path d="M6 22V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18"/><path d="M6 12H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2"/><path d="M18 9h2a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-2"/><line x1="10" y1="6" x2="14" y2="6"/><line x1="10" y1="10" x2="14" y2="10"/><line x1="10" y1="14" x2="14" y2="14"/><line x1="10" y1="18" x2="14" y2="18"/></svg>',
'bot-config' => '<svg '.$s.'><rect x="4" y="4" width="16" height="16" rx="2"/><rect x="9" y="9" width="6" height="6"/><path d="M15 2v2M9 2v2M2 15h2M2 9h2M15 20v2M9 20v2M20 15h2M20 9h2"/></svg>',
'conv-flow' => '<svg '.$s.'><circle cx="18" cy="18" r="3"/><circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M6 9v6"/><path d="M13 6h3a2 2 0 0 1 2 2v7"/></svg>',
'settings' => '<svg '.$s.'><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>',
'sync' => '<svg '.$s.'><path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"/><path d="M8 16H3v5"/></svg>',
'send' => '<svg '.$s.'><path d="m22 2-7 20-4-9-9-4Z"/><path d="M22 2 11 13"/></svg>',
];
return $icons[$name] ?? '';
}
public static function close(): string
{
return '</div></body></html>';
}
public static function open(
string $title,
string $active,
string $userName,
int $pending = 0
): string {
$t = self::h($title);
$u = self::h($userName);
$groups = [
[
['dashboard', '/admin/dashboard', 'dashboard', 'Dashboard'],
['live', '/admin/live', 'live', 'Live'],
['chat', '/admin/chat', 'chat', 'Chat'],
],
[
['companies', '/admin/companies', 'companies', 'Empresas'],
],
[
['bot-config', '/admin/bot-config', 'bot-config', 'Bot'],
['conv-flow', '/admin/conversation-flow', 'conv-flow', 'Flujos'],
['settings', '/admin/settings', 'settings', 'Ajustes'],
],
];
$navLinks = '';
foreach ($groups as $gi => $group) {
if ($gi > 0) {
$navLinks .= '<span class="nav-sep"></span>';
}
foreach ($group as $item) {
[$key, $href, $iconKey, $label] = $item;
$badge = isset($item[4]) && $item[4] > 0
? '<span class="nav-badge">' . (int)$item[4] . '</span>'
: '';
$cls = $active === $key ? ' active' : '';
$svg = self::icon($iconKey);
$navLinks .= "<a href=\"{$href}\" class=\"nav-link{$cls}\" onclick=\"closeNav()\">{$svg}<span>{$label}</span>{$badge}</a>";
}
}
$navLinks .= '<span class="nav-sep"></span>';
$navLinks .= '<a href="/admin/sync-companies" class="nav-link nav-action" title="Sincronizar ERP" onclick="return confirm(\'¿Sincronizar empresas?\')&&(closeNav(),true)">' . self::icon('sync') . '</a>';
$navLinks .= '<a href="/admin/process-queue" class="nav-link nav-action" title="Procesar cola" onclick="return confirm(\'¿Procesar cola de mensajes?\')&&(closeNav(),true)">' . self::icon('send') . '</a>';
$initial = mb_strtoupper(mb_substr($userName, 0, 1, 'UTF-8'), 'UTF-8');
return <<<HTML
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{$t} &mdash; Palmas360</title>
<link rel="stylesheet" href="/assets/app.css?v=2">
</head>
<body>
<header class="topbar">
<div class="topbar-inner">
<div class="topbar-left">
<button class="hamburger" id="hamburgerBtn" onclick="toggleNav()" aria-label="Menú">
<span></span><span></span><span></span>
</button>
<a href="/admin/dashboard" class="brand">Palmas<strong>360</strong></a>
</div>
<nav class="topnav">
{$navLinks}
</nav>
<div class="topbar-right">
<div class="user-chip">
<div class="user-avatar">{$initial}</div>
<span class="user-name">{$u}</span>
</div>
<a href="/logout" class="btn-out">Salir</a>
</div>
</div>
</header>
<div class="nav-overlay" id="navOverlay" onclick="closeNav()"></div>
<div class="nav-drawer" id="navDrawer">
<div class="nav-drawer-header">
<a href="/admin/dashboard" class="brand" onclick="closeNav()">Palmas<strong>360</strong></a>
<button class="drawer-close" onclick="closeNav()">&#x2715;</button>
</div>
<div class="nav-drawer-body">
{$navLinks}
</div>
<div class="nav-drawer-footer">
<div class="user-chip">
<div class="user-avatar">{$initial}</div>
<span style="font-size:13px;color:#374151;font-weight:500">{$u}</span>
</div>
<a href="/logout" class="btn-out" style="font-size:12px;padding:4px 12px">Salir</a>
</div>
</div>
<script>
function toggleNav() {
const open = document.getElementById('navDrawer').classList.toggle('open');
document.getElementById('navOverlay').classList.toggle('show', open);
document.getElementById('hamburgerBtn').classList.toggle('active', open);
}
function closeNav() {
document.getElementById('navDrawer').classList.remove('open');
document.getElementById('navOverlay').classList.remove('show');
document.getElementById('hamburgerBtn').classList.remove('active');
}
document.addEventListener('keydown', e => { if (e.key === 'Escape') closeNav(); });
</script>
HTML;
}
}