V.AISTUDIO / chat-fix.js
bep40's picture
chat-fix v14: hookAI trước tất cả + SP click mở trên trang hiện tại (showDetail) + fix AI tư vấn
b1fe016 verified
/**
* V.AI STUDIO — Chat Fix v14
*
* v14 CHANGES:
* - hookAI chạy NGAY đầu file (trước mọi code khác)
* - SP click trong AI search & chat cards → mở showDetail() trên trang hiện tại (ko popup)
* - Fix: nếu chatbox gọi fetch trước hook → vẫn OK vì hook chạy trước DOMContentLoaded
* - Thêm fallback: nếu showDetail không tồn tại → navigate to slug page
*/
// === HOOK AI NGAY LẬP TỨC — TRƯỚC MỌI THỨ ===
(function(){
var _origFetch = window.fetch;
var _hookInstalled = false;
var _D = function(){ return (typeof D !== 'undefined' && D && D.length) ? D : []; };
function norm(s){return(s||'').normalize('NFD').replace(/[\u0300-\u036f]/g,'').replace(/[Đđ]/g,'d').toLowerCase();}
function fmt(n){if(!n||isNaN(n))return'LH';return Number(n).toLocaleString('vi-VN')+'đ';}
var PRIORITY_BRANDS=['malloca','grob','canzy','eurogold','garis','demax'];
var STOPWORDS='tìm tim giup giúp cho toi tôi anh chi chị em xin muon muốn cần can co có nao nào loai loại mua kiểu kieu nên nen duoc được mấy may cai cái xem hay hoac hoặc va và với voi the thế nay này kia đó do ấy ay bao lam làm sao gi gì vay vậy hỏi hoi ơi la là một mot nha nhé nhe ạ a ơ ừ uk ok vâng dạ da rồi roi duoc không khong ko sp san pham sản phẩm cua của'.split(' ');
var CATEGORY_MAP={
'bep tu':['bep tu','bep dien tu','bep cam ung','induction','bep tu doi','bep tu 2','bep tu 3','bep tu don','bep tu ba'],
'bep gas':['bep gas','bep ga','gas am','gas doi'],
'bep hong ngoai':['bep hong ngoai','hong ngoai','infrared'],
'bep ket hop':['bep gas ket hop','gas ket hop dien','bep ket hop','ket hop tu gas'],
'may hut mui':['may hut mui','hut mui','hood','hut khoi','khu mui','may hut khoi'],
'may rua bat':['may rua bat','rua bat','rua chen','may rua chen','dishwasher'],
'lo nuong':['lo nuong','oven','lo am tu','lo nuong am','lo nuong dien'],
'lo vi song':['lo vi song','vi song','microwave'],
'chau rua':['chau rua','bon rua','sink','chau rua chen','chau da','chau inox'],
'voi rua':['voi rua','faucet','voi rua chen','voi nong lanh','voi chen'],
'tu lanh':['tu lanh','tu ruou','wine','wine cooler'],
'may say chen':['may say chen','say chen','say bat','may say bat'],
'phu kien tu bep':['phu kien tu bep','phu kien bep','ke bat','gia bat','gia dia','tu do kho','ke gia vi','gia gia vi','thung rac','ke xoong','mam xoay','phu kien'],
'gia bat':['gia bat','gia dia','ke bat','gia nang ha'],
'tu do kho':['tu do kho','tu kho','he kho'],
'ray':['ray am','ray bi','ray giam chan','ray hop'],
'thung rac':['thung rac','thung gao'],
'khoa cua':['khoa cua','khoa van tay','khoa thong minh','khoa dien tu','smart lock'],
'tay nam':['tay nam','num tu','tay cam'],
'may giat':['may giat','may say','washing'],
'may loc nuoc':['may loc nuoc','loc nuoc','water filter'],
'tivi':['tivi','tv','television'],
'dieu hoa':['dieu hoa','may lanh','air conditioner'],
'noi chien':['noi chien khong dau','air fryer','chien khong dau'],
'may hut am':['may hut am','hut am','dehumidifier']
};
function detectCategory(text){
var n=norm(text);var bestCat='',bestLen=0;
for(var cat in CATEGORY_MAP){var kws=CATEGORY_MAP[cat];for(var i=0;i<kws.length;i++){if(n.includes(kws[i])&&kws[i].length>bestLen){bestCat=cat;bestLen=kws[i].length;}}}
return bestCat;
}
function detectBrand(text){
var n=norm(text);
var allBrands=['malloca','grob','canzy','eurogold','garis','demax','boss','hafele','teka','bosch','panasonic','electrolux','samsung','lg','toshiba','sharp'];
for(var i=0;i<allBrands.length;i++){if(n.includes(allBrands[i]))return allBrands[i];}
return '';
}
function detectPriceRange(text){
var n=norm(text);var min=0,max=Infinity;
var m1=n.match(/(duoi|<|thap hon|re hon)\s*([\d.,]+)\s*(trieu|tr|t|m)?/);if(m1){max=parsePrice(m1[2],m1[3]);}
var m2=n.match(/(tren|>|tu|toi thieu|lon hon)\s*([\d.,]+)\s*(trieu|tr|t|m)?/);if(m2){min=parsePrice(m2[2],m2[3]);}
var m3=n.match(/(tu|from)\s*([\d.,]+)\s*(trieu|tr|t|m)?\s*(den|toi|to|-)\s*([\d.,]+)\s*(trieu|tr|t|m)?/);if(m3){min=parsePrice(m3[2],m3[3]||m3[6]);max=parsePrice(m3[5],m3[6]);}
var m4=n.match(/(tam|khoang|around|gang)\s*([\d.,]+)\s*(trieu|tr|t|m)?/);if(m4&&max===Infinity){var mid=parsePrice(m4[2],m4[3]);min=mid*0.7;max=mid*1.3;}
if(max===Infinity&&min===0){var m5=n.match(/([\d.,]+)\s*(trieu|tr)\b/);if(m5){if(n.includes('duoi')||n.includes('thap')||n.includes('re'))max=parsePrice(m5[1],m5[2]);}}
return{min:min,max:max};
}
function parsePrice(numStr,unit){
var v=parseFloat((numStr||'').replace(/\./g,'').replace(',','.'));if(isNaN(v))return 0;
unit=(unit||'').toLowerCase();
if(unit==='trieu'||unit==='tr'||unit==='t'||unit==='m')return v*1000000;
if(v>1000)return v;if(v>0&&v<200)return v*1000000;return v;
}
function extractKeywords(query){
var n=norm(query);var words=n.split(/[\s,;.!?]+/).filter(function(w){return w.length>=2;});
var filtered=words.filter(function(w){return STOPWORDS.indexOf(w)===-1;});
return filtered.length>0?filtered:words.filter(function(w){return w.length>=2;});
}
function searchProductsByContext(text,limit){
limit=limit||24;var data=_D();if(!data.length)return[];
var cat=detectCategory(text);var brand=detectBrand(text);var priceRange=detectPriceRange(text);var keywords=extractKeywords(text);
if(cat&&CATEGORY_MAP[cat]){var catW=[];CATEGORY_MAP[cat].forEach(function(kw){kw.split(' ').forEach(function(w){if(w.length>=2)catW.push(w);});});keywords=keywords.filter(function(w){return catW.indexOf(w)===-1;});}
if(brand)keywords=keywords.filter(function(w){return w!==brand;});
keywords=keywords.filter(function(w){return!w.match(/^\d+$/);});
keywords=keywords.filter(function(w){return['trieu','tr','duoi','tren','den','tam','khoang','gia','tot','nhat','re','dep','chat','luong'].indexOf(w)===-1;});
var results=[];
for(var i=0;i<data.length;i++){
var p=data[i];if(!p)continue;
var nameN=norm(p.name||p.n||'');var brandN=norm(p.brand||'');var catN=norm(p.cat||p.c||'');
var descN=norm(p.summary||p.sum||p.desc||'');var featsN=norm((p.feats||[]).join(' '));
var specsN=norm(typeof p.specs==='object'?Object.values(p.specs||{}).join(' '):'');
var skuN=norm(p.sku||p.model||p.mod||'');
var price=p.priceNum||p.pn||0;if(!price)price=parseInt((p.price||p.p||'').toString().replace(/[^\d]/g,''))||0;
var img=p.image||p.img||p.i||'';var score=0;
if(cat){var catKws=CATEGORY_MAP[cat]||[];var inCat=false;for(var ci=0;ci<catKws.length;ci++){if(catN.includes(catKws[ci])||nameN.includes(catKws[ci])){inCat=true;break;}}if(!inCat)continue;score+=30;}
if(brand){if(brandN.includes(brand)||nameN.includes(brand))score+=25;else continue;}
if(price>0){if(price<priceRange.min||price>priceRange.max)continue;score+=10;}else if(priceRange.max<Infinity){continue;}
for(var bi=0;bi<PRIORITY_BRANDS.length;bi++){if(brandN.includes(PRIORITY_BRANDS[bi])){score+=10-bi;break;}}
var kwMatched=0;
for(var w=0;w<keywords.length;w++){var kw=keywords[w];if(nameN.includes(kw)){score+=25;kwMatched++;}else if(skuN.includes(kw)){score+=20;kwMatched++;}else if(descN.includes(kw)){score+=12;kwMatched++;}else if(featsN.includes(kw)){score+=12;kwMatched++;}else if(specsN.includes(kw)){score+=10;kwMatched++;}else if(brandN.includes(kw)){score+=8;kwMatched++;}}
if(kwMatched>=2)score+=kwMatched*5;
if(score>0&&img){results.push({p:p,score:score,price:price});}
}
results.sort(function(a,b){return b.score-a.score||(a.price-b.price);});
return results.slice(0,limit);
}
// Export cho bên ngoài
window._vaiSearchContext=searchProductsByContext;
window._vaiDetectCategory=detectCategory;
window._vaiDetectBrand=detectBrand;
window._vaiDetectPrice=detectPriceRange;
// === NAVIGATE TO PRODUCT (trên trang hiện tại, không popup) ===
window._vaiGoProduct=function(slug){
if(!slug)return;
// Nếu showDetail tồn tại (defined in index.html inline) → dùng nó
if(typeof showDetail==='function'){
showDetail(slug);
// Scroll lên top
window.scrollTo({top:0,behavior:'smooth'});
return;
}
// Fallback: navigate
window.location.href='/san-pham/'+slug+'/index.html';
};
// === HOOK FETCH NGAY LẬP TỨC ===
var _lastProduct=null;
var _conversationHistory=[];
var VISION_MODEL='meta-llama/Llama-4-Scout-17B-16E-Instruct';
window.fetch=function(url,options){
if(url&&typeof url==='string'&&url.includes('router.huggingface.co')&&options&&options.body){
try{
var body=JSON.parse(options.body);
if(body.messages&&Array.isArray(body.messages)){
var userMsg=body.messages.filter(function(m){return m.role==='user';}).pop();
if(!userMsg)return _origFetch.apply(this,arguments);
var userText=typeof userMsg.content==='string'?userMsg.content:(userMsg.content&&userMsg.content[0]?userMsg.content[0].text:'');
var data=_D();var product=null;
if(data.length){
var q=norm(userText).replace(/[.\-_ ]/g,'');
for(var i=0;i<data.length;i++){var p=data[i];var sku=(p.sku||p.model||p.mod||'').replace(/[.\-_ ]/g,'').toLowerCase();if(sku&&sku.length>3&&q.includes(sku)){product=p;break;}}
if(!product){var qn=norm(userText);for(var j=0;j<data.length;j++){var p2=data[j];var nameN=norm(p2.name||p2.n||'');if(nameN.length>8&&qn.includes(nameN)){product=p2;break;}}}
}
if(product){_lastProduct=product;}else if(_lastProduct){product=_lastProduct;}
var contextProducts=[];
var cat=detectCategory(userText);var brand=detectBrand(userText);var priceRange=detectPriceRange(userText);
var isContextQuery=cat||(brand&&!product)||(priceRange.max<Infinity||priceRange.min>0);
if(isContextQuery||!product){contextProducts=searchProductsByContext(userText,8);}
// Vision model for design questions
if(product&&/thiết kế|kiểu dáng|màu sắc|design|phong cách|chất liệu/i.test(userText)){
var imgV=product.image||product.img||product.i||'';
if(imgV){body.model=VISION_MODEL;var lu=body.messages[body.messages.length-1];if(lu&&lu.role==='user'&&typeof lu.content==='string')lu.content=[{type:'text',text:lu.content},{type:'image_url',image_url:{url:imgV}}];}
}
var strict='\n\n[QUY TẮC TUYỆT ĐỐI]:\n1. CHỈ trả lời dựa trên [DỮ LIỆU] bên dưới. KHÔNG bịa thông số/giá.\n2. Nếu không có data → "Em chưa có thông tin SP này, anh/chị liên hệ Zalo 0981873395".\n3. LUÔN đề cập TÊN SẢN PHẨM + GIÁ cụ thể.\n4. Gạch đầu dòng, ngắn gọn.\n5. Khi có nhiều SP: so sánh ưu/nhược.\n6. Cuối câu: gợi ý SP phù hợp nhất.';
if(product&&!isContextQuery){
var specs=product.specs||{};var ss='';if(typeof specs==='object')for(var sk2 in specs)ss+=sk2+':'+specs[sk2]+'; ';
var feats=(product.feats||[]).slice(0,10).join('; ');
strict+='\n\n[DỮ LIỆU SP]:\nTên: '+(product.name||product.n)+'\nGiá: '+(product.price||product.p||'LH')+'\nBrand: '+(product.brand||'')+'\nMã: '+(product.sku||product.mod||'');
if(ss)strict+='\nThông số: '+ss;if(feats)strict+='\nTính năng: '+feats;
if(product.summary||product.sum)strict+='\nMô tả: '+(product.summary||product.sum||'').substring(0,500);
}
if(contextProducts.length>0){
strict+='\n\n[DANH SÁCH SP PHÙ HỢP';
if(cat)strict+=' | Loại:'+cat;if(brand)strict+=' | Brand:'+brand;
if(priceRange.max<Infinity)strict+=' | Giá<'+fmt(priceRange.max);strict+=']:';
contextProducts.forEach(function(r,idx){var cp=r.p;strict+='\n'+(idx+1)+'. '+(cp.name||cp.n)+' | Giá:'+(cp.price||cp.p||'LH')+' | Mã:'+(cp.sku||cp.mod||'');if(cp.brand)strict+=' | '+cp.brand;var f=(cp.feats||[]).slice(0,3).join(', ');if(f)strict+=' | '+f;});
strict+='\n\n→ Giới thiệu TẤT CẢ SP trên, nêu tên + giá + ưu điểm chính. Gợi ý SP phù hợp nhất.';
}
var sys=body.messages.find(function(m){return m.role==='system';});
var sysPrompt='Bạn là tư vấn viên V.AI STUDIO — thiết bị bếp & gia dụng cao cấp. Xưng em, gọi anh/chị. Trả lời ngắn gọn, chuyên nghiệp, gạch đầu dòng. LUÔN nêu tên SP + giá cụ thể. Khi gợi ý, đề cập ít nhất 2-3 sản phẩm với giá.';
if(sys){if(typeof sys.content==='string')sys.content=sysPrompt+strict;}
else body.messages.unshift({role:'system',content:sysPrompt+strict});
options.body=JSON.stringify(body);
}
}catch(e){console.warn('[Chat Fix v14] hookAI error:',e);}
}
return _origFetch.apply(this,arguments);
};
_hookInstalled=true;
console.log('[Chat Fix v14] ✅ hookAI installed IMMEDIATELY');
// === CARD INJECTION + doAISearch (chạy sau DOM ready) ===
var PROCESSED='data-vc';
var _currentCategory='';
function getCards(botText,userText,limit){
limit=limit||6;
var cat=detectCategory(userText)||detectCategory(botText)||_currentCategory;
if(cat)_currentCategory=cat;
var contextResults=searchProductsByContext(userText,limit);
if(contextResults.length>=2)return contextResults.map(function(r){var p=r.p;return{name:p.name||p.n||'',slug:p.slug||'',price:p.price||p.p||'',image:p.image||p.img||p.i||'',model:p.model||p.mod||p.sku||'',brand:p.brand||''};});
var data=_D();if(data.length){
var n=norm(botText);var found=[];var seen={};
for(var i=0;i<data.length&&found.length<limit;i++){var p=data[i];if(!p||!p.slug||seen[p.slug])continue;var sku=(p.sku||p.model||p.mod||'').replace(/[.\-_ ]/g,'').toLowerCase();if(sku&&sku.length>3&&n.includes(sku)){seen[p.slug]=true;found.push({name:p.name||p.n||'',slug:p.slug,price:p.price||p.p||'',image:p.image||p.img||p.i||'',model:p.model||p.mod||'',brand:p.brand||''});}}
if(found.length)return found;
var botResults=searchProductsByContext(botText,limit);
if(botResults.length>=1)return botResults.map(function(r){var p=r.p;return{name:p.name||p.n||'',slug:p.slug||'',price:p.price||p.p||'',image:p.image||p.img||p.i||'',model:p.model||p.mod||p.sku||'',brand:p.brand||''};});
if(_conversationHistory.length){var histResults=searchProductsByContext(_conversationHistory.slice(-3).join(' '),limit);if(histResults.length>=1)return histResults.map(function(r){var p=r.p;return{name:p.name||p.n||'',slug:p.slug||'',price:p.price||p.p||'',image:p.image||p.img||p.i||'',model:p.model||p.mod||p.sku||'',brand:p.brand||''};});}
}
return[];
}
function createCardsHTML(products){
if(!products||!products.length)return'';
var h='<div style="display:flex;gap:8px;overflow-x:auto;padding:8px 0;margin-top:8px;scrollbar-width:thin">';
products.forEach(function(p){
h+='<div style="flex:0 0 130px;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.06);display:flex;flex-direction:column">';
h+='<div onclick="window._vaiGoProduct(\''+p.slug+'\')" style="cursor:pointer;flex:1">';
if(p.image)h+='<img src="'+p.image+'" style="width:100%;height:70px;object-fit:contain;background:#f8fafc;padding:3px" onerror="this.style.display=\'none\'">';
h+='<div style="padding:4px 6px"><div style="font-size:9.5px;font-weight:600;color:#003f62;line-height:1.2;height:22px;overflow:hidden">'+(p.name||'').substring(0,35)+'</div>';
if(p.model)h+='<div style="font-size:8px;color:#94a3b8;margin-top:1px">'+(p.model||'').substring(0,20)+'</div>';
h+='<div style="font-size:10px;font-weight:700;color:#059669;margin-top:2px">'+(p.price||'LH')+'</div></div></div>';
h+='<button class="vai-card-add" data-slug="'+p.slug+'" style="margin:2px 4px 4px;padding:3px;background:#003f62;color:#fff;border:none;border-radius:4px;font-size:9px;font-weight:700;cursor:pointer">+ Đơn</button>';
h+='</div>';
});
h+='</div>';return h;
}
function injectLoop(){
var chatBody=document.querySelector('.chat-body');if(!chatBody)return;
var lastUserMsg='';var userMsgs=chatBody.querySelectorAll('.chat-msg.user');
if(userMsgs.length)lastUserMsg=userMsgs[userMsgs.length-1].textContent||'';
var botMsgs=chatBody.querySelectorAll('.chat-msg.bot');
for(var i=0;i<botMsgs.length;i++){
var msg=botMsgs[i];if(msg.getAttribute(PROCESSED))continue;
var text=msg.textContent||'';
if(msg.querySelector('.chat-typing'))continue;
if(msg.classList.contains('streaming'))continue;
if(text.trim().length<5)continue;
msg.setAttribute(PROCESSED,'1');
if(lastUserMsg&&_conversationHistory[_conversationHistory.length-1]!==lastUserMsg){_conversationHistory.push(lastUserMsg);if(_conversationHistory.length>10)_conversationHistory.shift();}
var cards=getCards(text,lastUserMsg,6);
if(cards.length){var div=document.createElement('div');div.innerHTML=createCardsHTML(cards);msg.appendChild(div.firstChild);}
}
chatBody.querySelectorAll('.vai-card-add:not([data-b])').forEach(function(btn){
btn.setAttribute('data-b','1');
btn.addEventListener('click',function(e){e.preventDefault();e.stopPropagation();var slug=this.getAttribute('data-slug');if(!slug)return;var self=this;var data=_D();for(var i=0;i<data.length;i++){if(data[i]&&data[i].slug===slug){if(window._showOrderPicker){window._showOrderPicker(data[i],function(r){if(r==='ok'){self.textContent='✓';self.style.background='#059669';}else if(r==='dup'){self.textContent='Đã có';self.style.background='#94a3b8';}setTimeout(function(){self.textContent='+ Đơn';self.style.background='#003f62';},2500);});}break;}}});
});
}
// === doAISearch — SP mở trên trang hiện tại ===
window.doAISearch=function(){
var input=document.getElementById('aiSearch');var resultsDiv=document.getElementById('aiResults');
if(!input||!resultsDiv)return;var query=input.value.trim();
if(!query||query.length<2){resultsDiv.style.display='none';return;}
var data=_D();if(!data.length){resultsDiv.innerHTML='<p style="color:#64748b;text-align:center;padding:12px">Đang tải dữ liệu...</p>';resultsDiv.style.display='block';return;}
var results=searchProductsByContext(query,24);
if(!results.length){resultsDiv.innerHTML='<p style="color:#64748b;text-align:center;padding:16px">Không tìm thấy SP phù hợp.<br><span style="font-size:11px">VD: "bếp từ Grob dưới 10 triệu", "máy hút mùi Malloca"</span></p>';resultsDiv.style.display='block';return;}
var cat=detectCategory(query);var brand=detectBrand(query);var priceRange=detectPriceRange(query);
var parts=[];if(cat)parts.push('📂 '+cat);if(brand)parts.push('🏷 '+brand);if(priceRange.max<Infinity)parts.push('💰 <'+fmt(priceRange.max));if(priceRange.min>0)parts.push('💰 >'+fmt(priceRange.min));parts.push('🔍 '+results.length+' SP');
var html='<div style="margin-bottom:10px;display:flex;gap:6px;flex-wrap:wrap">'+parts.map(function(p){return'<span style="background:#eff6ff;padding:3px 8px;border-radius:20px;font-size:11px;font-weight:600;color:#1e40af;border:1px solid #bfdbfe">'+p+'</span>';}).join('')+'</div>';
html+='<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(145px,1fr));gap:8px">';
results.forEach(function(r){var p=r.p;var name=p.name||p.n||'';var price=p.price||p.p||'LH';var img=p.image||p.img||p.i||'';var slug=p.slug||'';var brand2=p.brand||'';var sku=p.sku||p.model||p.mod||'';
var feats=(p.feats||[]).slice(0,2).join(' • ');
html+='<div style="background:#fff;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden;transition:all .2s;cursor:pointer" onclick="window._vaiGoProduct(\''+slug+'\')" onmouseover="this.style.transform=\'translateY(-2px)\';this.style.boxShadow=\'0 4px 12px rgba(0,0,0,.1)\'" onmouseout="this.style.transform=\'\';this.style.boxShadow=\'\'">';
if(img)html+='<div style="height:85px;background:#f8fafc;display:flex;align-items:center;justify-content:center"><img src="'+img+'" style="max-width:100%;max-height:80px;object-fit:contain" onerror="this.parentElement.style.display=\'none\'"></div>';
html+='<div style="padding:6px 8px"><div style="font-size:11px;font-weight:600;color:#003f62;line-height:1.3;height:30px;overflow:hidden">'+name.substring(0,55)+'</div>';
if(sku)html+='<div style="font-size:9px;color:#94a3b8;margin-top:2px">'+sku+'</div>';
if(feats)html+='<div style="font-size:8.5px;color:#64748b;margin-top:2px;height:12px;overflow:hidden">'+feats+'</div>';
html+='<div style="font-size:12px;font-weight:800;color:#059669;margin-top:3px">'+price+'</div>';
if(brand2)html+='<div style="font-size:9px;color:#64748b;margin-top:1px">'+brand2+'</div>';
html+='</div>';
html+='<button onclick="event.stopPropagation();window._vaiAddFromAI(\''+slug+'\',this)" style="display:block;width:calc(100% - 10px);margin:0 5px 5px;padding:5px;background:#003f62;color:#fff;border:none;border-radius:6px;font-size:10px;font-weight:700;cursor:pointer">+ Đơn</button></div>';
});
html+='</div>';resultsDiv.innerHTML=html;resultsDiv.style.display='block';
};
window._vaiAddFromAI=function(slug,btn){
if(!slug)return;var data=_D();
for(var i=0;i<data.length;i++){if(data[i]&&data[i].slug===slug){if(window._showOrderPicker){window._showOrderPicker(data[i],function(r){if(r==='ok'){btn.textContent='✓';btn.style.background='#059669';}else if(r==='dup'){btn.textContent='Đã có';btn.style.background='#94a3b8';}setTimeout(function(){btn.textContent='+ Đơn';btn.style.background='#003f62';},2500);});}break;}}
};
// === SEARCH DROPDOWN ===
function initSearchDropdown(){
var searchInput=document.getElementById('q');if(!searchInput||searchInput.getAttribute('data-dd'))return;
searchInput.setAttribute('data-dd','1');
var dropdown=document.createElement('div');dropdown.id='vai-search-dropdown';
dropdown.style.cssText='position:absolute;left:0;right:0;top:100%;background:#fff;border:1px solid #e2e8f0;border-radius:0 0 12px 12px;box-shadow:0 8px 24px rgba(0,0,0,.12);max-height:520px;overflow-y:auto;z-index:9999;display:none';
var parent=searchInput.parentElement;if(parent){parent.style.position='relative';parent.appendChild(dropdown);}
var timer=null;
searchInput.addEventListener('input',function(){clearTimeout(timer);var q=this.value.trim();if(q.length<2){dropdown.style.display='none';return;}timer=setTimeout(function(){showDD(q);},200);});
searchInput.addEventListener('focus',function(){if(this.value.trim().length>=2)showDD(this.value.trim());});
document.addEventListener('click',function(e){if(!dropdown.contains(e.target)&&e.target!==searchInput)dropdown.style.display='none';});
function showDD(query){
var data=_D();if(!data.length){dropdown.style.display='none';return;}
var results=searchProductsByContext(query,15);
if(results.length<3){var kw=extractKeywords(query);var seen={};results.forEach(function(r){seen[r.p.slug]=true;});for(var i=0;i<data.length&&results.length<15;i++){var p=data[i];if(!p||seen[p.slug])continue;var nameN=norm(p.name||p.n||'');var score=0;for(var w=0;w<kw.length;w++){if(nameN.includes(kw[w]))score+=10;}if(score>0){seen[p.slug]=true;results.push({p:p,score:score});}}}
if(!results.length){dropdown.style.display='none';return;}
var html='';results.forEach(function(r){var p=r.p;var name=p.name||p.n||'';var price=p.price||p.p||'LH';var img=p.image||p.img||p.i||'';var slug=p.slug||'';var brand2=p.brand||'';
html+='<div class="vai-dd-item" style="padding:8px 12px;border-bottom:1px solid #f1f5f9;display:flex;align-items:center;gap:10px;cursor:pointer" onmouseover="this.style.background=\'#f8fafc\'" onmouseout="this.style.background=\'\'" data-slug="'+slug+'">';
if(img)html+='<img src="'+img+'" style="width:36px;height:36px;object-fit:contain;border-radius:4px;background:#f1f5f9;flex-shrink:0" onerror="this.style.display=\'none\'">';
html+='<div style="flex:1;overflow:hidden"><div style="font-size:12px;font-weight:600;color:#003f62;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">'+name.substring(0,55)+'</div><div style="font-size:10px;color:#64748b">'+brand2+'</div></div>';
html+='<div style="font-size:11px;font-weight:700;color:#059669;white-space:nowrap">'+price+'</div></div>';
});
dropdown.innerHTML=html;dropdown.style.display='block';
dropdown.querySelectorAll('.vai-dd-item').forEach(function(item){item.addEventListener('click',function(){var sl=this.getAttribute('data-slug');if(sl)window._vaiGoProduct(sl);dropdown.style.display='none';});});
}
}
function init(){
setInterval(injectLoop,800);
var chatBody=document.querySelector('.chat-body');
if(chatBody){var mo=new MutationObserver(function(){setTimeout(injectLoop,300);});mo.observe(chatBody,{childList:true,subtree:true});}
else{var retryObs=setInterval(function(){var cb=document.querySelector('.chat-body');if(cb){clearInterval(retryObs);var mo2=new MutationObserver(function(){setTimeout(injectLoop,300);});mo2.observe(cb,{childList:true,subtree:true});}},2000);setTimeout(function(){clearInterval(retryObs);},60000);}
var ddTimer=setInterval(function(){if(_D().length>100){clearInterval(ddTimer);initSearchDropdown();}},2000);
setTimeout(function(){clearInterval(ddTimer);initSearchDropdown();},15000);
}
if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',init);else init();
console.log('✅ Chat Fix v14 loaded: hookAI immediate + showDetail navigation + purge Malloca DMX');
})();