- 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>
474 lines
13 KiB
Markdown
474 lines
13 KiB
Markdown
# 🎛️ 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-tabs` y `tab-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
|
|
<?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
|
|
|
|
```php
|
|
<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
|
|
|
|
```php
|
|
<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`:
|
|
|
|
```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
|
|
|
|
```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
|
|
|
|
```php
|
|
<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`
|
|
|
|
```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:
|
|
|
|
1. Componentes críticos/visibles (Header, Navbar, Hero)
|
|
2. Componentes de contenido (Secciones, CTAs)
|
|
3. Componentes complementarios (Footer, Forms)
|
|
4. Configuraciones generales
|
|
|
|
### Ejemplo de Orden
|
|
|
|
```php
|
|
<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:
|
|
|
|
```php
|
|
<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
|
|
|
|
```javascript
|
|
// 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
|
|
|
|
```css
|
|
@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
|
|
|
|
```php
|
|
<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`: Activo
|
|
- `bg-secondary`: Inactivo
|
|
- `bg-warning text-dark`: Requiere atención
|
|
|
|
### Indicador de Cambios Sin Guardar
|
|
|
|
```javascript
|
|
// 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 `active` y `show`
|
|
|
|
---
|
|
|
|
## Volver al Índice
|
|
|
|
[← Volver al README](README.md)
|