Migración completa a Clean Architecture con componentes funcionales
- Reorganización de estructura: Admin/, Public/, Shared/, Schemas/ - 12 componentes migrados: TopNotificationBar, Navbar, CtaLetsTalk, Hero, FeaturedImage, TableOfContents, CtaBoxSidebar, SocialShare, CtaPost, RelatedPost, ContactForm, Footer - Panel de administración con tabs Bootstrap 5 funcionales - Schemas JSON para configuración de componentes - Renderers dinámicos con CSSGeneratorService (cero CSS hardcodeado) - FormBuilders para UI admin con Design System consistente - Fix: Bootstrap JS cargado en header para tabs funcionales - Fix: buildTextInput maneja valores mixed (bool/string) - Eliminación de estructura legacy (src/, admin/, assets/css/componente-*) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
160
Admin/Infrastructure/Ui/AdminDashboardRenderer.php
Normal file
160
Admin/Infrastructure/Ui/AdminDashboardRenderer.php
Normal file
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ROITheme\Admin\Infrastructure\Ui;
|
||||
|
||||
use ROITheme\Admin\Domain\Contracts\DashboardRendererInterface;
|
||||
use ROITheme\Shared\Application\UseCases\GetComponentSettings\GetComponentSettingsUseCase;
|
||||
|
||||
/**
|
||||
* Renderiza el dashboard del panel de administración
|
||||
*
|
||||
* Infrastructure - Implementación con WordPress
|
||||
*/
|
||||
final class AdminDashboardRenderer implements DashboardRendererInterface
|
||||
{
|
||||
private const SUPPORTED_VIEWS = ['dashboard'];
|
||||
|
||||
/**
|
||||
* @param GetComponentSettingsUseCase|null $getComponentSettingsUseCase
|
||||
* @param array<string, mixed> $components Componentes disponibles
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly ?GetComponentSettingsUseCase $getComponentSettingsUseCase = null,
|
||||
private readonly array $components = []
|
||||
) {
|
||||
}
|
||||
|
||||
public function render(): string
|
||||
{
|
||||
ob_start();
|
||||
require __DIR__ . '/Views/dashboard.php';
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
public function supports(string $viewType): bool
|
||||
{
|
||||
return in_array($viewType, self::SUPPORTED_VIEWS, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene los componentes disponibles
|
||||
*
|
||||
* @return array<string, array<string, string>>
|
||||
*/
|
||||
public function getComponents(): array
|
||||
{
|
||||
return [
|
||||
'top-notification-bar' => [
|
||||
'id' => 'top-notification-bar',
|
||||
'label' => 'TopBar',
|
||||
'icon' => 'bi-megaphone-fill',
|
||||
],
|
||||
'navbar' => [
|
||||
'id' => 'navbar',
|
||||
'label' => 'Navbar',
|
||||
'icon' => 'bi-list',
|
||||
],
|
||||
'cta-lets-talk' => [
|
||||
'id' => 'cta-lets-talk',
|
||||
'label' => "Let's Talk",
|
||||
'icon' => 'bi-lightning-charge-fill',
|
||||
],
|
||||
'hero' => [
|
||||
'id' => 'hero',
|
||||
'label' => 'Hero Section',
|
||||
'icon' => 'bi-image',
|
||||
],
|
||||
'featured-image' => [
|
||||
'id' => 'featured-image',
|
||||
'label' => 'Featured Image',
|
||||
'icon' => 'bi-card-image',
|
||||
],
|
||||
'table-of-contents' => [
|
||||
'id' => 'table-of-contents',
|
||||
'label' => 'Table of Contents',
|
||||
'icon' => 'bi-list-nested',
|
||||
],
|
||||
'cta-box-sidebar' => [
|
||||
'id' => 'cta-box-sidebar',
|
||||
'label' => 'CTA Sidebar',
|
||||
'icon' => 'bi-megaphone',
|
||||
],
|
||||
'social-share' => [
|
||||
'id' => 'social-share',
|
||||
'label' => 'Social Share',
|
||||
'icon' => 'bi-share',
|
||||
],
|
||||
'cta-post' => [
|
||||
'id' => 'cta-post',
|
||||
'label' => 'CTA Post',
|
||||
'icon' => 'bi-megaphone-fill',
|
||||
],
|
||||
'related-post' => [
|
||||
'id' => 'related-post',
|
||||
'label' => 'Related Posts',
|
||||
'icon' => 'bi-grid-3x3-gap',
|
||||
],
|
||||
'contact-form' => [
|
||||
'id' => 'contact-form',
|
||||
'label' => 'Contact Form',
|
||||
'icon' => 'bi-envelope-paper',
|
||||
],
|
||||
'footer' => [
|
||||
'id' => 'footer',
|
||||
'label' => 'Footer',
|
||||
'icon' => 'bi-layout-text-window-reverse',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene las configuraciones de un componente
|
||||
*
|
||||
* @param string $componentName Nombre del componente
|
||||
* @return array<string, array<string, mixed>> Configuraciones agrupadas por grupo
|
||||
*/
|
||||
public function getComponentSettings(string $componentName): array
|
||||
{
|
||||
if ($this->getComponentSettingsUseCase === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->getComponentSettingsUseCase->execute($componentName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene el valor de un campo de configuración
|
||||
*
|
||||
* @param string $componentName Nombre del componente
|
||||
* @param string $groupName Nombre del grupo
|
||||
* @param string $attributeName Nombre del atributo
|
||||
* @param mixed $default Valor por defecto si no existe
|
||||
* @return mixed
|
||||
*/
|
||||
public function getFieldValue(string $componentName, string $groupName, string $attributeName, mixed $default = null): mixed
|
||||
{
|
||||
$settings = $this->getComponentSettings($componentName);
|
||||
|
||||
return $settings[$groupName][$attributeName] ?? $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene la clase del FormBuilder para un componente
|
||||
*
|
||||
* @param string $componentId ID del componente en kebab-case (ej: 'top-notification-bar')
|
||||
* @return string Namespace completo del FormBuilder
|
||||
*/
|
||||
public function getFormBuilderClass(string $componentId): string
|
||||
{
|
||||
// Convertir kebab-case a PascalCase
|
||||
// 'top-notification-bar' → 'TopNotificationBar'
|
||||
$className = str_replace('-', '', ucwords($componentId, '-'));
|
||||
|
||||
// Construir namespace completo
|
||||
// ROITheme\Admin\TopNotificationBar\Infrastructure\Ui\TopNotificationBarFormBuilder
|
||||
return "ROITheme\\Admin\\{$className}\\Infrastructure\\Ui\\{$className}FormBuilder";
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user