JezK
Edit File: advaxe-shop-grid.php
<?php /* Plugin Name: Advaxe Shop & Home Grid Description: Professional Shop UI, Dynamic Grid Control (Mobile/PC), Modern Admin Panel with Style 1 & Style 2 (Elegant/Fabrilife Cart System). Version: 7.8 (Fixed Variable Product Price Range and Minimum Variant Discount Logic) Author: Advaxe License: GPLv2 or later */ if ( ! defined( 'ABSPATH' ) ) exit; // ============================================================== // ০. Cache Clear Function // ============================================================== function advaxe_purge_all_caches() { wp_cache_flush(); if ( function_exists( 'w3tc_flush_all' ) ) { w3tc_flush_all(); } if ( function_exists( 'rocket_clean_domain' ) ) { rocket_clean_domain(); } if ( has_action( 'litespeed_purge_all' ) ) { do_action( 'litespeed_purge_all' ); } if ( function_exists( 'wp_cache_clear_cache' ) ) { wp_cache_clear_cache(); } } // ============================================================== // ১. এডমিন মেনু স্ট্রাকচার // ============================================================== add_action('admin_menu', 'advaxe_shop_plugin_menu'); add_action('admin_enqueue_scripts', 'advaxe_shop_admin_assets'); function advaxe_shop_plugin_menu() { add_menu_page('Advaxe Shop', 'Advaxe Shop', 'manage_options', 'advaxe-shop', 'advaxe_page_redirect', 'dashicons-store', 6); add_submenu_page('advaxe-shop', 'Home Layout', 'Home Layout', 'manage_options', 'advaxe-home-layout', 'advaxe_page_home_layout'); add_submenu_page('advaxe-shop', 'Manage Banners', 'Banners', 'manage_options', 'advaxe-banners', 'advaxe_page_banners'); add_submenu_page('advaxe-shop', 'Global Settings', 'Global Settings', 'manage_options', 'advaxe-global-settings', 'advaxe_page_settings'); remove_submenu_page('advaxe-shop', 'advaxe-shop'); } function advaxe_page_redirect() { wp_redirect(admin_url('admin.php?page=advaxe-home-layout')); exit; } // ============================================================== // ২. প্রিমিয়াম এডমিন UI (Premium CSS) // ============================================================== function advaxe_shop_admin_assets($hook) { if (strpos($hook, 'advaxe') === false) return; wp_enqueue_media(); wp_enqueue_script('jquery-ui-sortable'); // Add Color Picker wp_enqueue_style('wp-color-picker'); wp_enqueue_script('wp-color-picker'); wp_enqueue_style('advaxe-admin-css', false); wp_add_inline_style('advaxe-admin-css', " :root { --adv-primary: #0ea5e9; --adv-primary-hover: #0284c7; --adv-bg: #f8fafc; --adv-card-bg: #ffffff; --adv-text: #0f172a; --adv-text-muted: #64748b; --adv-border: #e2e8f0; --adv-radius: 12px; --adv-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -2px rgba(0, 0, 0, 0.05); } body { background: var(--adv-bg); } .advaxe-wrap { max-width: 1000px; margin: 30px auto; font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; color: var(--adv-text); } .advaxe-wrap h1 { color: #0f172a; font-weight: 700; font-size: 28px; margin-bottom: 8px; letter-spacing: -0.5px; } .advaxe-subtitle { color: var(--adv-text-muted); font-size: 15px; margin-bottom: 30px; } .advaxe-card { background: var(--adv-card-bg); border-radius: var(--adv-radius); box-shadow: var(--adv-shadow); padding: 30px; margin-bottom: 25px; border: 1px solid var(--adv-border); } .advaxe-header { border-bottom: 1px solid var(--adv-border); padding-bottom: 15px; margin-bottom: 25px; } .advaxe-header h2 { font-size: 18px; font-weight: 600; margin: 0; color: #0f172a; } .advaxe-input { width: 100%; height: 44px; background: #f8fafc; border: 1px solid #cbd5e1; border-radius: 8px; padding: 0 16px; font-size: 14px; font-family: inherit; transition: all 0.2s ease; color: #334155; } .advaxe-input:focus { border-color: var(--adv-primary); outline: none; background: #fff; box-shadow: 0 0 0 3px rgba(14, 165, 233, 0.15); } .advaxe-label { display: block; font-weight: 600; margin-bottom: 8px; color: #475569; font-size: 13px; text-transform: uppercase; letter-spacing: 0.5px; } .advaxe-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 24px; margin-bottom: 24px; } .advaxe-btn-primary { background: var(--adv-primary); color: #fff; border: none; padding: 12px 28px; border-radius: 8px; cursor: pointer; font-size: 15px; font-weight: 600; transition: 0.2s; display: inline-flex; align-items: center; justify-content: center; text-decoration: none; box-shadow: 0 2px 4px rgba(14, 165, 233, 0.2); } .advaxe-btn-primary:hover { background: var(--adv-primary-hover); transform: translateY(-1px); box-shadow: 0 4px 6px rgba(14, 165, 233, 0.3); } .advaxe-btn-secondary { background: #fff; color: #334155; border: 1px dashed #cbd5e1; padding: 14px 20px; border-radius: 8px; cursor: pointer; font-size: 15px; font-weight: 600; transition: all 0.2s; width: 100%; } .advaxe-btn-secondary:hover { background: #f1f5f9; border-color: #94a3b8; color: #0f172a; } .advaxe-icon-btn { background: #f1f5f9; border: none; cursor: pointer; color: #475569; padding: 8px; border-radius: 6px; display: inline-flex; align-items: center; transition: 0.2s; } .advaxe-icon-btn:hover { background: #e2e8f0; color: #0f172a; } .advaxe-btn-danger { color: #ef4444; background: #fef2f2; } .advaxe-btn-danger:hover { background: #fee2e2; color: #dc2626; } .advaxe-switch { position: relative; display: inline-block; width: 44px; height: 24px; margin: 0; } .advaxe-switch input { opacity: 0; width: 0; height: 0; } .advaxe-slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #cbd5e1; transition: .3s; border-radius: 34px; } .advaxe-slider:before { position: absolute; content: ''; height: 18px; width: 18px; left: 3px; bottom: 3px; background-color: white; transition: .3s; border-radius: 50%; box-shadow: 0 1px 2px rgba(0,0,0,0.2); } input:checked + .advaxe-slider { background-color: #10b981; } input:checked + .advaxe-slider:before { transform: translateX(20px); } .advaxe-section-item { background: #fff; border: 1px solid var(--adv-border); border-radius: var(--adv-radius); margin-bottom: 20px; transition: all 0.2s; box-shadow: var(--adv-shadow); } .advaxe-section-item:hover { border-color: #cbd5e1; box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); } .advaxe-sec-header { padding: 18px 24px; display: flex; align-items: center; cursor: grab; background: #fff; border-bottom: 1px solid var(--adv-border); border-radius: var(--adv-radius) var(--adv-radius) 0 0; } .advaxe-section-item.closed .advaxe-sec-header { border-bottom: none; border-radius: var(--adv-radius); } .advaxe-section-item.closed .advaxe-sec-body { display: none; } .sec-drag-handle { color: #94a3b8; margin-right: 15px; font-size: 20px; } .sec-title-display { font-weight: 700; color: #0f172a; font-size: 16px; } .sec-type-badge { background: #f0f9ff; color: #0284c7; font-size: 11px; padding: 4px 10px; border-radius: 20px; margin-left: 12px; font-weight: 700; text-transform: uppercase; border: 1px solid #bae6fd; } .advaxe-sec-actions { margin-left: auto; display: flex; align-items: center; gap: 12px; } .advaxe-sec-body { padding: 30px; background: #fafafc; border-radius: 0 0 var(--adv-radius) var(--adv-radius); } .adv-b-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 20px; margin-top: 20px; } .adv-b-item { position: relative; aspect-ratio: 21/9; border-radius: 10px; overflow: hidden; box-shadow: var(--adv-shadow); cursor: grab; border: 2px solid transparent; transition: 0.2s; } .adv-b-item:hover { border-color: var(--adv-primary); } .adv-b-item img { width: 100%; height: 100%; object-fit: cover; } .remove-banner { position: absolute; top: 8px; right: 8px; background: rgba(239, 68, 68, 0.9); color: white; width: 26px; height: 26px; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; font-weight: bold; font-size: 14px; transition: 0.2s; } .remove-banner:hover { background: #dc2626; transform: scale(1.1); } .notice { border-left: 4px solid #10b981; margin: 20px 0 !important; background: #fff; box-shadow: var(--adv-shadow); border-radius: 4px; } hr.advaxe-divider { border: 0; height: 1px; background: #e2e8f0; margin: 25px 0; } /* Fix Color picker style */ .wp-picker-container { display: inline-block; } "); } // ============================================================== // ৩. PAGE: HOME LAYOUT BUILDER // ============================================================== function advaxe_page_home_layout() { if (isset($_POST['advaxe_save_layout']) && check_admin_referer('advaxe_save_layout_nonce')) { $sections = array(); if(isset($_POST['advaxe_sections']) && is_array($_POST['advaxe_sections'])) { $raw_sections = array_values($_POST['advaxe_sections']); foreach($raw_sections as $sec) { $sections[] = array( 'title' => sanitize_text_field($sec['title']), 'type' => sanitize_text_field($sec['type']), 'source_id' => isset($sec['source_id']) ? sanitize_text_field($sec['source_id']) : '', 'visible' => isset($sec['visible']) ? 1 : 0, 'align' => sanitize_text_field($sec['align']), 'limit' => !empty($sec['limit']) ? intval($sec['limit']) : 8, 'col_mobile' => !empty($sec['col_mobile']) ? intval($sec['col_mobile']) : '', 'col_desktop' => !empty($sec['col_desktop']) ? intval($sec['col_desktop']) : '', 'show_btn' => isset($sec['show_btn']) ? 1 : 0, 'btn_url_type' => sanitize_text_field($sec['btn_url_type']), 'custom_url' => esc_url_raw($sec['custom_url']), ); } } update_option('advaxe_home_sections', $sections); advaxe_purge_all_caches(); echo '<div class="notice notice-success is-dismissible"><p style="padding:10px; font-weight:500;">✨ Home layout updated successfully. Cache cleared automatically.</p></div>'; } $saved_sections = get_option('advaxe_home_sections', array()); $categories = get_terms(array('taxonomy' => 'product_cat', 'hide_empty' => false)); $tags = get_terms(array('taxonomy' => 'product_tag', 'hide_empty' => false)); ?> <div class="wrap advaxe-wrap"> <h1>Homepage Builder</h1> <p class="advaxe-subtitle">Design your storefront exactly how you want it. Drag & drop sections to reorder.</p> <form method="post" id="advaxe-builder-form"> <?php wp_nonce_field('advaxe_save_layout_nonce'); ?> <div id="advaxe-sections-container"> <?php if(!empty($saved_sections)): foreach($saved_sections as $index => $sec): $type = isset($sec['type']) ? $sec['type'] : 'latest'; $source_id = isset($sec['source_id']) ? $sec['source_id'] : ''; ?> <div class="advaxe-section-item closed"> <div class="advaxe-sec-header"> <span class="dashicons dashicons-menu sec-drag-handle"></span> <div style="display:flex; align-items:center;"> <span class="sec-title-display"><?php echo esc_html($sec['title']); ?></span> <span class="sec-type-badge type-label"><?php echo ucfirst($type); ?></span> </div> <div class="advaxe-sec-actions"> <label class="advaxe-switch" title="Toggle Visibility"> <input type="checkbox" name="advaxe_sections[<?php echo $index; ?>][visible]" <?php checked(isset($sec['visible']) ? $sec['visible'] : 1, 1); ?>> <span class="advaxe-slider"></span> </label> <button type="button" class="advaxe-icon-btn toggle-btn" title="Edit Settings"><span class="dashicons dashicons-edit"></span></button> <button type="button" class="advaxe-icon-btn advaxe-btn-danger remove-sec-btn" title="Delete Section"><span class="dashicons dashicons-trash"></span></button> </div> </div> <div class="advaxe-sec-body"> <div class="advaxe-grid"> <div> <label class="advaxe-label">Section Title</label> <input type="text" name="advaxe_sections[<?php echo $index; ?>][title]" class="advaxe-input sec-title-input" value="<?php echo esc_attr($sec['title']); ?>" required> </div> <div> <label class="advaxe-label">Content Source</label> <select name="advaxe_sections[<?php echo $index; ?>][type]" class="advaxe-input sec-type-select"> <option value="latest" <?php selected($type, 'latest'); ?>>Latest Products</option> <option value="category" <?php selected($type, 'category'); ?>>Specific Category</option> <option value="tag" <?php selected($type, 'tag'); ?>>Specific Tag</option> <option value="custom" <?php selected($type, 'custom'); ?>>Custom Product IDs</option> </select> </div> </div> <div class="advaxe-grid source-wrapper"> <div class="source-input source-category" style="<?php echo ($type == 'category') ? '' : 'display:none;'; ?>"> <label class="advaxe-label">Select Category</label> <select name="advaxe_sections[<?php echo $index; ?>][source_id]" class="advaxe-input"> <option value="">-- Choose Category --</option> <?php foreach($categories as $cat) echo '<option value="'.$cat->term_id.'" '.selected($source_id, $cat->term_id, false).'>'.$cat->name.'</option>'; ?> </select> </div> <div class="source-input source-tag" style="<?php echo ($type == 'tag') ? '' : 'display:none;'; ?>"> <label class="advaxe-label">Select Tag</label> <select name="advaxe_sections[<?php echo $index; ?>][source_id]" class="advaxe-input"> <option value="">-- Choose Tag --</option> <?php foreach($tags as $t) echo '<option value="'.$t->term_id.'" '.selected($source_id, $t->term_id, false).'>'.$t->name.'</option>'; ?> </select> </div> <div class="source-input source-custom" style="<?php echo ($type == 'custom') ? '' : 'display:none;'; ?>"> <label class="advaxe-label">Product IDs (comma separated)</label> <input type="text" name="advaxe_sections[<?php echo $index; ?>][source_id]" class="advaxe-input" placeholder="e.g. 102, 105, 203" value="<?php echo ($type == 'custom') ? esc_attr($source_id) : ''; ?>"> </div> </div> <hr class="advaxe-divider"> <div class="advaxe-grid"> <div> <label class="advaxe-label">Total Products to Show</label> <input type="number" name="advaxe_sections[<?php echo $index; ?>][limit]" class="advaxe-input" placeholder="Default: 8" value="<?php echo isset($sec['limit']) ? esc_attr($sec['limit']) : 8; ?>"> </div> <div> <label class="advaxe-label">Mobile Columns</label> <input type="number" name="advaxe_sections[<?php echo $index; ?>][col_mobile]" class="advaxe-input" placeholder="Leave empty for default" value="<?php echo isset($sec['col_mobile']) ? esc_attr($sec['col_mobile']) : ''; ?>"> </div> <div> <label class="advaxe-label">PC Columns</label> <input type="number" name="advaxe_sections[<?php echo $index; ?>][col_desktop]" class="advaxe-input" placeholder="Leave empty for default" value="<?php echo isset($sec['col_desktop']) ? esc_attr($sec['col_desktop']) : ''; ?>"> </div> </div> <div class="advaxe-grid"> <div> <label class="advaxe-label">Title Alignment</label> <select name="advaxe_sections[<?php echo $index; ?>][align]" class="advaxe-input"> <option value="center" <?php selected(isset($sec['align'])?$sec['align']:'center', 'center'); ?>>Center</option> <option value="left" <?php selected(isset($sec['align'])?$sec['align']:'center', 'left'); ?>>Left</option> </select> </div> <div style="display:flex; align-items:center;"> <label style="cursor:pointer; display:flex; align-items:center; font-weight:600; color:#0f172a;"> <input type="checkbox" class="show-btn-check" name="advaxe_sections[<?php echo $index; ?>][show_btn]" <?php checked(isset($sec['show_btn']) ? $sec['show_btn'] : 0, 1); ?> style="margin-right:10px; width:18px; height:18px;"> Enable "View All" Button </label> </div> </div> <div class="btn-settings" style="<?php echo (isset($sec['show_btn']) && $sec['show_btn']) ? '' : 'display:none;'; ?>"> <div class="advaxe-grid"> <div> <label class="advaxe-label">Button Link Type</label> <select name="advaxe_sections[<?php echo $index; ?>][btn_url_type]" class="advaxe-input btn-url-type"> <option value="auto" <?php selected(isset($sec['btn_url_type'])?$sec['btn_url_type']:'auto', 'auto'); ?>>Auto Detect Link</option> <option value="custom" <?php selected(isset($sec['btn_url_type'])?$sec['btn_url_type']:'auto', 'custom'); ?>>Custom URL</option> </select> </div> <div class="btn-custom-url" style="<?php echo (isset($sec['btn_url_type']) && $sec['btn_url_type'] == 'custom') ? '' : 'visibility:hidden;'; ?>"> <label class="advaxe-label">Custom URL</label> <input type="url" name="advaxe_sections[<?php echo $index; ?>][custom_url]" class="advaxe-input" placeholder="https://" value="<?php echo isset($sec['custom_url']) ? esc_attr($sec['custom_url']) : ''; ?>"> </div> </div> </div> </div> </div> <?php endforeach; endif; ?> </div> <div style="margin: 30px 0;"> <button type="button" class="advaxe-btn-secondary" id="add-new-section">+ Add New Section</button> </div> <div style="background: #fff; padding: 20px; border-radius: 12px; border: 1px solid #e2e8f0; display:flex; justify-content:space-between; align-items:center; box-shadow: 0 4px 6px -1px rgba(0,0,0,0.05);"> <p style="margin:0; color:#64748b; font-size:14px;">Make sure to save after making structural changes.</p> <button type="submit" name="advaxe_save_layout" class="advaxe-btn-primary"><span class="dashicons dashicons-saved" style="margin-right:8px;"></span> Save Layout</button> </div> </form> </div> <div id="sec-template" style="display:none;"> <div class="advaxe-section-item"> <div class="advaxe-sec-header"> <span class="dashicons dashicons-menu sec-drag-handle"></span> <div style="display:flex; align-items:center;"> <span class="sec-title-display">New Section</span> <span class="sec-type-badge type-label">Latest</span> </div> <div class="advaxe-sec-actions"> <label class="advaxe-switch" title="Toggle Visibility"> <input type="checkbox" name="advaxe_sections[999][visible]" checked> <span class="advaxe-slider"></span> </label> <button type="button" class="advaxe-icon-btn toggle-btn"><span class="dashicons dashicons-edit"></span></button> <button type="button" class="advaxe-icon-btn advaxe-btn-danger remove-sec-btn"><span class="dashicons dashicons-trash"></span></button> </div> </div> <div class="advaxe-sec-body"> <div class="advaxe-grid"> <div> <label class="advaxe-label">Section Title</label> <input type="text" name="advaxe_sections[999][title]" class="advaxe-input sec-title-input" value="New Section"> </div> <div> <label class="advaxe-label">Content Source</label> <select name="advaxe_sections[999][type]" class="advaxe-input sec-type-select"> <option value="latest">Latest Products</option> <option value="category">Specific Category</option> <option value="tag">Specific Tag</option> <option value="custom">Custom IDs</option> </select> </div> </div> <div class="advaxe-grid source-wrapper"> <div class="source-input source-category" style="display:none;"> <label class="advaxe-label">Select Category</label> <select name="advaxe_sections[999][source_id]" class="advaxe-input"> <option value="">-- Choose Category --</option> <?php foreach($categories as $cat) echo '<option value="'.$cat->term_id.'">'.$cat->name.'</option>'; ?> </select> </div> <div class="source-input source-tag" style="display:none;"> <label class="advaxe-label">Select Tag</label> <select name="advaxe_sections[999][source_id]" class="advaxe-input"> <option value="">-- Choose Tag --</option> <?php foreach($tags as $t) echo '<option value="'.$t->term_id.'">'.$t->name.'</option>'; ?> </select> </div> <div class="source-input source-custom" style="display:none;"> <label class="advaxe-label">Product IDs</label> <input type="text" name="advaxe_sections[999][source_id]" class="advaxe-input"> </div> </div> <hr class="advaxe-divider"> <div class="advaxe-grid"> <div> <label class="advaxe-label">Total Products</label> <input type="number" name="advaxe_sections[999][limit]" class="advaxe-input" placeholder="Default: 8"> </div> <div> <label class="advaxe-label">Mobile Col</label> <input type="number" name="advaxe_sections[999][col_mobile]" class="advaxe-input" placeholder="Default"> </div> <div> <label class="advaxe-label">PC Col</label> <input type="number" name="advaxe_sections[999][col_desktop]" class="advaxe-input" placeholder="Default"> </div> </div> <div class="advaxe-grid"> <div> <label class="advaxe-label">Align</label> <select name="advaxe_sections[999][align]" class="advaxe-input"> <option value="center">Center</option> <option value="left">Left</option> </select> </div> <div style="display:flex; align-items:center;"> <label style="cursor:pointer; display:flex; align-items:center; font-weight:600; color:#0f172a;"> <input type="checkbox" class="show-btn-check" name="advaxe_sections[999][show_btn]" style="margin-right:10px; width:18px; height:18px;"> Enable "View All" Button </label> </div> </div> <div class="btn-settings" style="display:none;"> <div class="advaxe-grid"> <div> <label class="advaxe-label">Link Type</label> <select name="advaxe_sections[999][btn_url_type]" class="advaxe-input btn-url-type"> <option value="auto">Auto</option> <option value="custom">Custom</option> </select> </div> <div class="btn-custom-url" style="visibility:hidden;"> <label class="advaxe-label">URL</label> <input type="url" name="advaxe_sections[999][custom_url]" class="advaxe-input"> </div> </div> </div> </div> </div> </div> <script> jQuery(document).ready(function($){ $('#advaxe-sections-container').sortable({ handle: '.advaxe-sec-header', opacity: 0.8, placeholder: "ui-state-highlight", forcePlaceholderSize: true }); $(document).on('click', '.toggle-btn', function(){ $(this).closest('.advaxe-section-item').toggleClass('closed'); }); $('#add-new-section').click(function(){ var template = $('#sec-template').html(); $('#advaxe-sections-container').append(template); var newItem = $('#advaxe-sections-container .advaxe-section-item:last'); newItem.hide().slideDown(300); newItem.find('.source-input').find('input, select').prop('disabled', true); }); $(document).on('click', '.remove-sec-btn', function(){ if(confirm('Delete this section?')) { $(this).closest('.advaxe-section-item').slideUp(300, function(){ $(this).remove(); }); } }); function handleSourceInputs(selectElem) { var val = selectElem.val(); var wrapper = selectElem.closest('.advaxe-sec-body'); wrapper.closest('.advaxe-section-item').find('.type-label').text(val); wrapper.find('.source-input').hide(); wrapper.find('.source-input input, .source-input select').prop('disabled', true); if(val == 'category') { wrapper.find('.source-category').fadeIn(200).find('select').prop('disabled', false); } else if(val == 'tag') { wrapper.find('.source-tag').fadeIn(200).find('select').prop('disabled', false); } else if(val == 'custom') { wrapper.find('.source-custom').fadeIn(200).find('input').prop('disabled', false); } } $('.sec-type-select').each(function(){ handleSourceInputs($(this)); }); $(document).on('change', '.sec-type-select', function(){ handleSourceInputs($(this)); }); $(document).on('input', '.sec-title-input', function(){ $(this).closest('.advaxe-section-item').find('.sec-title-display').text($(this).val()); }); $(document).on('change', '.show-btn-check', function(){ var box = $(this).closest('.advaxe-sec-body').find('.btn-settings'); if($(this).is(':checked')) box.slideDown(200); else box.slideUp(200); }); $(document).on('change', '.btn-url-type', function(){ var box = $(this).closest('.btn-settings').find('.btn-custom-url'); if($(this).val() == 'custom') box.css('visibility', 'visible'); else box.css('visibility', 'hidden'); }); $('#advaxe-builder-form').on('submit', function(){ $('#advaxe-sections-container .advaxe-section-item').each(function(index){ var item = $(this); item.find('input, select').each(function(){ var name = $(this).attr('name'); if(name) { $(this).attr('name', name.replace(/\[\d+\]/, '[' + index + ']')); } }); }); }); }); </script> <?php } // ============================================================== // ৪. PAGE: MANAGE BANNERS // ============================================================== function advaxe_page_banners() { if (isset($_POST['advaxe_save_banners']) && check_admin_referer('advaxe_banner_nonce')) { update_option('advaxe_banner_ids', sanitize_text_field($_POST['banner_ids'])); advaxe_purge_all_caches(); echo '<div class="notice notice-success is-dismissible"><p style="padding:10px; font-weight:500;">✨ Banners updated successfully!</p></div>'; } $saved_banner_ids = get_option('advaxe_banner_ids', ''); $preview_html = ''; if(!empty($saved_banner_ids)){ $ids = explode(',', $saved_banner_ids); foreach($ids as $id){ $img_url = wp_get_attachment_image_url($id, 'large'); if($img_url) $preview_html .= '<div class="adv-b-item" data-id="'.$id.'"><img src="'.$img_url.'"><span class="remove-banner" title="Remove Banner">×</span></div>'; } } ?> <div class="wrap advaxe-wrap"> <h1>Banner Management</h1> <p class="advaxe-subtitle">Upload and arrange your homepage slider images.</p> <form method="post"> <?php wp_nonce_field('advaxe_banner_nonce'); ?> <div class="advaxe-card"> <div class="advaxe-header"><h2>Slider Images</h2></div> <div style="background: #f8fafc; padding: 25px; border-radius: 12px; border: 2px dashed #cbd5e1; min-height: 150px;"> <div id="advaxe-banner-preview" class="adv-b-grid"> <?php echo $preview_html ? $preview_html : '<p style="color:#94a3b8; text-align:center; width:100%; grid-column: 1 / -1; font-weight:500; font-size: 15px; margin-top:20px;">No banners selected yet. Click below to add.</p>'; ?> </div> </div> <input type="hidden" name="banner_ids" id="advaxe_banner_ids" value="<?php echo esc_attr($saved_banner_ids); ?>"> <div style="margin-top:25px; display:flex; gap: 15px;"> <button type="button" class="advaxe-btn-secondary" id="advaxe_upload_btn" style="width:auto;"><span class="dashicons dashicons-images-alt2" style="margin-right:8px;"></span> Select Images</button> <button type="submit" name="advaxe_save_banners" class="advaxe-btn-primary"><span class="dashicons dashicons-saved" style="margin-right:8px;"></span> Save Banners</button> </div> </div> </form> </div> <script> jQuery(document).ready(function($){ var frame; $(document).on('click', '.remove-banner', function(){ $(this).parent().fadeOut(200, function(){ $(this).remove(); updateIds(); }); }); $('#advaxe_upload_btn').click(function(e) { e.preventDefault(); if (frame) { frame.open(); return; } frame = wp.media({ title: 'Select Banners', button: { text: 'Insert' }, multiple: true }); frame.on('select', function() { var selection = frame.state().get('selection'); if(selection.length > 0) $('#advaxe-banner-preview p').remove(); selection.map(function(attachment) { attachment = attachment.toJSON(); $('#advaxe-banner-preview').append('<div class="adv-b-item" data-id="'+attachment.id+'" style="display:none;"><img src="'+attachment.url+'"><span class="remove-banner">×</span></div>'); $('#advaxe-banner-preview .adv-b-item:last').fadeIn(300); }); updateIds(); }); frame.open(); }); function updateIds(){ var ids = []; $('.adv-b-item').each(function(){ ids.push($(this).data('id')); }); $('#advaxe_banner_ids').val(ids.join(',')); } $('#advaxe-banner-preview').sortable({ update: function(){ updateIds(); } }); }); </script> <?php } // ============================================================== // ৫. PAGE: GLOBAL SETTINGS // ============================================================== function advaxe_page_settings() { if (isset($_POST['advaxe_save_global']) && check_admin_referer('advaxe_global_nonce')) { update_option('advaxe_max_width', intval($_POST['container_max_width'])); update_option('advaxe_title_lines', intval($_POST['p_title_lines'])); update_option('advaxe_margin_top', intval($_POST['container_margin_top'])); update_option('advaxe_def_col_mobile', intval($_POST['def_col_mobile'])); update_option('advaxe_def_col_desktop', intval($_POST['def_col_desktop'])); update_option('advaxe_grid_style', sanitize_text_field($_POST['advaxe_grid_style'])); update_option('advaxe_primary_color', sanitize_hex_color($_POST['advaxe_primary_color'])); update_option('advaxe_badge_color', sanitize_hex_color($_POST['advaxe_badge_color'])); update_option('advaxe_save_tag_color', sanitize_hex_color($_POST['advaxe_save_tag_color'])); update_option('advaxe_show_save_badge', isset($_POST['advaxe_show_save_badge']) ? 1 : 0); advaxe_purge_all_caches(); echo '<div class="notice notice-success is-dismissible"><p style="padding:10px; font-weight:500;">✨ Global settings updated successfully!</p></div>'; } $def_m = get_option('advaxe_def_col_mobile', 2); $def_d = get_option('advaxe_def_col_desktop', 4); $def_width = get_option('advaxe_max_width', 1200); $grid_style = get_option('advaxe_grid_style', 'style-1'); $primary_color = get_option('advaxe_primary_color', '#00796b'); $badge_color = get_option('advaxe_badge_color', '#ff2d55'); $save_tag_color = get_option('advaxe_save_tag_color', '#059669'); $show_save_badge = get_option('advaxe_show_save_badge', 1); ?> <div class="wrap advaxe-wrap"> <h1>Global Configuration</h1> <p class="advaxe-subtitle">Manage site-wide colors, grid constraints, container sizes, and styles.</p> <form method="post"> <?php wp_nonce_field('advaxe_global_nonce'); ?> <div class="advaxe-card"> <div class="advaxe-header"><h2>Design & Color Scheme</h2></div> <div class="advaxe-grid" style="align-items: end;"> <div> <label class="advaxe-label">Primary Color (Theme Color)</label> <input type="text" name="advaxe_primary_color" class="advaxe-color-picker" value="<?php echo esc_attr($primary_color); ?>" data-default-color="#00796b"> </div> <div> <label class="advaxe-label">Discount Label Color (Upper % Badge)</label> <input type="text" name="advaxe_badge_color" class="advaxe-color-picker" value="<?php echo esc_attr($badge_color); ?>" data-default-color="#ff2d55"> </div> <div> <label class="advaxe-label">Save Amount Tag Color (Bottom Tag)</label> <input type="text" name="advaxe_save_tag_color" class="advaxe-color-picker" value="<?php echo esc_attr($save_tag_color); ?>" data-default-color="#059669"> </div> </div> <div style="margin-top: 25px;"> <label style="cursor:pointer; display:flex; align-items:center; font-weight:600; color:#0f172a;"> <input type="checkbox" name="advaxe_show_save_badge" <?php checked($show_save_badge, 1); ?> style="margin-right:10px; width:18px; height:18px;"> Show "Save Amount" Tag (Both Styles) </label> </div> </div> <div class="advaxe-card"> <div class="advaxe-header"><h2>Product Grid Configuration</h2></div> <div class="advaxe-grid"> <div> <label class="advaxe-label">Product Grid Style</label> <select name="advaxe_grid_style" class="advaxe-input"> <option value="style-1" <?php selected($grid_style, 'style-1'); ?>>Style 1 (Classic Checkout Button)</option> <option value="style-2" <?php selected($grid_style, 'style-2'); ?>>Style 2 (Elegant/Fabrilife Cart System)</option> </select> </div> <div> <label class="advaxe-label">Product Title Lines Limit</label> <input type="number" name="p_title_lines" class="advaxe-input" min="1" max="4" value="<?php echo get_option('advaxe_title_lines', 2); ?>"> </div> <div> <label class="advaxe-label">Mobile Columns</label> <input type="number" name="def_col_mobile" class="advaxe-input" min="1" max="6" value="<?php echo $def_m; ?>"> </div> <div> <label class="advaxe-label">PC/Tablet Columns</label> <input type="number" name="def_col_desktop" class="advaxe-input" min="1" max="8" value="<?php echo $def_d; ?>"> </div> </div> </div> <div class="advaxe-card"> <div class="advaxe-header"><h2>Layout & Container Spacing</h2></div> <div class="advaxe-grid"> <div> <label class="advaxe-label">Container Max Width (px)</label> <input type="number" name="container_max_width" class="advaxe-input" value="<?php echo $def_width; ?>"> </div> <div> <label class="advaxe-label">Top Spacing (px)</label> <input type="number" name="container_margin_top" class="advaxe-input" value="<?php echo get_option('advaxe_margin_top', 20); ?>"> </div> </div> </div> <button type="submit" name="advaxe_save_global" class="advaxe-btn-primary"><span class="dashicons dashicons-saved" style="margin-right:8px;"></span> Save Settings</button> </form> </div> <script> jQuery(document).ready(function($){ $('.advaxe-color-picker').wpColorPicker(); }); </script> <?php } // ============================================================== // ৬. ফ্রন্টএন্ড স্টাইলস & স্ক্রিপ্টস // ============================================================== add_action('wp_head', 'advaxe_shop_global_styles', 999); add_action('wp_footer', 'advaxe_shop_global_scripts'); function advaxe_shop_global_styles() { $m_width = get_option('advaxe_max_width', 1200); $m_top = get_option('advaxe_margin_top', 20); $lines = get_option('advaxe_title_lines', 2); $def_m = get_option('advaxe_def_col_mobile', 2); $def_d = get_option('advaxe_def_col_desktop', 4); $primary_color = get_option('advaxe_primary_color', '#00796b'); $badge_color = get_option('advaxe_badge_color', '#ff2d55'); $save_tag_color = get_option('advaxe_save_tag_color', '#059669'); ?> <style> :root { --pfs-primary: <?php echo $primary_color; ?>; --pfs-badge-color: <?php echo $badge_color; ?>; --pfs-save-tag-color: <?php echo $save_tag_color; ?>; --adv-max-width: <?php echo $m_width; ?>px; --adv-m-top: <?php echo $m_top; ?>px; --adv-grid-m: <?php echo $def_m; ?>; --adv-grid-d: <?php echo $def_d; ?>; } body.woocommerce-page #primary, body.woocommerce-page #main, body.woocommerce-page .site-main, body.home #primary, body.home .site-main { padding: 0 !important; margin: 0 !important; width: 100% !important; max-width: 100% !important; overflow-x: hidden; } .advaxe-global-wrapper { font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif !important; width: 100% !important; max-width: var(--adv-max-width) !important; margin: 0 auto !important; padding-top: var(--adv-m-top) !important; padding-left: 15px !important; padding-right: 15px !important; box-sizing: border-box !important; display: block !important; } @media (min-width: 1024px) { .advaxe-global-wrapper { padding-left: 0 !important; padding-right: 0 !important; } } .woocommerce ul.products, .woocommerce-page ul.products { display: grid !important; grid-template-columns: repeat(var(--adv-grid-m), 1fr) !important; gap: 12px !important; margin: 0 !important; padding: 0 !important; } .woocommerce ul.products::before, .woocommerce ul.products::after { content: none !important; display: none !important; } .woocommerce ul.products li.product, .woocommerce-page ul.products li.product { width: 100% !important; margin: 0 !important; padding: 0 !important; float: none !important; background: transparent !important; border: none !important; box-shadow: none !important; list-style: none !important; } .woocommerce ul.products li.product .woocommerce-loop-product__link, .woocommerce ul.products li.product .woocommerce-loop-category__title, .woocommerce ul.products li.product .price, .woocommerce ul.products li.product .onsale { display: none !important; } .pfs-product-grid { display: grid; grid-template-columns: repeat(var(--sec-grid-m, var(--adv-grid-m)), 1fr); gap: 12px; } @media (min-width: 768px) { .woocommerce ul.products { grid-template-columns: repeat(var(--adv-grid-d), 1fr) !important; gap: 20px !important; } .pfs-product-grid { grid-template-columns: repeat(var(--sec-grid-d, var(--adv-grid-d)), 1fr); gap: 20px; } .advaxe-cat-circle { width: 100px; height: 100px; } } /* --- Hide "View Cart" text after adding standard products --- */ .pfs2-bottom a.added_to_cart, .pfs-p-info a.added_to_cart { display: none !important; } /* Save Tags Common (Style 1 & 2) */ .pfs-save-tag, .pfs2-save-tag { display: inline-flex; align-items: center; background: var(--pfs-save-tag-color); color: #fff; font-size: 11px; font-weight: 600; padding: 3px 8px; border-radius: 4px; } .pfs-save-tag svg, .pfs2-save-tag svg { width: 12px; height: 12px; margin-right: 4px; fill: currentColor; } /* --- STYLE 1 (Classic) --- */ .pfs-p-card { background: #fff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.06); display: flex; flex-direction: column; position: relative; height: 100%; width: 100%; border: 1px solid #f1f1f1; transition: 0.3s; } .pfs-p-card:hover { box-shadow: 0 8px 16px rgba(0,0,0,0.1); } .pfs-badge { position: absolute; top: 10px; left: 10px; background: var(--pfs-badge-color); color: white; padding: 3px 8px; font-size: 11px; border-radius: 3px; font-weight: bold; z-index: 2; } .pfs-p-img-box { width: 100%; aspect-ratio: 1/1; overflow: hidden; display: flex; align-items: center; justify-content: center; cursor: pointer; position: relative; background: #f9f9f9; } .pfs-p-img-box img { max-width: 100%; max-height: 100%; width: 100%; object-fit: cover; transition: 0.4s ease; } .pfs-p-card:hover .pfs-p-img-box img { transform: scale(1.05); } .pfs-p-info { padding: 12px; text-align: center; display: flex; flex-direction: column; justify-content: space-between; flex-grow: 1; } .pfs-p-name { font-size: 14px; margin-bottom: 6px; line-height: 1.4; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: <?php echo $lines; ?>; } .pfs-save-tag { align-self: center; margin-bottom: 8px; } /* Centered for Style 1 */ .pfs-p-price { font-size: 16px; font-weight: 700; color: var(--pfs-primary); margin-bottom: 10px; } .pfs-p-price del { color: #999; font-size: 13px; font-weight: 400; margin-left: 5px; } .pfs-btn-order { width: 100%; background: var(--pfs-primary); color: white; border: none; padding: 9px; font-weight: 600; cursor: pointer; border-radius: 4px; transition: 0.2s; font-family: inherit; } /* --- STYLE 2 (Elegant/Fabrilife Cart System) --- */ .pfs2-card { background: #fff; border: 1px solid #e2e8f0; border-radius: 8px; overflow: hidden; display: flex; flex-direction: column; position: relative; height: 100%; transition: all 0.2s ease; font-family: 'Segoe UI', sans-serif; } .pfs2-card:hover { border-color: #cbd5e1; box-shadow: 0 4px 12px rgba(0,0,0,0.08); } .pfs2-img-box { position: relative; width: 100%; background: #f1f2f4; aspect-ratio: 1/1; overflow: hidden; cursor: pointer; display: flex; align-items: center; justify-content: center; } .pfs2-img-box img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.4s ease; } .pfs2-badge-percent { position: absolute; top: 12px; left: 12px; background: var(--pfs-badge-color); color: #fff; font-size: 11px; font-weight: 700; padding: 4px 8px; border-radius: 4px; z-index: 2; } .pfs2-wishlist-btn { position: absolute; top: 12px; right: 12px; background: #fff; width: 32px; height: 32px; border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 5px rgba(0,0,0,0.1); z-index: 2; cursor: pointer; color: #94a3b8; font-size: 16px; transition: 0.2s; text-decoration: none; border: none; outline: none; } .pfs2-wishlist-btn:hover { color: var(--pfs-primary); transform: scale(1.05); } .pfs2-info { padding: 15px; display: flex; flex-direction: column; flex-grow: 1; } .pfs2-title { font-size: 14px; font-weight: 600; color: #1e293b; margin: 0 0 8px 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: <?php echo $lines; ?>; -webkit-box-orient: vertical; overflow: hidden; text-align: left; } .pfs2-title a { color: inherit; text-decoration: none; } .pfs2-save-tag { align-self: flex-start; margin-bottom: 2px; } .pfs2-bottom { display: flex; align-items: center; justify-content: space-between; margin-top: auto; } .pfs2-price-wrap { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; } .pfs2-price-current { font-size: 15px; font-weight: 800; color: var(--pfs-primary); } .pfs2-price-old { font-size: 12px; font-weight: 500; color: #94a3b8; text-decoration: line-through; } /* 🔥 THE STRICTEST CART BUTTON CSS (Overriding any Theme CSS) 🔥 */ .woocommerce ul.products li.product .pfs2-cart-btn, .woocommerce-page ul.products li.product .pfs2-cart-btn, .pfs2-cart-btn { width: 36px !important; height: 36px !important; min-width: 36px !important; min-height: 36px !important; border-radius: 50% !important; background-color: var(--pfs-primary) !important; color: #fff !important; display: flex !important; align-items: center !important; justify-content: center !important; border: none !important; cursor: pointer !important; transition: all 0.2s ease !important; text-decoration: none !important; padding: 0 !important; margin: 0 !important; box-sizing: border-box !important; line-height: 1 !important; outline: none !important; box-shadow: none !important; } .woocommerce ul.products li.product .pfs2-cart-btn:hover, .woocommerce-page ul.products li.product .pfs2-cart-btn:hover, .pfs2-cart-btn:hover { filter: brightness(0.9) !important; transform: scale(1.05) !important; color: #fff !important; } .woocommerce ul.products li.product .pfs2-cart-btn svg, .woocommerce-page ul.products li.product .pfs2-cart-btn svg, .pfs2-cart-btn svg { width: 16px !important; height: 16px !important; min-width: 16px !important; min-height: 16px !important; fill: currentColor !important; display: block !important; margin: 0 !important; padding: 0 !important; box-sizing: border-box !important; } .pfs2-cart-btn.loading { opacity: 0.7; pointer-events: none; animation: pulse 1s infinite; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(0.9); } 100% { transform: scale(1); } } /* Banners & Categories */ .advaxe-banner-wrapper { width: 100%; margin: 0 0 30px 0; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 15px rgba(0,0,0,0.06); } .advaxe-banner-img { width: 100%; height: auto; display: block; object-fit: cover; aspect-ratio: 21/9; } .pfs-section { margin-bottom: 40px; } .pfs-sec-header { display: flex; align-items: center; margin: 0 0 20px; position: relative; justify-content: space-between; } .pfs-title { font-size: 20px; color: #111; font-weight: 700; text-transform: uppercase; margin: 0; letter-spacing: 0.5px; } .pfs-view-btn { background: var(--pfs-primary); color: #fff; padding: 6px 14px; border-radius: 4px; text-decoration: none !important; font-size: 13px; font-weight: 600; transition: 0.2s; font-family: inherit; } .pfs-view-btn:hover { filter: brightness(0.9); } .pfs-header-center { justify-content: center; position: relative; } .pfs-header-center .pfs-view-btn { position: absolute; right: 0; top: 50%; transform: translateY(-50%); } .advaxeCatSwiper { padding: 10px 5px; } .advaxe-cat-slide { text-align: center; display: block; text-decoration: none !important; transition: transform 0.2s; } .advaxe-cat-slide:hover { transform: translateY(-3px); } .advaxe-cat-circle { width: 90px; height: 90px; border-radius: 50%; overflow: hidden; margin: 0 auto 10px; border: 2px solid var(--pfs-primary); background: #fff; padding: 0px; transition: border-color 0.3s; } .advaxe-cat-circle img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; } .advaxe-cat-name { font-size: 14px; color: #333; margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 600; } .swiper-pagination-bullet-active { background: var(--pfs-primary) !important; } /* Custom Modal / Popup for Variable Products */ .advaxe-modal { display: none; position: fixed; z-index: 999999; left: 0; top: 0; width: 100%; height: 100%; background-color: rgba(15, 23, 42, 0.6); backdrop-filter: blur(4px); } .advaxe-modal-content { background-color: #fff; margin: 5% auto; padding: 0; border: none; width: 90%; max-width: 400px; border-radius: 12px; position: relative; box-shadow: 0 20px 25px -5px rgba(0,0,0,0.1); animation: modalSlideIn 0.3s ease; overflow: hidden; font-family: 'Segoe UI', sans-serif; } @keyframes modalSlideIn { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } .advaxe-modal-header { background: var(--pfs-primary); color: white; padding: 15px 20px; display: flex; justify-content: space-between; align-items: center; font-weight: 600; } .advaxe-modal-close { color: #fff; font-size: 24px; font-weight: bold; cursor: pointer; line-height: 1; } .advaxe-modal-body { padding: 25px; text-align: center; } .adv-qv-img { width: 180px; height: 180px; object-fit: cover; border-radius: 8px; margin: 0 auto 15px; display: block; border: 1px solid #e2e8f0; } .adv-qv-title { font-size: 16px; font-weight: 700; color: #0f172a; margin-bottom: 5px; } .adv-qv-price-box { font-size: 18px; font-weight: 800; color: var(--pfs-primary); margin-bottom: 15px; } .adv-qv-price-box del { color: #94a3b8; font-size: 14px; font-weight: 500; margin-left: 6px; } .adv-qv-size-guide { display: block; font-size: 13px; color: #64748b; text-decoration: underline; margin-bottom: 20px; cursor: pointer; } .adv-qv-attr-title { font-size: 14px; font-weight: 600; color: #1e293b; margin-bottom: 12px; } .adv-qv-boxes { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin-bottom: 25px; } .adv-qv-box { display: inline-block; cursor: pointer; } .adv-qv-box input { display: none; } .adv-qv-box span { display: flex; align-items: center; justify-content: center; min-width: 44px; height: 44px; padding: 0 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 14px; font-weight: 600; color: #475569; transition: all 0.2s; } .adv-qv-box input:checked + span { background: var(--pfs-primary); color: #fff; border-color: var(--pfs-primary); } .adv-qv-box.adv-color-swatch input:checked + span { border-color: var(--pfs-primary); box-shadow: 0 0 0 2px #fff inset; } .adv-qv-submit { width: 100%; background: var(--pfs-primary); color: white; border: none; padding: 14px; border-radius: 8px; font-size: 16px; font-weight: 600; cursor: pointer; transition: 0.2s; filter: brightness(0.9); } .adv-qv-submit:hover { filter: brightness(1); } .adv-qv-submit:disabled { opacity: 0.7; cursor: not-allowed; } </style> <?php } function advaxe_shop_global_scripts() { ?> <div id="advaxe-quick-modal" class="advaxe-modal"> <div class="advaxe-modal-content"> <div class="advaxe-modal-header"> <span>Select Options</span> <span class="advaxe-modal-close">×</span> </div> <div id="advaxe-modal-body" class="advaxe-modal-body"> </div> </div> </div> <script> function directCheckout(pid) { window.location.href = '<?php echo wc_get_checkout_url(); ?>?add-to-cart=' + pid; } jQuery(document).ready(function($){ // Open Modal for Variable Products $(document).on('click', '.advaxe-var-btn', function(e){ e.preventDefault(); let pid = $(this).data('pid'); $('#advaxe-modal-body').html('<p style="padding: 40px 0; color: #64748b;">Loading options...</p>'); $('#advaxe-quick-modal').fadeIn(200); $.post('<?php echo admin_url('admin-ajax.php'); ?>', { action: 'advaxe_get_var_modal', pid: pid }, function(res){ $('#advaxe-modal-body').html(res); }); }); // Close Modal $('.advaxe-modal-close').click(function(){ $('#advaxe-quick-modal').fadeOut(200); }); $(window).click(function(e) { if ($(e.target).is('.advaxe-modal')) { $('#advaxe-quick-modal').fadeOut(200); } }); // Dynamically change price in modal based on variation $(document).on('change', '#advaxe-var-form input', function(){ var form = $('#advaxe-var-form'); var formData = form.serializeArray(); var selectedAttrs = {}; formData.forEach(function(item){ if(item.name.startsWith('attribute_')) selectedAttrs[item.name] = item.value; }); if(typeof advaxe_vars !== 'undefined') { var matched_v = null; for(var i=0; i<advaxe_vars.length; i++) { var v = advaxe_vars[i]; var match = true; for(var key in selectedAttrs) { if(v.attributes[key] !== undefined && v.attributes[key] !== '' && v.attributes[key] !== selectedAttrs[key]) { match = false; break; } } if(match) { matched_v = v; break; } } if(matched_v && matched_v.price_html) { $('#advaxe-modal-price').html(matched_v.price_html); } } }); // Handle Variable Form Submit inside Modal & Sync live cart $(document).on('submit', '#advaxe-var-form', function(e){ e.preventDefault(); var form = $(this); var pid = form.data('pid'); var btn = form.find('.adv-qv-submit'); var formData = form.serializeArray(); var selectedAttrs = {}; formData.forEach(function(item){ if(item.name.startsWith('attribute_')) selectedAttrs[item.name] = item.value; }); var var_id = 0; if(typeof advaxe_vars !== 'undefined') { for(var i=0; i<advaxe_vars.length; i++) { var v = advaxe_vars[i]; var match = true; for(var key in selectedAttrs) { if(v.attributes[key] !== undefined && v.attributes[key] !== '' && v.attributes[key] !== selectedAttrs[key]) { match = false; break; } } if(match) { var_id = v.variation_id; break; } } } if(!var_id) { alert('Please select all required options.'); return; } var ajaxData = { 'add-to-cart': pid, 'variation_id': var_id, 'quantity': 1 }; for(var key in selectedAttrs) { ajaxData[key] = selectedAttrs[key]; } btn.text('Adding...').prop('disabled', true); var ajax_url = typeof wc_add_to_cart_params !== 'undefined' ? wc_add_to_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'add_to_cart' ) : '/?wc-ajax=add_to_cart'; $.post(ajax_url, ajaxData, function(response) { if ( response.error && response.product_url ) { window.location = response.product_url; return; } // Trigger standard WooCommerce events to update cart instantly $(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash, form]); $(document.body).trigger('wc_fragment_refresh'); $('#advaxe-quick-modal').fadeOut(200); }); }); // Wishlist Heart Icon Action $(document).on('click', '.pfs2-wishlist-btn', function(e){ if(!$(this).hasClass('add_to_wishlist')) { e.preventDefault(); alert('Please install YITH Wishlist plugin to use this feature.'); } }); }); </script> <?php } // ============================================================== // ৭. AJAX HANDLER: VARIABLE PRODUCT MODAL // ============================================================== add_action('wp_ajax_advaxe_get_var_modal', 'advaxe_get_var_modal_callback'); add_action('wp_ajax_nopriv_advaxe_get_var_modal', 'advaxe_get_var_modal_callback'); function advaxe_get_var_modal_callback() { $product_id = intval($_POST['pid']); $product = wc_get_product($product_id); if(!$product || !$product->is_type('variable')) wp_die(); $img = wp_get_attachment_image_url($product->get_image_id(), 'medium') ?: wc_placeholder_img_src(); $title = $product->get_name(); $attributes = $product->get_variation_attributes(); $variations = $product->get_available_variations(); echo '<img src="'.esc_url($img).'" class="adv-qv-img">'; echo '<div class="adv-qv-title">'.esc_html($title).'</div>'; // Dynamic price container echo '<div class="adv-qv-price-box" id="advaxe-modal-price">'.$product->get_price_html().'</div>'; echo '<form id="advaxe-var-form" data-pid="'.$product_id.'">'; foreach($attributes as $attr => $options) { $label = wc_attribute_label($attr); // Check if attribute is a color swatch $is_color = (strpos(strtolower($attr), 'color') !== false || strpos(strtolower($label), 'color') !== false || strpos(strtolower($label), 'রঙ') !== false); echo '<div class="adv-qv-attr-title">Choose '.$label.'</div>'; echo '<div class="adv-qv-boxes">'; foreach($options as $opt) { $term = get_term_by('slug', $opt, $attr); $name = $term ? $term->name : $opt; if ($is_color) { // Determine color code $hex = $term ? get_term_meta($term->term_id, 'color', true) : ''; if(empty($hex) && $term) $hex = get_term_meta($term->term_id, 'product_attribute_color', true); if(empty($hex)) $hex = strtolower($name); // fallback css valid color like 'red' echo '<label class="adv-qv-box adv-color-swatch" title="'.esc_attr($name).'"><input type="radio" name="attribute_'.$attr.'" value="'.esc_attr($opt).'" required> <span style="background-color: '.esc_attr($hex).'; width: 34px; height: 34px; min-width: 34px; padding: 0; border-radius: 50%; color: transparent; text-indent: -9999px; overflow: hidden; border: 2px solid #cbd5e1;">'.esc_html($name).'</span></label>'; } else { echo '<label class="adv-qv-box"><input type="radio" name="attribute_'.$attr.'" value="'.esc_attr($opt).'" required> <span>'.esc_html($name).'</span></label>'; } } echo '</div>'; } echo '<button type="submit" class="adv-qv-submit">Add to Cart</button>'; echo '</form>'; // Pass variations to JS echo '<script>var advaxe_vars = '.json_encode($variations).';</script>'; wp_die(); } // ============================================================== // ৮. TEMPLATE LOGIC (Card Injection & Wrappers) // ============================================================== add_action('woocommerce_before_main_content', function(){ echo '<div class="advaxe-global-wrapper">'; }, 1); add_action('woocommerce_after_main_content', function(){ echo '</div>'; }, 999); add_action('woocommerce_init', 'advaxe_override_loop'); function advaxe_override_loop() { remove_action( 'woocommerce_before_shop_loop_item', 'woocommerce_template_loop_product_link_open', 10 ); remove_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_show_product_loop_sale_flash', 10 ); remove_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 ); remove_action( 'woocommerce_shop_loop_item_title', 'woocommerce_template_loop_product_title', 10 ); remove_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_rating', 5 ); remove_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_price', 10 ); remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_product_link_close', 5 ); remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 ); add_action( 'woocommerce_before_shop_loop_item', 'advaxe_render_card' ); } function advaxe_render_card() { global $product; if( ! $product ) return; $style = get_option('advaxe_grid_style', 'style-1'); $show_save_badge = get_option('advaxe_show_save_badge', 1); // --- Variable Product Price & Discount Range Logic --- $reg = 0; $curr = 0; $price_display = ''; $old_price_display = ''; if ( $product->is_type( 'variable' ) ) { $prices = $product->get_variation_prices(); if ( ! empty( $prices['price'] ) ) { asort($prices['price']); // Sort by current price ascending $min_var_id = key($prices['price']); $min_price = current($prices['price']); $max_price = end($prices['price']); // Get original/regular price corresponding to the minimum variation $min_reg_price = isset($prices['regular_price'][$min_var_id]) ? $prices['regular_price'][$min_var_id] : $min_price; $reg = floatval($min_reg_price); $curr = floatval($min_price); if ( $min_price != $max_price ) { $price_display = '৳' . $min_price . ' - ৳' . $max_price; } else { $price_display = '৳' . $min_price; } $old_price_display = '৳' . $reg; } else { $reg = floatval($product->get_regular_price()); $curr = floatval($product->get_price()); $price_display = '৳' . $curr; $old_price_display = '৳' . $reg; } } else { $reg = floatval($product->get_regular_price()); $curr = floatval($product->get_price()); $price_display = '৳' . $curr; $old_price_display = '৳' . $reg; } $disc = ($reg > 0 && $reg > $curr) ? round((($reg - $curr) / $reg) * 100) : 0; $save_amt = ($reg > 0 && $reg > $curr) ? ($reg - $curr) : 0; $img = wp_get_attachment_image_url($product->get_image_id(), 'woocommerce_thumbnail') ?: wc_placeholder_img_src(); $lines = get_option('advaxe_title_lines', 2); $type = $product->get_type(); $pid = $product->get_id(); $link = esc_url(get_permalink()); $title = $product->get_name(); // Wishlist Shortcode logic $wishlist_html = shortcode_exists('yith_wcwl_add_to_wishlist') ? do_shortcode('[yith_wcwl_add_to_wishlist product_id="'.$pid.'"]') : '<a href="#" class="pfs2-wishlist-btn add_to_wishlist" data-product_id="'.$pid.'">♥</a>'; if ($style == 'style-2') { // --- STYLE 2 HTML --- ?> <div class="pfs2-card"> <div class="pfs2-img-box" onclick="window.location.href='<?php echo $link; ?>'"> <?php if($disc > 0): ?><div class="pfs2-badge-percent">-<?php echo $disc; ?>%</div><?php endif; ?> <?php echo $wishlist_html; ?> <img src="<?php echo esc_url($img); ?>"> </div> <div class="pfs2-info"> <div class="pfs2-title"><a href="<?php echo $link; ?>"><?php echo $title; ?></a></div> <?php if($show_save_badge && $save_amt > 0): ?> <div class="pfs2-save-tag"><svg viewBox="0 0 24 24"><path d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.41l9 9c.36.36.86.59 1.41.59s1.05-.22 1.41-.59l7-7c.36-.36.59-.86.59-1.41s-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/></svg> Save ৳<?php echo $save_amt; ?></div> <?php endif; ?> <div class="pfs2-bottom"> <div class="pfs2-price-wrap"> <span class="pfs2-price-current"><?php echo $price_display; ?></span> <?php if($disc > 0): ?><span class="pfs2-price-old"><?php echo $old_price_display; ?></span><?php endif; ?> </div> <?php if($type == 'variable'): ?> <a href="#" class="pfs2-cart-btn advaxe-var-btn" data-pid="<?php echo $pid; ?>" title="Select Options"> <svg viewBox="0 0 24 24"><path d="M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zM1 2v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.58-6.49c.08-.14.12-.31.12-.48 0-.55-.45-1-1-1H5.21l-.94-2H1zm16 16c-1.1 0-1.99.9-1.99 2s.89 2 1.99 2 2-.9 2-2-.9-2-2-2z"/></svg> </a> <?php else: ?> <a href="?add-to-cart=<?php echo $pid; ?>" data-quantity="1" class="pfs2-cart-btn add_to_cart_button ajax_add_to_cart" data-product_id="<?php echo $pid; ?>" aria-label="Add to cart" rel="nofollow"> <svg viewBox="0 0 24 24"><path d="M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zM1 2v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.58-6.49c.08-.14.12-.31.12-.48 0-.55-.45-1-1-1H5.21l-.94-2H1zm16 16c-1.1 0-1.99.9-1.99 2s.89 2 1.99 2 2-.9 2-2-.9-2-2-2z"/></svg> </a> <?php endif; ?> </div> </div> </div> <?php } else { // --- STYLE 1 HTML --- ?> <div class="pfs-p-card"> <?php if($disc > 0): ?><div class="pfs-badge">-<?php echo $disc; ?>%</div><?php endif; ?> <div class="pfs-p-img-box" onclick="window.location.href='<?php echo $link; ?>'"> <img src="<?php echo esc_url($img); ?>"> </div> <div class="pfs-p-info"> <div class="pfs-p-name"><a href="<?php echo $link; ?>" style="text-decoration:none; color:inherit;"><?php echo $title; ?></a></div> <?php if($show_save_badge && $save_amt > 0): ?> <div class="pfs-save-tag"><svg viewBox="0 0 24 24"><path d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.41l9 9c.36.36.86.59 1.41.59s1.05-.22 1.41-.59l7-7c.36-.36.59-.86.59-1.41s-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/></svg> Save ৳<?php echo $save_amt; ?></div> <?php endif; ?> <div class="pfs-p-price"><?php echo $price_display; ?> <?php if($disc > 0) echo '<del>' . $old_price_display . '</del>'; ?></div> <button class="pfs-btn-order" onclick="directCheckout(<?php echo $pid; ?>)">Order Now</button> </div> </div> <?php } } // ============================================================== // ৯. SHORTCODE: [ultimate_shop] // ============================================================== add_shortcode('ultimate_shop', 'advaxe_home_shortcode'); function advaxe_home_shortcode() { if ( ! class_exists( 'WooCommerce' ) ) return ''; $style = get_option('advaxe_grid_style', 'style-1'); $show_save_badge = get_option('advaxe_show_save_badge', 1); $banner_ids = explode(',', get_option('advaxe_banner_ids', '')); $banners = []; foreach($banner_ids as $id) { if($u = wp_get_attachment_image_url($id, 'full')) $banners[] = $u; } if(empty($banners)) $banners[] = 'https://via.placeholder.com/1200x400?text=Welcome+to+Shop'; $cats = get_terms(['taxonomy'=>'product_cat', 'hide_empty'=>true]); $cat_list = []; foreach($cats as $c) { $thumb = wp_get_attachment_url(get_term_meta($c->term_id, 'thumbnail_id', true)) ?: wc_placeholder_img_src(); $cat_list[] = ['name'=>$c->name, 'img'=>$thumb, 'link'=>get_term_link($c)]; } $sections = get_option('advaxe_home_sections', []); $sec_data = []; $g_m = get_option('advaxe_def_col_mobile', 2); $g_d = get_option('advaxe_def_col_desktop', 4); foreach($sections as $k => $s) { if(!isset($s['visible']) || !$s['visible']) continue; $limit = (!empty($s['limit'])) ? intval($s['limit']) : 8; $args = ['limit'=>$limit, 'status'=>'publish', 'visibility'=>'visible']; if($s['type'] == 'latest') { $args['orderby']='date'; $args['order']='DESC'; } elseif($s['type'] == 'category' && $s['source_id']) { $args['category'] = [get_term($s['source_id'])->slug]; } elseif($s['type'] == 'tag' && $s['source_id']) { $args['tag'] = [get_term($s['source_id'])->slug]; } elseif($s['type'] == 'custom' && $s['source_id']) { $args['include'] = array_map('intval', explode(',', $s['source_id'])); $args['orderby']='post__in'; } $prods = wc_get_products($args); if(empty($prods)) continue; $url = '#'; if($s['show_btn']) { if($s['btn_url_type'] == 'custom') $url = $s['custom_url']; else { if($s['type']=='category' && $s['source_id']) $url = get_term_link((int)$s['source_id'], 'product_cat'); elseif($s['type']=='tag' && $s['source_id']) $url = get_term_link((int)$s['source_id'], 'product_tag'); else $url = get_permalink(wc_get_page_id('shop')); } } $p_list = []; foreach($prods as $p) { // --- Variable Product Price Fix for Shortcode --- $reg = 0; $curr = 0; $price_display = ''; $old_price_display = ''; if ( $p->is_type( 'variable' ) ) { $prices = $p->get_variation_prices(); if ( ! empty( $prices['price'] ) ) { asort($prices['price']); $min_var_id = key($prices['price']); $min_price = current($prices['price']); $max_price = end($prices['price']); $min_reg_price = isset($prices['regular_price'][$min_var_id]) ? $prices['regular_price'][$min_var_id] : $min_price; $reg = floatval($min_reg_price); $curr = floatval($min_price); if ( $min_price != $max_price ) { $price_display = '৳' . $min_price . ' - ৳' . $max_price; } else { $price_display = '৳' . $min_price; } $old_price_display = '৳' . $reg; } else { $reg = floatval($p->get_regular_price()); $curr = floatval($p->get_price()); $price_display = '৳' . $curr; $old_price_display = '৳' . $reg; } } else { $reg = floatval($p->get_regular_price()); $curr = floatval($p->get_price()); $price_display = '৳' . $curr; $old_price_display = '৳' . $reg; } $disc = ($reg > 0 && $reg > $curr) ? round((($reg - $curr) / $reg) * 100) : 0; $save_amt = ($reg > 0 && $reg > $curr) ? ($reg - $curr) : 0; $pid = $p->get_id(); // Generate standard wishlist button string for JS injection $wish = shortcode_exists('yith_wcwl_add_to_wishlist') ? do_shortcode('[yith_wcwl_add_to_wishlist product_id="'.$pid.'"]') : '<a href="#" class="pfs2-wishlist-btn add_to_wishlist" data-product_id="'.$pid.'">♥</a>'; $p_list[] = [ 'id'=>$pid, 'name'=>$p->get_name(), 'price_display'=>$price_display, 'old_price_display'=>$old_price_display, 'save'=>$save_amt, 'type'=>$p->get_type(), 'wishlist'=>$wish, 'img'=>wp_get_attachment_image_url($p->get_image_id(),'woocommerce_thumbnail')?:wc_placeholder_img_src(), 'disc'=>$disc, 'link'=>get_permalink($p->get_id()) ]; } $col_m = !empty($s['col_mobile']) ? $s['col_mobile'] : $g_m; $col_d = !empty($s['col_desktop']) ? $s['col_desktop'] : $g_d; $sec_data[] = [ 'title'=>$s['title'], 'align'=>isset($s['align'])?$s['align']:'center', 'btn'=>isset($s['show_btn'])?$s['show_btn']:0, 'url'=>$url, 'prods'=>$p_list, 'id'=>$k, 'col_m' => $col_m, 'col_d' => $col_d ]; } wp_enqueue_style('swiper-css', 'https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css'); wp_enqueue_script('swiper-js', 'https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js', [], null, true); ob_start(); ?> <div class="advaxe-global-wrapper"> <div class="advaxe-banner-wrapper"> <div class="swiper advaxeBanner"><div class="swiper-wrapper"> <?php foreach($banners as $b): ?><div class="swiper-slide"><img src="<?php echo $b; ?>" class="advaxe-banner-img"></div><?php endforeach; ?> </div><div class="swiper-pagination"></div></div> </div> <div class="pfs-section"> <div class="pfs-sec-header pfs-header-center"> <h2 class="pfs-title">Categories</h2> </div> <div class="swiper advaxeCat"><div class="swiper-wrapper"> <?php foreach($cat_list as $c): ?> <a href="<?php echo $c['link']; ?>" class="swiper-slide advaxe-cat-slide"> <div class="advaxe-cat-circle"><img src="<?php echo $c['img']; ?>"></div> <p class="advaxe-cat-name"><?php echo $c['name']; ?></p> </a> <?php endforeach; ?> </div></div> </div> <?php foreach($sec_data as $sec): ?> <div class="pfs-section"> <div class="pfs-sec-header <?php echo ($sec['align']=='left')?'pfs-header-left':'pfs-header-center'; ?>"> <h2 class="pfs-title"><?php echo $sec['title']; ?></h2> <?php if($sec['btn']): ?><a href="<?php echo $sec['url']; ?>" class="pfs-view-btn">View All</a><?php endif; ?> </div> <div class="pfs-product-grid" id="pfs-s-<?php echo $sec['id']; ?>" style="--sec-grid-m: <?php echo $sec['col_m']; ?>; --sec-grid-d: <?php echo $sec['col_d']; ?>;"></div> </div> <?php endforeach; ?> </div> <script> document.addEventListener('DOMContentLoaded', () => { new Swiper(".advaxeBanner", { autoplay:{delay:3500}, loop:true, pagination:{el:".swiper-pagination"} }); new Swiper(".advaxeCat", { slidesPerView:3.5, spaceBetween:8, centerInsufficientSlides:true, breakpoints:{640:{slidesPerView:4.5}, 1024:{slidesPerView:7.5}} }); const secs = <?php echo json_encode($sec_data); ?>; const style = '<?php echo $style; ?>'; const showSaveBadge = <?php echo $show_save_badge ? 'true' : 'false'; ?>; secs.forEach(s => { let h = ''; s.prods.forEach(p => { if(style === 'style-2') { let btnHtml = p.type === 'variable' ? `<a href="#" class="pfs2-cart-btn advaxe-var-btn" data-pid="${p.id}" title="Select Options"><svg viewBox="0 0 24 24"><path d="M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zM1 2v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.58-6.49c.08-.14.12-.31.12-.48 0-.55-.45-1-1-1H5.21l-.94-2H1zm16 16c-1.1 0-1.99.9-1.99 2s.89 2 1.99 2 2-.9 2-2-.9-2-2-2z"/></svg></a>` : `<a href="?add-to-cart=${p.id}" data-quantity="1" class="pfs2-cart-btn add_to_cart_button ajax_add_to_cart" data-product_id="${p.id}"><svg viewBox="0 0 24 24"><path d="M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zM1 2v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.58-6.49c.08-.14.12-.31.12-.48 0-.55-.45-1-1-1H5.21l-.94-2H1zm16 16c-1.1 0-1.99.9-1.99 2s.89 2 1.99 2 2-.9 2-2-.9-2-2-2z"/></svg></a>`; h += `<div class="pfs2-card"> <div class="pfs2-img-box" onclick="window.location.href='${p.link}'"> ${p.disc>0 ? `<div class="pfs2-badge-percent">-${p.disc}%</div>` : ''} ${p.wishlist} <img src="${p.img}"> </div> <div class="pfs2-info"> <div class="pfs2-title"><a href="${p.link}">${p.name}</a></div> ${(showSaveBadge && p.save > 0) ? `<div class="pfs2-save-tag"><svg viewBox="0 0 24 24"><path d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.41l9 9c.36.36.86.59 1.41.59s1.05-.22 1.41-.59l7-7c.36-.36.59-.86.59-1.41s-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/></svg> Save ৳${p.save}</div>` : ''} <div class="pfs2-bottom"> <div class="pfs2-price-wrap"> <span class="pfs2-price-current">${p.price_display}</span> ${p.disc > 0 ? `<span class="pfs2-price-old">${p.old_price_display}</span>` : ''} </div> ${btnHtml} </div> </div> </div>`; } else { h += `<div class="pfs-p-card"> ${p.disc>0 ? `<div class="pfs-badge">-${p.disc}%</div>` : ''} <div class="pfs-p-img-box" onclick="window.location.href='${p.link}'"><img src="${p.img}"></div> <div class="pfs-p-info"> <div class="pfs-p-name"><a href="${p.link}" style="text-decoration:none; color:inherit;">${p.name}</a></div> ${(showSaveBadge && p.save > 0) ? `<div class="pfs-save-tag"><svg viewBox="0 0 24 24"><path d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.41l9 9c.36.36.86.59 1.41.59s1.05-.22 1.41-.59l7-7c.36-.36.59-.86.59-1.41s-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/></svg> Save ৳${p.save}</div>` : ''} <div class="pfs-p-price">${p.price_display} ${p.disc > 0 ? `<del>${p.old_price_display}</del>` : ''}</div> <button class="pfs-btn-order" onclick="directCheckout(${p.id})">Order Now</button> </div> </div>`; } }); document.getElementById('pfs-s-'+s.id).innerHTML = h; }); }); </script> <?php return ob_get_clean(); } ?>