From 74957a9ec501dd6eb6eea3c241912e9a6e506f51 Mon Sep 17 00:00:00 2001 From: Kelly Date: Wed, 10 Dec 2025 13:41:17 -0700 Subject: [PATCH] feat(wordpress): Add new Elementor widgets and dynamic selectors v1.6.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New Widgets: - Brand Grid: Display brands in a grid with product counts - Category List: Show categories in grid/list/pills layouts - Specials Grid: Display products on sale with discount badges Enhanced Product Grid Widget: - Dynamic category dropdown (fetches from API) - Dynamic brand dropdown (fetches from API) - "On Special Only" toggle filter New Plugin Methods: - fetch_categories() - Get categories from API - fetch_brands() - Get brands from API - fetch_specials() - Get products on sale - get_category_options() - Cached options for Elementor - get_brand_options() - Cached options for Elementor 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- wordpress-plugin/VERSION | 2 +- wordpress-plugin/assets/css/cannaiq-menus.css | 181 +++++++++++ wordpress-plugin/cannaiq-menus.php | 156 +++++++++- wordpress-plugin/widgets/brand-grid.php | 184 +++++++++++ wordpress-plugin/widgets/category-list.php | 205 +++++++++++++ wordpress-plugin/widgets/product-grid.php | 45 ++- wordpress-plugin/widgets/specials-grid.php | 288 ++++++++++++++++++ 7 files changed, 1052 insertions(+), 9 deletions(-) create mode 100644 wordpress-plugin/widgets/brand-grid.php create mode 100644 wordpress-plugin/widgets/category-list.php create mode 100644 wordpress-plugin/widgets/specials-grid.php diff --git a/wordpress-plugin/VERSION b/wordpress-plugin/VERSION index 94fe62c2..dc1e644a 100644 --- a/wordpress-plugin/VERSION +++ b/wordpress-plugin/VERSION @@ -1 +1 @@ -1.5.4 +1.6.0 diff --git a/wordpress-plugin/assets/css/cannaiq-menus.css b/wordpress-plugin/assets/css/cannaiq-menus.css index 6768181b..dfbd7665 100644 --- a/wordpress-plugin/assets/css/cannaiq-menus.css +++ b/wordpress-plugin/assets/css/cannaiq-menus.css @@ -312,3 +312,184 @@ border-radius: 4px; border-left: 4px solid #c62828; } + +/* ======================================== + Brand Grid Widget + ======================================== */ +.cannaiq-brand-grid { + display: grid; + gap: 20px; + margin: 20px 0; +} + +.cannaiq-brand-card { + background: #fff; + border-radius: 8px; + padding: 20px; + text-align: center; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + transition: transform 0.2s, box-shadow 0.2s; +} + +.cannaiq-brand-card:hover { + transform: translateY(-4px); + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); +} + +.cannaiq-brand-name { + font-size: 16px; + font-weight: 600; + margin: 0 0 8px 0; + color: #333; +} + +.cannaiq-brand-count { + font-size: 13px; + color: #666; +} + +/* ======================================== + Category List Widget + ======================================== */ +.cannaiq-category-grid { + display: grid; + gap: 16px; + margin: 20px 0; +} + +.cannaiq-category-list { + display: flex; + flex-direction: column; + gap: 8px; + margin: 20px 0; +} + +.cannaiq-category-pills { + display: flex; + flex-wrap: wrap; + gap: 10px; + margin: 20px 0; +} + +.cannaiq-category-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 12px 16px; + background: #fff; + border-radius: 8px; + text-decoration: none; + color: #333; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); + transition: background 0.2s, transform 0.2s; +} + +.cannaiq-category-item:hover { + background: #f3f4f6; + transform: translateX(4px); +} + +.cannaiq-category-pills-item { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 8px 16px; + background: #f3f4f6; + border-radius: 20px; + text-decoration: none; + color: #333; + font-size: 14px; + transition: background 0.2s; +} + +.cannaiq-category-pills-item:hover { + background: #e5e7eb; +} + +.cannaiq-category-name { + font-weight: 500; +} + +.cannaiq-category-count { + font-size: 13px; + color: #666; +} + +/* ======================================== + Specials/Deals Grid Widget + ======================================== */ +.cannaiq-specials-grid { + display: grid; + gap: 24px; + margin: 20px 0; +} + +.cannaiq-special-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; + position: relative; +} + +.cannaiq-special-card:hover { + transform: translateY(-4px); + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); +} + +.cannaiq-discount-badge { + position: absolute; + top: 12px; + right: 12px; + background: #ef4444; + color: #fff; + font-size: 13px; + font-weight: 700; + padding: 4px 10px; + border-radius: 4px; + z-index: 1; +} + +.cannaiq-special-image { + width: 100%; + aspect-ratio: 1; + overflow: hidden; + background: #f5f5f5; +} + +.cannaiq-special-image img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.cannaiq-special-content { + padding: 16px; +} + +.cannaiq-special-title { + font-size: 16px; + font-weight: 600; + margin: 0 0 8px 0; + color: #333; + line-height: 1.4; +} + +.cannaiq-special-price { + display: flex; + align-items: center; + gap: 8px; + margin-top: 12px; +} + +.cannaiq-special-price .cannaiq-price-sale { + font-size: 20px; + font-weight: 700; + color: #16a34a; +} + +.cannaiq-special-price .cannaiq-price-regular { + font-size: 14px; + color: #999; +} diff --git a/wordpress-plugin/cannaiq-menus.php b/wordpress-plugin/cannaiq-menus.php index 8c2fc63e..f8ac5d7a 100644 --- a/wordpress-plugin/cannaiq-menus.php +++ b/wordpress-plugin/cannaiq-menus.php @@ -3,7 +3,7 @@ * 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.4 + * Version: 1.6.0 * Author: CannaIQ * Author URI: https://cannaiq.co * License: GPL v2 or later @@ -15,7 +15,7 @@ if (!defined('ABSPATH')) { exit; // Exit if accessed directly } -define('CANNAIQ_MENUS_VERSION', '1.5.4'); +define('CANNAIQ_MENUS_VERSION', '1.6.0'); 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__)); @@ -62,9 +62,15 @@ class CannaIQ_Menus_Plugin { 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'; + require_once CANNAIQ_MENUS_PLUGIN_DIR . 'widgets/brand-grid.php'; + require_once CANNAIQ_MENUS_PLUGIN_DIR . 'widgets/category-list.php'; + require_once CANNAIQ_MENUS_PLUGIN_DIR . 'widgets/specials-grid.php'; $widgets_manager->register(new \CannaIQ_Menus_Product_Grid_Widget()); $widgets_manager->register(new \CannaIQ_Menus_Single_Product_Widget()); + $widgets_manager->register(new \CannaIQ_Menus_Brand_Grid_Widget()); + $widgets_manager->register(new \CannaIQ_Menus_Category_List_Widget()); + $widgets_manager->register(new \CannaIQ_Menus_Specials_Grid_Widget()); } /** @@ -392,6 +398,152 @@ class CannaIQ_Menus_Plugin { return $data['product'] ?? false; } + + /** + * Fetch Categories from API + */ + public function fetch_categories($args = []) { + $api_token = get_option('cannaiq_api_token'); + + if (!$api_token) { + return false; + } + + $query_args = http_build_query($args); + $url = CANNAIQ_MENUS_API_URL . '/categories' . ($query_args ? '?' . $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['categories'] ?? false; + } + + /** + * Fetch Brands from API + */ + public function fetch_brands($args = []) { + $api_token = get_option('cannaiq_api_token'); + + if (!$api_token) { + return false; + } + + $query_args = http_build_query($args); + $url = CANNAIQ_MENUS_API_URL . '/brands' . ($query_args ? '?' . $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['brands'] ?? false; + } + + /** + * Fetch Specials/Deals from API + */ + public function fetch_specials($args = []) { + $api_token = get_option('cannaiq_api_token'); + + if (!$api_token) { + return false; + } + + $query_args = http_build_query($args); + $url = CANNAIQ_MENUS_API_URL . '/specials' . ($query_args ? '?' . $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; + } + + /** + * Get categories as options for Elementor select control + * Returns cached results for performance + */ + public function get_category_options() { + $cache_key = 'cannaiq_category_options'; + $cached = get_transient($cache_key); + + if ($cached !== false) { + return $cached; + } + + $categories = $this->fetch_categories(); + $options = ['' => __('All Categories', 'cannaiq-menus')]; + + if ($categories) { + foreach ($categories as $cat) { + $name = $cat['type'] ?? $cat['name'] ?? ''; + if ($name) { + $options[$name] = ucwords(str_replace('_', ' ', $name)); + } + } + } + + set_transient($cache_key, $options, 5 * MINUTE_IN_SECONDS); + return $options; + } + + /** + * Get brands as options for Elementor select control + * Returns cached results for performance + */ + public function get_brand_options() { + $cache_key = 'cannaiq_brand_options'; + $cached = get_transient($cache_key); + + if ($cached !== false) { + return $cached; + } + + $brands = $this->fetch_brands(['limit' => 200]); + $options = ['' => __('All Brands', 'cannaiq-menus')]; + + if ($brands) { + foreach ($brands as $brand) { + $name = $brand['brand'] ?? $brand['brand_name'] ?? ''; + if ($name) { + $options[$name] = $name; + } + } + } + + set_transient($cache_key, $options, 5 * MINUTE_IN_SECONDS); + return $options; + } } // Initialize Plugin diff --git a/wordpress-plugin/widgets/brand-grid.php b/wordpress-plugin/widgets/brand-grid.php new file mode 100644 index 00000000..d16dbe74 --- /dev/null +++ b/wordpress-plugin/widgets/brand-grid.php @@ -0,0 +1,184 @@ +start_controls_section( + 'content_section', + [ + 'label' => __('Content', 'cannaiq-menus'), + 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, + ] + ); + + $this->add_control( + 'limit', + [ + 'label' => __('Number of Brands', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::NUMBER, + 'default' => 12, + 'min' => 1, + 'max' => 100, + ] + ); + + $this->add_control( + 'columns', + [ + 'label' => __('Columns', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::SELECT, + 'default' => '4', + 'options' => [ + '2' => __('2 Columns', 'cannaiq-menus'), + '3' => __('3 Columns', 'cannaiq-menus'), + '4' => __('4 Columns', 'cannaiq-menus'), + '6' => __('6 Columns', 'cannaiq-menus'), + ], + ] + ); + + $this->add_control( + 'show_product_count', + [ + 'label' => __('Show Product Count', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'cannaiq-menus'), + 'label_off' => __('No', 'cannaiq-menus'), + 'return_value' => 'yes', + 'default' => 'yes', + ] + ); + + $this->add_control( + 'link_to_products', + [ + 'label' => __('Link to Products Page', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::URL, + 'placeholder' => __('/products', 'cannaiq-menus'), + 'description' => __('Brand name will be appended as ?brand=Name', 'cannaiq-menus'), + ] + ); + + $this->end_controls_section(); + + // Style Section + $this->start_controls_section( + 'style_section', + [ + 'label' => __('Style', 'cannaiq-menus'), + 'tab' => \Elementor\Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'card_background', + [ + 'label' => __('Card Background', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::COLOR, + 'default' => '#ffffff', + 'selectors' => [ + '{{WRAPPER}} .cannaiq-brand-card' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'card_border_radius', + [ + 'label' => __('Border Radius', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::SLIDER, + 'size_units' => ['px'], + 'range' => [ + 'px' => [ + 'min' => 0, + 'max' => 50, + ], + ], + 'default' => [ + 'size' => 8, + ], + 'selectors' => [ + '{{WRAPPER}} .cannaiq-brand-card' => 'border-radius: {{SIZE}}{{UNIT}};', + ], + ] + ); + + $this->add_control( + 'text_color', + [ + 'label' => __('Text Color', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::COLOR, + 'default' => '#333333', + 'selectors' => [ + '{{WRAPPER}} .cannaiq-brand-card' => 'color: {{VALUE}};', + ], + ] + ); + + $this->end_controls_section(); + } + + protected function render() { + $settings = $this->get_settings_for_display(); + + $plugin = CannaIQ_Menus_Plugin::instance(); + $brands = $plugin->fetch_brands(['limit' => $settings['limit']]); + + if (!$brands) { + echo '

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

'; + return; + } + + $columns = $settings['columns']; + $link_base = $settings['link_to_products']['url'] ?? ''; + ?> +
+ +
onclick="window.location.href=''" + style="cursor: ;"> +
+

+ +

+ 0): ?> + + + + +
+
+ +
+ start_controls_section( + 'content_section', + [ + 'label' => __('Content', 'cannaiq-menus'), + 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, + ] + ); + + $this->add_control( + 'layout', + [ + 'label' => __('Layout', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::SELECT, + 'default' => 'grid', + 'options' => [ + 'grid' => __('Grid', 'cannaiq-menus'), + 'list' => __('List', 'cannaiq-menus'), + 'pills' => __('Pills/Tags', 'cannaiq-menus'), + ], + ] + ); + + $this->add_control( + 'columns', + [ + 'label' => __('Columns', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::SELECT, + 'default' => '3', + 'options' => [ + '2' => __('2 Columns', 'cannaiq-menus'), + '3' => __('3 Columns', 'cannaiq-menus'), + '4' => __('4 Columns', 'cannaiq-menus'), + '6' => __('6 Columns', 'cannaiq-menus'), + ], + 'condition' => [ + 'layout' => 'grid', + ], + ] + ); + + $this->add_control( + 'show_product_count', + [ + 'label' => __('Show Product Count', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'cannaiq-menus'), + 'label_off' => __('No', 'cannaiq-menus'), + 'return_value' => 'yes', + 'default' => 'yes', + ] + ); + + $this->add_control( + 'link_to_products', + [ + 'label' => __('Link to Products Page', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::URL, + 'placeholder' => __('/products', 'cannaiq-menus'), + 'description' => __('Category name will be appended as ?category=Name', 'cannaiq-menus'), + ] + ); + + $this->end_controls_section(); + + // Style Section + $this->start_controls_section( + 'style_section', + [ + 'label' => __('Style', 'cannaiq-menus'), + 'tab' => \Elementor\Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'card_background', + [ + 'label' => __('Card Background', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::COLOR, + 'default' => '#ffffff', + 'selectors' => [ + '{{WRAPPER}} .cannaiq-category-item' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'card_border_radius', + [ + 'label' => __('Border Radius', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::SLIDER, + 'size_units' => ['px'], + 'range' => [ + 'px' => [ + 'min' => 0, + 'max' => 50, + ], + ], + 'default' => [ + 'size' => 8, + ], + 'selectors' => [ + '{{WRAPPER}} .cannaiq-category-item' => 'border-radius: {{SIZE}}{{UNIT}};', + ], + ] + ); + + $this->add_control( + 'text_color', + [ + 'label' => __('Text Color', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::COLOR, + 'default' => '#333333', + 'selectors' => [ + '{{WRAPPER}} .cannaiq-category-item' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'hover_background', + [ + 'label' => __('Hover Background', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::COLOR, + 'default' => '#f3f4f6', + 'selectors' => [ + '{{WRAPPER}} .cannaiq-category-item:hover' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->end_controls_section(); + } + + protected function render() { + $settings = $this->get_settings_for_display(); + + $plugin = CannaIQ_Menus_Plugin::instance(); + $categories = $plugin->fetch_categories(); + + if (!$categories) { + echo '

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

'; + return; + } + + $layout = $settings['layout']; + $columns = $settings['columns']; + $link_base = $settings['link_to_products']['url'] ?? ''; + + $container_class = 'cannaiq-category-' . $layout; + if ($layout === 'grid') { + $container_class .= ' cannaiq-grid-cols-' . $columns; + } + ?> + + add_control( - 'category_id', + 'category', [ - 'label' => __('Category ID', 'cannaiq-menus'), - 'type' => \Elementor\Controls_Manager::NUMBER, + 'label' => __('Category', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::SELECT, 'default' => '', - 'description' => __('Leave empty to show all categories', 'cannaiq-menus'), + 'options' => CannaIQ_Menus_Plugin::instance()->get_category_options(), + 'description' => __('Filter by product category', 'cannaiq-menus'), + ] + ); + + $this->add_control( + 'brand', + [ + 'label' => __('Brand', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::SELECT, + 'default' => '', + 'options' => CannaIQ_Menus_Plugin::instance()->get_brand_options(), + 'description' => __('Filter by brand', 'cannaiq-menus'), + ] + ); + + $this->add_control( + 'on_special', + [ + 'label' => __('On Special Only', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'cannaiq-menus'), + 'label_off' => __('No', 'cannaiq-menus'), + 'return_value' => 'yes', + 'default' => 'no', + 'description' => __('Show only products on sale', 'cannaiq-menus'), ] ); @@ -243,8 +268,16 @@ class CannaIQ_Menus_Product_Grid_Widget extends \Elementor\Widget_Base { 'in_stock' => $settings['in_stock_only'] === 'yes' ? 'true' : 'false', ]; - if (!empty($settings['category_id'])) { - $args['category_id'] = $settings['category_id']; + if (!empty($settings['category'])) { + $args['type'] = $settings['category']; + } + + if (!empty($settings['brand'])) { + $args['brandName'] = $settings['brand']; + } + + if ($settings['on_special'] === 'yes') { + $args['on_special'] = 'true'; } if (!empty($settings['search'])) { diff --git a/wordpress-plugin/widgets/specials-grid.php b/wordpress-plugin/widgets/specials-grid.php new file mode 100644 index 00000000..0f1d5536 --- /dev/null +++ b/wordpress-plugin/widgets/specials-grid.php @@ -0,0 +1,288 @@ +start_controls_section( + 'content_section', + [ + 'label' => __('Content', 'cannaiq-menus'), + 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, + ] + ); + + $this->add_control( + 'store_id', + [ + 'label' => __('Store ID', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::NUMBER, + 'default' => get_option('cannaiq_default_store_id', 1), + 'min' => 1, + ] + ); + + $this->add_control( + 'limit', + [ + 'label' => __('Number of Products', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::NUMBER, + 'default' => 8, + 'min' => 1, + 'max' => 50, + ] + ); + + $this->add_control( + 'columns', + [ + 'label' => __('Columns', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::SELECT, + 'default' => '4', + 'options' => [ + '2' => __('2 Columns', 'cannaiq-menus'), + '3' => __('3 Columns', 'cannaiq-menus'), + '4' => __('4 Columns', 'cannaiq-menus'), + ], + ] + ); + + $this->add_control( + 'category', + [ + 'label' => __('Category', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::SELECT, + 'default' => '', + 'options' => CannaIQ_Menus_Plugin::instance()->get_category_options(), + 'description' => __('Filter specials by category', 'cannaiq-menus'), + ] + ); + + $this->end_controls_section(); + + // Display Options Section + $this->start_controls_section( + 'display_section', + [ + 'label' => __('Display Options', 'cannaiq-menus'), + 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, + ] + ); + + $this->add_control( + 'show_image', + [ + 'label' => __('Show Image', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'cannaiq-menus'), + 'label_off' => __('No', 'cannaiq-menus'), + 'return_value' => 'yes', + 'default' => 'yes', + ] + ); + + $this->add_control( + 'show_discount_badge', + [ + 'label' => __('Show Discount Badge', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'cannaiq-menus'), + 'label_off' => __('No', 'cannaiq-menus'), + 'return_value' => 'yes', + 'default' => 'yes', + ] + ); + + $this->add_control( + 'show_original_price', + [ + 'label' => __('Show Original Price', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'cannaiq-menus'), + 'label_off' => __('No', 'cannaiq-menus'), + 'return_value' => 'yes', + 'default' => 'yes', + ] + ); + + $this->add_control( + 'show_thc', + [ + 'label' => __('Show THC', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'cannaiq-menus'), + 'label_off' => __('No', 'cannaiq-menus'), + 'return_value' => 'yes', + 'default' => 'no', + ] + ); + + $this->end_controls_section(); + + // Style Section + $this->start_controls_section( + 'style_section', + [ + 'label' => __('Style', 'cannaiq-menus'), + 'tab' => \Elementor\Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'card_background', + [ + 'label' => __('Card Background', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::COLOR, + 'default' => '#ffffff', + 'selectors' => [ + '{{WRAPPER}} .cannaiq-special-card' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'badge_background', + [ + 'label' => __('Badge Background', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::COLOR, + 'default' => '#ef4444', + 'selectors' => [ + '{{WRAPPER}} .cannaiq-discount-badge' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'sale_price_color', + [ + 'label' => __('Sale Price Color', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::COLOR, + 'default' => '#16a34a', + 'selectors' => [ + '{{WRAPPER}} .cannaiq-price-sale' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'card_border_radius', + [ + 'label' => __('Border Radius', 'cannaiq-menus'), + 'type' => \Elementor\Controls_Manager::SLIDER, + 'size_units' => ['px'], + 'range' => [ + 'px' => [ + 'min' => 0, + 'max' => 50, + ], + ], + 'default' => [ + 'size' => 8, + ], + 'selectors' => [ + '{{WRAPPER}} .cannaiq-special-card' => 'border-radius: {{SIZE}}{{UNIT}};', + ], + ] + ); + + $this->end_controls_section(); + } + + protected function render() { + $settings = $this->get_settings_for_display(); + + $args = [ + 'store_id' => $settings['store_id'], + 'limit' => $settings['limit'], + ]; + + if (!empty($settings['category'])) { + $args['type'] = $settings['category']; + } + + $plugin = CannaIQ_Menus_Plugin::instance(); + $products = $plugin->fetch_specials($args); + + if (!$products) { + echo '

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

'; + return; + } + + $columns = $settings['columns']; + ?> +
+ 0 && $sale_price < $regular_price) + ? round((($regular_price - $sale_price) / $regular_price) * 100) + : 0; + ?> +
onclick="window.open('', '_blank')" + style="cursor: ;"> + + 0): ?> +
+ -% +
+ + + +
+ <?php echo esc_attr($product['name']); ?> +
+ + +
+

+ +

+ + + + THC: % + + + +
+ $ + $sale_price): ?> + $ + +
+
+
+ +
+