JezK
Edit File: advaxe-single-product.php
<?php /* Plugin Name: Advaxe Single Product Suite Description: Custom Layout, Advanced Swatches, Top AJAX Popup & Perfect Cart Sync (Fixed Double Cart Core Conflict). Version: 2.5 Author: Advaxe License: GPLv2 or later */ if ( ! defined( 'ABSPATH' ) ) exit; // ============================================================== // ১. এডমিন মেনু এবং সেটিংস // ============================================================== add_action('admin_menu', 'advaxe_single_plugin_menu'); function advaxe_single_plugin_menu() { add_menu_page('Single Product Settings', 'Single Product', 'manage_options', 'advaxe-single-product', 'advaxe_single_settings_page', 'dashicons-products', 7); } function advaxe_single_settings_page() { if (isset($_POST['advaxe_save_single_settings'])) { if(isset($_POST['rel_prod_count'])) update_option('advaxe_rel_prod_count', intval($_POST['rel_prod_count'])); if(isset($_POST['contact_phone'])) update_option('advaxe_contact_phone', sanitize_text_field($_POST['contact_phone'])); if(isset($_POST['contact_whatsapp'])) update_option('advaxe_contact_whatsapp', sanitize_text_field($_POST['contact_whatsapp'])); if(isset($_POST['contact_card_style'])) update_option('advaxe_contact_card_style', sanitize_text_field($_POST['contact_card_style'])); if(isset($_POST['color_attrs'])) update_option('advaxe_color_attrs', sanitize_text_field($_POST['color_attrs'])); if(isset($_POST['text_attrs'])) update_option('advaxe_text_attrs', sanitize_text_field($_POST['text_attrs'])); if(isset($_POST['custom_colors'])) update_option('advaxe_custom_colors', sanitize_textarea_field($_POST['custom_colors'])); echo '<div class="updated"><p>Single Product Settings Saved!</p></div>'; } $saved_rel_limit = get_option('advaxe_rel_prod_count', 4); $saved_phone = get_option('advaxe_contact_phone', '01824222653'); $saved_whatsapp = get_option('advaxe_contact_whatsapp', '01814802802'); $saved_card_style = get_option('advaxe_contact_card_style', 'style-1'); $saved_color_attrs = get_option('advaxe_color_attrs', 'color, colour, রং'); $saved_text_attrs = get_option('advaxe_text_attrs', 'size, dimension'); $saved_custom_colors = get_option('advaxe_custom_colors', ''); ?> <div class="wrap"> <h1>Single Product Settings</h1> <form method="post"> <table class="form-table"> <tr> <th scope="row">Related Products Count</th> <td><input type="number" name="rel_prod_count" value="<?php echo esc_attr($saved_rel_limit); ?>" min="2" max="12" step="1"></td> </tr> <tr> <th scope="row">Contact Numbers</th> <td> <label>Phone: <input type="text" name="contact_phone" value="<?php echo esc_attr($saved_phone); ?>"></label><br><br> <label>WhatsApp: <input type="text" name="contact_whatsapp" value="<?php echo esc_attr($saved_whatsapp); ?>"></label> </td> </tr> <tr> <th scope="row">Contact Cards Style</th> <td> <select name="contact_card_style"> <option value="style-1" <?php selected($saved_card_style, 'style-1'); ?>>Style 1 (White Background)</option> <option value="style-2" <?php selected($saved_card_style, 'style-2'); ?>>Style 2 (Premium Colored Cards)</option> </select> <p class="description">Choose the design layout for the Call and WhatsApp cards.</p> </td> </tr> <tr><td colspan="2"><hr><h2>Advanced Swatches Settings</h2></td></tr> <tr> <th scope="row">Color Swatch Attributes</th> <td> <input type="text" name="color_attrs" value="<?php echo esc_attr($saved_color_attrs); ?>" style="width:100%; max-width: 400px;"> <p class="description">Comma-separated list of attributes that should show as <strong>Color Circles</strong>.</p> </td> </tr> <tr> <th scope="row">Text Swatch Attributes</th> <td> <input type="text" name="text_attrs" value="<?php echo esc_attr($saved_text_attrs); ?>" style="width:100%; max-width: 400px;"> <p class="description">Comma-separated list of attributes that should show as <strong>Text Boxes</strong>.</p> </td> </tr> <tr> <th scope="row">Custom Colors Mapping</th> <td> <textarea name="custom_colors" rows="6" style="width:100%; max-width: 400px;"><?php echo esc_textarea($saved_custom_colors); ?></textarea> <p class="description">Set specific hex colors. <strong>Format:</strong> <code>Term Name : #HexCode</code></p> </td> </tr> </table> <p><input type="submit" name="advaxe_save_single_settings" class="button button-primary" value="Save Changes"></p> </form> </div> <?php } // ============================================================== // ২. স্টাইল এবং স্ক্রিপ্ট // ============================================================== add_action('wp_head', 'advaxe_single_global_styles'); add_action('wp_footer', 'advaxe_single_global_scripts'); function advaxe_single_global_styles() { ?> <link rel="stylesheet" href="<?php echo includes_url('css/dashicons.min.css'); ?>"> <style> :root { --pfs-primary: #00796b; } /* Hide Defaults completely */ .onsale { display: none !important; } .single-product .woocommerce-notices-wrapper { display: none !important; } .single-product .added_to_cart { display: none !important; } /* Structure */ .single-product div.product { display: flex; flex-wrap: wrap; justify-content: space-between; position: relative; } .single-product div.product .advaxe-sp-gallery-wrapper { width: 100%; margin-bottom: 20px; } .single-product div.product div.summary { width: 100%; margin-bottom: 20px; padding-left: 0; } .woocommerce-tabs, .related.products { width: 100% !important; clear: both; } @media (min-width: 768px) { .single-product div.product .advaxe-sp-gallery-wrapper, .single-product div.product div.summary { width: 48%; flex: 0 0 48%; } .single-product div.product div.summary { display: flex; flex-direction: column; } } .advaxe-sp-gallery-wrapper { box-sizing: border-box; } /* Updated Image Wrap Design */ .advaxe-main-img-wrap { width: 100%; aspect-ratio: 1/1 !important; border-radius: 8px; overflow: hidden; border: 1px solid #eee !important; display: flex; align-items: center; justify-content: center; margin-bottom: 10px; background: #ffffff; } @media (min-width: 768px) { .advaxe-main-img-wrap { margin-bottom: 15px; } } .advaxe-main-img { width: 100%; height: 100%; object-fit: contain; } .advaxe-gallery-strip { display: flex; gap: 10px; overflow-x: auto; padding-bottom: 5px; } .advaxe-gallery-strip::-webkit-scrollbar { height: 4px; } .advaxe-gallery-strip::-webkit-scrollbar-thumb { background: #ccc; border-radius: 2px; } .advaxe-g-item { flex: 0 0 calc(20% - 8px); aspect-ratio: 1/1; border: 1px solid #ddd; border-radius: 4px; cursor: pointer; overflow: hidden; } .advaxe-g-item img { width: 100%; height: 100%; object-fit: cover; pointer-events: none; } .advaxe-g-item.active-thumb { border-color: var(--pfs-primary); border-width: 2px; } .advaxe-single-title { font-size: 22px; margin-top: 0; margin-bottom: 5px; color: #333; line-height: 1.3; } .advaxe-single-price { font-size: 24px; font-weight: 700; color: var(--pfs-primary); margin-bottom: 15px; display: block; } .advaxe-single-price del { font-size: 16px; color: #999; font-weight: 400; margin-left: 8px; } .woocommerce-product-details__short-description { margin-bottom: 25px; color: #555; line-height: 1.6; } /* CART LAYOUT */ .single-product div.product form.cart::after, .single-product div.product form.cart::before { display: none !important; content: none !important; } .single-product div.product form.cart { width: 100% !important; margin-bottom: 20px !important; } .single-product div.product form.variations_form { display: block !important; } .single-product table.variations { width: 100% !important; margin-bottom: 15px; border: none; } .single-product table.variations tbody, .single-product table.variations tr, .single-product table.variations td, .single-product table.variations th { display: block; border: none; background: transparent !important; padding: 0;} .single-product table.variations th { text-align: left; padding-bottom: 5px; font-weight: 600; color: #333; margin-top: 10px; } .single-product .reset_variations { display: none !important; } .advaxe-swatches { display: flex; flex-wrap: wrap; gap: 8px; } .advaxe-swatch-item { display: inline-flex; align-items: center; justify-content: center; border: 2px solid #ddd; border-radius: 4px; cursor: pointer; padding: 5px 15px; font-size: 14px; background: #fff; color: #333; transition: all 0.2s; min-height: 35px; min-width: 40px; box-sizing: border-box; user-select: none; } .advaxe-swatch-item:hover { border-color: #aaa; } .advaxe-swatch-item.selected { border-color: var(--pfs-primary); background: var(--pfs-primary); color: #fff; } .advaxe-swatch-item.swatch-color { border-radius: 50%; padding: 0; width: 35px; height: 35px; min-width: 35px; overflow: hidden; position: relative; border: 2px solid #ddd; } .advaxe-swatch-item.swatch-color.selected { border-color: #333; box-shadow: 0 0 0 2px #fff inset; } .single-product div.product form.cart:not(.variations_form), .single-product div.product .woocommerce-variation-add-to-cart { display: flex !important; flex-direction: row !important; flex-wrap: nowrap !important; gap: 10px !important; width: 100% !important; max-width: 100% !important; align-items: stretch !important; margin-top: 15px !important; padding: 0 !important; clear: both !important; box-sizing: border-box !important; } .single-product div.product form.cart .quantity { flex: 0 0 130px !important; width: 130px !important; max-width: 130px !important; margin: 0 !important; padding: 0 !important; display: flex !important; float: none !important; } .single-product .quantity input.qty::-webkit-outer-spin-button, .single-product .quantity input.qty::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; } .single-product .quantity input.qty { width: 100% !important; height: 45px !important; border-top: 1px solid var(--pfs-primary) !important; border-bottom: 1px solid var(--pfs-primary) !important; border-left: none !important; border-right: none !important; color: var(--pfs-primary) !important; border-radius: 0 !important; text-align: center !important; font-weight: bold !important; padding: 0 !important; background: #fff !important; box-shadow: none !important; min-height: 45px !important; } .advaxe-qty-btn { display: flex; align-items: center; justify-content: center; width: 45px; height: 45px; background: #fff; color: var(--pfs-primary); border: 1px solid var(--pfs-primary); font-size: 18px; font-weight: bold; cursor: pointer; user-select: none; } .advaxe-qty-btn.minus { border-radius: 4px 0 0 4px; border-right: none; } .advaxe-qty-btn.plus { border-radius: 0 4px 4px 0; border-left: none; } .single-product div.product form.cart button.single_add_to_cart_button { flex: 1 1 auto !important; width: 100% !important; max-width: 100% !important; height: 45px !important; min-height: 45px !important; background: #fff !important; color: var(--pfs-primary) !important; border: 1px solid var(--pfs-primary) !important; border-radius: 4px !important; font-weight: 600 !important; display: flex !important; align-items: center !important; justify-content: center !important; gap: 5px !important; margin: 0 !important; padding: 0 10px !important; float: none !important; clear: none !important; } .single-product button.single_add_to_cart_button::before { content: "\f174"; font-family: dashicons; font-size: 18px; } .single-product button.single_add_to_cart_button:hover { background: #f9f9f9 !important; } .single-product button.single_add_to_cart_button.loading { opacity: 0.6; cursor: not-allowed; } .advaxe-direct-order-btn { width: 100%; background: var(--pfs-primary); color: #fff; border: none; padding: 12px; font-size: 16px; font-weight: bold; text-align: center; border-radius: 4px; cursor: pointer; display: block; margin-bottom: 15px; text-decoration: none; transition: 0.3s; box-sizing: border-box; } .advaxe-direct-order-btn:hover { background: #004d40; color: #fff; } /* ============================================================== */ /* PREMIUM CONTACT CARDS (Call & WhatsApp) */ /* ============================================================== */ .advaxe-contact-grid { display: flex; gap: 15px; width: 100%; margin-bottom: 5px; margin-top: 10px; } .advaxe-contact-card { flex: 1; border-radius: 12px; padding: 10px 5px; display: flex; align-items: center; gap: 12px; transition: all 0.3s ease; position: relative; overflow: hidden; text-decoration: none !important; } .advaxe-contact-card:hover { transform: translateY(-3px); box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -2px rgba(0, 0, 0, 0.04); } .advaxe-c-icon { width: 45px; height: 45px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 24px; flex-shrink: 0; transition: all 0.3s ease; } .advaxe-c-text { display: flex; flex-direction: column; justify-content: center; } .advaxe-c-text h4 { margin: 0; font-size: 13px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; line-height: 1.2; margin-bottom: 2px; } .advaxe-c-text p { margin: 0; font-size: 12px; font-weight: 700; line-height: 1.2; } /* --- Style 1: White Cards --- */ .advaxe-contact-card.style-1 { background: #fff; border: 1px solid #e2e8f0; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.03); } .advaxe-contact-card.style-1:hover { border-color: #cbd5e1; } .advaxe-contact-card.style-1 .advaxe-c-text h4 { color: #64748b; } .advaxe-contact-card.style-1 .advaxe-c-text p { color: #1e293b; } .advaxe-contact-card.style-1 .icon-call { background: linear-gradient(135deg, #e0f2f1 0%, #b2dfdb 100%); color: #00796b; } .advaxe-contact-card.style-1 .icon-wa { background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%); color: #128c7e; } /* --- Style 2: Premium Colored Cards --- */ .advaxe-contact-card.style-2 { border: none; box-shadow: 0 4px 10px rgba(0,0,0,0.1); } .advaxe-contact-card.style-2.call-card { background: linear-gradient(135deg, #00796b 0%, #004d40 100%); } .advaxe-contact-card.style-2.wa-card { background: linear-gradient(135deg, #25D366 0%, #128C7E 100%); } .advaxe-contact-card.style-2 .advaxe-c-icon { background: rgba(255, 255, 255, 0.2); color: #ffffff; } .advaxe-contact-card.style-2 .advaxe-c-text h4 { color: rgba(255, 255, 255, 0.8); } .advaxe-contact-card.style-2 .advaxe-c-text p { color: #ffffff; } .advaxe-contact-card.style-2:hover { box-shadow: 0 8px 15px rgba(0,0,0,0.15); } /* ============================================================== */ /* PREMIUM TABS, DESCRIPTION, REVIEWS & ADDITIONAL INFO DESIGN */ /* ============================================================== */ /* Unified Card Layout */ .woocommerce-tabs { margin-top: 1px !important; background: #fff; border: 1px solid #e2e8f0; border-radius: 8px; overflow: hidden; box-shadow: none !important; display: block; } /* Modern Segmented Tab Buttons (Centered & Responsive) */ .woocommerce-tabs ul.tabs { margin: 0 !important; padding: 0 !important; display: flex !important; flex-wrap: wrap !important; justify-content: center !important; width: 100% !important; background: #f8fafc !important; border-bottom: 1px solid #e2e8f0 !important; list-style: none !important; } .woocommerce-tabs ul.tabs li { width: auto !important; flex-grow: 1 !important; margin: 0 !important; border: none !important; background: transparent !important; text-align: center; display: block !important; border-right: 1px solid #e2e8f0 !important; } .woocommerce-tabs ul.tabs li:last-child { border-right: none !important; } .woocommerce-tabs ul.tabs li a { padding: 14px 10px !important; width: 100%; display: block; font-weight: 600; color: #64748b !important; text-transform: uppercase; font-size: 14px; letter-spacing: 0.5px; transition: all 0.3s ease; text-decoration: none; box-sizing: border-box; } .woocommerce-tabs ul.tabs li.active { background: #fff !important; } .woocommerce-tabs ul.tabs li.active a { color: var(--pfs-primary) !important; } @media (max-width: 480px) { .woocommerce-tabs ul.tabs li a { font-size: 12px; padding: 12px 5px !important; } } /* Inside Tab Content Panel (Reduced Padding) */ .woocommerce-tabs .panel { padding: 15px !important; margin: 0 !important; border: none !important; box-shadow: none !important; } .woocommerce-tabs .panel > h2:first-of-type { display: none !important; } /* Description Tab Typography & WP Editor HTML Support */ .woocommerce-Tabs-panel--description, .woocommerce-product-details__short-description { color: #475569; font-size: 16px; line-height: 1.8 !important; } .woocommerce-Tabs-panel--description p, .woocommerce-product-details__short-description p { margin-bottom: 15px; } .woocommerce-Tabs-panel--description img { max-width: 100%; height: auto; border-radius: 8px; margin: 15px 0; display: block; } .woocommerce-Tabs-panel--description strong, .woocommerce-Tabs-panel--description b, .woocommerce-product-details__short-description strong, .woocommerce-product-details__short-description b { font-weight: bold !important; color: #1e293b; } .woocommerce-Tabs-panel--description em, .woocommerce-Tabs-panel--description i, .woocommerce-product-details__short-description em, .woocommerce-product-details__short-description i { font-style: italic !important; } .woocommerce-Tabs-panel--description ul, .woocommerce-Tabs-panel--description ol, .woocommerce-product-details__short-description ul, .woocommerce-product-details__short-description ol { margin-bottom: 15px; padding-left: 20px !important; } .woocommerce-Tabs-panel--description ul, .woocommerce-product-details__short-description ul { list-style-type: disc !important; } .woocommerce-Tabs-panel--description ol, .woocommerce-product-details__short-description ol { list-style-type: decimal !important; } .woocommerce-Tabs-panel--description li, .woocommerce-product-details__short-description li { margin-bottom: 8px; display: list-item; } .woocommerce-Tabs-panel--description h1, .woocommerce-Tabs-panel--description h2, .woocommerce-Tabs-panel--description h3, .woocommerce-Tabs-panel--description h4, .woocommerce-Tabs-panel--description h5, .woocommerce-Tabs-panel--description h6 { color: #1e293b; margin-top: 1.5em; margin-bottom: 0.5em; font-weight: 600; line-height: 1.3; } /* Additional Information Tab Redesign (No inner border/radius) */ .woocommerce-Tabs-panel--additional_information table.woocommerce-product-attributes { width: 100%; border-collapse: collapse; border: none !important; margin: 0; } .woocommerce-Tabs-panel--additional_information table th, .woocommerce-Tabs-panel--additional_information table td { padding: 10px 5px !important; border-bottom: 1px solid #e2e8f0; text-align: left; font-size: 15px; } .woocommerce-Tabs-panel--additional_information table th { width: 35%; font-weight: 600; color: #1e293b; border-right: none !important; background: transparent !important; } .woocommerce-Tabs-panel--additional_information table td { color: #475569; } .woocommerce-Tabs-panel--additional_information table td p { margin: 0; } .woocommerce-Tabs-panel--additional_information table tr:last-child th, .woocommerce-Tabs-panel--additional_information table tr:last-child td { border-bottom: none; } /* Reviews Tab Redesign (Minimalist) */ #reviews #comments h2 { font-size: 18px; font-weight: 600; color: #1e293b; margin-bottom: 20px; display: block !important; } #reviews ol.commentlist { padding: 0; list-style: none; margin: 0; } #reviews ol.commentlist li { margin-bottom: 15px; } #reviews .comment_container { display: flex; gap: 15px; padding: 10px 0 !important; border: none !important; background: transparent !important; border-bottom: 1px solid #f1f5f9 !important; border-radius: 0 !important; } #reviews .comment_container img.avatar { width: 50px; height: 50px; border-radius: 50%; padding: 0; border: none; } #reviews .comment-text { flex: 1; position: relative; } #reviews .comment-text p.meta { font-size: 13px; color: #94a3b8; margin-bottom: 5px; } #reviews .comment-text p.meta strong { color: #1e293b; font-size: 15px; font-weight: 600; } #reviews .description { color: #475569; line-height: 1.6; font-size: 14px; } #reviews .description p { margin: 0; } /* Updated Stars Color & Smaller Size */ #reviews .star-rating { position: absolute; top: 0; right: 0; font-size: 10px !important; } .woocommerce .star-rating, .woocommerce .star-rating span::before, .woocommerce p.stars a, .woocommerce p.stars a::before { color: var(--pfs-primary) !important; } .woocommerce p.stars a, .woocommerce p.stars a::before { font-size: 16px !important; } /* Review Form Redesign (Minimalist) */ #review_form_wrapper { margin-top: 30px; padding: 15px; border: 1px solid #e2e8f0; border-radius: 8px; background: #fafafa; } #review_form_wrapper .comment-reply-title { font-size: 16px; font-weight: 600; color: #1e293b; margin-bottom: 15px; display: block; } #review_form_wrapper .comment-form-rating { margin-bottom: 15px; display: flex; align-items: center; gap: 10px; } #review_form_wrapper .comment-form-rating label { font-weight: 600; color: #475569; } #review_form_wrapper p.comment-form-comment textarea { width: 100%; border: 1px solid #cbd5e1; border-radius: 6px; padding: 12px; font-family: inherit; font-size: 14px; resize: vertical; min-height: 100px; transition: 0.3s; } #review_form_wrapper p.comment-form-comment textarea:focus { border-color: var(--pfs-primary); outline: none; } #review_form_wrapper p.comment-form-author input, #review_form_wrapper p.comment-form-email input { width: 100%; border: 1px solid #cbd5e1; border-radius: 6px; padding: 10px 12px; margin-bottom: 10px; font-size: 14px; transition: 0.3s; } #review_form_wrapper p.comment-form-author input:focus, #review_form_wrapper p.comment-form-email input:focus { border-color: var(--pfs-primary); outline: none; } #review_form_wrapper .form-submit { margin-top: 15px; } #review_form_wrapper .form-submit input.submit { background: var(--pfs-primary); color: #fff; border: none; padding: 10px 20px; border-radius: 6px; font-weight: bold; font-size: 14px; cursor: pointer; transition: 0.3s; } #review_form_wrapper .form-submit input.submit:hover { background: #004d40; } .related.products { width:100%; margin-top: 30px; border-top: 1px solid #e2e8f0; padding-top: 20px; } .related.products > h2 { font-size: 20px; margin-bottom: 15px; border-left: 4px solid var(--pfs-primary); padding-left: 10px; text-transform: uppercase; font-weight: 700; color: #1e293b; } /* PREMIUM POPUP DESIGN */ #advaxe-ajax-notify { position: fixed; top: -100px; left: 50%; transform: translateX(-50%); background: #fff; color: #333; padding: 16px 24px; border-radius: 12px; z-index: 999999; display: flex; align-items: center; justify-content: space-between; gap: 20px; box-shadow: 0 10px 40px rgba(0,0,0,0.2); font-size: 15px; font-weight: 600; transition: top 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); min-width: 320px; max-width: 90%; border-left: 6px solid var(--pfs-primary); } #advaxe-ajax-notify.show { top: 30px; } #advaxe-ajax-notify.error { border-left-color: #dc3232; } #advaxe-ajax-notify .advaxe-notify-content { display: flex; align-items: center; gap: 12px; } .advaxe-icon-wrap { display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 50%; } #advaxe-ajax-notify.success .advaxe-icon-wrap { background: rgba(0, 121, 107, 0.1); color: var(--pfs-primary); } #advaxe-ajax-notify.error .advaxe-icon-wrap { background: rgba(220, 50, 50, 0.1); color: #dc3232; } #advaxe-ajax-notify .dashicons { font-size: 18px; width: 18px; height: 18px; } #advaxe-ajax-notify .advaxe-notify-btn { background: var(--pfs-primary); color: #fff; padding: 8px 16px; border-radius: 6px; text-decoration: none; font-size: 13px; font-weight: bold; transition: all 0.3s ease; white-space: nowrap; box-shadow: 0 4px 10px rgba(0, 121, 107, 0.2); } #advaxe-ajax-notify .advaxe-notify-btn:hover { background: #004d40; transform: translateY(-2px); color: #fff; } </style> <?php } function advaxe_single_global_scripts() { if(!is_product()) return; ?> <script> var advaxe_cart_url = "<?php echo wc_get_cart_url(); ?>"; var advaxe_ajax_url = "<?php echo admin_url('admin-ajax.php'); ?>"; </script> <div id="advaxe-ajax-notify"></div> <script> jQuery(document).ready(function($){ function showAdvaxeNotice(type, msg, link = '') { var $notify = $('#advaxe-ajax-notify'); $notify.removeClass('success error'); $notify.addClass(type); var iconHtml = type === 'success' ? '<div class="advaxe-icon-wrap"><span class="dashicons dashicons-yes-alt"></span></div>' : '<div class="advaxe-icon-wrap"><span class="dashicons dashicons-warning"></span></div>'; var html = '<div class="advaxe-notify-content">' + iconHtml + '<span>' + msg + '</span></div>'; if(link !== '' && type === 'success') { html += '<a href="' + link + '" class="advaxe-notify-btn">View Cart</a>'; } $notify.html(html).addClass('show'); setTimeout(function(){ $notify.removeClass('show'); }, 5000); } $('.advaxe-g-item').on('click', function(){ var fullSrc = $(this).data('full'); $('.advaxe-main-img').attr('src', fullSrc).attr('srcset', ''); $('.advaxe-g-item').removeClass('active-thumb'); $(this).addClass('active-thumb'); }); $(document).on('click', '.advaxe-swatch-item', function() { var $this = $(this); var val = $this.data('value'); var $wrapper = $this.closest('.advaxe-swatches'); var selectId = $wrapper.data('select-id'); var $select = $('#' + selectId); if($this.hasClass('selected')) { $this.removeClass('selected'); $select.val('').trigger('change'); } else { $wrapper.find('.advaxe-swatch-item').removeClass('selected'); $this.addClass('selected'); $select.val(val).trigger('change'); } }); $(document).on('reset_data', function() { $('.advaxe-swatch-item').removeClass('selected'); }); $('body').on('click', '.advaxe-qty-btn', function() { var $button = $(this); var $input = $button.parent().find('.qty'); var val = parseFloat($input.val()); var step = parseFloat($input.attr('step')) || 1; var min = parseFloat($input.attr('min')) || 1; if ($button.hasClass('plus')) { $input.val(val + step).trigger('change'); } else { if (val > min) $input.val(val - step).trigger('change'); } }); function initQtyButtons() { $('.quantity').each(function() { var $qty = $(this).find('.qty'); if($(this).find('.advaxe-qty-btn').length === 0 && $qty.length > 0) { $qty.before('<span class="advaxe-qty-btn minus">-</span>'); $qty.after('<span class="advaxe-qty-btn plus">+</span>'); } }); } initQtyButtons(); $(document).on('found_variation', function() { initQtyButtons(); }); // ANTI-DOUBLE CART SUBMISSION LOGIC $(document).off('submit', 'form.cart').on('submit', 'form.cart', function(e) { var $form = $(this); if($form.closest('.product').hasClass('product-type-external')) return true; e.preventDefault(); e.stopImmediatePropagation(); var is_variable = $form.find('.variations').length > 0; if( is_variable ) { var varID = $form.find('input[name="variation_id"]').val(); if( !varID || varID == 0 || varID == '' ) { showAdvaxeNotice('error', 'Please select product options first.'); return false; } } var $btn = $form.find('button[name="add-to-cart"], button[type="submit"], .single_add_to_cart_button'); if( $btn.hasClass('disabled') || $btn.hasClass('loading') ) return false; $btn.addClass('loading'); var formData = new FormData($form[0]); formData.append('action', 'advaxe_add_to_cart'); var product_id = $btn.val() || $form.find('input[name="product_id"]').val() || formData.get('add-to-cart'); if(formData.has('add-to-cart')) { formData.delete('add-to-cart'); } formData.set('product_id', product_id); $.ajax({ type: 'POST', url: advaxe_ajax_url, data: formData, processData: false, contentType: false, success: function(response) { $btn.removeClass('loading'); if (response.error || response.success === false) { showAdvaxeNotice('error', 'Could not add to cart.'); return; } showAdvaxeNotice('success', 'Successfully added to your cart!', advaxe_cart_url); var fragments = response.fragments || {}; var cart_hash = response.cart_hash || ''; if (fragments) { $.each(fragments, function(key, value) { $(key).replaceWith(value); }); } $(document.body).trigger('added_to_cart', [ fragments, cart_hash, $btn ]); $(document.body).trigger('wc_fragment_refresh'); }, error: function() { $btn.removeClass('loading'); showAdvaxeNotice('error', 'Something went wrong. Please try again.'); } }); return false; }); }); </script> <?php } // ============================================================== // ৩. সিংগেল প্রোডাক্ট লুপ ওভাররাইড ও ট্যাব রি-অর্ডার // ============================================================== add_action('woocommerce_init', 'advaxe_single_override_templates'); function advaxe_single_override_templates() { remove_action( 'woocommerce_before_single_product_summary', 'woocommerce_show_product_images', 20 ); remove_action( 'woocommerce_before_single_product_summary', 'woocommerce_show_product_sale_flash', 10 ); remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_title', 5 ); remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_rating', 10 ); remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 ); remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_excerpt', 20 ); remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_meta', 40 ); remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_product_data_tabs', 10 ); remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20 ); add_action( 'woocommerce_before_single_product_summary', 'advaxe_custom_single_gallery', 20 ); add_action( 'woocommerce_single_product_summary', 'advaxe_custom_single_title', 5 ); add_action( 'woocommerce_single_product_summary', 'advaxe_custom_single_price', 10 ); add_action( 'woocommerce_single_product_summary', 'advaxe_custom_single_excerpt', 20 ); add_action( 'woocommerce_after_add_to_cart_form', 'advaxe_single_product_custom_elements', 15 ); add_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_product_data_tabs', 20 ); add_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 30 ); } // ট্যাব সিরিয়াল পরিবর্তন এবং Additional Information হাইড/শো add_filter( 'woocommerce_product_tabs', 'advaxe_reorder_tabs', 98 ); function advaxe_reorder_tabs( $tabs ) { if(isset($tabs['description'])) { $tabs['description']['priority'] = 10; } if(isset($tabs['reviews'])) { $tabs['reviews']['priority'] = 20; } // --- Additional Information Tab Control --- // নিচে unset(...) লাইনটির কারণে "Additional Information" ট্যাবটি এখন অফ আছে। // ভবিষ্যতে আবার অন করতে চাইলে unset লাইনটি মুছে ফেলুন (বা শুরুতে // দিন) এবং নিচের /* ... */ কমেন্ট ব্লকটি সরিয়ে দিন। unset($tabs['additional_information']); // ট্যাবটি অফ করতে এই লাইনটি কাজ করছে /* if(isset($tabs['additional_information'])) { $tabs['additional_information']['priority'] = 30; } */ return $tabs; } // ============================================================== // ৪. সুইচার জেনারেটর (Advanced Swatches Integration) // ============================================================== add_filter( 'woocommerce_dropdown_variation_attribute_options_html', 'advaxe_custom_swatches_html', 10, 2 ); function advaxe_custom_swatches_html( $html, $args ) { $options = $args['options']; $product = $args['product']; $attribute = $args['attribute']; $name = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title( $attribute ); $id = $args['id'] ? $args['id'] : sanitize_title( $attribute ); $class = $args['class']; $html = '<select id="' . esc_attr( $id ) . '" class="' . esc_attr( $class ) . '" name="' . esc_attr( $name ) . '" data-attribute_name="attribute_' . esc_attr( sanitize_title( $attribute ) ) . '" data-show_option_none="' . ( $args['show_option_none'] ? 'yes' : 'no' ) . '" style="display:none !important;">'; $html .= '<option value="">' . esc_html( $args['show_option_none'] ? $args['show_option_none'] : __( 'Choose an option', 'woocommerce' ) ) . '</option>'; if ( ! empty( $options ) ) { if ( $product && taxonomy_exists( $attribute ) ) { $terms = wc_get_product_terms( $product->get_id(), $attribute, array( 'fields' => 'all' ) ); foreach ( $terms as $term ) { if ( in_array( $term->slug, $options, true ) ) { $html .= '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name, $term, $attribute, $product ) ) . '</option>'; } } } else { foreach ( $options as $option ) { $selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false ); $html .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option, null, $attribute, $product ) ) . '</option>'; } } } $html .= '</select>'; $forced_colors = array_map('trim', explode(',', get_option('advaxe_color_attrs', 'color, colour, রং'))); $forced_texts = array_map('trim', explode(',', get_option('advaxe_text_attrs', 'size, dimension'))); $raw_colors = get_option('advaxe_custom_colors', ''); $custom_color_map = []; if(!empty($raw_colors)) { $lines = preg_split("/\r\n|\n|\r/", $raw_colors); foreach($lines as $line) { if(strpos($line, ':') !== false) { list($c_name, $c_hex) = explode(':', $line, 2); $custom_color_map[mb_strtolower(trim($c_name))] = trim($c_hex); } } } $is_color = false; $attr_label = wc_attribute_label( $attribute ); $label_lower = mb_strtolower($attr_label); if ( in_array($label_lower, array_map('mb_strtolower', $forced_colors)) ) { $is_color = true; } elseif ( in_array($label_lower, array_map('mb_strtolower', $forced_texts)) ) { $is_color = false; } else { if( stripos($attr_label, 'color') !== false || stripos($attr_label, 'colour') !== false || stripos($attr_label, 'রং') !== false ) { $is_color = true; } } $html .= '<div class="advaxe-swatches" data-select-id="' . esc_attr( $id ) . '">'; if ( ! empty( $options ) ) { if ( $product && taxonomy_exists( $attribute ) ) { $terms = wc_get_product_terms( $product->get_id(), $attribute, array( 'fields' => 'all' ) ); foreach ( $terms as $term ) { if ( in_array( $term->slug, $options, true ) ) { $val = esc_attr( $term->slug ); $label = esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name, $term, $attribute, $product ) ); $specific_color = ''; $label_key = mb_strtolower($label); if(isset($custom_color_map[$label_key])) { $specific_color = $custom_color_map[$label_key]; $is_color_item = true; } else { $is_color_item = $is_color; } $html .= advaxe_generate_swatch_item($val, $label, $is_color_item, $args['selected'], $specific_color); } } } else { foreach ( $options as $option ) { $val = esc_attr( $option ); $label = esc_html( apply_filters( 'woocommerce_variation_option_name', $option, null, $attribute, $product ) ); $specific_color = ''; $label_key = mb_strtolower($label); if(isset($custom_color_map[$label_key])) { $specific_color = $custom_color_map[$label_key]; $is_color_item = true; } else { $is_color_item = $is_color; } $html .= advaxe_generate_swatch_item($val, $label, $is_color_item, $args['selected'], $specific_color); } } } $html .= '</div>'; return $html; } function advaxe_generate_swatch_item($val, $label, $is_color, $selected_val, $specific_color = '') { $class = 'advaxe-swatch-item'; $class .= $is_color ? ' swatch-color' : ' swatch-text'; if( sanitize_title($selected_val) === sanitize_title($val) || $selected_val === $val ) { $class .= ' selected'; } $style = ''; if($is_color) { $bg_color = !empty($specific_color) ? $specific_color : strtolower($label); $style = 'background-color: ' . esc_attr($bg_color) . ';'; } return '<span class="'.esc_attr($class).'" data-value="'.esc_attr($val).'" style="'.esc_attr($style).'" title="'.esc_attr($label).'">' . ($is_color ? '' : esc_html($label)) . '</span>'; } // ============================================================== // ৫. সিংগেল প্রোডাক্ট কাস্টম ফাংশনস // ============================================================== function advaxe_custom_single_gallery() { global $product; $feat_id = $product->get_image_id(); $gallery_ids = $product->get_gallery_image_ids(); $main_img_url = wp_get_attachment_image_url($feat_id, 'large') ?: wc_placeholder_img_src(); $all_images = []; if($feat_id) $all_images[] = $feat_id; if($gallery_ids) { foreach($gallery_ids as $gid) { $all_images[] = $gid; } } $all_images = array_unique($all_images); ?> <div class="advaxe-sp-gallery-wrapper"> <div class="advaxe-main-img-wrap"><img src="<?php echo esc_url($main_img_url); ?>" class="advaxe-main-img"></div> <?php if(count($all_images) > 0): ?> <div class="advaxe-gallery-strip"> <?php $count = 0; foreach($all_images as $img_id): $thumb_url = wp_get_attachment_image_url($img_id, 'woocommerce_thumbnail'); $full_url = wp_get_attachment_image_url($img_id, 'large'); $active_class = ($count == 0) ? 'active-thumb' : ''; ?> <div class="advaxe-g-item <?php echo $active_class; ?>" data-full="<?php echo esc_url($full_url); ?>"> <img src="<?php echo esc_url($thumb_url); ?>"> </div> <?php $count++; endforeach; ?> </div> <?php endif; ?> </div> <?php } function advaxe_custom_single_title() { the_title( '<h1 class="advaxe-single-title">', '</h1>' ); } function advaxe_custom_single_price() { global $product; if( $product->is_type('variable') ) { echo '<div class="advaxe-single-price">'. $product->get_price_html() .'</div>'; } else { echo '<div class="advaxe-single-price">'; echo $product->get_price() . ' TK'; if($product->is_on_sale() && $product->get_regular_price()){ echo '<del>' . $product->get_regular_price() . ' TK</del>'; } echo '</div>'; } } function advaxe_custom_single_excerpt() { global $post; if ( ! $post->post_excerpt ) return; echo '<div class="woocommerce-product-details__short-description">' . do_shortcode( wpautop( $post->post_excerpt ) ) . '</div>'; } function advaxe_single_product_custom_elements() { global $product; $phone = get_option('advaxe_contact_phone', '01824222653'); $whatsapp = get_option('advaxe_contact_whatsapp', '01814802802'); $card_style = get_option('advaxe_contact_card_style', 'style-1'); // Get user choice $btn_attr = "onclick=\" var f=jQuery('form.cart'); if(f.find('.variations').length > 0) { var vid = f.find('input[name=variation_id]').val(); if(!vid || vid == 0){ alert('Please select options first.'); return; } } var qty = f.find('input[name=quantity]').val() || 1; var pid = f.find('input[name=variation_id]').val() || " . $product->get_id() . "; window.location.href = '" . wc_get_checkout_url() . "?add-to-cart=' + pid + '&quantity=' + qty; \""; ?> <button type="button" class="advaxe-direct-order-btn" <?php echo $btn_attr; ?>> Order Now <span class="dashicons dashicons-yes"></span> </button> <div class="advaxe-contact-grid"> <a href="tel:<?php echo esc_attr($phone); ?>" class="advaxe-contact-card call-card <?php echo esc_attr($card_style); ?>" style="text-decoration:none;"> <div class="advaxe-c-icon icon-call"><span class="dashicons dashicons-phone"></span></div> <div class="advaxe-c-text"><h4>Call Now</h4><p><?php echo esc_html($phone); ?></p></div> </a> <a href="https://wa.me/<?php echo str_replace(['+','-',' '], '', $whatsapp); ?>" class="advaxe-contact-card wa-card <?php echo esc_attr($card_style); ?>" style="text-decoration:none;"> <div class="advaxe-c-icon icon-wa"><span class="dashicons dashicons-whatsapp"></span></div> <div class="advaxe-c-text"><h4>Whatsapp</h4><p><?php echo esc_html($whatsapp); ?></p></div> </a> </div> <?php } add_filter( 'woocommerce_output_related_products_args', 'advaxe_change_related_products_limit' ); function advaxe_change_related_products_limit( $args ) { $args['posts_per_page'] = get_option('advaxe_rel_prod_count', 4); $args['columns'] = 2; return $args; } // ============================================================== // ৬. কাস্টম AJAX অ্যাড টু কার্ট (সিম্পল এবং ভেরিয়েবল উভয়ের জন্য) // ============================================================== add_action('wp_ajax_advaxe_add_to_cart', 'advaxe_ajax_add_to_cart_handler'); add_action('wp_ajax_nopriv_advaxe_add_to_cart', 'advaxe_ajax_add_to_cart_handler'); function advaxe_ajax_add_to_cart_handler() { ob_start(); $product_id = apply_filters('woocommerce_add_to_cart_product_id', absint($_POST['product_id'])); $quantity = empty($_POST['quantity']) ? 1 : wc_stock_amount(wp_unslash($_POST['quantity'])); $variation_id = isset($_POST['variation_id']) ? absint($_POST['variation_id']) : 0; $variations = []; foreach ($_POST as $key => $value) { if ('attribute_' === substr($key, 0, 10)) { $variations[$key] = wp_unslash($value); } } $passed_validation = apply_filters('woocommerce_add_to_cart_validation', true, $product_id, $quantity, $variation_id, $variations); if ($passed_validation && WC()->cart->add_to_cart($product_id, $quantity, $variation_id, $variations)) { do_action('woocommerce_ajax_added_to_cart', $product_id); WC_AJAX::get_refreshed_fragments(); } else { wp_send_json_error(array('error' => true)); } wp_die(); } ?>