- renombrar openspec/ a _openspec/ (carpeta auxiliar) - mover specs de features a changes/ - crear specs base: arquitectura-limpia, estandares-codigo, nomenclatura - migrar _planificacion/ con design-system y roi-theme-template - agregar especificacion recaptcha anti-spam (proposal, tasks, spec) - corregir rutas y referencias en todas las specs Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
13 KiB
13 KiB
🎛️ PANEL DE ADMINISTRACIÓN PRINCIPAL
Arquitectura del Sistema
El panel de administración utiliza un sistema de tabs (pestañas) de Bootstrap 5, donde todos los componentes existen en una sola página y se alternan mediante JavaScript.
Características Principales
- ✅ Single Page: Todos los componentes en un solo archivo
main.php - ✅ Bootstrap Tabs: Navegación mediante
nav-tabsytab-pane - ✅ Carga Modular: Cada componente se incluye con
require_once - ✅ Botones Globales: Save/Cancel compartidos para todos los componentes
- ✅ Sin Recargas: Cambio de tabs sin reload de página
Estructura del main.php
<?php
/**
* Admin Panel - Main Page
*/
if (!defined('ABSPATH')) {
exit;
}
?>
<div class="wrap apus-admin">
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
<p class="description">Configure los componentes del tema</p>
<!-- Navigation Tabs -->
<ul class="nav nav-tabs" role="tablist">
<!-- Tabs aquí -->
</ul>
<!-- Tab Content -->
<div class="tab-content mt-3">
<?php
// Componentes incluidos aquí
?>
</div>
<!-- Action Buttons (Global) -->
<div class="d-flex justify-content-end gap-2 p-3 rounded border mt-4"
style="background-color: #f8f9fa;">
<button type="button" class="btn btn-outline-secondary" id="cancelChanges">
<i class="bi bi-x-circle me-1"></i>
Cancelar
</button>
<button type="button" id="saveSettings"
class="btn fw-semibold text-white"
style="background-color: #FF8600; border-color: #FF8600;">
<i class="bi bi-check-circle me-1"></i>
Guardar Cambios
</button>
</div>
</div>
Agregar un Nuevo Tab
Paso 1: Agregar el Tab en la Navegación
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item">
<a class="nav-link active"
data-bs-toggle="tab"
data-bs-target="#[tabId]"
href="#[tabId]"
role="tab">
<i class="bi bi-[icon-class] me-2"></i>
[Nombre del Componente]
</a>
</li>
<!-- Más tabs... -->
</ul>
Reemplazar:
[tabId]: ID único del tab (ej:notificationBarTab,siteFooterTab)[icon-class]: Clase del icono de Bootstrap Icons (ej:megaphone-fill)[Nombre del Componente]: Nombre visible del tab (ej: "Barra de Notificaciones")
Paso 2: Incluir el Componente en Tab Content
<div class="tab-content mt-3">
<?php
/**
* [Component Name] Component
* Archivo: Admin/Components/component-[name].php
*/
require_once APUS_ADMIN_PANEL_PATH . 'Admin/Components/component-[name].php';
?>
<!-- Más componentes... -->
</div>
Reemplazar:
[Component Name]: Nombre descriptivo del componente[name]: Nombre del archivo (ej:notification-bar,site-footer)
Paso 3: Crear el Archivo del Componente
Crear Admin/Components/component-[name].php:
<!-- Tab Pane: [Component Name] -->
<div class="tab-pane fade show active" id="[tabId]" role="tabpanel">
<!-- Header del Tab -->
<div class="rounded p-4 mb-4 shadow text-white"
style="background: linear-gradient(135deg, #0E2337 0%, #1e3a5f 100%);
border-left: 4px solid #FF8600;">
<div class="d-flex align-items-center justify-content-between flex-wrap gap-3">
<div>
<h3 class="h4 mb-1 fw-bold">
<i class="bi bi-[icon-class] me-2" style="color: #FF8600;"></i>
[Título del Componente]
</h3>
<p class="mb-0 small" style="opacity: 0.85;">
[Descripción breve del componente]
</p>
</div>
<button type="button" class="btn btn-sm btn-outline-light" id="reset[Component]Defaults">
<i class="bi bi-arrow-counterclockwise me-1"></i>
Restaurar valores por defecto
</button>
</div>
</div>
<!-- Grid de Configuración -->
<div class="row g-3">
<!-- Columna izquierda: Configuración -->
<div class="col-lg-6">
<!-- Cards de configuración -->
</div>
<!-- Columna derecha: Preview -->
<div class="col-lg-6">
<!-- Card de vista previa -->
</div>
</div>
</div><!-- /tab-pane -->
Iconos Sugeridos por Tipo de Componente
| Tipo de Componente | Icono | Clase Bootstrap Icons |
|---|---|---|
| Notificaciones/Anuncios | 📢 | bi-megaphone-fill |
| Navegación/Menú | 📋 | bi-layout-text-window |
| Sección Hero | 🖼️ | bi-image |
| Footer | ⬇️ | bi-box-arrow-down |
| Formularios | 📝 | bi-clipboard-check |
| Call-to-Action | 👆 | bi-cursor-fill |
| Testimonios | 💬 | bi-chat-quote |
| Configuración | ⚙️ | bi-gear-fill |
Ejemplo Completo: Agregar Componente de Navegación
1. Agregar Tab en main.php
<ul class="nav nav-tabs" role="tablist">
<!-- Tab existente -->
<li class="nav-item">
<a class="nav-link active"
data-bs-toggle="tab"
data-bs-target="#topBarTab"
href="#topBarTab"
role="tab">
<i class="bi bi-megaphone-fill me-2"></i>
Top Bar
</a>
</li>
<!-- NUEVO TAB -->
<li class="nav-item">
<a class="nav-link"
data-bs-toggle="tab"
data-bs-target="#navbarTab"
href="#navbarTab"
role="tab">
<i class="bi bi-layout-text-window me-2"></i>
Navbar
</a>
</li>
</ul>
Notas:
- El primer tab tiene
class="nav-link active" - Los demás tabs solo tienen
class="nav-link"
2. Incluir Componente en Tab Content
<div class="tab-content mt-3">
<?php
// Componente existente
require_once APUS_ADMIN_PANEL_PATH . 'Admin/Components/component-top-bar.php';
// NUEVO COMPONENTE
require_once APUS_ADMIN_PANEL_PATH . 'Admin/Components/component-navbar.php';
?>
</div>
3. Crear component-navbar.php
Crear archivo: Admin/Components/component-navbar.php
<!-- Tab Pane: Navbar -->
<div class="tab-pane fade" id="navbarTab" role="tabpanel">
<!-- Header del Tab -->
<div class="rounded p-4 mb-4 shadow text-white"
style="background: linear-gradient(135deg, #0E2337 0%, #1e3a5f 100%);
border-left: 4px solid #FF8600;">
<div class="d-flex align-items-center justify-content-between flex-wrap gap-3">
<div>
<h3 class="h4 mb-1 fw-bold">
<i class="bi bi-layout-text-window me-2" style="color: #FF8600;"></i>
Configuración del Navbar
</h3>
<p class="mb-0 small" style="opacity: 0.85;">
Gestiona los colores, estilo y comportamiento del menú de navegación
</p>
</div>
<button type="button" class="btn btn-sm btn-outline-light" id="resetNavbarDefaults">
<i class="bi bi-arrow-counterclockwise me-1"></i>
Restaurar valores por defecto
</button>
</div>
</div>
<!-- Grid de Configuración -->
<div class="row g-3">
<!-- Configuración -->
<div class="col-lg-6">
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-palette me-2" style="color: #FF8600;"></i>
Colores
</h5>
<!-- Campos de configuración aquí -->
</div>
</div>
</div>
<!-- Vista Previa -->
<div class="col-lg-6">
<div class="card shadow-sm mb-3" style="border-left: 4px solid #FF8600;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-eye me-2" style="color: #FF8600;"></i>
Vista Previa
</h5>
<!-- Preview del componente aquí -->
<div id="navbarPreview">
<!-- HTML idéntico al front-end -->
</div>
</div>
</div>
</div>
</div>
</div><!-- /tab-pane -->
Notas:
- El primer tab-pane tiene
class="tab-pane fade show active" - Los demás tab-panes tienen
class="tab-pane fade"
Orden de los Tabs
Por Prioridad
Organizar los tabs de más importante a menos importante:
- Componentes críticos/visibles (Header, Navbar, Hero)
- Componentes de contenido (Secciones, CTAs)
- Componentes complementarios (Footer, Forms)
- Configuraciones generales
Ejemplo de Orden
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item"><!-- Barra de Notificaciones --></li>
<li class="nav-item"><!-- Navbar --></li>
<li class="nav-item"><!-- Hero Section --></li>
<li class="nav-item"><!-- Call-to-Action --></li>
<li class="nav-item"><!-- Footer --></li>
<li class="nav-item"><!-- Configuración General --></li>
</ul>
Botones Globales Save/Cancel
Los botones de guardar y cancelar son globales para todos los tabs:
<div class="d-flex justify-content-end gap-2 p-3 rounded border mt-4"
style="background-color: #f8f9fa; border-color: #e9ecef !important;">
<!-- Cancelar -->
<button type="button" class="btn btn-outline-secondary" id="cancelChanges">
<i class="bi bi-x-circle me-1"></i>
Cancelar
</button>
<!-- Guardar -->
<button type="button" id="saveSettings"
class="btn fw-semibold text-white"
style="background-color: #FF8600; border-color: #FF8600;"
disabled>
<i class="bi bi-check-circle me-1"></i>
Guardar Cambios
</button>
</div>
JavaScript para Activar/Desactivar Guardar
// Detectar cambios en cualquier campo
document.querySelectorAll('input, select, textarea').forEach(field => {
field.addEventListener('change', function() {
// Activar botón de guardar
document.getElementById('saveSettings').disabled = false;
});
});
// Guardar cambios
document.getElementById('saveSettings').addEventListener('click', function() {
// Guardar configuración de todos los componentes
saveAllConfigs();
// Desactivar botón de guardar
this.disabled = true;
});
// Cancelar cambios
document.getElementById('cancelChanges').addEventListener('click', function() {
if (confirm('¿Descartar todos los cambios sin guardar?')) {
// Recargar configuraciones originales
loadAllConfigs();
// Desactivar botón de guardar
document.getElementById('saveSettings').disabled = true;
}
});
Responsive Behavior
Desktop (≥992px)
- Tabs en una sola línea horizontal
- Grid de 2 columnas (configuración + preview)
- Espaciado completo
Tablet (768px - 991px)
- Tabs pueden hacer wrap a 2 líneas
- Grid de 2 columnas (se mantiene)
- Espaciado reducido
Mobile (<768px)
- Tabs en scroll horizontal o stacked vertical
- Grid stacked (1 columna)
- Botones Save/Cancel pueden hacer stack
@media (max-width: 991px) {
.nav-tabs {
flex-wrap: wrap;
}
.nav-tabs .nav-link {
font-size: 0.9rem;
padding: 0.5rem 0.75rem;
}
}
@media (max-width: 767px) {
.nav-tabs {
overflow-x: auto;
flex-wrap: nowrap;
}
.nav-tabs .nav-item {
white-space: nowrap;
}
}
Funcionalidad Adicional (Opcional)
Badges de Estado en Tabs
<li class="nav-item">
<a class="nav-link" data-bs-toggle="tab" data-bs-target="#[tabId]" role="tab">
<i class="bi bi-[icon-class] me-2"></i>
[Nombre del Componente]
<span class="badge bg-success ms-2" style="font-size: 0.65rem;">Activo</span>
</a>
</li>
Estados posibles:
bg-success: Activobg-secondary: Inactivobg-warning text-dark: Requiere atención
Indicador de Cambios Sin Guardar
// Agregar asterisco al tab si tiene cambios sin guardar
function markTabAsModified(tabId) {
const tabLink = document.querySelector(`a[data-bs-target="#${tabId}"]`);
if (!tabLink.querySelector('.modified-indicator')) {
tabLink.innerHTML += ' <span class="modified-indicator" style="color: #FF8600;">*</span>';
}
}
Checklist de Implementación
Cuando agregues un nuevo componente al panel, asegúrate de:
- Agregar el tab en la navegación (
<ul class="nav nav-tabs">) - Crear el archivo PHP del componente (
component-[name].php) - Incluir el componente en tab-content con
require_once - Crear archivo CSS del componente (
component-[name].css) - Crear archivo JS del componente (
component-[name].js) - Crear archivo de configuración JSON (
[name]-config.json) - Agregar estilos específicos del componente
- Implementar vista previa en tiempo real
- Conectar con sistema de guardar/cancelar global
- Probar responsive behavior
- Verificar que el tab-pane tenga el ID correcto
- Verificar que el primer tab y tab-pane tengan
activeyshow