feat: Rename WordPress plugin to CannaIQ Menus v1.5.3

- Rename plugin from Crawlsy Menus to CannaIQ Menus
- Update version to 1.5.3
- Update text domain to cannaiq-menus
- Rename all CSS classes from crawlsy-* to cannaiq-*
- Update shortcodes to [cannaiq_products] and [cannaiq_product]
- Add backward compatibility for legacy shortcodes
- Update download links on Home and LandingPage
- Fix health panel Redis timeout issue
- Add clear error message when backend not running

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Kelly
2025-12-08 00:24:43 -07:00
parent bf4ceaf09e
commit 948a732dd5
12 changed files with 1010 additions and 241 deletions

View File

@@ -0,0 +1,314 @@
/**
* CannaIQ Menus - WordPress Plugin Styles
* v1.5.3
*/
/* Product Grid */
.cannaiq-product-grid {
display: grid;
gap: 24px;
margin: 20px 0;
}
.cannaiq-grid-cols-2 {
grid-template-columns: repeat(2, 1fr);
}
.cannaiq-grid-cols-3 {
grid-template-columns: repeat(3, 1fr);
}
.cannaiq-grid-cols-4 {
grid-template-columns: repeat(4, 1fr);
}
.cannaiq-grid-cols-6 {
grid-template-columns: repeat(6, 1fr);
}
@media (max-width: 1024px) {
.cannaiq-grid-cols-4,
.cannaiq-grid-cols-6 {
grid-template-columns: repeat(3, 1fr);
}
}
@media (max-width: 768px) {
.cannaiq-grid-cols-3,
.cannaiq-grid-cols-4,
.cannaiq-grid-cols-6 {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 480px) {
.cannaiq-product-grid {
grid-template-columns: 1fr;
}
}
/* Product Card */
.cannaiq-product-card {
background: #fff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: transform 0.2s, box-shadow 0.2s;
display: flex;
flex-direction: column;
}
.cannaiq-product-card:hover {
transform: translateY(-4px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}
.cannaiq-product-image {
width: 100%;
aspect-ratio: 1;
overflow: hidden;
background: #f5f5f5;
}
.cannaiq-product-image img {
width: 100%;
height: 100%;
object-fit: cover;
}
.cannaiq-product-content {
padding: 16px;
flex: 1;
display: flex;
flex-direction: column;
}
.cannaiq-product-title {
font-size: 18px;
font-weight: 600;
margin: 0 0 8px 0;
color: #333;
line-height: 1.4;
}
.cannaiq-product-brand {
font-size: 14px;
color: #666;
margin-bottom: 8px;
}
.cannaiq-product-description {
font-size: 14px;
color: #666;
line-height: 1.6;
margin: 0 0 12px 0;
}
.cannaiq-product-meta {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin: 12px 0;
}
.cannaiq-meta-item {
font-size: 13px;
padding: 4px 10px;
border-radius: 4px;
background: #f0f0f0;
}
.cannaiq-meta-item strong {
color: #333;
}
.cannaiq-thc {
background: #e8f5e9;
color: #2e7d32;
}
.cannaiq-cbd {
background: #e3f2fd;
color: #1565c0;
}
.cannaiq-product-price {
font-size: 20px;
font-weight: 700;
color: #2e7d32;
margin-top: auto;
padding-top: 12px;
}
.cannaiq-price-sale {
color: #c62828;
}
.cannaiq-price-regular.cannaiq-strikethrough {
text-decoration: line-through;
color: #999;
font-size: 16px;
margin-left: 8px;
}
.cannaiq-out-of-stock {
display: inline-block;
padding: 6px 12px;
background: #ffebee;
color: #c62828;
font-size: 13px;
font-weight: 600;
border-radius: 4px;
margin-top: 8px;
}
/* Single Product */
.cannaiq-single-product {
background: #fff;
border-radius: 8px;
padding: 24px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
margin: 20px 0;
}
.cannaiq-layout-horizontal {
display: grid;
grid-template-columns: 400px 1fr;
gap: 32px;
}
.cannaiq-layout-vertical {
display: flex;
flex-direction: column;
gap: 24px;
}
@media (max-width: 768px) {
.cannaiq-layout-horizontal {
grid-template-columns: 1fr;
}
}
.cannaiq-single-product-image {
width: 100%;
aspect-ratio: 1;
overflow: hidden;
border-radius: 8px;
background: #f5f5f5;
}
.cannaiq-single-product-image img {
width: 100%;
height: 100%;
object-fit: cover;
}
.cannaiq-single-product-details {
display: flex;
flex-direction: column;
gap: 16px;
}
.cannaiq-single-product-title {
font-size: 28px;
font-weight: 700;
margin: 0;
color: #333;
line-height: 1.3;
}
.cannaiq-single-product-brand {
font-size: 16px;
color: #666;
}
.cannaiq-single-product-brand strong {
color: #333;
}
.cannaiq-single-product-description {
font-size: 16px;
line-height: 1.6;
color: #555;
}
.cannaiq-single-product-info {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
padding: 16px;
background: #f8f8f8;
border-radius: 8px;
}
.cannaiq-info-item {
display: flex;
flex-direction: column;
gap: 4px;
}
.cannaiq-info-item strong {
font-size: 14px;
color: #333;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.cannaiq-info-item span {
font-size: 16px;
color: #555;
}
.cannaiq-info-item.cannaiq-terpenes span,
.cannaiq-info-item.cannaiq-effects span,
.cannaiq-info-item.cannaiq-flavors span {
font-size: 14px;
}
.cannaiq-single-product-price {
font-size: 32px;
font-weight: 700;
color: #2e7d32;
}
/* Loading State */
.cannaiq-loading {
text-align: center;
padding: 40px;
color: #666;
}
.cannaiq-loading:after {
content: "...";
animation: cannaiq-dots 1.5s steps(4, end) infinite;
}
@keyframes cannaiq-dots {
0%, 20% {
color: rgba(0, 0, 0, 0);
text-shadow: 0.25em 0 0 rgba(0, 0, 0, 0),
0.5em 0 0 rgba(0, 0, 0, 0);
}
40% {
color: #666;
text-shadow: 0.25em 0 0 rgba(0, 0, 0, 0),
0.5em 0 0 rgba(0, 0, 0, 0);
}
60% {
text-shadow: 0.25em 0 0 #666,
0.5em 0 0 rgba(0, 0, 0, 0);
}
80%, 100% {
text-shadow: 0.25em 0 0 #666,
0.5em 0 0 #666;
}
}
/* Error State */
.cannaiq-error {
padding: 16px;
background: #ffebee;
color: #c62828;
border-radius: 4px;
border-left: 4px solid #c62828;
}

View File

@@ -0,0 +1,58 @@
/**
* CannaIQ Menus - WordPress Plugin JavaScript
* v1.5.3
*/
(function($) {
'use strict';
/**
* Initialize plugin
*/
$(document).ready(function() {
// Lazy load images
if ('IntersectionObserver' in window) {
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
if (img.dataset.src) {
img.src = img.dataset.src;
img.removeAttribute('data-src');
observer.unobserve(img);
}
}
});
});
document.querySelectorAll('.cannaiq-product-image img[data-src]').forEach(img => {
imageObserver.observe(img);
});
}
// Add animation to product cards on scroll
if ('IntersectionObserver' in window) {
const cardObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '0';
entry.target.style.transform = 'translateY(20px)';
setTimeout(() => {
entry.target.style.transition = 'opacity 0.5s, transform 0.5s';
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}, 10);
cardObserver.unobserve(entry.target);
}
});
}, {
threshold: 0.1
});
document.querySelectorAll('.cannaiq-product-card').forEach(card => {
cardObserver.observe(card);
});
}
});
})(jQuery);

View File

@@ -1,23 +1,23 @@
#!/bin/bash
# WordPress Plugin Build Script
# Builds the plugin zip with the correct naming convention: cb-wpmenu-{version}.zip
# Builds the plugin zip with the correct naming convention: cannaiq-menus-{version}.zip
set -e
# Get the version from the main plugin file
VERSION=$(grep -oP "Version:\s*\K[0-9.]+" crawlsy-menus.php)
VERSION=$(grep -oP "Version:\s*\K[0-9.]+" cannaiq-menus.php)
if [ -z "$VERSION" ]; then
echo "Error: Could not extract version from crawlsy-menus.php"
echo "Error: Could not extract version from cannaiq-menus.php"
exit 1
fi
# Define paths
PLUGIN_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="${PLUGIN_DIR}/../backend/public/downloads"
OUTPUT_FILE="cb-wpmenu-${VERSION}.zip"
OUTPUT_FILE="cannaiq-menus-${VERSION}.zip"
echo "Building WordPress plugin..."
echo "Building CannaIQ Menus WordPress plugin..."
echo " Version: ${VERSION}"
echo " Output: ${OUTPUT_DIR}/${OUTPUT_FILE}"
@@ -27,13 +27,18 @@ mkdir -p "${OUTPUT_DIR}"
# Create the zip file (from the plugin directory)
cd "${PLUGIN_DIR}"
rm -f "${OUTPUT_DIR}/${OUTPUT_FILE}"
zip -r "${OUTPUT_DIR}/${OUTPUT_FILE}" . -x "*.git*" -x "build-plugin.sh"
# Exclude old/legacy files and build script
zip -r "${OUTPUT_DIR}/${OUTPUT_FILE}" . \
-x "*.git*" \
-x "build-plugin.sh" \
-x "crawlsy-menus.php" \
-x "assets/css/crawlsy-menus.css" \
-x "assets/js/crawlsy-menus.js"
echo ""
echo "Build complete!"
echo " File: ${OUTPUT_DIR}/${OUTPUT_FILE}"
echo " Size: $(ls -lh "${OUTPUT_DIR}/${OUTPUT_FILE}" | awk '{print $5}')"
echo ""
echo "IMPORTANT: Update frontend/src/pages/LandingPage.tsx with the new version:"
echo " href=\"/downloads/cb-wpmenu-${VERSION}.zip\""
echo " Download Plugin v${VERSION}"
echo "Download URL: https://cannaiq.co/downloads/cannaiq-menus-${VERSION}.zip"

View File

@@ -0,0 +1,402 @@
<?php
/**
* Plugin Name: CannaIQ Menus
* Plugin URI: https://cannaiq.co
* Description: Display cannabis product menus from CannaIQ with Elementor integration. Real-time menu data updated daily.
* Version: 1.5.3
* Author: CannaIQ
* Author URI: https://cannaiq.co
* License: GPL v2 or later
* Text Domain: cannaiq-menus
* Requires PHP: 7.4
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
define('CANNAIQ_MENUS_VERSION', '1.5.3');
define('CANNAIQ_MENUS_API_URL', 'https://cannaiq.co/api/v1');
define('CANNAIQ_MENUS_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('CANNAIQ_MENUS_PLUGIN_URL', plugin_dir_url(__FILE__));
/**
* Main Plugin Class
*/
class CannaIQ_Menus_Plugin {
private static $instance = null;
public static function instance() {
if (is_null(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
public function __construct() {
add_action('plugins_loaded', [$this, 'init']);
add_action('elementor/widgets/register', [$this, 'register_elementor_widgets']);
add_action('admin_menu', [$this, 'add_admin_menu']);
add_action('admin_init', [$this, 'register_settings']);
add_action('wp_enqueue_scripts', [$this, 'enqueue_scripts']);
}
public function init() {
// Initialize plugin
load_plugin_textdomain('cannaiq-menus', false, dirname(plugin_basename(__FILE__)) . '/languages');
// Register shortcodes
add_shortcode('cannaiq_products', [$this, 'products_shortcode']);
add_shortcode('cannaiq_product', [$this, 'single_product_shortcode']);
// Legacy shortcode support (backward compatibility)
add_shortcode('crawlsy_products', [$this, 'products_shortcode']);
add_shortcode('crawlsy_product', [$this, 'single_product_shortcode']);
add_shortcode('dutchie_products', [$this, 'products_shortcode']);
add_shortcode('dutchie_product', [$this, 'single_product_shortcode']);
}
/**
* Register Elementor Widgets
*/
public function register_elementor_widgets($widgets_manager) {
require_once CANNAIQ_MENUS_PLUGIN_DIR . 'widgets/product-grid.php';
require_once CANNAIQ_MENUS_PLUGIN_DIR . 'widgets/single-product.php';
$widgets_manager->register(new \CannaIQ_Menus_Product_Grid_Widget());
$widgets_manager->register(new \CannaIQ_Menus_Single_Product_Widget());
}
/**
* Enqueue Scripts and Styles
*/
public function enqueue_scripts() {
wp_enqueue_style(
'cannaiq-menus-styles',
CANNAIQ_MENUS_PLUGIN_URL . 'assets/css/cannaiq-menus.css',
[],
CANNAIQ_MENUS_VERSION
);
wp_enqueue_script(
'cannaiq-menus-script',
CANNAIQ_MENUS_PLUGIN_URL . 'assets/js/cannaiq-menus.js',
['jquery'],
CANNAIQ_MENUS_VERSION,
true
);
}
/**
* Add Admin Menu
*/
public function add_admin_menu() {
add_menu_page(
'CannaIQ Menus',
'CannaIQ Menus',
'manage_options',
'cannaiq-menus',
[$this, 'admin_page'],
'dashicons-products',
30
);
}
/**
* Register Plugin Settings
*/
public function register_settings() {
register_setting('cannaiq_menus_settings', 'cannaiq_api_token');
// Migrate old settings if they exist
$old_crawlsy_token = get_option('crawlsy_api_token');
$old_dutchie_token = get_option('dutchie_api_token');
if (!get_option('cannaiq_api_token')) {
if ($old_crawlsy_token) {
update_option('cannaiq_api_token', $old_crawlsy_token);
} elseif ($old_dutchie_token) {
update_option('cannaiq_api_token', $old_dutchie_token);
}
}
}
/**
* Admin Page
*/
public function admin_page() {
?>
<div class="wrap">
<h1>CannaIQ Menus Settings</h1>
<p>Version <?php echo CANNAIQ_MENUS_VERSION; ?> by <a href="https://cannaiq.co" target="_blank">CannaIQ</a></p>
<p class="description">Display real-time cannabis menus with data updated daily from CannaIQ.</p>
<form method="post" action="options.php">
<?php settings_fields('cannaiq_menus_settings'); ?>
<?php do_settings_sections('cannaiq_menus_settings'); ?>
<table class="form-table">
<tr>
<th scope="row"><label for="cannaiq_api_token">API Token</label></th>
<td>
<input type="password" id="cannaiq_api_token" name="cannaiq_api_token"
value="<?php echo esc_attr(get_option('cannaiq_api_token')); ?>"
class="regular-text" />
<p class="description">Your authentication token from the CannaIQ admin dashboard. The token includes your store configuration.</p>
</td>
</tr>
</table>
<?php submit_button(); ?>
</form>
<hr />
<h2>Test Connection</h2>
<button type="button" id="test-api-connection" class="button button-primary">Test API Connection</button>
<div id="api-test-result" style="margin-top: 10px;"></div>
<script>
jQuery(document).ready(function($) {
$('#test-api-connection').on('click', function() {
var apiUrl = '<?php echo CANNAIQ_MENUS_API_URL; ?>';
var apiToken = $('#cannaiq_api_token').val();
if (!apiToken || apiToken.trim() === '') {
$('#api-test-result').html(
'<div class="notice notice-warning"><p><strong>Warning:</strong> Please enter an API token first.</p></div>'
);
return;
}
$('#api-test-result').html('<p><span class="spinner is-active" style="float:none;margin:0 5px 0 0;"></span>Testing connection...</p>');
$.ajax({
url: apiUrl + '/menu',
method: 'GET',
headers: {
'X-API-Key': apiToken
},
timeout: 30000,
success: function(response) {
var html = '<div class="notice notice-success"><p><strong>Success!</strong> Connected to: ' +
response.dispensary + '</p>';
if (response.menu) {
html += '<ul style="margin-left: 20px;">';
html += '<li>Total Products: ' + (response.menu.total_products || 0) + '</li>';
html += '<li>In Stock: ' + (response.menu.in_stock_count || 0) + '</li>';
html += '<li>Brands: ' + (response.menu.brand_count || 0) + '</li>';
html += '<li>Categories: ' + (response.menu.category_count || 0) + '</li>';
if (response.menu.last_updated) {
html += '<li>Last Updated: ' + new Date(response.menu.last_updated).toLocaleString() + '</li>';
}
html += '</ul>';
}
html += '</div>';
$('#api-test-result').html(html);
},
error: function(xhr, textStatus, errorThrown) {
var errorHtml = '<div class="notice notice-error">';
errorHtml += '<p><strong>Connection Failed</strong></p>';
// Show HTTP status
if (xhr.status) {
errorHtml += '<p><strong>HTTP Status:</strong> ' + xhr.status + ' ' + (xhr.statusText || '') + '</p>';
}
// Show error message from API
if (xhr.responseJSON) {
if (xhr.responseJSON.error) {
errorHtml += '<p><strong>Error:</strong> ' + xhr.responseJSON.error + '</p>';
}
if (xhr.responseJSON.message) {
errorHtml += '<p><strong>Details:</strong> ' + xhr.responseJSON.message + '</p>';
}
if (xhr.responseJSON.client_ip) {
errorHtml += '<p><strong>Your IP:</strong> ' + xhr.responseJSON.client_ip + '</p>';
}
if (xhr.responseJSON.origin) {
errorHtml += '<p><strong>Origin:</strong> ' + xhr.responseJSON.origin + '</p>';
}
} else if (textStatus === 'timeout') {
errorHtml += '<p><strong>Error:</strong> Request timed out. The API server may be unavailable.</p>';
} else if (textStatus === 'error' && !xhr.status) {
errorHtml += '<p><strong>Error:</strong> Could not connect to the API. This may be a CORS issue or network problem.</p>';
errorHtml += '<p><em>Note: If testing from wp-admin, try saving the token and testing on the frontend shortcode instead.</em></p>';
} else {
errorHtml += '<p><strong>Error:</strong> ' + (errorThrown || textStatus || 'Unknown error') + '</p>';
}
// Debug info
errorHtml += '<details style="margin-top: 10px;"><summary style="cursor:pointer;"><strong>Debug Info</strong></summary>';
errorHtml += '<pre style="background:#f5f5f5;padding:10px;margin-top:5px;overflow-x:auto;font-size:11px;">';
errorHtml += 'API URL: ' + apiUrl + '/menu\n';
errorHtml += 'Token Length: ' + apiToken.length + ' chars\n';
errorHtml += 'Token Preview: ' + apiToken.substring(0, 8) + '...' + apiToken.substring(apiToken.length - 4) + '\n';
errorHtml += 'Status: ' + xhr.status + '\n';
errorHtml += 'Response: ' + (xhr.responseText ? xhr.responseText.substring(0, 500) : 'none') + '\n';
errorHtml += '</pre></details>';
// Help text based on status
if (xhr.status === 401) {
errorHtml += '<p style="margin-top:10px;"><strong>Troubleshooting:</strong> Your API token is invalid or inactive. Please check that you copied the full token from the CannaIQ admin dashboard.</p>';
} else if (xhr.status === 403) {
errorHtml += '<p style="margin-top:10px;"><strong>Troubleshooting:</strong> Access denied. Your IP address or domain may not be in the allowed list. Contact support to update your permissions.</p>';
} else if (xhr.status === 500) {
errorHtml += '<p style="margin-top:10px;"><strong>Troubleshooting:</strong> Server error. This may be a temporary issue. Try again in a few minutes, or contact support if the problem persists.</p>';
} else if (xhr.status === 503) {
errorHtml += '<p style="margin-top:10px;"><strong>Troubleshooting:</strong> Menu data is not yet available for your dispensary. The data may still be processing.</p>';
}
errorHtml += '</div>';
$('#api-test-result').html(errorHtml);
}
});
});
});
</script>
<hr />
<h2>Usage</h2>
<h3>Shortcodes</h3>
<table class="widefat" style="max-width: 800px;">
<thead>
<tr>
<th>Shortcode</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>[cannaiq_products]</code></td>
<td>Display a grid of products. Options: <code>category_id</code>, <code>limit</code>, <code>columns</code>, <code>in_stock</code></td>
</tr>
<tr>
<td><code>[cannaiq_product id="123"]</code></td>
<td>Display a single product by ID</td>
</tr>
</tbody>
</table>
<h3>Elementor Widgets</h3>
<p>If you have Elementor installed, you can use the CannaIQ widgets:</p>
<ul style="list-style: disc; margin-left: 20px;">
<li><strong>CannaIQ Product Grid</strong> - Display a grid of products with filtering options</li>
<li><strong>CannaIQ Single Product</strong> - Display a single product card</li>
</ul>
</div>
<?php
}
/**
* Products Shortcode
*/
public function products_shortcode($atts) {
$atts = shortcode_atts([
'category_id' => '',
'limit' => 12,
'columns' => 3,
'in_stock' => 'true'
], $atts);
$products = $this->fetch_products($atts);
if (!$products) {
return '<p>No products found.</p>';
}
ob_start();
include CANNAIQ_MENUS_PLUGIN_DIR . 'templates/product-grid.php';
return ob_get_clean();
}
/**
* Single Product Shortcode
*/
public function single_product_shortcode($atts) {
$atts = shortcode_atts([
'id' => 0
], $atts);
if (!$atts['id']) {
return '<p>Product ID required.</p>';
}
$product = $this->fetch_product($atts['id']);
if (!$product) {
return '<p>Product not found.</p>';
}
ob_start();
include CANNAIQ_MENUS_PLUGIN_DIR . 'templates/single-product.php';
return ob_get_clean();
}
/**
* Fetch Products from API
*/
public function fetch_products($args = []) {
$api_token = get_option('cannaiq_api_token');
if (!$api_token) {
return false;
}
$query_args = http_build_query($args);
$url = CANNAIQ_MENUS_API_URL . '/products?' . $query_args;
$response = wp_remote_get($url, [
'headers' => [
'X-API-Key' => $api_token
],
'timeout' => 30
]);
if (is_wp_error($response)) {
return false;
}
$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);
return $data['products'] ?? false;
}
/**
* Fetch Single Product from API
*/
public function fetch_product($id) {
$api_token = get_option('cannaiq_api_token');
if (!$api_token) {
return false;
}
$url = CANNAIQ_MENUS_API_URL . '/products/' . intval($id);
$response = wp_remote_get($url, [
'headers' => [
'X-API-Key' => $api_token
],
'timeout' => 30
]);
if (is_wp_error($response)) {
return false;
}
$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);
return $data['product'] ?? false;
}
}
// Initialize Plugin
function cannaiq_menus() {
return CannaIQ_Menus_Plugin::instance();
}
cannaiq_menus();

View File

@@ -10,62 +10,67 @@ if (!defined('ABSPATH')) {
$columns = isset($atts['columns']) ? $atts['columns'] : 3;
?>
<div class="crawlsy-product-grid crawlsy-grid-cols-<?php echo esc_attr($columns); ?>">
<div class="cannaiq-product-grid cannaiq-grid-cols-<?php echo esc_attr($columns); ?>">
<?php foreach ($products as $product):
$image_url = $product['image_url'] ?? $product['primary_image_url'] ?? $product['image_url_full'] ?? '';
$product_url = !empty($product['dutchie_url']) ? $product['dutchie_url'] : '#';
$image_url = $product['image_url'] ?? $product['primary_image_url'] ?? '';
$product_url = !empty($product['menu_url']) ? $product['menu_url'] : '#';
?>
<div class="crawlsy-product-card"
<div class="cannaiq-product-card"
<?php if ($product_url !== '#'): ?>onclick="window.open('<?php echo esc_url($product_url); ?>', '_blank')"<?php endif; ?>
style="cursor: <?php echo ($product_url !== '#') ? 'pointer' : 'default'; ?>;">
<?php if (!empty($image_url)): ?>
<div class="crawlsy-product-image">
<div class="cannaiq-product-image">
<img src="<?php echo esc_url($image_url); ?>"
alt="<?php echo esc_attr($product['name']); ?>"
loading="lazy" />
</div>
<?php endif; ?>
<div class="crawlsy-product-content">
<h3 class="crawlsy-product-title">
<div class="cannaiq-product-content">
<h3 class="cannaiq-product-title">
<?php echo esc_html($product['name']); ?>
</h3>
<?php if (!empty($product['brand'])): ?>
<div class="crawlsy-product-brand">
<div class="cannaiq-product-brand">
<?php echo esc_html($product['brand']); ?>
</div>
<?php endif; ?>
<?php if (!empty($product['description'])): ?>
<p class="crawlsy-product-description">
<p class="cannaiq-product-description">
<?php echo esc_html(wp_trim_words($product['description'], 15)); ?>
</p>
<?php endif; ?>
<div class="crawlsy-product-meta">
<?php if (!empty($product['metadata']['thc'])): ?>
<span class="crawlsy-meta-item crawlsy-thc">
<strong>THC:</strong> <?php echo esc_html($product['metadata']['thc']); ?>
<div class="cannaiq-product-meta">
<?php if (!empty($product['thc_percentage'])): ?>
<span class="cannaiq-meta-item cannaiq-thc">
<strong>THC:</strong> <?php echo esc_html($product['thc_percentage']); ?>%
</span>
<?php endif; ?>
<?php if (!empty($product['metadata']['cbd'])): ?>
<span class="crawlsy-meta-item crawlsy-cbd">
<strong>CBD:</strong> <?php echo esc_html($product['metadata']['cbd']); ?>
<?php if (!empty($product['cbd_percentage'])): ?>
<span class="cannaiq-meta-item cannaiq-cbd">
<strong>CBD:</strong> <?php echo esc_html($product['cbd_percentage']); ?>%
</span>
<?php endif; ?>
</div>
<?php if (isset($product['price'])): ?>
<div class="crawlsy-product-price">
$<?php echo number_format($product['price'], 2); ?>
<?php if (isset($product['regular_price'])): ?>
<div class="cannaiq-product-price">
<?php if (!empty($product['sale_price']) && $product['sale_price'] != $product['regular_price']): ?>
<span class="cannaiq-price-sale">$<?php echo esc_html($product['sale_price']); ?></span>
<span class="cannaiq-price-regular cannaiq-strikethrough">$<?php echo esc_html($product['regular_price']); ?></span>
<?php else: ?>
$<?php echo esc_html($product['regular_price']); ?>
<?php endif; ?>
</div>
<?php endif; ?>
<?php if (!$product['in_stock']): ?>
<div class="crawlsy-out-of-stock">
<?php _e('Out of Stock', 'crawlsy-menus'); ?>
<div class="cannaiq-out-of-stock">
<?php _e('Out of Stock', 'cannaiq-menus'); ?>
</div>
<?php endif; ?>
</div>

View File

@@ -6,92 +6,77 @@
if (!defined('ABSPATH')) {
exit;
}
$image_url = $product['image_url'] ?? '';
?>
<div class="crawlsy-single-product crawlsy-layout-horizontal">
<?php if (!empty($product['image_url_full'])): ?>
<div class="crawlsy-single-product-image">
<img src="<?php echo esc_url($product['image_url_full']); ?>"
<div class="cannaiq-single-product cannaiq-layout-horizontal">
<?php if (!empty($image_url)): ?>
<div class="cannaiq-single-product-image">
<img src="<?php echo esc_url($image_url); ?>"
alt="<?php echo esc_attr($product['name']); ?>" />
</div>
<?php endif; ?>
<div class="crawlsy-single-product-details">
<h2 class="crawlsy-single-product-title">
<div class="cannaiq-single-product-details">
<h2 class="cannaiq-single-product-title">
<?php echo esc_html($product['name']); ?>
</h2>
<?php if (!empty($product['brand'])): ?>
<div class="crawlsy-single-product-brand">
<strong><?php _e('Brand:', 'crawlsy-menus'); ?></strong>
<div class="cannaiq-single-product-brand">
<strong><?php _e('Brand:', 'cannaiq-menus'); ?></strong>
<?php echo esc_html($product['brand']); ?>
</div>
<?php endif; ?>
<?php if (!empty($product['description'])): ?>
<div class="crawlsy-single-product-description">
<div class="cannaiq-single-product-description">
<?php echo wp_kses_post(nl2br($product['description'])); ?>
</div>
<?php endif; ?>
<div class="crawlsy-single-product-info">
<?php if (!empty($product['metadata']['thc'])): ?>
<div class="crawlsy-info-item">
<strong><?php _e('THC:', 'crawlsy-menus'); ?></strong>
<span><?php echo esc_html($product['metadata']['thc']); ?></span>
<div class="cannaiq-single-product-info">
<?php if (!empty($product['thc_percentage'])): ?>
<div class="cannaiq-info-item">
<strong><?php _e('THC:', 'cannaiq-menus'); ?></strong>
<span><?php echo esc_html($product['thc_percentage']); ?>%</span>
</div>
<?php endif; ?>
<?php if (!empty($product['metadata']['cbd'])): ?>
<div class="crawlsy-info-item">
<strong><?php _e('CBD:', 'crawlsy-menus'); ?></strong>
<span><?php echo esc_html($product['metadata']['cbd']); ?></span>
<?php if (!empty($product['cbd_percentage'])): ?>
<div class="cannaiq-info-item">
<strong><?php _e('CBD:', 'cannaiq-menus'); ?></strong>
<span><?php echo esc_html($product['cbd_percentage']); ?>%</span>
</div>
<?php endif; ?>
<?php if (!empty($product['metadata']['terpenes'])): ?>
<div class="crawlsy-info-item crawlsy-terpenes">
<strong><?php _e('Terpenes:', 'crawlsy-menus'); ?></strong>
<?php if (is_array($product['metadata']['terpenes'])): ?>
<span><?php echo esc_html(implode(', ', $product['metadata']['terpenes'])); ?></span>
<?php if (!empty($product['effects'])): ?>
<div class="cannaiq-info-item cannaiq-effects">
<strong><?php _e('Effects:', 'cannaiq-menus'); ?></strong>
<?php if (is_array($product['effects'])): ?>
<span><?php echo esc_html(implode(', ', $product['effects'])); ?></span>
<?php else: ?>
<span><?php echo esc_html($product['metadata']['terpenes']); ?></span>
<?php endif; ?>
</div>
<?php endif; ?>
<?php if (!empty($product['metadata']['effects'])): ?>
<div class="crawlsy-info-item crawlsy-effects">
<strong><?php _e('Effects:', 'crawlsy-menus'); ?></strong>
<?php if (is_array($product['metadata']['effects'])): ?>
<span><?php echo esc_html(implode(', ', $product['metadata']['effects'])); ?></span>
<?php else: ?>
<span><?php echo esc_html($product['metadata']['effects']); ?></span>
<?php endif; ?>
</div>
<?php endif; ?>
<?php if (!empty($product['metadata']['flavors'])): ?>
<div class="crawlsy-info-item crawlsy-flavors">
<strong><?php _e('Flavors:', 'crawlsy-menus'); ?></strong>
<?php if (is_array($product['metadata']['flavors'])): ?>
<span><?php echo esc_html(implode(', ', $product['metadata']['flavors'])); ?></span>
<?php else: ?>
<span><?php echo esc_html($product['metadata']['flavors']); ?></span>
<span><?php echo esc_html($product['effects']); ?></span>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<?php if (isset($product['price'])): ?>
<div class="crawlsy-single-product-price">
$<?php echo number_format($product['price'], 2); ?>
<?php if (isset($product['regular_price'])): ?>
<div class="cannaiq-single-product-price">
<?php if (!empty($product['sale_price']) && $product['sale_price'] != $product['regular_price']): ?>
<span class="cannaiq-price-sale">$<?php echo esc_html($product['sale_price']); ?></span>
<span class="cannaiq-price-regular cannaiq-strikethrough">$<?php echo esc_html($product['regular_price']); ?></span>
<?php else: ?>
$<?php echo esc_html($product['regular_price']); ?>
<?php endif; ?>
</div>
<?php endif; ?>
<?php if (!$product['in_stock']): ?>
<div class="crawlsy-out-of-stock">
<?php _e('Out of Stock', 'crawlsy-menus'); ?>
<div class="cannaiq-out-of-stock">
<?php _e('Out of Stock', 'cannaiq-menus'); ?>
</div>
<?php endif; ?>
</div>

View File

@@ -7,14 +7,14 @@ if (!defined('ABSPATH')) {
exit;
}
class Crawlsy_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
class CannaIQ_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
public function get_name() {
return 'crawlsy_product_grid';
return 'cannaiq_product_grid';
}
public function get_title() {
return __('Crawlsy Product Grid', 'crawlsy-menus');
return __('CannaIQ Product Grid', 'cannaiq-menus');
}
public function get_icon() {
@@ -31,7 +31,7 @@ class Crawlsy_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
$this->start_controls_section(
'content_section',
[
'label' => __('Content', 'crawlsy-menus'),
'label' => __('Content', 'cannaiq-menus'),
'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
]
);
@@ -39,9 +39,9 @@ class Crawlsy_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
$this->add_control(
'store_id',
[
'label' => __('Store ID', 'crawlsy-menus'),
'label' => __('Store ID', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::NUMBER,
'default' => get_option('crawlsy_default_store_id', 1),
'default' => get_option('cannaiq_default_store_id', 1),
'min' => 1,
]
);
@@ -49,17 +49,17 @@ class Crawlsy_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
$this->add_control(
'category_id',
[
'label' => __('Category ID', 'crawlsy-menus'),
'label' => __('Category ID', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::NUMBER,
'default' => '',
'description' => __('Leave empty to show all categories', 'crawlsy-menus'),
'description' => __('Leave empty to show all categories', 'cannaiq-menus'),
]
);
$this->add_control(
'limit',
[
'label' => __('Number of Products', 'crawlsy-menus'),
'label' => __('Number of Products', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::NUMBER,
'default' => 12,
'min' => 1,
@@ -70,14 +70,14 @@ class Crawlsy_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
$this->add_control(
'columns',
[
'label' => __('Columns', 'crawlsy-menus'),
'label' => __('Columns', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::SELECT,
'default' => '3',
'options' => [
'2' => __('2 Columns', 'crawlsy-menus'),
'3' => __('3 Columns', 'crawlsy-menus'),
'4' => __('4 Columns', 'crawlsy-menus'),
'6' => __('6 Columns', 'crawlsy-menus'),
'2' => __('2 Columns', 'cannaiq-menus'),
'3' => __('3 Columns', 'cannaiq-menus'),
'4' => __('4 Columns', 'cannaiq-menus'),
'6' => __('6 Columns', 'cannaiq-menus'),
],
]
);
@@ -85,10 +85,10 @@ class Crawlsy_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
$this->add_control(
'in_stock_only',
[
'label' => __('In Stock Only', 'crawlsy-menus'),
'label' => __('In Stock Only', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::SWITCHER,
'label_on' => __('Yes', 'crawlsy-menus'),
'label_off' => __('No', 'crawlsy-menus'),
'label_on' => __('Yes', 'cannaiq-menus'),
'label_off' => __('No', 'cannaiq-menus'),
'return_value' => 'yes',
'default' => 'yes',
]
@@ -97,10 +97,10 @@ class Crawlsy_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
$this->add_control(
'search',
[
'label' => __('Search Filter', 'crawlsy-menus'),
'label' => __('Search Filter', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::TEXT,
'default' => '',
'description' => __('Filter products by name', 'crawlsy-menus'),
'description' => __('Filter products by name', 'cannaiq-menus'),
]
);
@@ -110,7 +110,7 @@ class Crawlsy_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
$this->start_controls_section(
'display_section',
[
'label' => __('Display Options', 'crawlsy-menus'),
'label' => __('Display Options', 'cannaiq-menus'),
'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
]
);
@@ -118,10 +118,10 @@ class Crawlsy_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
$this->add_control(
'show_image',
[
'label' => __('Show Image', 'crawlsy-menus'),
'label' => __('Show Image', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::SWITCHER,
'label_on' => __('Yes', 'crawlsy-menus'),
'label_off' => __('No', 'crawlsy-menus'),
'label_on' => __('Yes', 'cannaiq-menus'),
'label_off' => __('No', 'cannaiq-menus'),
'return_value' => 'yes',
'default' => 'yes',
]
@@ -130,10 +130,10 @@ class Crawlsy_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
$this->add_control(
'show_price',
[
'label' => __('Show Price', 'crawlsy-menus'),
'label' => __('Show Price', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::SWITCHER,
'label_on' => __('Yes', 'crawlsy-menus'),
'label_off' => __('No', 'crawlsy-menus'),
'label_on' => __('Yes', 'cannaiq-menus'),
'label_off' => __('No', 'cannaiq-menus'),
'return_value' => 'yes',
'default' => 'yes',
]
@@ -142,10 +142,10 @@ class Crawlsy_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
$this->add_control(
'show_thc',
[
'label' => __('Show THC', 'crawlsy-menus'),
'label' => __('Show THC', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::SWITCHER,
'label_on' => __('Yes', 'crawlsy-menus'),
'label_off' => __('No', 'crawlsy-menus'),
'label_on' => __('Yes', 'cannaiq-menus'),
'label_off' => __('No', 'cannaiq-menus'),
'return_value' => 'yes',
'default' => 'yes',
]
@@ -154,10 +154,10 @@ class Crawlsy_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
$this->add_control(
'show_cbd',
[
'label' => __('Show CBD', 'crawlsy-menus'),
'label' => __('Show CBD', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::SWITCHER,
'label_on' => __('Yes', 'crawlsy-menus'),
'label_off' => __('No', 'crawlsy-menus'),
'label_on' => __('Yes', 'cannaiq-menus'),
'label_off' => __('No', 'cannaiq-menus'),
'return_value' => 'yes',
'default' => 'yes',
]
@@ -166,10 +166,10 @@ class Crawlsy_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
$this->add_control(
'show_description',
[
'label' => __('Show Description', 'crawlsy-menus'),
'label' => __('Show Description', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::SWITCHER,
'label_on' => __('Yes', 'crawlsy-menus'),
'label_off' => __('No', 'crawlsy-menus'),
'label_on' => __('Yes', 'cannaiq-menus'),
'label_off' => __('No', 'cannaiq-menus'),
'return_value' => 'yes',
'default' => 'no',
]
@@ -181,7 +181,7 @@ class Crawlsy_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
$this->start_controls_section(
'style_section',
[
'label' => __('Style', 'crawlsy-menus'),
'label' => __('Style', 'cannaiq-menus'),
'tab' => \Elementor\Controls_Manager::TAB_STYLE,
]
);
@@ -189,11 +189,11 @@ class Crawlsy_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
$this->add_control(
'card_background',
[
'label' => __('Card Background', 'crawlsy-menus'),
'label' => __('Card Background', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::COLOR,
'default' => '#ffffff',
'selectors' => [
'{{WRAPPER}} .crawlsy-product-card' => 'background-color: {{VALUE}};',
'{{WRAPPER}} .cannaiq-product-card' => 'background-color: {{VALUE}};',
],
]
);
@@ -201,7 +201,7 @@ class Crawlsy_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
$this->add_control(
'card_border_radius',
[
'label' => __('Border Radius', 'crawlsy-menus'),
'label' => __('Border Radius', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::SLIDER,
'size_units' => ['px'],
'range' => [
@@ -214,7 +214,7 @@ class Crawlsy_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
'size' => 8,
],
'selectors' => [
'{{WRAPPER}} .crawlsy-product-card' => 'border-radius: {{SIZE}}{{UNIT}};',
'{{WRAPPER}} .cannaiq-product-card' => 'border-radius: {{SIZE}}{{UNIT}};',
],
]
);
@@ -222,11 +222,11 @@ class Crawlsy_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
$this->add_control(
'text_color',
[
'label' => __('Text Color', 'crawlsy-menus'),
'label' => __('Text Color', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::COLOR,
'default' => '#333333',
'selectors' => [
'{{WRAPPER}} .crawlsy-product-card' => 'color: {{VALUE}};',
'{{WRAPPER}} .cannaiq-product-card' => 'color: {{VALUE}};',
],
]
);
@@ -251,66 +251,71 @@ class Crawlsy_Menus_Product_Grid_Widget extends \Elementor\Widget_Base {
$args['search'] = $settings['search'];
}
$plugin = Crawlsy_Menus_Plugin::instance();
$plugin = CannaIQ_Menus_Plugin::instance();
$products = $plugin->fetch_products($args);
if (!$products) {
echo '<p>' . __('No products found.', 'crawlsy-menus') . '</p>';
echo '<p>' . __('No products found.', 'cannaiq-menus') . '</p>';
return;
}
$columns = $settings['columns'];
?>
<div class="crawlsy-product-grid crawlsy-grid-cols-<?php echo esc_attr($columns); ?>">
<div class="cannaiq-product-grid cannaiq-grid-cols-<?php echo esc_attr($columns); ?>">
<?php foreach ($products as $product):
$image_url = $product['image_url'] ?? $product['primary_image_url'] ?? $product['image_url_full'] ?? '';
$product_url = !empty($product['dutchie_url']) ? $product['dutchie_url'] : '#';
$product_url = !empty($product['menu_url']) ? $product['menu_url'] : '#';
?>
<div class="crawlsy-product-card"
<div class="cannaiq-product-card"
<?php if ($product_url !== '#'): ?>onclick="window.open('<?php echo esc_url($product_url); ?>', '_blank')"<?php endif; ?>
style="cursor: <?php echo ($product_url !== '#') ? 'pointer' : 'default'; ?>;">
<?php if ($settings['show_image'] === 'yes' && !empty($image_url)): ?>
<div class="crawlsy-product-image">
<div class="cannaiq-product-image">
<img src="<?php echo esc_url($image_url); ?>"
alt="<?php echo esc_attr($product['name']); ?>"
loading="lazy" />
</div>
<?php endif; ?>
<div class="crawlsy-product-content">
<h3 class="crawlsy-product-title">
<div class="cannaiq-product-content">
<h3 class="cannaiq-product-title">
<?php echo esc_html($product['name']); ?>
</h3>
<?php if ($settings['show_description'] === 'yes' && !empty($product['description'])): ?>
<p class="crawlsy-product-description">
<p class="cannaiq-product-description">
<?php echo esc_html(wp_trim_words($product['description'], 15)); ?>
</p>
<?php endif; ?>
<div class="crawlsy-product-meta">
<?php if ($settings['show_thc'] === 'yes' && !empty($product['metadata']['thc'])): ?>
<span class="crawlsy-meta-item crawlsy-thc">
<strong>THC:</strong> <?php echo esc_html($product['metadata']['thc']); ?>
<div class="cannaiq-product-meta">
<?php if ($settings['show_thc'] === 'yes' && !empty($product['thc_percentage'])): ?>
<span class="cannaiq-meta-item cannaiq-thc">
<strong>THC:</strong> <?php echo esc_html($product['thc_percentage']); ?>%
</span>
<?php endif; ?>
<?php if ($settings['show_cbd'] === 'yes' && !empty($product['metadata']['cbd'])): ?>
<span class="crawlsy-meta-item crawlsy-cbd">
<strong>CBD:</strong> <?php echo esc_html($product['metadata']['cbd']); ?>
<?php if ($settings['show_cbd'] === 'yes' && !empty($product['cbd_percentage'])): ?>
<span class="cannaiq-meta-item cannaiq-cbd">
<strong>CBD:</strong> <?php echo esc_html($product['cbd_percentage']); ?>%
</span>
<?php endif; ?>
</div>
<?php if ($settings['show_price'] === 'yes' && isset($product['price'])): ?>
<div class="crawlsy-product-price">
$<?php echo number_format($product['price'], 2); ?>
<?php if ($settings['show_price'] === 'yes' && isset($product['regular_price'])): ?>
<div class="cannaiq-product-price">
<?php if (!empty($product['sale_price']) && $product['sale_price'] != $product['regular_price']): ?>
<span class="cannaiq-price-sale">$<?php echo esc_html($product['sale_price']); ?></span>
<span class="cannaiq-price-regular cannaiq-strikethrough">$<?php echo esc_html($product['regular_price']); ?></span>
<?php else: ?>
$<?php echo esc_html($product['regular_price']); ?>
<?php endif; ?>
</div>
<?php endif; ?>
<?php if (!$product['in_stock']): ?>
<div class="crawlsy-out-of-stock">
<?php _e('Out of Stock', 'crawlsy-menus'); ?>
<div class="cannaiq-out-of-stock">
<?php _e('Out of Stock', 'cannaiq-menus'); ?>
</div>
<?php endif; ?>
</div>

View File

@@ -7,14 +7,14 @@ if (!defined('ABSPATH')) {
exit;
}
class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
class CannaIQ_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
public function get_name() {
return 'crawlsy_single_product';
return 'cannaiq_single_product';
}
public function get_title() {
return __('Crawlsy Single Product', 'crawlsy-menus');
return __('CannaIQ Single Product', 'cannaiq-menus');
}
public function get_icon() {
@@ -31,9 +31,9 @@ class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
* @return array Associative array of product_id => product_name
*/
protected function get_products_for_select() {
$options = ['' => __('-- Select a Product --', 'crawlsy-menus')];
$options = ['' => __('-- Select a Product --', 'cannaiq-menus')];
$plugin = Crawlsy_Menus_Plugin::instance();
$plugin = CannaIQ_Menus_Plugin::instance();
$products = $plugin->fetch_products(['limit' => 500]);
if ($products && is_array($products)) {
@@ -58,7 +58,7 @@ class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
$this->start_controls_section(
'content_section',
[
'label' => __('Content', 'crawlsy-menus'),
'label' => __('Content', 'cannaiq-menus'),
'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
]
);
@@ -69,22 +69,22 @@ class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
$this->add_control(
'product_id',
[
'label' => __('Select Product', 'crawlsy-menus'),
'label' => __('Select Product', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::SELECT2,
'options' => $products_options,
'default' => '',
'label_block' => true,
'description' => __('Search and select a product to display', 'crawlsy-menus'),
'description' => __('Search and select a product to display', 'cannaiq-menus'),
]
);
$this->add_control(
'product_id_manual',
[
'label' => __('Or Enter Product ID', 'crawlsy-menus'),
'label' => __('Or Enter Product ID', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::NUMBER,
'default' => '',
'description' => __('Manually enter a product ID if not found in dropdown', 'crawlsy-menus'),
'description' => __('Manually enter a product ID if not found in dropdown', 'cannaiq-menus'),
'condition' => [
'product_id' => '',
],
@@ -94,12 +94,12 @@ class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
$this->add_control(
'layout',
[
'label' => __('Layout', 'crawlsy-menus'),
'label' => __('Layout', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::SELECT,
'default' => 'horizontal',
'options' => [
'horizontal' => __('Horizontal', 'crawlsy-menus'),
'vertical' => __('Vertical', 'crawlsy-menus'),
'horizontal' => __('Horizontal', 'cannaiq-menus'),
'vertical' => __('Vertical', 'cannaiq-menus'),
],
]
);
@@ -110,7 +110,7 @@ class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
$this->start_controls_section(
'display_section',
[
'label' => __('Display Options', 'crawlsy-menus'),
'label' => __('Display Options', 'cannaiq-menus'),
'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
]
);
@@ -118,10 +118,10 @@ class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
$this->add_control(
'show_image',
[
'label' => __('Show Image', 'crawlsy-menus'),
'label' => __('Show Image', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::SWITCHER,
'label_on' => __('Yes', 'crawlsy-menus'),
'label_off' => __('No', 'crawlsy-menus'),
'label_on' => __('Yes', 'cannaiq-menus'),
'label_off' => __('No', 'cannaiq-menus'),
'return_value' => 'yes',
'default' => 'yes',
]
@@ -130,10 +130,10 @@ class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
$this->add_control(
'show_price',
[
'label' => __('Show Price', 'crawlsy-menus'),
'label' => __('Show Price', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::SWITCHER,
'label_on' => __('Yes', 'crawlsy-menus'),
'label_off' => __('No', 'crawlsy-menus'),
'label_on' => __('Yes', 'cannaiq-menus'),
'label_off' => __('No', 'cannaiq-menus'),
'return_value' => 'yes',
'default' => 'yes',
]
@@ -142,10 +142,10 @@ class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
$this->add_control(
'show_description',
[
'label' => __('Show Description', 'crawlsy-menus'),
'label' => __('Show Description', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::SWITCHER,
'label_on' => __('Yes', 'crawlsy-menus'),
'label_off' => __('No', 'crawlsy-menus'),
'label_on' => __('Yes', 'cannaiq-menus'),
'label_off' => __('No', 'cannaiq-menus'),
'return_value' => 'yes',
'default' => 'yes',
]
@@ -154,10 +154,10 @@ class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
$this->add_control(
'show_thc',
[
'label' => __('Show THC', 'crawlsy-menus'),
'label' => __('Show THC', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::SWITCHER,
'label_on' => __('Yes', 'crawlsy-menus'),
'label_off' => __('No', 'crawlsy-menus'),
'label_on' => __('Yes', 'cannaiq-menus'),
'label_off' => __('No', 'cannaiq-menus'),
'return_value' => 'yes',
'default' => 'yes',
]
@@ -166,10 +166,10 @@ class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
$this->add_control(
'show_cbd',
[
'label' => __('Show CBD', 'crawlsy-menus'),
'label' => __('Show CBD', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::SWITCHER,
'label_on' => __('Yes', 'crawlsy-menus'),
'label_off' => __('No', 'crawlsy-menus'),
'label_on' => __('Yes', 'cannaiq-menus'),
'label_off' => __('No', 'cannaiq-menus'),
'return_value' => 'yes',
'default' => 'yes',
]
@@ -178,10 +178,10 @@ class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
$this->add_control(
'show_terpenes',
[
'label' => __('Show Terpenes', 'crawlsy-menus'),
'label' => __('Show Terpenes', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::SWITCHER,
'label_on' => __('Yes', 'crawlsy-menus'),
'label_off' => __('No', 'crawlsy-menus'),
'label_on' => __('Yes', 'cannaiq-menus'),
'label_off' => __('No', 'cannaiq-menus'),
'return_value' => 'yes',
'default' => 'yes',
]
@@ -190,10 +190,10 @@ class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
$this->add_control(
'show_effects',
[
'label' => __('Show Effects', 'crawlsy-menus'),
'label' => __('Show Effects', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::SWITCHER,
'label_on' => __('Yes', 'crawlsy-menus'),
'label_off' => __('No', 'crawlsy-menus'),
'label_on' => __('Yes', 'cannaiq-menus'),
'label_off' => __('No', 'cannaiq-menus'),
'return_value' => 'yes',
'default' => 'yes',
]
@@ -202,10 +202,10 @@ class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
$this->add_control(
'show_brand',
[
'label' => __('Show Brand', 'crawlsy-menus'),
'label' => __('Show Brand', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::SWITCHER,
'label_on' => __('Yes', 'crawlsy-menus'),
'label_off' => __('No', 'crawlsy-menus'),
'label_on' => __('Yes', 'cannaiq-menus'),
'label_off' => __('No', 'cannaiq-menus'),
'return_value' => 'yes',
'default' => 'yes',
]
@@ -217,7 +217,7 @@ class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
$this->start_controls_section(
'style_section',
[
'label' => __('Style', 'crawlsy-menus'),
'label' => __('Style', 'cannaiq-menus'),
'tab' => \Elementor\Controls_Manager::TAB_STYLE,
]
);
@@ -225,11 +225,11 @@ class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
$this->add_control(
'background_color',
[
'label' => __('Background Color', 'crawlsy-menus'),
'label' => __('Background Color', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::COLOR,
'default' => '#ffffff',
'selectors' => [
'{{WRAPPER}} .crawlsy-single-product' => 'background-color: {{VALUE}};',
'{{WRAPPER}} .cannaiq-single-product' => 'background-color: {{VALUE}};',
],
]
);
@@ -237,7 +237,7 @@ class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
$this->add_control(
'border_radius',
[
'label' => __('Border Radius', 'crawlsy-menus'),
'label' => __('Border Radius', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::SLIDER,
'size_units' => ['px'],
'range' => [
@@ -250,7 +250,7 @@ class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
'size' => 8,
],
'selectors' => [
'{{WRAPPER}} .crawlsy-single-product' => 'border-radius: {{SIZE}}{{UNIT}};',
'{{WRAPPER}} .cannaiq-single-product' => 'border-radius: {{SIZE}}{{UNIT}};',
],
]
);
@@ -258,11 +258,11 @@ class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
$this->add_control(
'text_color',
[
'label' => __('Text Color', 'crawlsy-menus'),
'label' => __('Text Color', 'cannaiq-menus'),
'type' => \Elementor\Controls_Manager::COLOR,
'default' => '#333333',
'selectors' => [
'{{WRAPPER}} .crawlsy-single-product' => 'color: {{VALUE}};',
'{{WRAPPER}} .cannaiq-single-product' => 'color: {{VALUE}};',
],
]
);
@@ -277,93 +277,88 @@ class Crawlsy_Menus_Single_Product_Widget extends \Elementor\Widget_Base {
$product_id = !empty($settings['product_id']) ? $settings['product_id'] : $settings['product_id_manual'];
if (empty($product_id)) {
echo '<p>' . __('Please select or enter a product ID.', 'crawlsy-menus') . '</p>';
echo '<p>' . __('Please select or enter a product ID.', 'cannaiq-menus') . '</p>';
return;
}
$plugin = Crawlsy_Menus_Plugin::instance();
$plugin = CannaIQ_Menus_Plugin::instance();
$product = $plugin->fetch_product($product_id);
if (!$product) {
echo '<p>' . __('Product not found.', 'crawlsy-menus') . '</p>';
echo '<p>' . __('Product not found.', 'cannaiq-menus') . '</p>';
return;
}
$layout = $settings['layout'];
$image_url = $product['image_url'] ?? '';
?>
<div class="crawlsy-single-product crawlsy-layout-<?php echo esc_attr($layout); ?>">
<?php if ($settings['show_image'] === 'yes' && !empty($product['image_url_full'])): ?>
<div class="crawlsy-single-product-image">
<img src="<?php echo esc_url($product['image_url_full']); ?>"
<div class="cannaiq-single-product cannaiq-layout-<?php echo esc_attr($layout); ?>">
<?php if ($settings['show_image'] === 'yes' && !empty($image_url)): ?>
<div class="cannaiq-single-product-image">
<img src="<?php echo esc_url($image_url); ?>"
alt="<?php echo esc_attr($product['name']); ?>" />
</div>
<?php endif; ?>
<div class="crawlsy-single-product-details">
<h2 class="crawlsy-single-product-title">
<div class="cannaiq-single-product-details">
<h2 class="cannaiq-single-product-title">
<?php echo esc_html($product['name']); ?>
</h2>
<?php if ($settings['show_brand'] === 'yes' && !empty($product['brand'])): ?>
<div class="crawlsy-single-product-brand">
<strong><?php _e('Brand:', 'crawlsy-menus'); ?></strong>
<div class="cannaiq-single-product-brand">
<strong><?php _e('Brand:', 'cannaiq-menus'); ?></strong>
<?php echo esc_html($product['brand']); ?>
</div>
<?php endif; ?>
<?php if ($settings['show_description'] === 'yes' && !empty($product['description'])): ?>
<div class="crawlsy-single-product-description">
<div class="cannaiq-single-product-description">
<?php echo wp_kses_post(nl2br($product['description'])); ?>
</div>
<?php endif; ?>
<div class="crawlsy-single-product-info">
<?php if ($settings['show_thc'] === 'yes' && !empty($product['metadata']['thc'])): ?>
<div class="crawlsy-info-item">
<strong><?php _e('THC:', 'crawlsy-menus'); ?></strong>
<span><?php echo esc_html($product['metadata']['thc']); ?></span>
<div class="cannaiq-single-product-info">
<?php if ($settings['show_thc'] === 'yes' && !empty($product['thc_percentage'])): ?>
<div class="cannaiq-info-item">
<strong><?php _e('THC:', 'cannaiq-menus'); ?></strong>
<span><?php echo esc_html($product['thc_percentage']); ?>%</span>
</div>
<?php endif; ?>
<?php if ($settings['show_cbd'] === 'yes' && !empty($product['metadata']['cbd'])): ?>
<div class="crawlsy-info-item">
<strong><?php _e('CBD:', 'crawlsy-menus'); ?></strong>
<span><?php echo esc_html($product['metadata']['cbd']); ?></span>
<?php if ($settings['show_cbd'] === 'yes' && !empty($product['cbd_percentage'])): ?>
<div class="cannaiq-info-item">
<strong><?php _e('CBD:', 'cannaiq-menus'); ?></strong>
<span><?php echo esc_html($product['cbd_percentage']); ?>%</span>
</div>
<?php endif; ?>
<?php if ($settings['show_terpenes'] === 'yes' && !empty($product['metadata']['terpenes'])): ?>
<div class="crawlsy-info-item crawlsy-terpenes">
<strong><?php _e('Terpenes:', 'crawlsy-menus'); ?></strong>
<?php if (is_array($product['metadata']['terpenes'])): ?>
<span><?php echo esc_html(implode(', ', $product['metadata']['terpenes'])); ?></span>
<?php if ($settings['show_effects'] === 'yes' && !empty($product['effects'])): ?>
<div class="cannaiq-info-item cannaiq-effects">
<strong><?php _e('Effects:', 'cannaiq-menus'); ?></strong>
<?php if (is_array($product['effects'])): ?>
<span><?php echo esc_html(implode(', ', $product['effects'])); ?></span>
<?php else: ?>
<span><?php echo esc_html($product['metadata']['terpenes']); ?></span>
<?php endif; ?>
</div>
<?php endif; ?>
<?php if ($settings['show_effects'] === 'yes' && !empty($product['metadata']['effects'])): ?>
<div class="crawlsy-info-item crawlsy-effects">
<strong><?php _e('Effects:', 'crawlsy-menus'); ?></strong>
<?php if (is_array($product['metadata']['effects'])): ?>
<span><?php echo esc_html(implode(', ', $product['metadata']['effects'])); ?></span>
<?php else: ?>
<span><?php echo esc_html($product['metadata']['effects']); ?></span>
<span><?php echo esc_html($product['effects']); ?></span>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<?php if ($settings['show_price'] === 'yes' && isset($product['price'])): ?>
<div class="crawlsy-single-product-price">
$<?php echo number_format($product['price'], 2); ?>
<?php if ($settings['show_price'] === 'yes' && isset($product['regular_price'])): ?>
<div class="cannaiq-single-product-price">
<?php if (!empty($product['sale_price']) && $product['sale_price'] != $product['regular_price']): ?>
<span class="cannaiq-price-sale">$<?php echo esc_html($product['sale_price']); ?></span>
<span class="cannaiq-price-regular cannaiq-strikethrough">$<?php echo esc_html($product['regular_price']); ?></span>
<?php else: ?>
$<?php echo esc_html($product['regular_price']); ?>
<?php endif; ?>
</div>
<?php endif; ?>
<?php if (!$product['in_stock']): ?>
<div class="crawlsy-out-of-stock">
<?php _e('Out of Stock', 'crawlsy-menus'); ?>
<div class="cannaiq-out-of-stock">
<?php _e('Out of Stock', 'cannaiq-menus'); ?>
</div>
<?php endif; ?>
</div>