From 46d681c6b825d21b3f698d793c4e630c687d90ad Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Thu, 21 May 2026 21:41:53 +0000
Subject: [PATCH] =Major CustomBlocks.php overhaul, expanding block support and customization from the editor. theme.json should now be updated on new themes to set brand colours, etc. Also note: major change to .col vs .row alignment: simplifying it to .top .bottom vs the confusion of the differences for .col/.row .start and .a-start

---
 inc/blocks/FormBlock.php |  142 +++++++++++++++++++++++++++--------------------
 1 files changed, 81 insertions(+), 61 deletions(-)

diff --git a/inc/blocks/FormBlock.php b/inc/blocks/FormBlock.php
index 6cec6de..0d447da 100644
--- a/inc/blocks/FormBlock.php
+++ b/inc/blocks/FormBlock.php
@@ -1,11 +1,9 @@
 <?php
 namespace JVBase\blocks;
 
-use JVBase\managers\CacheManager;
-use JVBase\meta\MetaManager;
-use JVBase\managers\CloudflareTurnstile;
-use Exception;
-use WP_Block;
+use JVBase\managers\Cache;
+use JVBase\meta\Form;
+use JVBase\base\Site;
 
 if (!defined('ABSPATH')) {
 	exit; // Exit if accessed directly
@@ -18,8 +16,8 @@
  */
 class FormBlock
 {
-	protected static FormBlock|null $instance = null;
-	protected CacheManager $cache;
+	protected static ?FormBlock $instance = null;
+	protected Cache $cache;
 	protected array $forms;
 	protected string $form_contact;
 
@@ -35,7 +33,7 @@
 
 	public function __construct()
 	{
-		$this->cache = new CacheManager('form_blocks', HOUR_IN_SECONDS);
+		$this->cache = Cache::for('forms', WEEK_IN_SECONDS);
 
 		// Initialize forms from filter
 		$this->forms = $this->registerForms();
@@ -46,14 +44,36 @@
 
 		// Register forms data for the block editor
 		add_action('enqueue_block_editor_assets', [$this, 'localizeFormsData']);
-
 		add_action('init', [$this, 'registerBlock']);
+		add_filter('render_block', [$this, 'maybeEnqueueScripts'], 10, 2);
+	}
+
+	/**
+	 * Enqueue scripts when rendering form block
+	 */
+	public function maybeEnqueueScripts(string $block_content, array $block): string
+	{
+		// Only process our form blocks
+		if ($block['blockName'] !== 'jvb/forms') {
+			return $block_content;
+		}
+
+		// Enqueue Turnstile if needed
+		if (Site::hasIntegration('cloudflare')) {
+			$cloudflare = JVB()->connect('cloudflare');
+			if ($cloudflare->isSetUp()) {
+				$cloudflare->enqueueTurnstileScripts();
+			}
+		}
+
+		return $block_content;
 	}
 
 	public function registerBlock()
 	{
 		register_block_type($this->path, [
-			'render_callback'	=> [$this, 'render']
+			'render_callback'	=> [$this, 'render'],
+        	'style' => 'jvb-icons-forms',
 		]);
 	}
 
@@ -94,9 +114,7 @@
 			'sections' => []
 		];
 
-		$config = array_merge($defaults, $config);
-
-		return $config;
+		return array_merge($defaults, $config);
 	}
 
 	/**
@@ -111,16 +129,12 @@
 		}
 
 		$cache_key = $this->cache->generateKey($block);
-		$cached = $this->cache->get($cache_key);
-
-		if ($cached) {
-			return $cached;
-		}
-
-		$rendered = $this->renderForm($form_type, $block);
-
-		$this->cache->set($cache_key, $rendered);
-		return $rendered;
+		return $this->cache->remember(
+			$cache_key,
+			function() use ($form_type, $block) {
+				return $this->renderForm($form_type, $block);
+			}
+		);
 	}
 
 	/**
@@ -165,7 +179,6 @@
 		$this->renderTurnstile();
 		$this->renderFormEnd($type, $form_id);
 		echo '</div>';
-
 		return ob_get_clean();
 	}
 
@@ -263,8 +276,8 @@
 			}
 		}
 
-		echo '<form id="' . esc_attr($form_id) . '" data-form-id="'.esc_attr($type).'" data-save="form" data-noautosave>';
-		wp_nonce_field('jvb_form_' . $type);
+		echo '<form id="' . esc_attr($form_id) . '" data-form-id="'.esc_attr($type).'" data-save="form">';
+//		wp_nonce_field('jvb_form_' . $type);
 	}
 
 	/**
@@ -278,54 +291,63 @@
 			return;
 		}
 
-		// Create MetaManager instance for form rendering
-		$meta = new MetaManager();
-
 		// If sections are defined, render in sections
 		if (!empty($form_config['sections'])) {
-			$this->renderSections($type, $meta);
+			$this->renderSections($type);
 		} else {
+			echo jvbFormStatus();
 			// Render fields directly
 			foreach ($form_config['fields'] as $field_name => $field_config) {
-				$meta->render('form', $field_name, $field_config);
+				echo Form::render($field_name, null, $field_config);
 			}
+			$submit_text = $form_config['submit'] ?? 'Submit';
+			echo '<button type="submit" class="button primary">' . esc_html($submit_text) . '</button>';
 		}
 	}
 
 	/**
 	 * Render form sections
 	 */
-	protected function renderSections(string $type, MetaManager $meta): void
+	protected function renderSections(string $type): void
 	{
 		$form_config = $this->forms[$type];
 		$sections = $form_config['sections'];
 		$fields = $form_config['fields'];
+		$total = count($sections);
 
 		echo '<div class="container">';
+		if ($total > 1) {
+			echo '<div class="form-progress">';
+			jvbRenderProgressBar('<span class="step-text">Step <span class="current">1</span> of ' . $total . '</span>');
+			echo '</div>';
+		}
 
 		// Render navigation if multiple sections
 		if (count($sections) > 1) {
-			echo '<nav class="tabs row start" role="tablist">';
+			echo '<nav class="tabs row left" role="tablist">';
 			$i = 1;
 			foreach ($sections as $slug => $section) {
 				$active_class = $i === 1 ? ' active' : '';
 				$aria_selected = $i === 1 ? 'true' : 'false';
 
-				echo '<button type="button" class="tab' . $active_class . '" data-tab="' . esc_attr($slug) . '" role="tab" aria-selected="' . $aria_selected . '">';
+				echo '<button type="button" class="tab' . $active_class . '" data-tab="' . esc_attr($slug) . '" data-step="'.$i.'" role="tab" aria-selected="' . $aria_selected . '">';
+				echo '<span class="step-number">' . $i . '</span>';
 				echo '<h2>' . esc_html($section['label'] ?? $section) . '</h2>';
 				echo '</button>';
 				$i++;
 			}
 			echo '</nav>';
 		}
+		echo jvbFormStatus();
 
 		// Render section content
 		$i = 0;
 		$total = count($sections);
 		foreach ($sections as $slug => $section) {
 			$active_class = $i === 0 ? ' active' : '';
+			$is_last = $i === ($total -1);
 
-			echo '<section id="' . esc_attr($slug) . '" class="tab-content' . $active_class . '" data-tab="' . esc_attr($slug) . '" role="tabpanel">';
+			echo '<section id="' . esc_attr($slug) . '" class="tab-content' . $active_class . '" data-tab="' . esc_attr($slug) . '" data-step="'.($i + 1).'" role="tabpanel">';
 
 			if (is_array($section) && !empty($section['title'])) {
 				echo '<h2>' . esc_html($section['title']) . '</h2>';
@@ -341,17 +363,33 @@
 			});
 
 			foreach ($section_fields as $field_name => $field_config) {
-				$meta->render('form', $field_name, $field_config);
+				echo Form::render($field_name, null, $field_config);
 			}
 
-			if ($i === ($total - 1)){
-				$submit_text = $form_config['submit'] ?? 'Submit';
-				// Submit button
-				echo '<div class="form-actions">';
-				echo '<button type="submit">' . esc_html($submit_text) . '</button>';
-				echo '</div>';
+			// Add step navigation buttons
+			echo '<div class="step-navigation row x-btw">';
+
+			if ($i > 0) {
+				echo '<button type="button" class="button secondary prev-step" data-action="prev-step">';
+				echo jvbIcon('caret-left');
+				echo '<span>Previous</span>';
+				echo '</button>';
+			} else {
+				echo '<div></div>'; // Spacer for flex layout
 			}
 
+			if ($is_last) {
+				$submit_text = $form_config['submit'] ?? 'Submit';
+				echo '<button type="submit" class="button primary">' . esc_html($submit_text) . '</button>';
+			} else {
+				echo '<button type="button" class="button primary next-step" data-action="next-step">';
+				echo '<span>Next Step</span>';
+				echo jvbIcon('caret-right');
+				echo '</button>';
+			}
+
+			echo '</div>'; // .step-navigation
+
 			echo '</section>';
 			$i++;
 		}
@@ -364,7 +402,7 @@
 	 */
 	protected function renderTurnstile(): void
 	{
-		if (!jvbSiteUsesCloudflare()) {
+		if (!Site::hasIntegration('cloudflare')) {
 			return;
 		}
 
@@ -389,19 +427,6 @@
 		echo '<input type="hidden" name="timestamp" value="' . time() . '">';
 
 		echo '</form>';
-
-		echo '<template class="formSummary">
-		<section class="form-summary">
-		<h2></h2>
-		<div class="message"><p>You\'ll get an email with this information, too. If you need to make any changes, respond to that email.</p></div>
-		<h3>Summary:</h3>';
-
-		foreach($form_config['fields'] as $field=>$config) {
-			$label = $config['summaryTitle'] ?? $config['label'];
-
-			echo '<div id="'.$field.'"><h4>'.$label.'</h4><div></div></div>';
-		}
-		echo '</section></template>';
 	}
 
 	/**
@@ -423,11 +448,6 @@
 			];
 		}
 
-		error_log('Form Localization: '.print_r([
-			'formTypes' => $form_types,
-			'availableForms' => $this->forms,
-			'nonce'			=> wp_create_nonce('jvbForm')
-		], true));
 		wp_localize_script('jvb-forms-editor-script', 'jvbFormsData', [
 			'formTypes' => $form_types,
 			'availableForms' => $this->forms,

--
Gitblit v1.10.0