bep40 commited on
Commit
7dc97ea
·
verified ·
1 Parent(s): c97f940

v16: fix applyAiDiscount with phụ phí/cọc in quote + add +Giỏ/+Đơn buttons to AI search results

Browse files
Files changed (1) hide show
  1. index.html +73 -22
index.html CHANGED
@@ -2041,18 +2041,19 @@ let btn=document.getElementById('aiDiscBtn');
2041
  let statusEl=document.getElementById('aiDiscStatus');
2042
  if(!txt){if(statusEl)statusEl.textContent='VD: Malloca ck 35%, Eurogold ck 50%, gov304190 giá 7tr';return}
2043
 
2044
- // Parse commands — split by comma, semicolon, or newline
2045
  let commands=txt.split(/[,;\n]+/).map(c=>c.trim()).filter(c=>c.length>1);
2046
  let results=[];
2047
  let applied=0;
 
 
 
2048
 
2049
- // Known brands for matching
2050
  const BRANDS=['malloca','grob','canzy','eurogold','garis','demax','hafele','boss','teka','bosch'];
2051
 
2052
  commands.forEach(cmd=>{
2053
  let cmdLow=cmd.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g,'').replace(/[đĐ]/g,'d');
2054
 
2055
- // Pattern 1: [Brand] ck/giảm [X]% — brand-specific discount
2056
  let brandCkMatch=cmdLow.match(/^(\w+)\s+(?:ck|chiet khau|giam|discount)\s*(\d+)\s*%?/);
2057
  if(brandCkMatch){
2058
  let brandName=brandCkMatch[1];
@@ -2075,62 +2076,70 @@ commands.forEach(cmd=>{
2075
  }
2076
  }
2077
 
2078
- // Pattern 2: [Mã SP] giá [X] — fixed price for specific SKU
2079
- let skuPriceMatch=cmdLow.match(/^([a-z0-9_\-]+)\s+(?:gia|giá|price)\s*([\d.,]+)\s*(tr|trieu|k|m|nghin|nghìn)?/);
2080
  if(skuPriceMatch){
2081
  let skuQuery=skuPriceMatch[1].replace(/[.\-_ ]/g,'');
2082
  let priceVal=parseFloat(skuPriceMatch[2].replace(/\./g,'').replace(',','.'));
2083
  let unit=(skuPriceMatch[3]||'').toLowerCase();
2084
  if(unit==='tr'||unit==='trieu'||unit==='m')priceVal*=1000000;
2085
- else if(unit==='k'||unit==='nghin'||unit==='nghìn')priceVal*=1000;
2086
- else if(priceVal>0&&priceVal<500)priceVal*=1000000; // auto: dưới 500 → triệu
2087
-
2088
  if(priceVal>0){
2089
  cart.forEach((c,i)=>{
2090
- let cSku=((c.sku||'')+(c.mod||'')).toLowerCase().replace(/[.\-_ ]/g,'');
2091
  if(cSku.indexOf(skuQuery)!==-1||skuQuery.indexOf(cSku)!==-1){
2092
  let el=document.querySelector('.qt-disc[data-idx="'+i+'"]');
2093
- if(el){el.value=priceVal.toLocaleString('vi-VN');applied++;results.push((c.sku||c.mod||skuQuery)+' → '+priceVal.toLocaleString('vi-VN')+'đ');}
2094
  }
2095
  });
2096
  }
2097
  return;
2098
  }
2099
 
2100
- // Pattern 3: ck/giảm [X]% (tất cả) — global discount
2101
  let globalCkMatch=cmdLow.match(/(?:ck|chiet khau|giam|discount)\s*(\d+)\s*%/);
2102
  if(globalCkMatch){
2103
  let pct=parseFloat(globalCkMatch[1]);
2104
  if(pct>0&&pct<=90){
 
2105
  cart.forEach((c,i)=>{
2106
  if(c.priceNum>0){
2107
  let dp=Math.round(c.priceNum*(1-pct/100));
2108
  let el=document.querySelector('.qt-disc[data-idx="'+i+'"]');
2109
- if(el){el.value=dp.toLocaleString('vi-VN');applied++;}
2110
  }
2111
  });
2112
- results.push('CK '+pct+'% tất cả ('+applied+' SP)');
2113
  }
2114
  return;
2115
  }
2116
 
2117
- // Pattern 4: phụ phí / cọc
2118
- let feeMatch=cmdLow.match(/(?:phu phi|phi|fee)\s*([\d.,]+)\s*(k|tr|trieu|m|nghin)?/);
2119
  if(feeMatch){
2120
  let fee=parseFloat(feeMatch[1].replace(/\./g,'').replace(',','.'));
2121
  let u2=(feeMatch[2]||'').toLowerCase();
2122
  if(u2==='k'||u2==='nghin')fee*=1000;
2123
  else if(u2==='tr'||u2==='trieu'||u2==='m')fee*=1000000;
2124
- results.push('Phụ phí: '+fee.toLocaleString('vi-VN')+'đ');
 
 
2125
  return;
2126
  }
 
 
2127
  let cocMatch=cmdLow.match(/(?:coc|dat coc|deposit)\s*([\d.,]+)\s*(k|tr|trieu|%|m)?/);
2128
  if(cocMatch){
2129
  let cocVal=parseFloat(cocMatch[1].replace(/\./g,'').replace(',','.'));
2130
  let cu=(cocMatch[2]||'').toLowerCase();
2131
- if(cu==='%'){results.push('Cọc: '+cocVal+'% tổng');}
2132
- else{
 
 
2133
  if(cu==='k')cocVal*=1000;else if(cu==='tr'||cu==='trieu'||cu==='m')cocVal*=1000000;
 
 
2134
  results.push('Cọc: '+cocVal.toLocaleString('vi-VN')+'đ');
2135
  }
2136
  return;
@@ -2138,9 +2147,47 @@ commands.forEach(cmd=>{
2138
  });
2139
 
2140
  updateQuoteTotal();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2141
  if(statusEl){
2142
  if(results.length)statusEl.innerHTML='✅ '+results.join(' | ');
2143
- else statusEl.textContent='⚠️ Không nhận diện. VD: Malloca ck 35%, gov304190 giá 7tr, ck 20% tất cả';
2144
  }
2145
  }
2146
 
@@ -2834,10 +2881,9 @@ Miễn phí giao hàng trong TPHCM. | Giá đã bao gồm VAT.
2834
  document.getElementById('aiResults').innerHTML='⏳ Đang tải dữ liệu...';document.getElementById('aiResults').style.display='block';
2835
  }
2836
  function _renderAIResults(prods,res){
2837
- var norm=window._vaiSearchContext?function(s){return(s||'').normalize('NFD').replace(/[\u0300-\u036f]/g,'').replace(/[Đđ]/g,'d').toLowerCase()}:function(s){return(s||'').toLowerCase()};
2838
  var cat=window._vaiDetectCategory?window._vaiDetectCategory(document.getElementById('aiSearch').value):'';
2839
  var brand=window._vaiDetectBrand?window._vaiDetectBrand(document.getElementById('aiSearch').value):'';
2840
- var fmt=function(n){if(!n||isNaN(n))return'LH';return Number(n).toLocaleString('vi-VN')+'đ'};
2841
  var parts=[];
2842
  if(cat)parts.push('📂 '+cat);if(brand)parts.push('🏷 '+brand);
2843
  parts.push('🔍 '+prods.length+' SP');
@@ -2845,7 +2891,7 @@ function _renderAIResults(prods,res){
2845
  h+='<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(170px,1fr));gap:10px">';
2846
  prods.slice(0,24).forEach(function(p){
2847
  var idx=D.indexOf(p);
2848
- var name=p.name||p.n||'';var price=p.price||p.p||'LH';var img=p.image||p.img||p.i||'';var sku=p.sku||p.model||p.mod||'';var brand2=p.brand||'';
2849
  var feats=(p.feats||[]).slice(0,2).join(' • ');
2850
  var specs=p.specs||{};var sk=Object.entries(specs).slice(0,3);
2851
  h+='<div style="background:#fff;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden;transition:all .2s;cursor:pointer" onclick="showDetail('+idx+')" onmouseover="this.style.transform=\'translateY(-2px)\';this.style.boxShadow=\'0 4px 12px rgba(0,0,0,.1)\'" onmouseout="this.style.transform=\'\';this.style.boxShadow=\'\'">';
@@ -2856,6 +2902,11 @@ function _renderAIResults(prods,res){
2856
  if(feats)h+='<div style="font-size:8.5px;color:#64748b;margin-top:2px;height:12px;overflow:hidden">'+feats+'</div>';
2857
  if(sk.length){h+='<div style="margin-top:3px;font-size:8px;color:#555;border-top:1px solid #f0f0f0;padding-top:3px">';sk.forEach(function(kv){h+=kv[0]+': <b>'+kv[1]+'</b><br>'});h+='</div>'}
2858
  h+='<div style="font-size:13px;font-weight:800;color:#059669;margin-top:4px">'+price+'</div>';
 
 
 
 
 
2859
  h+='</div></div>';
2860
  });
2861
  h+='</div>';res.innerHTML=h;
 
2041
  let statusEl=document.getElementById('aiDiscStatus');
2042
  if(!txt){if(statusEl)statusEl.textContent='VD: Malloca ck 35%, Eurogold ck 50%, gov304190 giá 7tr';return}
2043
 
 
2044
  let commands=txt.split(/[,;\n]+/).map(c=>c.trim()).filter(c=>c.length>1);
2045
  let results=[];
2046
  let applied=0;
2047
+ let extraFee=0;
2048
+ let deposit=0;
2049
+ let depositPct=0;
2050
 
 
2051
  const BRANDS=['malloca','grob','canzy','eurogold','garis','demax','hafele','boss','teka','bosch'];
2052
 
2053
  commands.forEach(cmd=>{
2054
  let cmdLow=cmd.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g,'').replace(/[đĐ]/g,'d');
2055
 
2056
+ // Pattern 1: [Brand] ck/giảm [X]%
2057
  let brandCkMatch=cmdLow.match(/^(\w+)\s+(?:ck|chiet khau|giam|discount)\s*(\d+)\s*%?/);
2058
  if(brandCkMatch){
2059
  let brandName=brandCkMatch[1];
 
2076
  }
2077
  }
2078
 
2079
+ // Pattern 2: [Mã SP] giá [X]
2080
+ let skuPriceMatch=cmdLow.match(/^([a-z0-9_\-]+)\s+(?:gia|price)\s*([\d.,]+)\s*(tr|trieu|k|m|nghin)?/);
2081
  if(skuPriceMatch){
2082
  let skuQuery=skuPriceMatch[1].replace(/[.\-_ ]/g,'');
2083
  let priceVal=parseFloat(skuPriceMatch[2].replace(/\./g,'').replace(',','.'));
2084
  let unit=(skuPriceMatch[3]||'').toLowerCase();
2085
  if(unit==='tr'||unit==='trieu'||unit==='m')priceVal*=1000000;
2086
+ else if(unit==='k'||unit==='nghin')priceVal*=1000;
2087
+ else if(priceVal>0&&priceVal<500)priceVal*=1000000;
 
2088
  if(priceVal>0){
2089
  cart.forEach((c,i)=>{
2090
+ let cSku=((c.sku||'')+(c.model||c.mod||'')).toLowerCase().replace(/[.\-_ ]/g,'');
2091
  if(cSku.indexOf(skuQuery)!==-1||skuQuery.indexOf(cSku)!==-1){
2092
  let el=document.querySelector('.qt-disc[data-idx="'+i+'"]');
2093
+ if(el){el.value=priceVal.toLocaleString('vi-VN');applied++;results.push((c.sku||c.model||skuQuery)+' → '+priceVal.toLocaleString('vi-VN')+'đ');}
2094
  }
2095
  });
2096
  }
2097
  return;
2098
  }
2099
 
2100
+ // Pattern 3: ck/giảm [X]% (tất cả)
2101
  let globalCkMatch=cmdLow.match(/(?:ck|chiet khau|giam|discount)\s*(\d+)\s*%/);
2102
  if(globalCkMatch){
2103
  let pct=parseFloat(globalCkMatch[1]);
2104
  if(pct>0&&pct<=90){
2105
+ let count=0;
2106
  cart.forEach((c,i)=>{
2107
  if(c.priceNum>0){
2108
  let dp=Math.round(c.priceNum*(1-pct/100));
2109
  let el=document.querySelector('.qt-disc[data-idx="'+i+'"]');
2110
+ if(el){el.value=dp.toLocaleString('vi-VN');count++;}
2111
  }
2112
  });
2113
+ results.push('CK '+pct+'% tất cả ('+count+' SP)');applied+=count;
2114
  }
2115
  return;
2116
  }
2117
 
2118
+ // Pattern 4: phụ phí
2119
+ let feeMatch=cmdLow.match(/(?:phu phi|phi|fee|van chuyen|ship)\s*([\d.,]+)\s*(k|tr|trieu|m|nghin)?/);
2120
  if(feeMatch){
2121
  let fee=parseFloat(feeMatch[1].replace(/\./g,'').replace(',','.'));
2122
  let u2=(feeMatch[2]||'').toLowerCase();
2123
  if(u2==='k'||u2==='nghin')fee*=1000;
2124
  else if(u2==='tr'||u2==='trieu'||u2==='m')fee*=1000000;
2125
+ else if(fee>0&&fee<500)fee*=1000;
2126
+ extraFee+=fee;
2127
+ results.push('Phụ phí: +'+fee.toLocaleString('vi-VN')+'đ');
2128
  return;
2129
  }
2130
+
2131
+ // Pattern 5: cọc
2132
  let cocMatch=cmdLow.match(/(?:coc|dat coc|deposit)\s*([\d.,]+)\s*(k|tr|trieu|%|m)?/);
2133
  if(cocMatch){
2134
  let cocVal=parseFloat(cocMatch[1].replace(/\./g,'').replace(',','.'));
2135
  let cu=(cocMatch[2]||'').toLowerCase();
2136
+ if(cu==='%'){
2137
+ depositPct=cocVal;
2138
+ results.push('Cọc: '+cocVal+'%');
2139
+ }else{
2140
  if(cu==='k')cocVal*=1000;else if(cu==='tr'||cu==='trieu'||cu==='m')cocVal*=1000000;
2141
+ else if(cocVal>0&&cocVal<500)cocVal*=1000000;
2142
+ deposit=cocVal;
2143
  results.push('Cọc: '+cocVal.toLocaleString('vi-VN')+'đ');
2144
  }
2145
  return;
 
2147
  });
2148
 
2149
  updateQuoteTotal();
2150
+
2151
+ // Add phụ phí/cọc rows to quote footer
2152
+ let tfoot=document.querySelector('.quote-table tfoot');
2153
+ // Remove old extra rows
2154
+ document.querySelectorAll('.qt-extra-row').forEach(r=>r.remove());
2155
+
2156
+ if(tfoot&&(extraFee>0||deposit>0||depositPct>0)){
2157
+ let totalCell=document.getElementById('quoteTotalCell');
2158
+ let totalVal=parseInt((totalCell?totalCell.textContent:'0').replace(/\D/g,''))||0;
2159
+ let insertBefore=tfoot.querySelector('.quote-total-row');
2160
+
2161
+ if(extraFee>0){
2162
+ let feeRow=document.createElement('tr');
2163
+ feeRow.className='qt-extra-row';
2164
+ feeRow.innerHTML='<td colspan="8" style="text-align:right;padding-right:12px;font-size:.82rem;color:#64748b">Phụ phí:</td><td class="qt-price" style="font-size:.82rem;color:#e53935;font-weight:700">+'+extraFee.toLocaleString('vi-VN')+'đ</td><td></td>';
2165
+ if(insertBefore)tfoot.insertBefore(feeRow,insertBefore);else tfoot.appendChild(feeRow);
2166
+ totalVal+=extraFee;
2167
+ }
2168
+
2169
+ // Update total with fee
2170
+ if(extraFee>0&&totalCell){
2171
+ totalCell.textContent=totalVal.toLocaleString('vi-VN')+'đ';
2172
+ }
2173
+
2174
+ if(deposit>0||depositPct>0){
2175
+ let cocAmt=deposit>0?deposit:Math.round(totalVal*depositPct/100);
2176
+ let cocRow=document.createElement('tr');
2177
+ cocRow.className='qt-extra-row';
2178
+ cocRow.innerHTML='<td colspan="8" style="text-align:right;padding-right:12px;font-size:.82rem;color:#2563eb;font-weight:600">Đặt cọc'+(depositPct>0?' ('+depositPct+'%)':'')+':</td><td class="qt-price" style="font-size:.82rem;color:#2563eb;font-weight:700">'+cocAmt.toLocaleString('vi-VN')+'đ</td><td></td>';
2179
+ tfoot.appendChild(cocRow);
2180
+
2181
+ let remainRow=document.createElement('tr');
2182
+ remainRow.className='qt-extra-row';
2183
+ remainRow.innerHTML='<td colspan="8" style="text-align:right;padding-right:12px;font-size:.82rem;color:#059669;font-weight:600">Còn lại:</td><td class="qt-price" style="font-size:.82rem;color:#059669;font-weight:700">'+(totalVal-cocAmt).toLocaleString('vi-VN')+'đ</td><td></td>';
2184
+ tfoot.appendChild(remainRow);
2185
+ }
2186
+ }
2187
+
2188
  if(statusEl){
2189
  if(results.length)statusEl.innerHTML='✅ '+results.join(' | ');
2190
+ else statusEl.textContent='⚠️ Không nhận diện. VD: Malloca ck 35%, gov304190 giá 7tr, phụ phí 500k, cọc 30%';
2191
  }
2192
  }
2193
 
 
2881
  document.getElementById('aiResults').innerHTML='⏳ Đang tải dữ liệu...';document.getElementById('aiResults').style.display='block';
2882
  }
2883
  function _renderAIResults(prods,res){
2884
+ var fmt=function(n){if(!n||isNaN(n))return'LH';return Number(n).toLocaleString('vi-VN')+'đ'};
2885
  var cat=window._vaiDetectCategory?window._vaiDetectCategory(document.getElementById('aiSearch').value):'';
2886
  var brand=window._vaiDetectBrand?window._vaiDetectBrand(document.getElementById('aiSearch').value):'';
 
2887
  var parts=[];
2888
  if(cat)parts.push('📂 '+cat);if(brand)parts.push('🏷 '+brand);
2889
  parts.push('🔍 '+prods.length+' SP');
 
2891
  h+='<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(170px,1fr));gap:10px">';
2892
  prods.slice(0,24).forEach(function(p){
2893
  var idx=D.indexOf(p);
2894
+ var name=p.name||p.n||'';var price=p.price||p.p||'LH';var img=p.image||p.img||p.i||'';var sku=p.sku||p.model||p.mod||'';var brand2=p.brand||'';var slug=p.slug||'';
2895
  var feats=(p.feats||[]).slice(0,2).join(' • ');
2896
  var specs=p.specs||{};var sk=Object.entries(specs).slice(0,3);
2897
  h+='<div style="background:#fff;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden;transition:all .2s;cursor:pointer" onclick="showDetail('+idx+')" onmouseover="this.style.transform=\'translateY(-2px)\';this.style.boxShadow=\'0 4px 12px rgba(0,0,0,.1)\'" onmouseout="this.style.transform=\'\';this.style.boxShadow=\'\'">';
 
2902
  if(feats)h+='<div style="font-size:8.5px;color:#64748b;margin-top:2px;height:12px;overflow:hidden">'+feats+'</div>';
2903
  if(sk.length){h+='<div style="margin-top:3px;font-size:8px;color:#555;border-top:1px solid #f0f0f0;padding-top:3px">';sk.forEach(function(kv){h+=kv[0]+': <b>'+kv[1]+'</b><br>'});h+='</div>'}
2904
  h+='<div style="font-size:13px;font-weight:800;color:#059669;margin-top:4px">'+price+'</div>';
2905
+ h+='</div>';
2906
+ // Buttons: +Giỏ hàng + +Đơn
2907
+ h+='<div style="display:flex;gap:4px;padding:0 6px 6px">';
2908
+ h+='<button onclick="event.stopPropagation();if(typeof addToCart===\'function\')addToCart('+idx+')" style="flex:1;padding:4px;background:#db9815;color:#fff;border:none;border-radius:5px;font-size:9px;font-weight:700;cursor:pointer">+ Giỏ</button>';
2909
+ h+='<button onclick="event.stopPropagation();window._vaiAddOrder(\''+slug+'\',this)" style="flex:1;padding:4px;background:#003f62;color:#fff;border:none;border-radius:5px;font-size:9px;font-weight:700;cursor:pointer">+ Đơn</button>';
2910
  h+='</div></div>';
2911
  });
2912
  h+='</div>';res.innerHTML=h;