refactor: reorganizar openspec y planificacion con spec recaptcha
- 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>
This commit is contained in:
473
_planificacion/01-design-system/13-PANEL-ADMINISTRACION.md
Normal file
473
_planificacion/01-design-system/13-PANEL-ADMINISTRACION.md
Normal file
@@ -0,0 +1,473 @@
|
||||
# 🎛️ 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)
|
||||
Reference in New Issue
Block a user