All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
New modular component widgets: - Discount Ribbon (ribbon/pill/text styles) - Strain Badge (Sativa/Indica/Hybrid colored pills) - THC/CBD Meter (progress bars or badges) - Effects Display (styled chips with icons) - Price Block (original + sale price) - Cart Button (styled CTA linking to menu) - Stock Indicator (in/out of stock badges) - Product Image + Badges (image with overlays) New card template: - Premium Product Card (ready-to-use template) Extended dynamic tags (30+ total): - Discount %, Strain Badge, THC/CBD Badge - Effects Chips, Terpenes, Price Display - Menu URL, Stock Status, and more New files: - assets/css/components.css - includes/effects-icons.php (SVG icons) - 10 new widget files - dynamic-tags-extended.php Branding updated to "CannaiQ" throughout. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
193 lines
8.2 KiB
PHP
193 lines
8.2 KiB
PHP
<?php
|
|
/**
|
|
* Effects Icons Library
|
|
*
|
|
* SVG icons for cannabis effects display.
|
|
* Used by Effects Display widget and dynamic tags.
|
|
*
|
|
* @package CannaIQ_Menus
|
|
* @since 2.0.0
|
|
*/
|
|
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Get SVG icon for an effect
|
|
*
|
|
* @param string $effect Effect name (case-insensitive)
|
|
* @param array $args Optional args: size, class, color
|
|
* @return string SVG HTML or empty string if not found
|
|
*/
|
|
function cannaiq_get_effect_icon($effect, $args = []) {
|
|
$defaults = [
|
|
'size' => 16,
|
|
'class' => '',
|
|
'color' => 'currentColor',
|
|
];
|
|
$args = wp_parse_args($args, $defaults);
|
|
|
|
$effect_key = strtolower(trim($effect));
|
|
$icons = cannaiq_get_effect_icons();
|
|
|
|
if (!isset($icons[$effect_key])) {
|
|
return '';
|
|
}
|
|
|
|
$svg = $icons[$effect_key];
|
|
$size = intval($args['size']);
|
|
$class = esc_attr($args['class']);
|
|
$color = esc_attr($args['color']);
|
|
|
|
// Replace placeholders in SVG
|
|
$svg = str_replace(
|
|
['{SIZE}', '{CLASS}', '{COLOR}'],
|
|
[$size, $class, $color],
|
|
$svg
|
|
);
|
|
|
|
return $svg;
|
|
}
|
|
|
|
/**
|
|
* Get all effect icons
|
|
*
|
|
* @return array Associative array of effect => SVG
|
|
*/
|
|
function cannaiq_get_effect_icons() {
|
|
return [
|
|
'happy' => '<svg width="{SIZE}" height="{SIZE}" viewBox="0 0 24 24" fill="none" stroke="{COLOR}" stroke-width="2" class="{CLASS}"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>',
|
|
|
|
'relaxed' => '<svg width="{SIZE}" height="{SIZE}" viewBox="0 0 24 24" fill="none" stroke="{COLOR}" stroke-width="2" class="{CLASS}"><path d="M18 8h1a4 4 0 0 1 0 8h-1"/><path d="M2 8h16v9a4 4 0 0 1-4 4H6a4 4 0 0 1-4-4V8z"/><line x1="6" y1="1" x2="6" y2="4"/><line x1="10" y1="1" x2="10" y2="4"/><line x1="14" y1="1" x2="14" y2="4"/></svg>',
|
|
|
|
'sleepy' => '<svg width="{SIZE}" height="{SIZE}" viewBox="0 0 24 24" fill="none" stroke="{COLOR}" stroke-width="2" class="{CLASS}"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>',
|
|
|
|
'euphoric' => '<svg width="{SIZE}" height="{SIZE}" viewBox="0 0 24 24" fill="none" stroke="{COLOR}" stroke-width="2" class="{CLASS}"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>',
|
|
|
|
'creative' => '<svg width="{SIZE}" height="{SIZE}" viewBox="0 0 24 24" fill="none" stroke="{COLOR}" stroke-width="2" class="{CLASS}"><path d="M12 2v4"/><path d="m6.34 6.34 2.83 2.83"/><path d="M2 12h4"/><path d="m6.34 17.66 2.83-2.83"/><path d="M12 18v4"/><path d="m17.66 17.66-2.83-2.83"/><path d="M18 12h4"/><path d="m17.66 6.34-2.83 2.83"/></svg>',
|
|
|
|
'energetic' => '<svg width="{SIZE}" height="{SIZE}" viewBox="0 0 24 24" fill="none" stroke="{COLOR}" stroke-width="2" class="{CLASS}"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>',
|
|
|
|
'focused' => '<svg width="{SIZE}" height="{SIZE}" viewBox="0 0 24 24" fill="none" stroke="{COLOR}" stroke-width="2" class="{CLASS}"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2"/></svg>',
|
|
|
|
'hungry' => '<svg width="{SIZE}" height="{SIZE}" viewBox="0 0 24 24" fill="none" stroke="{COLOR}" stroke-width="2" class="{CLASS}"><path d="M18 8h1a4 4 0 0 1 0 8h-1"/><path d="M2 8h16v9a4 4 0 0 1-4 4H6a4 4 0 0 1-4-4V8z"/><line x1="6" y1="1" x2="6" y2="4"/><line x1="10" y1="1" x2="10" y2="4"/><line x1="14" y1="1" x2="14" y2="4"/></svg>',
|
|
|
|
'uplifted' => '<svg width="{SIZE}" height="{SIZE}" viewBox="0 0 24 24" fill="none" stroke="{COLOR}" stroke-width="2" class="{CLASS}"><path d="m18 15-6-6-6 6"/><path d="m18 9-6-6-6 6"/></svg>',
|
|
|
|
'talkative' => '<svg width="{SIZE}" height="{SIZE}" viewBox="0 0 24 24" fill="none" stroke="{COLOR}" stroke-width="2" class="{CLASS}"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>',
|
|
|
|
'giggly' => '<svg width="{SIZE}" height="{SIZE}" viewBox="0 0 24 24" fill="none" stroke="{COLOR}" stroke-width="2" class="{CLASS}"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><path d="M9 9h.01"/><path d="M15 9h.01"/></svg>',
|
|
|
|
'aroused' => '<svg width="{SIZE}" height="{SIZE}" viewBox="0 0 24 24" fill="none" stroke="{COLOR}" stroke-width="2" class="{CLASS}"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>',
|
|
|
|
'tingly' => '<svg width="{SIZE}" height="{SIZE}" viewBox="0 0 24 24" fill="none" stroke="{COLOR}" stroke-width="2" class="{CLASS}"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"/><polyline points="14 2 14 8 20 8"/><path d="M8 13h2"/><path d="M8 17h2"/><path d="M14 13h2"/><path d="M14 17h2"/></svg>',
|
|
|
|
'calm' => '<svg width="{SIZE}" height="{SIZE}" viewBox="0 0 24 24" fill="none" stroke="{COLOR}" stroke-width="2" class="{CLASS}"><path d="M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z"/></svg>',
|
|
|
|
'sedated' => '<svg width="{SIZE}" height="{SIZE}" viewBox="0 0 24 24" fill="none" stroke="{COLOR}" stroke-width="2" class="{CLASS}"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/><path d="M9 10h.01"/><path d="M15 10h.01"/><path d="M10 16s.5-1 2-1 2 1 2 1"/></svg>',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Get effect color
|
|
*
|
|
* @param string $effect Effect name
|
|
* @return string Hex color code
|
|
*/
|
|
function cannaiq_get_effect_color($effect) {
|
|
$colors = [
|
|
'happy' => '#FFD700', // Gold
|
|
'relaxed' => '#87CEEB', // Sky blue
|
|
'sleepy' => '#9370DB', // Medium purple
|
|
'euphoric' => '#FF69B4', // Hot pink
|
|
'creative' => '#FF8C00', // Dark orange
|
|
'energetic' => '#32CD32', // Lime green
|
|
'focused' => '#4169E1', // Royal blue
|
|
'hungry' => '#FF6347', // Tomato
|
|
'uplifted' => '#00CED1', // Dark turquoise
|
|
'talkative' => '#DDA0DD', // Plum
|
|
'giggly' => '#FFB6C1', // Light pink
|
|
'aroused' => '#DC143C', // Crimson
|
|
'tingly' => '#8A2BE2', // Blue violet
|
|
'calm' => '#98FB98', // Pale green
|
|
'sedated' => '#708090', // Slate gray
|
|
];
|
|
|
|
$key = strtolower(trim($effect));
|
|
return isset($colors[$key]) ? $colors[$key] : '#6B7280'; // Default gray
|
|
}
|
|
|
|
/**
|
|
* Render effect chip HTML
|
|
*
|
|
* @param string $effect Effect name
|
|
* @param array $args Optional args: show_icon, size, class
|
|
* @return string HTML for effect chip
|
|
*/
|
|
function cannaiq_render_effect_chip($effect, $args = []) {
|
|
$defaults = [
|
|
'show_icon' => true,
|
|
'size' => 'medium',
|
|
'class' => '',
|
|
];
|
|
$args = wp_parse_args($args, $defaults);
|
|
|
|
$effect_name = ucfirst(strtolower(trim($effect)));
|
|
$color = cannaiq_get_effect_color($effect);
|
|
$size_class = 'cannaiq-effect-chip--' . esc_attr($args['size']);
|
|
$extra_class = esc_attr($args['class']);
|
|
|
|
$icon_html = '';
|
|
if ($args['show_icon']) {
|
|
$icon_html = cannaiq_get_effect_icon($effect, [
|
|
'size' => $args['size'] === 'small' ? 12 : ($args['size'] === 'large' ? 20 : 16),
|
|
'color' => $color,
|
|
]);
|
|
}
|
|
|
|
return sprintf(
|
|
'<span class="cannaiq-effect-chip %s %s" style="--effect-color: %s">%s<span class="cannaiq-effect-chip__label">%s</span></span>',
|
|
$size_class,
|
|
$extra_class,
|
|
esc_attr($color),
|
|
$icon_html,
|
|
esc_html($effect_name)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Render multiple effect chips
|
|
*
|
|
* @param array $effects Array of effect names
|
|
* @param array $args Optional args: limit, show_icon, size
|
|
* @return string HTML for all effect chips
|
|
*/
|
|
function cannaiq_render_effects($effects, $args = []) {
|
|
$defaults = [
|
|
'limit' => 3,
|
|
'show_icon' => true,
|
|
'size' => 'medium',
|
|
'class' => '',
|
|
];
|
|
$args = wp_parse_args($args, $defaults);
|
|
|
|
if (!is_array($effects)) {
|
|
return '';
|
|
}
|
|
|
|
$effects = array_slice($effects, 0, intval($args['limit']));
|
|
$chips = array_map(function($effect) use ($args) {
|
|
return cannaiq_render_effect_chip($effect, [
|
|
'show_icon' => $args['show_icon'],
|
|
'size' => $args['size'],
|
|
]);
|
|
}, $effects);
|
|
|
|
return sprintf(
|
|
'<div class="cannaiq-effects-container %s">%s</div>',
|
|
esc_attr($args['class']),
|
|
implode('', $chips)
|
|
);
|
|
}
|