- 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>
188 lines
6.0 KiB
PHP
188 lines
6.0 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace ROITheme\Public\CtaPost\Infrastructure\Ui;
|
|
|
|
use ROITheme\Shared\Domain\Contracts\RendererInterface;
|
|
use ROITheme\Shared\Domain\Contracts\CSSGeneratorInterface;
|
|
use ROITheme\Shared\Domain\Entities\Component;
|
|
|
|
/**
|
|
* CtaPostRenderer - Renderiza CTA promocional debajo del contenido
|
|
*
|
|
* RESPONSABILIDAD: Generar HTML y CSS del componente CTA Post
|
|
*
|
|
* CARACTERISTICAS:
|
|
* - Gradiente configurable
|
|
* - Layout responsive (2 columnas en desktop)
|
|
* - Boton CTA con icono
|
|
* - Estilos 100% desde BD via CSSGenerator
|
|
*
|
|
* @package ROITheme\Public\CtaPost\Infrastructure\Ui
|
|
*/
|
|
final class CtaPostRenderer implements RendererInterface
|
|
{
|
|
public function __construct(
|
|
private CSSGeneratorInterface $cssGenerator
|
|
) {}
|
|
|
|
public function render(Component $component): string
|
|
{
|
|
$data = $component->getData();
|
|
|
|
if (!$this->isEnabled($data)) {
|
|
return '';
|
|
}
|
|
|
|
if (!$this->shouldShowOnCurrentPage($data)) {
|
|
return '';
|
|
}
|
|
|
|
$css = $this->generateCSS($data);
|
|
$html = $this->buildHTML($data);
|
|
|
|
return sprintf("<style>%s</style>\n%s", $css, $html);
|
|
}
|
|
|
|
public function supports(string $componentType): bool
|
|
{
|
|
return $componentType === 'cta-post';
|
|
}
|
|
|
|
private function isEnabled(array $data): bool
|
|
{
|
|
$value = $data['visibility']['is_enabled'] ?? false;
|
|
return $value === true || $value === '1' || $value === 1;
|
|
}
|
|
|
|
private function shouldShowOnCurrentPage(array $data): bool
|
|
{
|
|
$showOn = $data['visibility']['show_on_pages'] ?? 'posts';
|
|
|
|
switch ($showOn) {
|
|
case 'all':
|
|
return true;
|
|
case 'posts':
|
|
return is_single();
|
|
case 'pages':
|
|
return is_page();
|
|
default:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
private function generateCSS(array $data): string
|
|
{
|
|
$colors = $data['colors'] ?? [];
|
|
$effects = $data['visual_effects'] ?? [];
|
|
$visibility = $data['visibility'] ?? [];
|
|
|
|
$cssRules = [];
|
|
|
|
$gradientStart = $colors['gradient_start'] ?? '#FF8600';
|
|
$gradientEnd = $colors['gradient_end'] ?? '#FFB800';
|
|
$gradientAngle = $effects['gradient_angle'] ?? '135deg';
|
|
$buttonBgColor = $colors['button_bg_color'] ?? '#FF8600';
|
|
$buttonTextColor = $colors['button_text_color'] ?? '#ffffff';
|
|
$buttonHoverBgColor = $colors['button_hover_bg_color'] ?? '#e67a00';
|
|
|
|
// Container - gradient background
|
|
$cssRules[] = $this->cssGenerator->generate('.cta-post-container', [
|
|
'background' => "linear-gradient({$gradientAngle}, {$gradientStart} 0%, {$gradientEnd} 100%)",
|
|
]);
|
|
|
|
// Button styles (matching template .cta-button) - Using !important to override Bootstrap btn-light
|
|
$cssRules[] = ".cta-post-container .cta-button {
|
|
background-color: {$buttonBgColor} !important;
|
|
color: {$buttonTextColor} !important;
|
|
font-weight: 600;
|
|
padding: 0.75rem 2rem;
|
|
border: none !important;
|
|
border-radius: 8px;
|
|
transition: 0.3s;
|
|
text-decoration: none;
|
|
display: inline-block;
|
|
}";
|
|
|
|
// Button hover state
|
|
$cssRules[] = ".cta-post-container .cta-button:hover {
|
|
background-color: {$buttonHoverBgColor};
|
|
color: {$buttonTextColor};
|
|
}";
|
|
|
|
// Responsive: button full width on mobile
|
|
$cssRules[] = "@media (max-width: 768px) {
|
|
.cta-post-container .cta-button {
|
|
width: 100%;
|
|
margin-top: 1rem;
|
|
}
|
|
}";
|
|
|
|
// Responsive visibility
|
|
$showOnDesktop = $visibility['show_on_desktop'] ?? true;
|
|
$showOnDesktop = $showOnDesktop === true || $showOnDesktop === '1' || $showOnDesktop === 1;
|
|
$showOnMobile = $visibility['show_on_mobile'] ?? true;
|
|
$showOnMobile = $showOnMobile === true || $showOnMobile === '1' || $showOnMobile === 1;
|
|
|
|
if (!$showOnMobile) {
|
|
$cssRules[] = "@media (max-width: 991.98px) {
|
|
.cta-post-container { display: none !important; }
|
|
}";
|
|
}
|
|
|
|
if (!$showOnDesktop) {
|
|
$cssRules[] = "@media (min-width: 992px) {
|
|
.cta-post-container { display: none !important; }
|
|
}";
|
|
}
|
|
|
|
return implode("\n", $cssRules);
|
|
}
|
|
|
|
private function buildHTML(array $data): string
|
|
{
|
|
$content = $data['content'] ?? [];
|
|
|
|
$title = $content['title'] ?? 'Accede a 200,000+ Análisis de Precios Unitarios';
|
|
$description = $content['description'] ?? '';
|
|
$buttonText = $content['button_text'] ?? 'Ver Catálogo Completo';
|
|
$buttonUrl = $content['button_url'] ?? '#';
|
|
$buttonIcon = $content['button_icon'] ?? 'bi-arrow-right';
|
|
|
|
$html = '<div class="my-5 p-4 rounded cta-post-container">';
|
|
$html .= ' <div class="row align-items-center">';
|
|
|
|
// Left column - Content
|
|
$html .= ' <div class="col-md-8">';
|
|
$html .= sprintf(
|
|
' <h3 class="h4 fw-bold text-white mb-2">%s</h3>',
|
|
esc_html($title)
|
|
);
|
|
if (!empty($description)) {
|
|
$html .= sprintf(
|
|
' <p class="text-white mb-md-0">%s</p>',
|
|
esc_html($description)
|
|
);
|
|
}
|
|
$html .= ' </div>';
|
|
|
|
// Right column - Button
|
|
$html .= ' <div class="col-md-4 text-md-end mt-3 mt-md-0">';
|
|
$html .= sprintf(
|
|
' <a href="%s" class="btn btn-light btn-lg cta-button">%s',
|
|
esc_url($buttonUrl),
|
|
esc_html($buttonText)
|
|
);
|
|
if (!empty($buttonIcon)) {
|
|
$html .= sprintf(' <i class="bi %s ms-2"></i>', esc_attr($buttonIcon));
|
|
}
|
|
$html .= '</a>';
|
|
$html .= ' </div>';
|
|
|
|
$html .= ' </div>';
|
|
$html .= '</div>';
|
|
|
|
return $html;
|
|
}
|
|
}
|