V.AISTUDIO / order-button.js
bep40's picture
fix: expose showOrderPicker ra global cho cards AI gọi được nút +Đơn
51e6db5 verified
/**
* V.AI STUDIO — Order Button v4
*
* v4: Expose showOrderPicker ra window._showOrderPicker
* để cards SP trong chat AI cũng có nút "+ Đơn" hoạt động
*/
(function(){
'use strict';
var STORE_KEY='vai_orders';
function waitReady(cb){
var t=setInterval(function(){
if(typeof D!=='undefined'&&D.length>100){clearInterval(t);cb();}
},2000);
setTimeout(function(){clearInterval(t);cb();},20000);
}
function fmt(n){if(!n||isNaN(n))return'0đ';return Number(n).toLocaleString('vi-VN')+'đ';}
function getOrdersSafe(){
if(window.VAI_ORDERS&&typeof window.VAI_ORDERS.getAll==='function'){
var orders=window.VAI_ORDERS.getAll();
if(orders&&orders.length)return orders;
}
try{
var raw=localStorage.getItem(STORE_KEY);
if(raw){var parsed=JSON.parse(raw);if(Array.isArray(parsed)&&parsed.length)return parsed;}
}catch(e){}
return [];
}
function addOrderSafe(order){
if(window.VAI_ORDERS&&typeof window.VAI_ORDERS.add==='function'){
window.VAI_ORDERS.add(order);
}else{
try{
var orders=getOrdersSafe();
var idx=orders.findIndex(function(o){return o.code===order.code;});
if(idx>=0)orders[idx]=order;else orders.unshift(order);
localStorage.setItem(STORE_KEY,JSON.stringify(orders));
}catch(e){}
}
}
function showOrderPicker(product,onDone){
var old=document.getElementById('vai-order-picker');if(old)old.remove();
var orders=getOrdersSafe();
var overlay=document.createElement('div');
overlay.id='vai-order-picker';
overlay.style.cssText='position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:99999;display:flex;align-items:center;justify-content:center;padding:16px;backdrop-filter:blur(2px)';
overlay.addEventListener('click',function(e){if(e.target===overlay)overlay.remove();});
var name=product.name||product.n||'';
var sku=product.sku||product.model||product.mod||'';
var price=product.priceNum||product.pn||0;
if(!price)price=parseInt((product.price||product.p||'').toString().replace(/[^\d]/g,''))||0;
var h='<div style="background:#fff;border-radius:16px;max-width:420px;width:100%;max-height:75vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.3)">';
h+='<div style="padding:14px 18px;background:#003f62;border-radius:16px 16px 0 0;color:#fff"><div style="font-weight:800;font-size:14px">🛒 Thêm vào đơn</div><div style="font-size:11px;margin-top:4px;color:#bae6fd">'+name.substring(0,45)+'</div>';
if(sku)h+='<div style="font-size:10px;color:#93c5fd;margin-top:2px">Mã: '+sku+' • Giá: '+fmt(price)+'</div>';
h+='</div><div style="padding:14px 18px">';
if(!orders.length){
h+='<div style="text-align:center;padding:24px 16px;color:#64748b"><div style="font-size:32px;margin-bottom:8px">📋</div><div style="font-weight:600;margin-bottom:4px">Chưa có đơn hàng nào</div><div style="font-size:11px;color:#94a3b8">Vui lòng tạo báo giá trước, sau đó lưu đơn.</div></div>';
}else{
h+='<div style="font-size:11px;color:#64748b;margin-bottom:8px;font-weight:600">Chọn đơn hàng ('+orders.length+' đơn):</div>';
orders.forEach(function(o,idx){
var isC=o.status==='confirmed';var itemCount=(o.items&&o.items.length)||0;
h+='<div class="vai-op-item" data-idx="'+idx+'" style="padding:10px 12px;border:1px solid #e2e8f0;border-radius:8px;margin-bottom:6px;cursor:pointer;transition:all .15s;border-left:3px solid '+(isC?'#16a34a':'#f59e0b')+'" onmouseover="this.style.background=\'#f0f9ff\'" onmouseout="this.style.background=\'\'">';
h+='<div style="display:flex;justify-content:space-between;align-items:center"><b style="color:#003f62;font-size:13px">'+o.code+'</b><span style="font-size:10px;background:#f1f5f9;padding:2px 6px;border-radius:4px;color:#475569">'+itemCount+' SP</span></div>';
h+='<div style="font-size:11px;color:#64748b;margin-top:3px">'+(o.customer||'Chưa có KH')+(o.grandTotal?' • <b style="color:#059669">'+fmt(o.grandTotal)+'</b>':'')+'</div></div>';
});
}
h+='<button id="vai-op-close" style="margin-top:12px;width:100%;padding:10px;background:#e2e8f0;border:none;border-radius:8px;font-weight:600;cursor:pointer;font-size:12px;color:#475569">Đóng</button></div></div>';
overlay.innerHTML=h;document.body.appendChild(overlay);
document.getElementById('vai-op-close').onclick=function(){overlay.remove();};
overlay.querySelectorAll('.vai-op-item').forEach(function(item){
item.addEventListener('click',function(){
var idx=parseInt(this.getAttribute('data-idx'));
var order=JSON.parse(JSON.stringify(orders[idx]));
if(!order)return;order.items=order.items||[];
if(sku){for(var i=0;i<order.items.length;i++){if(order.items[i].model===sku){overlay.remove();if(typeof showToast==='function')showToast('ℹ️ SP đã có trong đơn '+order.code);if(onDone)onDone('dup');return;}}}
order.items.push({name:name,model:sku,image:product.image||product.img||product.i||'',price:price,discPrice:price,qty:1,total:price,brand:product.brand||'',note:''});
order.grandTotal=(order.grandTotal||0)+price;order.remaining=(order.remaining||0)+price;order.savedAt=new Date().toISOString();
addOrderSafe(order);overlay.remove();
if(typeof showToast==='function')showToast('✅ Đã thêm vào đơn '+order.code);
if(onDone)onDone('ok');
});
});
}
// === EXPOSE ra global để chat-fix.js cards gọi được ===
window._showOrderPicker=showOrderPicker;
function enhanceSearchDropdown(){
new MutationObserver(function(){
var dropdown=document.getElementById('vai-search-dropdown');
if(!dropdown||dropdown.style.display==='none')return;
dropdown.querySelectorAll('.vai-dd-item:not([data-ob])').forEach(function(item){
item.setAttribute('data-ob','1');
var slug=item.getAttribute('data-slug');if(!slug)return;
var btn=document.createElement('button');
btn.textContent='+ Đơn';
btn.style.cssText='padding:4px 8px;background:#003f62;color:#fff;border:none;border-radius:4px;font-size:10px;font-weight:700;cursor:pointer;white-space:nowrap;margin-left:6px;flex-shrink:0';
btn.addEventListener('click',function(e){
e.stopPropagation();e.preventDefault();
if(typeof D==='undefined'||!D.length)return;
for(var i=0;i<D.length;i++){
if(D[i]&&D[i].slug===slug){
showOrderPicker(D[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;
}
}
});
item.appendChild(btn);
});
}).observe(document.body,{childList:true,subtree:true,attributes:true});
}
function addProductPageButton(){
var slugMatch=window.location.pathname.match(/\/san-pham\/([^/]+)/);
if(!slugMatch)return;var slug=slugMatch[1];
var attempts=0;var t=setInterval(function(){
attempts++;if(attempts>30){clearInterval(t);return;}
if(typeof D==='undefined'||!D.length)return;
if(document.getElementById('vai-page-add-btn'))return;
var product=null;for(var i=0;i<D.length;i++){if(D[i]&&D[i].slug===slug){product=D[i];break;}}
if(!product)return;clearInterval(t);
var btn=document.createElement('button');btn.id='vai-page-add-btn';btn.innerHTML='🛒 Thêm vào đơn';
btn.style.cssText='position:fixed;bottom:80px;right:16px;z-index:999;padding:12px 20px;background:linear-gradient(135deg,#003f62,#0369a1);color:#fff;border:none;border-radius:30px;font-size:14px;font-weight:700;cursor:pointer;box-shadow:0 4px 16px rgba(0,63,98,.4);transition:transform .2s';
btn.onmouseover=function(){this.style.transform='scale(1.05)';};btn.onmouseout=function(){this.style.transform='';};
btn.addEventListener('click',function(){
showOrderPicker(product,function(r){
if(r==='ok'){btn.innerHTML='✅ Đã thêm!';btn.style.background='linear-gradient(135deg,#059669,#10b981)';}
else if(r==='dup'){btn.innerHTML='ℹ️ Đã có';btn.style.background='#64748b';}
setTimeout(function(){btn.innerHTML='🛒 Thêm vào đơn';btn.style.background='linear-gradient(135deg,#003f62,#0369a1)';},2500);
});
});
document.body.appendChild(btn);
},1500);
}
waitReady(function(){enhanceSearchDropdown();addProductPageButton();console.log('✅ Order buttons v4 | Exposed _showOrderPicker | Orders:',getOrdersSafe().length);});
})();