feat/fix: checkout email tracing, UI tweaks for add-to-cart, cart page overflow fix, implement hide admin bar setting
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace WooNooW\Frontend;
|
||||
|
||||
/**
|
||||
@@ -19,16 +20,16 @@ class PageSSR
|
||||
if (empty($structure) || empty($structure['sections'])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
$html = '';
|
||||
|
||||
|
||||
foreach ($structure['sections'] as $section) {
|
||||
$html .= self::render_section($section, $post_data);
|
||||
}
|
||||
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render a single section to HTML
|
||||
*
|
||||
@@ -42,13 +43,13 @@ class PageSSR
|
||||
$props = $section['props'] ?? [];
|
||||
$layout = $section['layoutVariant'] ?? 'default';
|
||||
$color_scheme = $section['colorScheme'] ?? 'default';
|
||||
|
||||
|
||||
// Resolve all props (replace dynamic placeholders with actual values)
|
||||
$resolved_props = self::resolve_props($props, $post_data);
|
||||
|
||||
|
||||
// Generate section ID for anchor links
|
||||
$section_id = $section['id'] ?? 'section-' . uniqid();
|
||||
|
||||
|
||||
$element_styles = $section['elementStyles'] ?? [];
|
||||
$styles = $section['styles'] ?? []; // Section wrapper styles (bg, overlay)
|
||||
|
||||
@@ -57,11 +58,11 @@ class PageSSR
|
||||
if (method_exists(__CLASS__, $method)) {
|
||||
return self::$method($resolved_props, $layout, $color_scheme, $section_id, $element_styles, $styles);
|
||||
}
|
||||
|
||||
|
||||
// Fallback: generic section wrapper
|
||||
return self::render_generic($resolved_props, $type, $section_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resolve props - replace dynamic placeholders with actual values
|
||||
*
|
||||
@@ -72,15 +73,15 @@ class PageSSR
|
||||
public static function resolve_props($props, $post_data = null)
|
||||
{
|
||||
$resolved = [];
|
||||
|
||||
|
||||
foreach ($props as $key => $prop) {
|
||||
if (!is_array($prop)) {
|
||||
$resolved[$key] = $prop;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
$type = $prop['type'] ?? 'static';
|
||||
|
||||
|
||||
if ($type === 'static') {
|
||||
$resolved[$key] = $prop['value'] ?? '';
|
||||
} elseif ($type === 'dynamic' && $post_data) {
|
||||
@@ -90,27 +91,28 @@ class PageSSR
|
||||
$resolved[$key] = $prop['value'] ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $resolved;
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Section Renderers
|
||||
// ========================================
|
||||
|
||||
|
||||
/**
|
||||
* Helper to generate style attribute string
|
||||
*/
|
||||
private static function generate_style_attr($styles) {
|
||||
private static function generate_style_attr($styles)
|
||||
{
|
||||
if (empty($styles)) return '';
|
||||
|
||||
|
||||
$css = [];
|
||||
if (!empty($styles['color'])) $css[] = "color: {$styles['color']}";
|
||||
if (!empty($styles['backgroundColor'])) $css[] = "background-color: {$styles['backgroundColor']}";
|
||||
if (!empty($styles['fontSize'])) $css[] = "font-size: {$styles['fontSize']}"; // Note: assumes value has unit or is handled by class, but inline style works for specific values
|
||||
// Add more mapping if needed, or rely on frontend to send valid CSS values
|
||||
|
||||
return empty($css) ? '' : 'style="' . implode(';', $css) . '"';
|
||||
|
||||
return empty($css) ? '' : 'style="' . implode(';', $css) . '"';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,26 +125,37 @@ class PageSSR
|
||||
$image = esc_url($props['image'] ?? '');
|
||||
$cta_text = esc_html($props['cta_text'] ?? '');
|
||||
$cta_url = esc_url($props['cta_url'] ?? '');
|
||||
|
||||
|
||||
// Section Styles (Background & Spacing)
|
||||
$bg_type = $section_styles['backgroundType'] ?? 'solid';
|
||||
$bg_color = $section_styles['backgroundColor'] ?? '';
|
||||
$bg_image = $section_styles['backgroundImage'] ?? '';
|
||||
$overlay_opacity = $section_styles['backgroundOverlay'] ?? 0;
|
||||
$pt = $section_styles['paddingTop'] ?? '';
|
||||
$pb = $section_styles['paddingBottom'] ?? '';
|
||||
$height_preset = $section_styles['heightPreset'] ?? '';
|
||||
|
||||
|
||||
$section_css = "";
|
||||
if ($bg_color) $section_css .= "background-color: {$bg_color};";
|
||||
if ($bg_image) $section_css .= "background-image: url('{$bg_image}'); background-size: cover; background-position: center;";
|
||||
if ($bg_type === 'gradient') {
|
||||
$from = $section_styles['gradientFrom'] ?? '#9333ea';
|
||||
$to = $section_styles['gradientTo'] ?? '#3b82f6';
|
||||
$angle = $section_styles['gradientAngle'] ?? 135;
|
||||
$section_css .= "background: linear-gradient({$angle}deg, {$from}, {$to});";
|
||||
} elseif ($bg_type === 'image' && $bg_image) {
|
||||
$section_css .= "background-image: url('{$bg_image}'); background-size: cover; background-position: center;";
|
||||
} else {
|
||||
if ($bg_color) $section_css .= "background-color: {$bg_color};";
|
||||
// Legacy: image without explicit type
|
||||
if ($bg_image && !$bg_type) $section_css .= "background-image: url('{$bg_image}'); background-size: cover; background-position: center;";
|
||||
}
|
||||
if ($pt) $section_css .= "padding-top: {$pt};";
|
||||
if ($pb) $section_css .= "padding-bottom: {$pb};";
|
||||
if ($height_preset === 'screen') $section_css .= "min-height: 100vh; display: flex; align-items: center;";
|
||||
|
||||
|
||||
$section_attr = $section_css ? "style=\"{$section_css}\"" : "";
|
||||
|
||||
|
||||
$html = "<section id=\"{$id}\" class=\"wn-section wn-hero wn-hero--{$layout} wn-scheme--{$color_scheme}\" {$section_attr}>";
|
||||
|
||||
|
||||
// Overlay
|
||||
if ($overlay_opacity > 0) {
|
||||
$opacity = $overlay_opacity / 100;
|
||||
@@ -156,9 +169,9 @@ class PageSSR
|
||||
|
||||
// Image (if not background)
|
||||
if ($image && !$bg_image && $layout !== 'default') {
|
||||
$html .= "<img src=\"{$image}\" alt=\"{$title}\" class=\"wn-hero__image\" />";
|
||||
$html .= "<img src=\"{$image}\" alt=\"{$title}\" class=\"wn-hero__image\" />";
|
||||
}
|
||||
|
||||
|
||||
$html .= '<div class="wn-hero__content" style="position: relative; z-index: 10;">';
|
||||
if ($title) {
|
||||
$html .= "<h1 class=\"wn-hero__title\" {$title_style}>{$title}</h1>";
|
||||
@@ -171,31 +184,32 @@ class PageSSR
|
||||
}
|
||||
$html .= '</div>';
|
||||
$html .= '</section>';
|
||||
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Universal Row Renderer (Shared logic for Content & ImageText)
|
||||
*/
|
||||
private static function render_universal_row($props, $layout, $color_scheme, $element_styles, $options = []) {
|
||||
private static function render_universal_row($props, $layout, $color_scheme, $element_styles, $options = [])
|
||||
{
|
||||
$title = esc_html($props['title']['value'] ?? ($props['title'] ?? ''));
|
||||
$text = $props['text']['value'] ?? ($props['text'] ?? ($props['content']['value'] ?? ($props['content'] ?? ''))); // Handle both props/values
|
||||
$image = esc_url($props['image']['value'] ?? ($props['image'] ?? ''));
|
||||
|
||||
|
||||
// Options
|
||||
$has_image = !empty($image);
|
||||
$image_pos = $layout ?: 'left';
|
||||
|
||||
|
||||
// Element Styles
|
||||
$title_style = self::generate_style_attr($element_styles['title'] ?? []);
|
||||
$text_style = self::generate_style_attr($element_styles['text'] ?? ($element_styles['content'] ?? []));
|
||||
|
||||
|
||||
// Wrapper Classes
|
||||
$wrapper_class = "wn-max-w-7xl wn-mx-auto wn-px-4";
|
||||
$grid_class = "wn-mx-auto";
|
||||
|
||||
|
||||
if ($has_image && in_array($image_pos, ['left', 'right', 'image-left', 'image-right'])) {
|
||||
$grid_class .= " wn-grid wn-grid-cols-1 wn-lg-grid-cols-2 wn-gap-12 wn-items-center";
|
||||
} else {
|
||||
@@ -204,7 +218,7 @@ class PageSSR
|
||||
|
||||
$html = "<div class=\"{$wrapper_class}\">";
|
||||
$html .= "<div class=\"{$grid_class}\">";
|
||||
|
||||
|
||||
// Image Output
|
||||
$image_html = "";
|
||||
if ($current_pos_right = ($image_pos === 'right' || $image_pos === 'image-right')) {
|
||||
@@ -218,7 +232,7 @@ class PageSSR
|
||||
$image_html .= "<img src=\"{$image}\" alt=\"{$title}\" class=\"wn-absolute wn-inset-0 wn-w-full wn-h-full wn-object-cover\" />";
|
||||
$image_html .= "</div>";
|
||||
}
|
||||
|
||||
|
||||
// Content Output
|
||||
$content_html = "<div class=\"wn-flex wn-flex-col\">";
|
||||
if ($title) {
|
||||
@@ -232,14 +246,14 @@ class PageSSR
|
||||
|
||||
// Render based on order (Grid handles order via CSS classes for left/right, but fallback for DOM order)
|
||||
if ($has_image) {
|
||||
// For grid layout, we output both. CSS order handles visual.
|
||||
$html .= $image_html . $content_html;
|
||||
// For grid layout, we output both. CSS order handles visual.
|
||||
$html .= $image_html . $content_html;
|
||||
} else {
|
||||
$html .= $content_html;
|
||||
$html .= $content_html;
|
||||
}
|
||||
|
||||
$html .= "</div></div>";
|
||||
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
@@ -253,72 +267,88 @@ class PageSSR
|
||||
$content = apply_filters('the_content', $content);
|
||||
// Normalize prop structure for universal renderer if needed
|
||||
if (is_string($props['content'])) {
|
||||
$props['content'] = ['value' => $content];
|
||||
$props['content'] = ['value' => $content];
|
||||
} else {
|
||||
$props['content']['value'] = $content;
|
||||
$props['content']['value'] = $content;
|
||||
}
|
||||
|
||||
// Section Styles (Background)
|
||||
$bg_type = $section_styles['backgroundType'] ?? 'solid';
|
||||
$bg_color = $section_styles['backgroundColor'] ?? '';
|
||||
$padding = $section_styles['paddingTop'] ?? '';
|
||||
$height_preset = $section_styles['heightPreset'] ?? '';
|
||||
|
||||
$css = "";
|
||||
if($bg_color) $css .= "background-color:{$bg_color};";
|
||||
|
||||
if ($bg_type === 'gradient') {
|
||||
$from = $section_styles['gradientFrom'] ?? '#9333ea';
|
||||
$to = $section_styles['gradientTo'] ?? '#3b82f6';
|
||||
$angle = $section_styles['gradientAngle'] ?? 135;
|
||||
$css .= "background: linear-gradient({$angle}deg, {$from}, {$to});";
|
||||
} elseif ($bg_color) {
|
||||
$css .= "background-color:{$bg_color};";
|
||||
}
|
||||
|
||||
// Height Logic
|
||||
if ($height_preset === 'screen') {
|
||||
$css .= "min-height: 100vh; display: flex; align-items: center;";
|
||||
$padding = '5rem'; // Default padding for screen to avoid edge collision
|
||||
$css .= "min-height: 100vh; display: flex; align-items: center;";
|
||||
$padding = '5rem'; // Default padding for screen to avoid edge collision
|
||||
} elseif ($height_preset === 'small') {
|
||||
$padding = '2rem';
|
||||
$padding = '2rem';
|
||||
} elseif ($height_preset === 'large') {
|
||||
$padding = '8rem';
|
||||
$padding = '8rem';
|
||||
} elseif ($height_preset === 'medium') {
|
||||
$padding = '4rem';
|
||||
$padding = '4rem';
|
||||
}
|
||||
|
||||
if($padding) $css .= "padding:{$padding} 0;";
|
||||
|
||||
|
||||
if ($padding) $css .= "padding:{$padding} 0;";
|
||||
|
||||
$style_attr = $css ? "style=\"{$css}\"" : "";
|
||||
|
||||
|
||||
$inner_html = self::render_universal_row($props, 'left', $color_scheme, $element_styles);
|
||||
|
||||
|
||||
return "<section id=\"{$id}\" class=\"wn-section wn-content wn-scheme--{$color_scheme}\" {$style_attr}>{$inner_html}</section>";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render Image + Text section
|
||||
*/
|
||||
public static function render_image_text($props, $layout, $color_scheme, $id, $element_styles = [], $section_styles = [])
|
||||
{
|
||||
$bg_type = $section_styles['backgroundType'] ?? 'solid';
|
||||
$bg_color = $section_styles['backgroundColor'] ?? '';
|
||||
$padding = $section_styles['paddingTop'] ?? '';
|
||||
$height_preset = $section_styles['heightPreset'] ?? '';
|
||||
|
||||
$css = "";
|
||||
if($bg_color) $css .= "background-color:{$bg_color};";
|
||||
if ($bg_type === 'gradient') {
|
||||
$from = $section_styles['gradientFrom'] ?? '#9333ea';
|
||||
$to = $section_styles['gradientTo'] ?? '#3b82f6';
|
||||
$angle = $section_styles['gradientAngle'] ?? 135;
|
||||
$css .= "background: linear-gradient({$angle}deg, {$from}, {$to});";
|
||||
} elseif ($bg_color) {
|
||||
$css .= "background-color:{$bg_color};";
|
||||
}
|
||||
|
||||
// Height Logic
|
||||
if ($height_preset === 'screen') {
|
||||
$css .= "min-height: 100vh; display: flex; align-items: center;";
|
||||
$padding = '5rem';
|
||||
$css .= "min-height: 100vh; display: flex; align-items: center;";
|
||||
$padding = '5rem';
|
||||
} elseif ($height_preset === 'small') {
|
||||
$padding = '2rem';
|
||||
$padding = '2rem';
|
||||
} elseif ($height_preset === 'large') {
|
||||
$padding = '8rem';
|
||||
$padding = '8rem';
|
||||
} elseif ($height_preset === 'medium') {
|
||||
$padding = '4rem';
|
||||
$padding = '4rem';
|
||||
}
|
||||
|
||||
if($padding) $css .= "padding:{$padding} 0;";
|
||||
if ($padding) $css .= "padding:{$padding} 0;";
|
||||
$style_attr = $css ? "style=\"{$css}\"" : "";
|
||||
|
||||
$inner_html = self::render_universal_row($props, $layout, $color_scheme, $element_styles);
|
||||
|
||||
return "<section id=\"{$id}\" class=\"wn-section wn-image-text wn-scheme--{$color_scheme}\" {$style_attr}>{$inner_html}</section>";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render Feature Grid section
|
||||
*/
|
||||
@@ -326,26 +356,26 @@ class PageSSR
|
||||
{
|
||||
$heading = esc_html($props['heading'] ?? '');
|
||||
$items = $props['items'] ?? [];
|
||||
|
||||
|
||||
$html = "<section id=\"{$id}\" class=\"wn-section wn-feature-grid wn-feature-grid--{$layout} wn-scheme--{$color_scheme}\">";
|
||||
|
||||
|
||||
if ($heading) {
|
||||
$html .= "<h2 class=\"wn-feature-grid__heading\">{$heading}</h2>";
|
||||
}
|
||||
|
||||
|
||||
// Feature Item Styles (Card)
|
||||
$item_style_attr = self::generate_style_attr($element_styles['feature_item'] ?? []); // BG, Border, Shadow handled by CSS classes mostly, but colors here
|
||||
$item_bg = $element_styles['feature_item']['backgroundColor'] ?? '';
|
||||
|
||||
|
||||
$html .= '<div class="wn-feature-grid__items">';
|
||||
foreach ($items as $item) {
|
||||
$item_title = esc_html($item['title'] ?? '');
|
||||
$item_desc = esc_html($item['description'] ?? '');
|
||||
$item_icon = esc_html($item['icon'] ?? '');
|
||||
|
||||
|
||||
// Allow overriding item specific style if needed, but for now global
|
||||
$html .= "<div class=\"wn-feature-grid__item\" {$item_style_attr}>";
|
||||
|
||||
|
||||
// Render Icon SVG
|
||||
if ($item_icon) {
|
||||
$icon_svg = self::get_icon_svg($item_icon);
|
||||
@@ -353,7 +383,7 @@ class PageSSR
|
||||
$html .= "<div class=\"wn-feature-grid__icon\">{$icon_svg}</div>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($item_title) {
|
||||
// Feature title style
|
||||
$f_title_style = self::generate_style_attr($element_styles['feature_title'] ?? []);
|
||||
@@ -368,10 +398,10 @@ class PageSSR
|
||||
}
|
||||
$html .= '</div>';
|
||||
$html .= '</section>';
|
||||
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render CTA Banner section
|
||||
*/
|
||||
@@ -381,10 +411,10 @@ class PageSSR
|
||||
$text = esc_html($props['text'] ?? '');
|
||||
$button_text = esc_html($props['button_text'] ?? '');
|
||||
$button_url = esc_url($props['button_url'] ?? '');
|
||||
|
||||
|
||||
$html = "<section id=\"{$id}\" class=\"wn-section wn-cta-banner wn-cta-banner--{$layout} wn-scheme--{$color_scheme}\">";
|
||||
$html .= '<div class="wn-cta-banner__content">';
|
||||
|
||||
|
||||
if ($title) {
|
||||
$html .= "<h2 class=\"wn-cta-banner__title\">{$title}</h2>";
|
||||
}
|
||||
@@ -394,13 +424,13 @@ class PageSSR
|
||||
if ($button_text && $button_url) {
|
||||
$html .= "<a href=\"{$button_url}\" class=\"wn-cta-banner__button\">{$button_text}</a>";
|
||||
}
|
||||
|
||||
|
||||
$html .= '</div>';
|
||||
$html .= '</section>';
|
||||
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render Contact Form section
|
||||
*/
|
||||
@@ -410,13 +440,13 @@ class PageSSR
|
||||
$webhook_url = esc_url($props['webhook_url'] ?? '');
|
||||
$redirect_url = esc_url($props['redirect_url'] ?? '');
|
||||
$fields = $props['fields'] ?? ['name', 'email', 'message'];
|
||||
|
||||
|
||||
// Extract styles
|
||||
$btn_bg = $element_styles['button']['backgroundColor'] ?? '';
|
||||
$btn_color = $element_styles['button']['color'] ?? '';
|
||||
$field_bg = $element_styles['fields']['backgroundColor'] ?? '';
|
||||
$field_color = $element_styles['fields']['color'] ?? '';
|
||||
|
||||
|
||||
$btn_style = "";
|
||||
if ($btn_bg) $btn_style .= "background-color: {$btn_bg};";
|
||||
if ($btn_color) $btn_style .= "color: {$btn_color};";
|
||||
@@ -428,14 +458,14 @@ class PageSSR
|
||||
$field_attr = $field_style ? "style=\"{$field_style}\"" : "";
|
||||
|
||||
$html = "<section id=\"{$id}\" class=\"wn-section wn-contact-form wn-scheme--{$color_scheme}\">";
|
||||
|
||||
|
||||
if ($title) {
|
||||
$html .= "<h2 class=\"wn-contact-form__title\">{$title}</h2>";
|
||||
}
|
||||
|
||||
|
||||
// Form is rendered but won't work for bots (they just see the structure)
|
||||
$html .= '<form class="wn-contact-form__form" method="post">';
|
||||
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$field_label = ucfirst(str_replace('_', ' ', $field));
|
||||
$html .= '<div class="wn-contact-form__field">';
|
||||
@@ -447,18 +477,19 @@ class PageSSR
|
||||
}
|
||||
$html .= '</div>';
|
||||
}
|
||||
|
||||
|
||||
$html .= "<button type=\"submit\" {$btn_attr}>Submit</button>";
|
||||
$html .= '</form>';
|
||||
$html .= '</section>';
|
||||
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to get SVG for known icons
|
||||
*/
|
||||
private static function get_icon_svg($name) {
|
||||
private static function get_icon_svg($name)
|
||||
{
|
||||
$icons = [
|
||||
'Star' => '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>',
|
||||
'Zap' => '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>',
|
||||
@@ -473,7 +504,7 @@ class PageSSR
|
||||
|
||||
return $icons[$name] ?? $icons['Star'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generic section fallback
|
||||
*/
|
||||
@@ -485,7 +516,7 @@ class PageSSR
|
||||
$content .= "<div class=\"wn-{$type}__{$key}\">" . wp_kses_post($value) . "</div>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return "<section id=\"{$id}\" class=\"wn-section wn-{$type}\">{$content}</section>";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user