From 32ce5c542c90be348895328078e392dde2052957 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Fri, 04 Sep 2026 19:15:16 +0000
Subject: [PATCH] =Working at adding defined fields to a dedicated panel in the gutenberg editor. Registrar now has AddCustomFields.php, which currently only supports post fields. Added a @wordpress/plugins base _meta/fields in /build and /src that successfully creates a panel. Next steps: determine sections and fields, group fields by section (each section to a panel), and save output

---
 inc/blocks/MenuBlock.php |   98 ++++++++++++++++++++++++++++++++++++------------
 1 files changed, 73 insertions(+), 25 deletions(-)

diff --git a/inc/blocks/MenuBlock.php b/inc/blocks/MenuBlock.php
index 264e41e..b1d7347 100644
--- a/inc/blocks/MenuBlock.php
+++ b/inc/blocks/MenuBlock.php
@@ -1,7 +1,6 @@
 <?php
 namespace JVBase\blocks;
 
-use JVBase\base\Options;
 use JVBase\base\Site;
 use JVBase\managers\Cache;
 use JVBase\meta\Meta;
@@ -126,7 +125,8 @@
         ?>
         <header id="top">
             <h1><?=$title?></h1>
-			<nav class="menu"><ul>
+        </header>
+		<nav class="menu"><ul>
 				<?php
 				$sections = $this->getSections();
 				foreach ($sections as $section) {
@@ -140,7 +140,6 @@
 				}
 				?>
 			</ul></nav>
-        </header>
         <?php
     }
 
@@ -212,26 +211,24 @@
 		$excerpt = get_the_excerpt($ID);
 		$isVariable = !empty($fields['variations']??[]);
 
-		$priceRange = jvbCurrency($fields['price']);
+
+		$product = wc_get_product($ID);
+		$isFeatured = $product->is_featured();
+		$isOnSale = $product->is_on_sale();
+		$isPurchasable = $product->is_purchasable() && $product->is_in_stock();
+
+		$priceRange = $this->getPrice($fields, $isOnSale, $isPurchasable);
+
 		if ($isVariable) {
 			$prices = array_map('floatval', array_column($fields['variations'], 'price'));
 			$min = min($prices);
 			$max = max($prices);
 			$priceRange = $min===$max ? jvbCurrency($min) : jvbCurrency($min) .' - '.jvbCurrency($max);
-
 		}
 
-//		if (!$isVariable) {
-//			jvbDump($fields, 'Fields');
+//		if (in_array($fields['post_title'],  ['Chopped Brisket Sandwich', 'Breakfast Poutine'])) {
+//			jvbDump ($fields);
 //		}
-//		jvbDump(get_post_thumbnail_id($ID), 'thumbnail');
-//		$product = wc_get_product($ID);
-//		jvbDump($product->get_image_id(), 'product image');
-//		jvbDump($product->get_gallery_image_ids(), 'Gallery images');
-		if ($fields['post_title'] === 'Breakfast Poutine') {
-//			jvbDump($ID);
-//			jvbDump($fields);
-		}
 
 		$gallery = '';
 		if (!empty($fields['gallery_image_ids'])) {
@@ -255,6 +252,7 @@
 
 		$out = sprintf(
 	'<div id="%s" class="menu-item%s" data-section="%s" data-label="%s" data-id="%s">
+				<div class="tags abs top left row">%s%s</div>
 				<div class="header row x-btw">
 					<figure>%s<figcaption>%s</figcaption></figure>
 					<div class="text row x-btw">
@@ -262,46 +260,64 @@
 						<p class="price">%s</p>
 					</div>
 				</div>
-				<div class="gallery row%s">%s</div>
+				<div class="gallery row left%s">%s</div>
 				<div class="description">%s</div>
-				<div class="info col right">',
+				<div class="info col right">
+				%s',
 			sanitize_title($fields['post_title']),
 			$isVariable ? ' variable' : '',
 			$slug,
 			$fields['post_title'],
 			$ID,
+			$isOnSale ? '<span class="sale row left top">'.jvbIcon('tag-chevron').'Sale!</span>' : '',
+			$isFeatured ? '<span class="featured row top">'.jvbIcon('star').'We Recommend</span>' : '',
 			!empty($fields['image_id']) ? jvbFormatImage((int)$fields['image_id'],'tiny','medium',true,'menu') : '',
 			$caption,
 			$fields['post_title'],
 			$priceRange,
 			empty($gallery) ? '' : ' has',
 			$gallery,
-			$excerpt
+			$excerpt,
+			$this->getSaleText($fields, $isPurchasable)
 		);
 
 		if (!empty($fields['variations']??[])) {
 			foreach ($fields['variations'] as $index => $row) {
+				$v = wc_get_product($row['id']);
+				$isOnSale = $v->is_on_sale();
+				$isPurchasable = $v->is_purchasable() && $v->is_in_stock();
+				$price = $this->getPrice($row, $isOnSale, $isPurchasable);
+
+
+				$title = str_replace($fields['post_title'].' - ','',$row['post_title']);
 				$out .= sprintf(
-				'<div class="row right nowrap">
+				'<div class="row right top nowrap">
+						%s
+						<figure>%s<figcaption>%s</figcaption></figure>
 						<div>
 							<h4>%s — %s</h4>
 							%s
-						</div><a href="?add-to-cart=%d&variation_id=%d"
+						</div><a %shref="?add-to-cart=%d&variation_id=%d"
    data-quantity="1"
    data-product_id="%d"
    data-variation_id="%d"
    class="btn chip add_to_cart_button ajax_add_to_cart add-to-cart">
    %s
    <span>Add to Cart</span>
-</a>', //Note: we had 3 %s%s%s before the last </div> last time. This was to add optional ingredients or preparation time duration, not default in WooCommerce
-						$row['title'],
-						jvbCurrency($row['price']),
+</a>%s', //Note: we had 3 %s%s%s before the last </div> last time. This was to add optional ingredients or preparation time duration, not default in WooCommerce
+				$isOnSale ? '<span class="abs top right">'.jvbIcon('tag-chevron').'Sale!</span>' : '',
+						!empty($row['image_id']) ? jvbFormatImage($row['image_id'], 'tiny', 'medium') : '',
+						empty($row['post_title']) ? $fields['post_title'] : $row['post_title'],
+						empty($title) ? $fields['post_title'] : $title,
+						$price,
 						empty($row['description']) ? '' : wpautop($row['description']),
+						$isPurchasable ? '' : 'class="disabled" ',
 						$ID,
 						$row['id'],
 						$ID,
 						$row['id'],
-						jvbIcon('plus-square')
+						jvbIcon('plus-square'),
+						$this->getSaleText($row, $isPurchasable)
 				);
 
 //				$out .= Form::render(
@@ -326,16 +342,18 @@
 				$out .= '</div>';
 			}
 		} else {
+			$isPurchasable = $product->is_purchasable() && $product->is_in_stock();
 			$out .= sprintf(
 				'<a href="?add-to-cart=%d"
 				   data-quantity="1"
 				   data-product_id="%d"
-				   class="btn chip add_to_cart_button ajax_add_to_cart add-to-cart">
+				   class="%sbtn chip add_to_cart_button ajax_add_to_cart add-to-cart">
 				   %s
    					<span>Add to Cart</span>
 				</a>',
 				$ID,
 				$ID,
+				$isPurchasable ? '' : 'disabled ',
 				jvbIcon('plus-square')
 			);
 //			$out .= Form::render(
@@ -365,6 +383,36 @@
 		echo $out;
 
 	}
+
+	protected function getPrice(array $item, bool $isOnSale, bool $isPurchasable):string
+	{
+		$price = jvbCurrency($item['regular_price']);
+		$price = $isOnSale ? '<s> '.$price.' </s> '.jvbCurrency($item['sale_price']) : $price;
+
+		return $price;
+	}
+
+	protected function getSaleText(array $item, bool $isPurchasable):string
+	{
+		if (empty($item['date_on_sale_to']) && $isPurchasable) {
+			return '';
+		}
+
+		$out = sprintf(
+			'<span class="sale-until">%sOn sale until <time datetime="%s">%s</time>.</span>',
+			jvbIcon('tag-chevron'),
+			$item['date_on_sale_to']->format('c'),
+			$item['date_on_sale_to']->format('l, F j, Y')
+		);
+
+		if (!$isPurchasable) {
+			$out .= sprintf(
+				'<span class="out-of-stock">%sTemporarily Out of Stock</span>',
+				jvbIcon('warning-circle')
+			);
+		}
+		return $out;
+	}
 	/**
 	protected function renderMenuItemOLD(int $ID, string $slug, string $postType = 'menu_item') {
 		$meta = Meta::forPost($ID);

--
Gitblit v1.10.0