621 - Wu Zi Yan Zong Wan
R$58,00 – R$80,00Price range: R$58,00 through R$80,00
630 - ZHI MU (ANEMARRHENAE RHIZOMA)
R$58,00 – R$80,00Price range: R$58,00 through R$80,00
[
'label' => 'Cápsula',
'sku_contains' => ['CAP', 'CAPS'],
'product_cat' => ['capsulas'],
'attribute' => ['pa_formulacao' => ['capsula']],
],
'gotas' => [
'label' => 'Gotas para infusão',
'sku_contains' => ['GOT'],
'product_cat' => ['gotas-infusao'],
'attribute' => ['pa_formulacao' => ['gotas']],
],
];
$parent_formulation_taxonomy = 'pa_formulacao';
$min_chars = 2;
$ajax_limit = 15;
$allow_duplicates = false;
// Formulações disponíveis no produto container (se existir taxonomia)
$available_keys = array_keys($formulation_rules);
if (taxonomy_exists($parent_formulation_taxonomy)) {
$term_slugs = wp_get_post_terms($product->get_id(), $parent_formulation_taxonomy, ['fields' => 'slugs']);
if (!is_wp_error($term_slugs) && !empty($term_slugs)) {
$filtered = array_values(array_intersect($available_keys, $term_slugs));
if (!empty($filtered)) $available_keys = $filtered;
}
}
$formulations_for_ui = [];
foreach ($available_keys as $k) {
if (!isset($formulation_rules[$k])) continue;
$formulations_for_ui[] = ['key' => $k, 'label' => $formulation_rules[$k]['label']];
}
// Garante jQuery
wp_enqueue_script('jquery');
// CSS inline (no handle do WooCommerce quando possível; fallback: wp_head via wp_add_inline_style em handle genérico)
$css = << '+esc(message)+' '+esc(t('no_results'))+' '+esc(r.title||'')+''
+ '');
}
return;
}
// Hide native add-to-cart button (keep in DOM)
var \$nativeBtn = $();
(S.selectors.addToCart || ["button[type='submit']"]).some(function(sel){
var \$b = \$form.find(sel).first();
if (\$b.length){ \$nativeBtn = \$b; return true; }
return false;
});
if (\$nativeBtn.length) \$nativeBtn.css({display:'none'});
// ===== State =====
var state = { qty: 1, formulation: '', slots: [null] };
var cache = {};
var debounceTimers = {};
function buildUI(){
var opts = '';
(S.formulations||[]).forEach(function(f){
opts += '';
});
var html = ''
+ 'Monte seu kit'
+ ''+esc(t('not_detected'))+''
+ ''+esc(debugLines.join("\\n"))+''
+ ''
+ '';
\$form.prepend(html);
}
function setQty(n){
n = parseInt(n,10); if (isNaN(n)) n = 1;
n = Math.max(1, Math.min(10, n));
state.qty = n;
if (state.slots.length > n) state.slots = state.slots.slice(0,n);
while (state.slots.length < n) state.slots.push(null);
renderSlots();
validate();
}
function setFormulation(key){
state.formulation = (key||'').toString();
state.slots = state.slots.map(function(){ return null; });
renderSlots();
validate();
}
function selectedIds(){
return state.slots.map(function(it){ return it && it.product_id ? parseInt(it.product_id,10) : null; }).filter(Boolean);
}
function isComplete(){
if (!state.qty || !state.formulation) return false;
for (var i=0;iMonte seu kit'
+ ''
+ ''
+ ''
+ ''
+ ''
+ ''
+ ''
+ ''
+ ''
+ ''
+ ''
+ ''
+ ''
+ ''
+ 'De 1 a 10. Isso define quantos slots aparecem abaixo.'
+ ''
+ ''
+ ''
+ ''
+ 'A busca será filtrada pela formulação selecionada.'
+ 'Resultados só aparecem ao digitar (mín. '+esc(S.min_chars||2)+').'
+ (parseInt(S.debug||0,10) ? ''+esc(debugLines.join("\\n"))+'' : '')
+ ''
+ ''+esc(label)+''
+ ''
+ ''
+ ''
+ '';
\$slots.append(slotHtml);
var \$slot = \$slots.find('.mnm-guided-slot[data-slot="'+i+'"]');
if (item && item.product_id){
\$slot.find('.mnm-guided-input').hide();
\$slot.find('.mnm-guided-results').hide();
\$slot.find('.mnm-guided-chip').show();
\$slot.find('.mnm-guided-chip-img').attr('src', item.thumbnail_url || '');
\$slot.find('.mnm-guided-chip-title').text(item.title || '');
var meta = [];
if (item.sku) meta.push('SKU: '+item.sku);
meta.push('#'+item.product_id);
\$slot.find('.mnm-guided-chip-meta').text(meta.join(' • '));
}
}
}
function renderResults(\$slot, results, message){
var \$box = \$slot.find('.mnm-guided-results');
if (message){
\$box.html(''
+ '
'
+ ''
+ ''
+ ''
+ ''
+ ''+esc(t('selected'))+''
+ ''
+ ''
+ '').show();
return;
}
if (!results || !results.length){
\$box.html('').show();
return;
}
var html = '';
results.forEach(function(r){
html += ''
+ '';
});
\$box.html(html).show();
}
function searchProducts(term, formulationKey, excludeIds, cb){
term = (term||'').toString();
var min = parseInt(S.min_chars||2,10);
if (term.length < min){
cb({results:[], message: t('type_more',{n:min})});
return;
}
var ckey = norm(formulationKey)+'|'+norm(term);
if (cache[ckey]){ cb({results: cache[ckey]}); return; }
$.ajax({
url: S.ajax_url,
method:'POST',
dataType:'json',
data:{
action:'mnm_guided_search',
nonce:S.nonce,
term:term,
formulation_key:formulationKey,
exclude: excludeIds || [],
allowed_ids: allowedIds || [],
limit: parseInt(S.limit||15,10)
}
}).done(function(resp){
if (resp && resp.success){
cache[ckey] = resp.data || [];
cb({results: cache[ckey]});
} else {
cb({results:[], message:'Erro na busca.'});
}
}).fail(function(){
cb({results:[], message:'Falha de rede/AJAX.'});
});
}
function closeAllResults(){ \$form.find('.mnm-guided-results').hide(); }
function countsByProductId(){
var counts = {};
state.slots.forEach(function(it){
if (!it || !it.product_id) return;
var id = parseInt(it.product_id,10);
counts[id] = (counts[id]||0) + 1;
});
return counts;
}
function applyToRealInputsAndSubmit(){
// zera tudo
Object.keys(qtyMap).forEach(function(pid){
qtyMap[pid].val(0).trigger('change');
});
// aplica
var counts = countsByProductId();
Object.keys(counts).forEach(function(pid){
pid = parseInt(pid,10);
if (qtyMap[pid]) qtyMap[pid].val(counts[pid]).trigger('change');
});
if (!\$form.find("input[name='mnm_guided_ui']").length){
\$form.append('');
}
\$form.trigger('submit');
}
// ===== Start =====
buildUI();
setQty(1);
validate();
// events
\$form.on('click','.mnm-guided-minus',function(){ setQty((state.qty||1)-1); \$form.find('.mnm-guided-qty').val(state.qty); });
\$form.on('click','.mnm-guided-plus', function(){ setQty((state.qty||1)+1); \$form.find('.mnm-guided-qty').val(state.qty); });
\$form.on('change','.mnm-guided-qty',function(){ setQty($(this).val()); $(this).val(state.qty); });
\$form.on('change','.mnm-guided-select',function(){ setFormulation($(this).val()); });
\$form.on('click','.mnm-guided-remove',function(){
var idx = parseInt($(this).closest('.mnm-guided-slot').data('slot'),10);
state.slots[idx] = null;
renderSlots(); validate();
});
$(document).on('click',function(e){
if (!$(e.target).closest('.mnm-guided-slot').length) closeAllResults();
});
\$form.on('input','.mnm-guided-input',function(){
var \$input = $(this);
var \$slot = \$input.closest('.mnm-guided-slot');
var idx = parseInt(\$slot.data('slot'),10);
var term = \$input.val()||'';
if (!state.formulation){ validate(); return; }
if (debounceTimers[idx]) clearTimeout(debounceTimers[idx]);
debounceTimers[idx] = setTimeout(function(){
var exclude = (parseInt(S.allow_duplicates||0,10) ? [] : selectedIds());
var current = state.slots[idx] ? parseInt(state.slots[idx].product_id,10) : null;
if (current) exclude = exclude.filter(function(id){ return id !== current; });
var min = parseInt(S.min_chars||2,10);
if (term.length >= min){
renderResults(\$slot, [], t('searching'));
}
searchProducts(term, state.formulation, exclude, function(res){
renderResults(\$slot, res.results||[], res.message||'');
});
}, 250);
});
\$form.on('click','.mnm-guided-item[data-id]',function(){
var \$item = $(this);
var \$slot = \$item.closest('.mnm-guided-slot');
var idx = parseInt(\$slot.data('slot'),10);
var product_id = parseInt(\$item.data('id'),10);
if (!parseInt(S.allow_duplicates||0,10)){
if (selectedIds().indexOf(product_id) >= 0){
\$form.find('.mnm-guided-status').text(t('dup_blocked'));
closeAllResults();
return;
}
}
state.slots[idx] = {
product_id: product_id,
sku: (\$item.data('sku')||'').toString(),
title: (\$item.data('title')||'').toString(),
thumbnail_url: (\$item.data('thumb')||'').toString(),
};
closeAllResults();
renderSlots(); validate();
});
\$form.on('click','.mnm-guided-submit',function(){
if (!isComplete()){ validate(); return; }
applyToRealInputsAndSubmit();
setTimeout(function(){ window.location.href = S.cart_url; }, 1200);
});
})(jQuery);
JS;
// injeta o JS no handle do jQuery (mais confiável do que “script vazio”)
wp_add_inline_script('jquery', $js, 'after');
}, 30);
/**
* AJAX — busca por SKU OU título, com filtro por regra
*/
add_action('wp_ajax_mnm_guided_search', 'mnm_guided_search_handler_v2');
add_action('wp_ajax_nopriv_mnm_guided_search', 'mnm_guided_search_handler_v2');
function mnm_guided_search_handler_v2(){
check_ajax_referer('mnm_guided_search', 'nonce');
$term = isset($_POST['term']) ? sanitize_text_field(wp_unslash($_POST['term'])) : '';
$term = trim($term);
if (mb_strlen($term) < 2) wp_send_json_success([]);
$formulation_key = isset($_POST['formulation_key']) ? sanitize_key(wp_unslash($_POST['formulation_key'])) : '';
if (!$formulation_key) wp_send_json_success([]);
$limit = isset($_POST['limit']) ? absint($_POST['limit']) : 15;
$limit = max(1, min(30, $limit));
// ====== MESMA CONFIGURAÇÃO DE REGRAS AQUI ======
$formulation_rules = [
'capsula' => [
'label' => 'Cápsula',
'sku_contains' => ['CAP', 'CAPS'],
'product_cat' => ['capsulas'],
'attribute' => ['pa_formulacao' => ['capsula']],
],
'gotas' => [
'label' => 'Gotas para infusão',
'sku_contains' => ['GOT'],
'product_cat' => ['gotas-infusao'],
'attribute' => ['pa_formulacao' => ['gotas']],
],
];
if (!isset($formulation_rules[$formulation_key])) wp_send_json_success([]);
$rule = $formulation_rules[$formulation_key];
$exclude = mnm_guided_parse_ids_v2($_POST['exclude'] ?? []);
$allowed = mnm_guided_parse_ids_v2($_POST['allowed_ids'] ?? []);
if (count($allowed) > 800) $allowed = array_slice($allowed, 0, 800);
$candidate_ids = [];
$base = [
'post_type' => 'product',
'post_status' => 'publish',
'fields' => 'ids',
'no_found_rows' => true,
'posts_per_page' => 200,
];
if (!empty($allowed)){
$base['post__in'] = $allowed;
$base['orderby'] = 'post__in';
}
// Query por título
$q1 = new WP_Query(array_merge($base, ['s' => $term]));
if (!empty($q1->posts)) $candidate_ids = array_merge($candidate_ids, $q1->posts);
// Query por SKU
$q2 = new WP_Query(array_merge($base, [
'meta_query' => [[
'key' => '_sku',
'value' => $term,
'compare' => 'LIKE',
]]
]));
if (!empty($q2->posts)) $candidate_ids = array_merge($candidate_ids, $q2->posts);
$candidate_ids = array_values(array_unique(array_map('absint', $candidate_ids)));
if (empty($candidate_ids)) wp_send_json_success([]);
$out = [];
foreach ($candidate_ids as $pid){
if ($pid <= 0) continue;
if (!empty($exclude) && in_array($pid, $exclude, true)) continue;
if (!mnm_guided_product_matches_rule_v2($pid, $rule)) continue;
$p = wc_get_product($pid);
if (!$p) continue;
$thumb_id = $p->get_image_id();
$thumb = $thumb_id ? wp_get_attachment_image_url($thumb_id, 'thumbnail') : wc_placeholder_img_src('thumbnail');
$out[] = [
'product_id' => $pid,
'sku' => (string) $p->get_sku(),
'title' => (string) $p->get_name(),
'thumbnail_url' => (string) $thumb,
];
if (count($out) >= $limit) break;
}
wp_send_json_success($out);
}
function mnm_guided_parse_ids_v2($raw){
if (is_string($raw)) $raw = explode(',', $raw);
if (!is_array($raw)) $raw = [$raw];
$ids = [];
foreach ($raw as $v){
if (is_array($v)) continue;
$v = trim((string)$v);
if ($v === '') continue;
$ids[] = absint($v);
}
return array_values(array_unique(array_filter($ids)));
}
function mnm_guided_product_matches_rule_v2($product_id, array $rule){
$product_id = absint($product_id);
if ($product_id <= 0) return false;
// sku_contains (OR dentro)
if (!empty($rule['sku_contains']) && is_array($rule['sku_contains'])){
$p = wc_get_product($product_id);
if (!$p) return false;
$sku = strtoupper((string)$p->get_sku());
if ($sku === '') return false;
$ok = false;
foreach ($rule['sku_contains'] as $frag){
$frag = strtoupper((string)$frag);
if ($frag !== '' && strpos($sku, $frag) !== false){ $ok = true; break; }
}
if (!$ok) return false;
}
// categoria (OR dentro)
if (!empty($rule['product_cat']) && is_array($rule['product_cat'])){
if (!has_term($rule['product_cat'], 'product_cat', $product_id)) return false;
}
// attributes (AND entre taxonomias, OR dentro)
if (!empty($rule['attribute']) && is_array($rule['attribute'])){
foreach ($rule['attribute'] as $tax => $terms){
$tax = sanitize_key($tax);
if (!$tax || empty($terms) || !is_array($terms)) continue;
if (!taxonomy_exists($tax)) return false;
if (!has_term($terms, $tax, $product_id)) return false;
}
}
return true;
}
add_filter('woocommerce_add_to_cart_redirect', function($url){
if (!empty($_REQUEST['mnm_guided_ui'])) return wc_get_cart_url();
return $url;
}, 20);
'
+ '
Avaliações
Não há avaliações ainda.