diff --git a/backend/public/downloads/cannaiq-menus-1.5.3.zip b/backend/public/downloads/cannaiq-menus-1.5.3.zip new file mode 100644 index 00000000..f605c0d6 Binary files /dev/null and b/backend/public/downloads/cannaiq-menus-1.5.3.zip differ diff --git a/cannaiq/src/pages/Home.tsx b/cannaiq/src/pages/Home.tsx index f9a8e4a6..b14244b8 100644 --- a/cannaiq/src/pages/Home.tsx +++ b/cannaiq/src/pages/Home.tsx @@ -440,7 +440,7 @@ export function Home() { Go to /admin @@ -497,7 +497,7 @@ export function Home() {
Sign in Contact - WordPress Plugin + WordPress Plugin
diff --git a/cannaiq/src/pages/LandingPage.tsx b/cannaiq/src/pages/LandingPage.tsx index 26607a05..36b6c388 100644 --- a/cannaiq/src/pages/LandingPage.tsx +++ b/cannaiq/src/pages/LandingPage.tsx @@ -23,7 +23,7 @@ export default function LandingPage() { Sign In - + Download WordPress Plugin @@ -74,20 +74,20 @@ export default function LandingPage() {

WordPress Integration

- Display your dispensary menu directly on your WordPress site with our Crawlsy Menus plugin. + Display your dispensary menu directly on your WordPress site with our CannaIQ Menus plugin. Features Elementor widgets and shortcode support for maximum flexibility.

// Display products grid
-
[crawlsy_products limit="12" columns="3"]
+
[cannaiq_products limit="12" columns="3"]
// Display single product
-
[crawlsy_product id="123"]
+
[cannaiq_product id="123"]
- Download Crawlsy Menus v1.3.0 + Download CannaIQ Menus v1.5.3
diff --git a/findadispo/frontend/.env.example b/findadispo/frontend/.env.example index 48001a73..3e620216 100644 --- a/findadispo/frontend/.env.example +++ b/findadispo/frontend/.env.example @@ -3,7 +3,7 @@ # API URL for dispensary data endpoints (public API) # Local development: http://localhost:3010 -# Production: https://dispos.crawlsy.com (or your production API URL) +# Production: https://cannaiq.co (or your production API URL) REACT_APP_DATA_API_URL=http://localhost:3010 # API Key for accessing the /api/v1/* endpoints diff --git a/wordpress-plugin/assets/css/cannaiq-menus.css b/wordpress-plugin/assets/css/cannaiq-menus.css new file mode 100644 index 00000000..6768181b --- /dev/null +++ b/wordpress-plugin/assets/css/cannaiq-menus.css @@ -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; +} diff --git a/wordpress-plugin/assets/js/cannaiq-menus.js b/wordpress-plugin/assets/js/cannaiq-menus.js new file mode 100644 index 00000000..a4990a70 --- /dev/null +++ b/wordpress-plugin/assets/js/cannaiq-menus.js @@ -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); diff --git a/wordpress-plugin/build-plugin.sh b/wordpress-plugin/build-plugin.sh index 1bdf7b00..780992c8 100755 --- a/wordpress-plugin/build-plugin.sh +++ b/wordpress-plugin/build-plugin.sh @@ -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" diff --git a/wordpress-plugin/cannaiq-menus.php b/wordpress-plugin/cannaiq-menus.php new file mode 100644 index 00000000..ebbaa4b2 --- /dev/null +++ b/wordpress-plugin/cannaiq-menus.php @@ -0,0 +1,402 @@ +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() { + ?> +
+

CannaIQ Menus Settings

+

Version by CannaIQ

+

Display real-time cannabis menus with data updated daily from CannaIQ.

+ +
+ + + + + + + + +
+ +

Your authentication token from the CannaIQ admin dashboard. The token includes your store configuration.

+
+ + +
+ +
+ +

Test Connection

+ +
+ + + +
+ +

Usage

+

Shortcodes

+ + + + + + + + + + + + + + + + + +
ShortcodeDescription
[cannaiq_products]Display a grid of products. Options: category_id, limit, columns, in_stock
[cannaiq_product id="123"]Display a single product by ID
+ +

Elementor Widgets

+

If you have Elementor installed, you can use the CannaIQ widgets:

+ +
+ '', + 'limit' => 12, + 'columns' => 3, + 'in_stock' => 'true' + ], $atts); + + $products = $this->fetch_products($atts); + + if (!$products) { + return '

No products found.

'; + } + + 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 '

Product ID required.

'; + } + + $product = $this->fetch_product($atts['id']); + + if (!$product) { + return '

Product not found.

'; + } + + 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(); diff --git a/wordpress-plugin/templates/product-grid.php b/wordpress-plugin/templates/product-grid.php index a9b2f178..78b6d9fe 100644 --- a/wordpress-plugin/templates/product-grid.php +++ b/wordpress-plugin/templates/product-grid.php @@ -10,62 +10,67 @@ if (!defined('ABSPATH')) { $columns = isset($atts['columns']) ? $atts['columns'] : 3; ?> -
+
-
onclick="window.open('', '_blank')" style="cursor: ;"> -
+
<?php echo esc_attr($product['name']); ?>
-
-

+
+

-
+
-

+

-
- - - THC: +
+ + + THC: % - - - CBD: + + + CBD: %
- -
- $ + +
+ + $ + $ + + $ +
-
- +
+
diff --git a/wordpress-plugin/templates/single-product.php b/wordpress-plugin/templates/single-product.php index bc92e22c..40024844 100644 --- a/wordpress-plugin/templates/single-product.php +++ b/wordpress-plugin/templates/single-product.php @@ -6,92 +6,77 @@ if (!defined('ABSPATH')) { exit; } + +$image_url = $product['image_url'] ?? ''; ?> -
- -
- + +
+ <?php echo esc_attr($product['name']); ?>
-
-

+
+

-
- +
+
-
+
-
- -
- - +
+ +
+ + %
- -
- - + +
+ + %
- -
- - - + +
+ + + - - -
- - - -
- - - - - - -
- - - -
- - - - - +
- -
- $ + +
+ + $ + $ + + $ +
-
- +
+
diff --git a/wordpress-plugin/widgets/product-grid.php b/wordpress-plugin/widgets/product-grid.php index 84499c9d..e92f4ad3 100644 --- a/wordpress-plugin/widgets/product-grid.php +++ b/wordpress-plugin/widgets/product-grid.php @@ -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 '

' . __('No products found.', 'crawlsy-menus') . '

'; + echo '

' . __('No products found.', 'cannaiq-menus') . '

'; return; } $columns = $settings['columns']; ?> -
+
-
onclick="window.open('', '_blank')" style="cursor: ;"> -
+
<?php echo esc_attr($product['name']); ?>
-
-

+
+

-

+

-
- - - THC: +
+ + + THC: % - - - CBD: + + + CBD: %
- -
- $ + +
+ + $ + $ + + $ +
-
- +
+
diff --git a/wordpress-plugin/widgets/single-product.php b/wordpress-plugin/widgets/single-product.php index 9d7bcaeb..4a23e8d4 100644 --- a/wordpress-plugin/widgets/single-product.php +++ b/wordpress-plugin/widgets/single-product.php @@ -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 '

' . __('Please select or enter a product ID.', 'crawlsy-menus') . '

'; + echo '

' . __('Please select or enter a product ID.', 'cannaiq-menus') . '

'; return; } - $plugin = Crawlsy_Menus_Plugin::instance(); + $plugin = CannaIQ_Menus_Plugin::instance(); $product = $plugin->fetch_product($product_id); if (!$product) { - echo '

' . __('Product not found.', 'crawlsy-menus') . '

'; + echo '

' . __('Product not found.', 'cannaiq-menus') . '

'; return; } $layout = $settings['layout']; + $image_url = $product['image_url'] ?? ''; ?> -
- -
- + +
+ <?php echo esc_attr($product['name']); ?>
-
-

+
+

-
- +
+
-
+
-
- -
- - +
+ +
+ + %
- -
- - + +
+ + %
- -
- - - + +
+ + + - - -
- - - -
- - - - - +
- -
- $ + +
+ + $ + $ + + $ +
-
- +
+