chore: purgar archivos no utilizados (plan 101 fase 1)
- eliminar carpetas vacias admin/herosection y bootstrapicons - eliminar 7 scripts legacy con credenciales hardcodeadas - eliminar formbuilder duplicado en shared/infrastructure/ui - eliminar 11 archivos .gitkeep en carpetas con contenido 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,697 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ROITheme\Shared\Infrastructure\Ui;
|
||||
|
||||
use ROITheme\Shared\Domain\Entities\Component;
|
||||
use ROITheme\Shared\Domain\Contracts\FormBuilderInterface;
|
||||
|
||||
/**
|
||||
* TopNotificationBarFormBuilder - Construye formulario de configuración
|
||||
*
|
||||
* RESPONSABILIDAD: Generar formulario HTML del admin para Top Notification Bar
|
||||
*
|
||||
* CARACTERÍSTICAS:
|
||||
* - 3 secciones: Visibilidad, Contenido, Estilos
|
||||
* - 19 campos configurables
|
||||
* - Lógica condicional (data-conditional-field)
|
||||
* - WordPress Media Library integration
|
||||
* - Vista previa en tiempo real
|
||||
*
|
||||
* @package ROITheme\Shared\Infrastructure\Ui
|
||||
*/
|
||||
final class TopNotificationBarFormBuilder implements FormBuilderInterface
|
||||
{
|
||||
public function build(Component $component): string
|
||||
{
|
||||
$data = $component->getData();
|
||||
$componentId = $component->getName();
|
||||
|
||||
$html = '<div class="roi-form-builder roi-top-notification-bar-form">';
|
||||
|
||||
// Sección de Visibilidad
|
||||
$html .= $this->buildVisibilitySection($data, $componentId);
|
||||
|
||||
// Sección de Contenido
|
||||
$html .= $this->buildContentSection($data, $componentId);
|
||||
|
||||
// Sección de Estilos
|
||||
$html .= $this->buildStylesSection($data, $componentId);
|
||||
|
||||
// Vista previa
|
||||
$html .= $this->buildPreviewSection($data);
|
||||
|
||||
$html .= '</div>';
|
||||
|
||||
// Agregar scripts de formulario
|
||||
$html .= $this->buildFormScripts($componentId);
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function buildVisibilitySection(array $data, string $componentId): string
|
||||
{
|
||||
$html = '<div class="roi-form-section" data-section="visibility">';
|
||||
$html .= '<h3 class="roi-form-section-title">Visibilidad</h3>';
|
||||
$html .= '<div class="roi-form-section-content">';
|
||||
|
||||
// Is Enabled
|
||||
$isEnabled = $data['visibility']['is_enabled'] ?? true;
|
||||
$html .= $this->buildToggle(
|
||||
'is_enabled',
|
||||
'Mostrar barra de notificación',
|
||||
$isEnabled,
|
||||
$componentId,
|
||||
'Activa o desactiva la barra de notificación superior'
|
||||
);
|
||||
|
||||
// Show On Pages
|
||||
$showOn = $data['visibility']['show_on_pages'] ?? 'all';
|
||||
$html .= $this->buildSelect(
|
||||
'show_on_pages',
|
||||
'Mostrar en',
|
||||
$showOn,
|
||||
[
|
||||
'all' => 'Todas las páginas',
|
||||
'home' => 'Solo página de inicio',
|
||||
'posts' => 'Solo posts individuales',
|
||||
'pages' => 'Solo páginas',
|
||||
'custom' => 'Páginas específicas'
|
||||
],
|
||||
$componentId,
|
||||
'Define en qué páginas se mostrará la barra'
|
||||
);
|
||||
|
||||
// Custom Page IDs
|
||||
$customPageIds = $data['visibility']['custom_page_ids'] ?? '';
|
||||
$html .= $this->buildTextField(
|
||||
'custom_page_ids',
|
||||
'IDs de páginas específicas',
|
||||
$customPageIds,
|
||||
$componentId,
|
||||
'IDs de páginas separados por comas',
|
||||
'Ej: 1,5,10',
|
||||
['data-conditional-field' => 'show_on_pages', 'data-conditional-value' => 'custom']
|
||||
);
|
||||
|
||||
// Hide On Mobile
|
||||
$hideOnMobile = $data['visibility']['hide_on_mobile'] ?? false;
|
||||
$html .= $this->buildToggle(
|
||||
'hide_on_mobile',
|
||||
'Ocultar en dispositivos móviles',
|
||||
$hideOnMobile,
|
||||
$componentId,
|
||||
'Oculta la barra en pantallas menores a 768px'
|
||||
);
|
||||
|
||||
// Is Dismissible
|
||||
$isDismissible = $data['visibility']['is_dismissible'] ?? false;
|
||||
$html .= $this->buildToggle(
|
||||
'is_dismissible',
|
||||
'Permitir cerrar',
|
||||
$isDismissible,
|
||||
$componentId,
|
||||
'Agrega botón X para que el usuario pueda cerrar la barra'
|
||||
);
|
||||
|
||||
// Dismissible Cookie Days
|
||||
$cookieDays = $data['visibility']['dismissible_cookie_days'] ?? 7;
|
||||
$html .= $this->buildNumberField(
|
||||
'dismissible_cookie_days',
|
||||
'Días antes de volver a mostrar',
|
||||
$cookieDays,
|
||||
$componentId,
|
||||
'Días que permanece oculta después de cerrarla',
|
||||
1,
|
||||
365,
|
||||
['data-conditional-field' => 'is_dismissible', 'data-conditional-value' => 'true']
|
||||
);
|
||||
|
||||
$html .= '</div>';
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function buildContentSection(array $data, string $componentId): string
|
||||
{
|
||||
$html = '<div class="roi-form-section" data-section="content">';
|
||||
$html .= '<h3 class="roi-form-section-title">Contenido</h3>';
|
||||
$html .= '<div class="roi-form-section-content">';
|
||||
|
||||
// Icon Type
|
||||
$iconType = $data['content']['icon_type'] ?? 'bootstrap';
|
||||
$html .= $this->buildSelect(
|
||||
'icon_type',
|
||||
'Tipo de ícono',
|
||||
$iconType,
|
||||
[
|
||||
'bootstrap' => 'Bootstrap Icons',
|
||||
'custom' => 'Imagen personalizada',
|
||||
'none' => 'Sin ícono'
|
||||
],
|
||||
$componentId,
|
||||
'Selecciona el tipo de ícono a mostrar'
|
||||
);
|
||||
|
||||
// Bootstrap Icon
|
||||
$bootstrapIcon = $data['content']['bootstrap_icon'] ?? 'bi-megaphone-fill';
|
||||
$html .= $this->buildTextField(
|
||||
'bootstrap_icon',
|
||||
'Clase de ícono Bootstrap',
|
||||
$bootstrapIcon,
|
||||
$componentId,
|
||||
'Nombre de la clase del ícono sin el prefijo \'bi\' (ej: megaphone-fill)',
|
||||
'Ej: bi-megaphone-fill',
|
||||
['data-conditional-field' => 'icon_type', 'data-conditional-value' => 'bootstrap']
|
||||
);
|
||||
|
||||
// Custom Icon URL
|
||||
$customIconUrl = $data['content']['custom_icon_url'] ?? '';
|
||||
$html .= $this->buildMediaField(
|
||||
'custom_icon_url',
|
||||
'Imagen personalizada',
|
||||
$customIconUrl,
|
||||
$componentId,
|
||||
'Sube una imagen personalizada (recomendado: PNG 24x24px)',
|
||||
['data-conditional-field' => 'icon_type', 'data-conditional-value' => 'custom']
|
||||
);
|
||||
|
||||
// Announcement Label
|
||||
$announcementLabel = $data['content']['announcement_label'] ?? 'Nuevo:';
|
||||
$html .= $this->buildTextField(
|
||||
'announcement_label',
|
||||
'Etiqueta del anuncio',
|
||||
$announcementLabel,
|
||||
$componentId,
|
||||
'Texto destacado en negrita antes del mensaje',
|
||||
'Ej: Nuevo:, Importante:, Aviso:'
|
||||
);
|
||||
|
||||
// Announcement Text
|
||||
$announcementText = $data['content']['announcement_text'] ?? 'Accede a más de 200,000 Análisis de Precios Unitarios actualizados para 2025.';
|
||||
$html .= $this->buildTextArea(
|
||||
'announcement_text',
|
||||
'Texto del anuncio',
|
||||
$announcementText,
|
||||
$componentId,
|
||||
'Mensaje principal del anuncio (máximo 200 caracteres)',
|
||||
3
|
||||
);
|
||||
|
||||
// Link Enabled
|
||||
$linkEnabled = $data['content']['link_enabled'] ?? true;
|
||||
$html .= $this->buildToggle(
|
||||
'link_enabled',
|
||||
'Mostrar enlace',
|
||||
$linkEnabled,
|
||||
$componentId,
|
||||
'Activa o desactiva el enlace de acción'
|
||||
);
|
||||
|
||||
// Link Text
|
||||
$linkText = $data['content']['link_text'] ?? 'Ver Catálogo';
|
||||
$html .= $this->buildTextField(
|
||||
'link_text',
|
||||
'Texto del enlace',
|
||||
$linkText,
|
||||
$componentId,
|
||||
'Texto del enlace de acción',
|
||||
'',
|
||||
['data-conditional-field' => 'link_enabled', 'data-conditional-value' => 'true']
|
||||
);
|
||||
|
||||
// Link URL
|
||||
$linkUrl = $data['content']['link_url'] ?? '#';
|
||||
$html .= $this->buildUrlField(
|
||||
'link_url',
|
||||
'URL del enlace',
|
||||
$linkUrl,
|
||||
$componentId,
|
||||
'URL de destino del enlace',
|
||||
'https://',
|
||||
['data-conditional-field' => 'link_enabled', 'data-conditional-value' => 'true']
|
||||
);
|
||||
|
||||
// Link Target
|
||||
$linkTarget = $data['content']['link_target'] ?? '_self';
|
||||
$html .= $this->buildSelect(
|
||||
'link_target',
|
||||
'Abrir enlace en',
|
||||
$linkTarget,
|
||||
[
|
||||
'_self' => 'Misma ventana',
|
||||
'_blank' => 'Nueva ventana'
|
||||
],
|
||||
$componentId,
|
||||
'Define cómo se abrirá el enlace',
|
||||
['data-conditional-field' => 'link_enabled', 'data-conditional-value' => 'true']
|
||||
);
|
||||
|
||||
$html .= '</div>';
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function buildStylesSection(array $data, string $componentId): string
|
||||
{
|
||||
$html = '<div class="roi-form-section" data-section="styles">';
|
||||
$html .= '<h3 class="roi-form-section-title">Estilos</h3>';
|
||||
$html .= '<div class="roi-form-section-content">';
|
||||
|
||||
// Background Color
|
||||
$bgColor = $data['styles']['background_color'] ?? '#FF8600';
|
||||
$html .= $this->buildColorField(
|
||||
'background_color',
|
||||
'Color de fondo',
|
||||
$bgColor,
|
||||
$componentId,
|
||||
'Color de fondo de la barra (por defecto: orange primary)'
|
||||
);
|
||||
|
||||
// Text Color
|
||||
$textColor = $data['styles']['text_color'] ?? '#FFFFFF';
|
||||
$html .= $this->buildColorField(
|
||||
'text_color',
|
||||
'Color del texto',
|
||||
$textColor,
|
||||
$componentId,
|
||||
'Color del texto del anuncio'
|
||||
);
|
||||
|
||||
// Link Color
|
||||
$linkColor = $data['styles']['link_color'] ?? '#FFFFFF';
|
||||
$html .= $this->buildColorField(
|
||||
'link_color',
|
||||
'Color del enlace',
|
||||
$linkColor,
|
||||
$componentId,
|
||||
'Color del enlace de acción'
|
||||
);
|
||||
|
||||
// Font Size
|
||||
$fontSize = $data['styles']['font_size'] ?? 'small';
|
||||
$html .= $this->buildSelect(
|
||||
'font_size',
|
||||
'Tamaño de fuente',
|
||||
$fontSize,
|
||||
[
|
||||
'extra-small' => 'Muy pequeño (0.75rem)',
|
||||
'small' => 'Pequeño (0.875rem)',
|
||||
'normal' => 'Normal (1rem)',
|
||||
'large' => 'Grande (1.125rem)'
|
||||
],
|
||||
$componentId,
|
||||
'Tamaño del texto del anuncio'
|
||||
);
|
||||
|
||||
// Padding Vertical
|
||||
$padding = $data['styles']['padding_vertical'] ?? 'normal';
|
||||
$html .= $this->buildSelect(
|
||||
'padding_vertical',
|
||||
'Padding vertical',
|
||||
$padding,
|
||||
[
|
||||
'compact' => 'Compacto (0.5rem)',
|
||||
'normal' => 'Normal (0.75rem)',
|
||||
'spacious' => 'Espacioso (1rem)'
|
||||
],
|
||||
$componentId,
|
||||
'Espaciado vertical interno de la barra'
|
||||
);
|
||||
|
||||
// Text Alignment
|
||||
$alignment = $data['styles']['text_alignment'] ?? 'center';
|
||||
$html .= $this->buildSelect(
|
||||
'text_alignment',
|
||||
'Alineación del texto',
|
||||
$alignment,
|
||||
[
|
||||
'left' => 'Izquierda',
|
||||
'center' => 'Centro',
|
||||
'right' => 'Derecha'
|
||||
],
|
||||
$componentId,
|
||||
'Alineación del contenido de la barra'
|
||||
);
|
||||
|
||||
// Animation Enabled
|
||||
$animationEnabled = $data['styles']['animation_enabled'] ?? false;
|
||||
$html .= $this->buildToggle(
|
||||
'animation_enabled',
|
||||
'Activar animación',
|
||||
$animationEnabled,
|
||||
$componentId,
|
||||
'Activa animación de entrada al cargar la página'
|
||||
);
|
||||
|
||||
// Animation Type
|
||||
$animationType = $data['styles']['animation_type'] ?? 'slide-down';
|
||||
$html .= $this->buildSelect(
|
||||
'animation_type',
|
||||
'Tipo de animación',
|
||||
$animationType,
|
||||
[
|
||||
'slide-down' => 'Deslizar desde arriba',
|
||||
'fade-in' => 'Aparecer gradualmente'
|
||||
],
|
||||
$componentId,
|
||||
'Tipo de animación de entrada',
|
||||
['data-conditional-field' => 'animation_enabled', 'data-conditional-value' => 'true']
|
||||
);
|
||||
|
||||
$html .= '</div>';
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function buildPreviewSection(array $data): string
|
||||
{
|
||||
$html = '<div class="roi-form-section roi-preview-section">';
|
||||
$html .= '<h3 class="roi-form-section-title">Vista Previa</h3>';
|
||||
$html .= '<div class="roi-form-section-content">';
|
||||
$html .= '<div id="roi-component-preview" class="border rounded p-3 bg-light">';
|
||||
$html .= '<p class="text-muted">La vista previa se actualizará automáticamente al modificar los campos.</p>';
|
||||
$html .= '</div>';
|
||||
$html .= '</div>';
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function buildToggle(string $name, string $label, bool $value, string $componentId, string $description = ''): string
|
||||
{
|
||||
$fieldId = "roi_{$componentId}_{$name}";
|
||||
$checked = $value ? 'checked' : '';
|
||||
|
||||
$html = '<div class="roi-form-field roi-form-field-toggle mb-3">';
|
||||
$html .= '<div class="form-check form-switch">';
|
||||
$html .= sprintf(
|
||||
'<input type="checkbox" class="form-check-input" id="%s" name="roi_component[%s][%s]" value="1" %s>',
|
||||
esc_attr($fieldId),
|
||||
esc_attr($componentId),
|
||||
esc_attr($name),
|
||||
$checked
|
||||
);
|
||||
$html .= sprintf('<label class="form-check-label" for="%s">%s</label>', esc_attr($fieldId), esc_html($label));
|
||||
$html .= '</div>';
|
||||
if (!empty($description)) {
|
||||
$html .= sprintf('<small class="form-text text-muted">%s</small>', esc_html($description));
|
||||
}
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function buildTextField(string $name, string $label, string $value, string $componentId, string $description = '', string $placeholder = '', array $attrs = []): string
|
||||
{
|
||||
$fieldId = "roi_{$componentId}_{$name}";
|
||||
|
||||
$html = '<div class="roi-form-field roi-form-field-text mb-3">';
|
||||
$html .= sprintf('<label for="%s" class="form-label">%s</label>', esc_attr($fieldId), esc_html($label));
|
||||
|
||||
$attrString = $this->buildAttributesString($attrs);
|
||||
|
||||
$html .= sprintf(
|
||||
'<input type="text" class="form-control" id="%s" name="roi_component[%s][%s]" value="%s" placeholder="%s"%s>',
|
||||
esc_attr($fieldId),
|
||||
esc_attr($componentId),
|
||||
esc_attr($name),
|
||||
esc_attr($value),
|
||||
esc_attr($placeholder),
|
||||
$attrString
|
||||
);
|
||||
|
||||
if (!empty($description)) {
|
||||
$html .= sprintf('<small class="form-text text-muted">%s</small>', esc_html($description));
|
||||
}
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function buildTextArea(string $name, string $label, string $value, string $componentId, string $description = '', int $rows = 3, array $attrs = []): string
|
||||
{
|
||||
$fieldId = "roi_{$componentId}_{$name}";
|
||||
|
||||
$html = '<div class="roi-form-field roi-form-field-textarea mb-3">';
|
||||
$html .= sprintf('<label for="%s" class="form-label">%s</label>', esc_attr($fieldId), esc_html($label));
|
||||
|
||||
$attrString = $this->buildAttributesString($attrs);
|
||||
|
||||
$html .= sprintf(
|
||||
'<textarea class="form-control" id="%s" name="roi_component[%s][%s]" rows="%d"%s>%s</textarea>',
|
||||
esc_attr($fieldId),
|
||||
esc_attr($componentId),
|
||||
esc_attr($name),
|
||||
$rows,
|
||||
$attrString,
|
||||
esc_textarea($value)
|
||||
);
|
||||
|
||||
if (!empty($description)) {
|
||||
$html .= sprintf('<small class="form-text text-muted">%s</small>', esc_html($description));
|
||||
}
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function buildSelect(string $name, string $label, string $value, array $options, string $componentId, string $description = '', array $attrs = []): string
|
||||
{
|
||||
$fieldId = "roi_{$componentId}_{$name}";
|
||||
|
||||
$html = '<div class="roi-form-field roi-form-field-select mb-3">';
|
||||
$html .= sprintf('<label for="%s" class="form-label">%s</label>', esc_attr($fieldId), esc_html($label));
|
||||
|
||||
$attrString = $this->buildAttributesString($attrs);
|
||||
|
||||
$html .= sprintf(
|
||||
'<select class="form-select" id="%s" name="roi_component[%s][%s]"%s>',
|
||||
esc_attr($fieldId),
|
||||
esc_attr($componentId),
|
||||
esc_attr($name),
|
||||
$attrString
|
||||
);
|
||||
|
||||
foreach ($options as $optValue => $optLabel) {
|
||||
$selected = ($value === $optValue) ? 'selected' : '';
|
||||
$html .= sprintf(
|
||||
'<option value="%s" %s>%s</option>',
|
||||
esc_attr($optValue),
|
||||
$selected,
|
||||
esc_html($optLabel)
|
||||
);
|
||||
}
|
||||
|
||||
$html .= '</select>';
|
||||
|
||||
if (!empty($description)) {
|
||||
$html .= sprintf('<small class="form-text text-muted">%s</small>', esc_html($description));
|
||||
}
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function buildNumberField(string $name, string $label, $value, string $componentId, string $description = '', int $min = null, int $max = null, array $attrs = []): string
|
||||
{
|
||||
$fieldId = "roi_{$componentId}_{$name}";
|
||||
|
||||
$html = '<div class="roi-form-field roi-form-field-number mb-3">';
|
||||
$html .= sprintf('<label for="%s" class="form-label">%s</label>', esc_attr($fieldId), esc_html($label));
|
||||
|
||||
$attrs['type'] = 'number';
|
||||
if ($min !== null) {
|
||||
$attrs['min'] = $min;
|
||||
}
|
||||
if ($max !== null) {
|
||||
$attrs['max'] = $max;
|
||||
}
|
||||
|
||||
$attrString = $this->buildAttributesString($attrs);
|
||||
|
||||
$html .= sprintf(
|
||||
'<input class="form-control" id="%s" name="roi_component[%s][%s]" value="%s"%s>',
|
||||
esc_attr($fieldId),
|
||||
esc_attr($componentId),
|
||||
esc_attr($name),
|
||||
esc_attr($value),
|
||||
$attrString
|
||||
);
|
||||
|
||||
if (!empty($description)) {
|
||||
$html .= sprintf('<small class="form-text text-muted">%s</small>', esc_html($description));
|
||||
}
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function buildUrlField(string $name, string $label, string $value, string $componentId, string $description = '', string $placeholder = '', array $attrs = []): string
|
||||
{
|
||||
$attrs['type'] = 'url';
|
||||
return $this->buildTextField($name, $label, $value, $componentId, $description, $placeholder, $attrs);
|
||||
}
|
||||
|
||||
private function buildColorField(string $name, string $label, string $value, string $componentId, string $description = ''): string
|
||||
{
|
||||
$fieldId = "roi_{$componentId}_{$name}";
|
||||
|
||||
$html = '<div class="roi-form-field roi-form-field-color mb-3">';
|
||||
$html .= sprintf('<label for="%s" class="form-label">%s</label>', esc_attr($fieldId), esc_html($label));
|
||||
$html .= '<div class="input-group">';
|
||||
$html .= sprintf(
|
||||
'<input type="color" class="form-control form-control-color" id="%s" name="roi_component[%s][%s]" value="%s">',
|
||||
esc_attr($fieldId),
|
||||
esc_attr($componentId),
|
||||
esc_attr($name),
|
||||
esc_attr($value)
|
||||
);
|
||||
$html .= sprintf(
|
||||
'<input type="text" class="form-control" value="%s" readonly>',
|
||||
esc_attr($value)
|
||||
);
|
||||
$html .= '</div>';
|
||||
if (!empty($description)) {
|
||||
$html .= sprintf('<small class="form-text text-muted">%s</small>', esc_html($description));
|
||||
}
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function buildMediaField(string $name, string $label, string $value, string $componentId, string $description = '', array $attrs = []): string
|
||||
{
|
||||
$fieldId = "roi_{$componentId}_{$name}";
|
||||
|
||||
$html = '<div class="roi-form-field roi-form-field-media mb-3">';
|
||||
$html .= sprintf('<label for="%s" class="form-label">%s</label>', esc_attr($fieldId), esc_html($label));
|
||||
$html .= '<div class="input-group">';
|
||||
|
||||
$attrString = $this->buildAttributesString($attrs);
|
||||
|
||||
$html .= sprintf(
|
||||
'<input type="text" class="form-control" id="%s" name="roi_component[%s][%s]" value="%s" readonly%s>',
|
||||
esc_attr($fieldId),
|
||||
esc_attr($componentId),
|
||||
esc_attr($name),
|
||||
esc_attr($value),
|
||||
$attrString
|
||||
);
|
||||
$html .= sprintf(
|
||||
'<button type="button" class="btn btn-primary roi-media-upload-btn" data-target="%s">Seleccionar</button>',
|
||||
esc_attr($fieldId)
|
||||
);
|
||||
$html .= '</div>';
|
||||
|
||||
if (!empty($value)) {
|
||||
$html .= sprintf('<div class="mt-2"><img src="%s" alt="Preview" style="max-width: 100px; height: auto;"></div>', esc_url($value));
|
||||
}
|
||||
|
||||
if (!empty($description)) {
|
||||
$html .= sprintf('<small class="form-text text-muted">%s</small>', esc_html($description));
|
||||
}
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function buildAttributesString(array $attrs): string
|
||||
{
|
||||
$attrString = '';
|
||||
foreach ($attrs as $key => $value) {
|
||||
$attrString .= sprintf(' %s="%s"', esc_attr($key), esc_attr($value));
|
||||
}
|
||||
return $attrString;
|
||||
}
|
||||
|
||||
private function buildFormScripts(string $componentId): string
|
||||
{
|
||||
return <<<SCRIPT
|
||||
<script>
|
||||
(function($) {
|
||||
'use strict';
|
||||
|
||||
$(document).ready(function() {
|
||||
// Conditional logic
|
||||
$('[data-conditional-field]').each(function() {
|
||||
const field = $(this);
|
||||
const targetFieldName = field.data('conditional-field');
|
||||
const targetValue = field.data('conditional-value');
|
||||
const targetField = $('[name*="[' + targetFieldName + ']"]');
|
||||
|
||||
function updateVisibility() {
|
||||
let currentValue;
|
||||
if (targetField.is(':checkbox')) {
|
||||
currentValue = targetField.is(':checked') ? 'true' : 'false';
|
||||
} else {
|
||||
currentValue = targetField.val();
|
||||
}
|
||||
|
||||
if (currentValue === targetValue) {
|
||||
field.closest('.roi-form-field').show();
|
||||
} else {
|
||||
field.closest('.roi-form-field').hide();
|
||||
}
|
||||
}
|
||||
|
||||
targetField.on('change', updateVisibility);
|
||||
updateVisibility();
|
||||
});
|
||||
|
||||
// Media upload
|
||||
$('.roi-media-upload-btn').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
const button = $(this);
|
||||
const targetId = button.data('target');
|
||||
const targetField = $('#' + targetId);
|
||||
|
||||
const mediaUploader = wp.media({
|
||||
title: 'Seleccionar imagen',
|
||||
button: { text: 'Usar esta imagen' },
|
||||
multiple: false
|
||||
});
|
||||
|
||||
mediaUploader.on('select', function() {
|
||||
const attachment = mediaUploader.state().get('selection').first().toJSON();
|
||||
targetField.val(attachment.url);
|
||||
|
||||
const preview = targetField.closest('.roi-form-field-media').find('img');
|
||||
if (preview.length) {
|
||||
preview.attr('src', attachment.url);
|
||||
} else {
|
||||
targetField.closest('.input-group').after('<div class="mt-2"><img src="' + attachment.url + '" alt="Preview" style="max-width: 100px; height: auto;"></div>');
|
||||
}
|
||||
});
|
||||
|
||||
mediaUploader.open();
|
||||
});
|
||||
|
||||
// Color picker sync
|
||||
$('.form-control-color').on('change', function() {
|
||||
$(this).next('input[type="text"]').val($(this).val());
|
||||
});
|
||||
|
||||
// Auto-update preview
|
||||
$('.roi-form-field input, .roi-form-field select, .roi-form-field textarea').on('change keyup', function() {
|
||||
updatePreview();
|
||||
});
|
||||
|
||||
function updatePreview() {
|
||||
// Aquí iría la lógica para actualizar la vista previa en tiempo real
|
||||
console.log('Preview updated');
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
||||
</script>
|
||||
SCRIPT;
|
||||
}
|
||||
|
||||
public function supports(string $componentType): bool
|
||||
{
|
||||
return $componentType === 'top-notification-bar';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user