bep40 commited on
Commit
dfb7fab
·
verified ·
1 Parent(s): d7fc62e

Fix search: strip . - space from queries for SKU matching, add cleaned SKU to search index

Browse files
Files changed (1) hide show
  1. index.html +10 -4
index.html CHANGED
@@ -712,25 +712,31 @@ function nVN(s){return s.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]
712
  const SYN={'ke':['gia'],'gia':['ke'],'bat':['chen'],'chen':['bat'],'xoong':['noi'],'noi':['xoong'],'dao':['thot'],'thot':['dao'],'ray':['truot'],'truot':['ray'],'khoa':['lock'],'lock':['khoa'],'bon':['chau'],'chau':['bon'],'ro':['gia','ke']};
713
 
714
  function smartSearch(query,text){
715
- // 1. Exact substring (fastest path)
 
 
 
 
716
  if(text.includes(query))return true;
717
  // 2. Split into words, ALL must match (any order)
718
  let words=query.split(/\s+/).filter(w=>w);
719
  if(!words.length)return true;
720
  let matched=0;
721
  for(let w of words){
722
- if(text.includes(w)){matched++;continue;}
 
723
  // Try synonym
724
  let hit=false;
725
  if(SYN[w]){for(let s of SYN[w]){if(text.includes(s)){hit=true;break;}}}
726
  if(hit){matched++;continue;}
727
  }
728
- // All words must match
729
  return matched===words.length;
730
  }
731
  function buildSearchIndex(p){
732
- // Only index product-specific content, NOT generic category names
733
  let parts=[p.name,p.sku,p.model,p.brand,p.price];
 
 
 
734
  if(p.feats&&p.feats.length)parts.push(p.feats.join(' '));
735
  if(p.specs){Object.entries(p.specs).forEach(([k,v])=>{parts.push(k);parts.push(String(v))})}
736
  // AI semantic keywords based on product name
 
712
  const SYN={'ke':['gia'],'gia':['ke'],'bat':['chen'],'chen':['bat'],'xoong':['noi'],'noi':['xoong'],'dao':['thot'],'thot':['dao'],'ray':['truot'],'truot':['ray'],'khoa':['lock'],'lock':['khoa'],'bon':['chau'],'chau':['bon'],'ro':['gia','ke']};
713
 
714
  function smartSearch(query,text){
715
+ // Strip . - space from query for SKU matching
716
+ let cleanQ=query.replace(/[.\- ]/g,'');
717
+ let cleanT=text.replace(/[.\- ]/g,'');
718
+ // 1. Exact substring on cleaned versions
719
+ if(cleanT.includes(cleanQ))return true;
720
  if(text.includes(query))return true;
721
  // 2. Split into words, ALL must match (any order)
722
  let words=query.split(/\s+/).filter(w=>w);
723
  if(!words.length)return true;
724
  let matched=0;
725
  for(let w of words){
726
+ let cw=w.replace(/[.\-]/g,'');
727
+ if(text.includes(w)||cleanT.includes(cw)){matched++;continue;}
728
  // Try synonym
729
  let hit=false;
730
  if(SYN[w]){for(let s of SYN[w]){if(text.includes(s)){hit=true;break;}}}
731
  if(hit){matched++;continue;}
732
  }
 
733
  return matched===words.length;
734
  }
735
  function buildSearchIndex(p){
 
736
  let parts=[p.name,p.sku,p.model,p.brand,p.price];
737
+ // Add cleaned SKU/model (no . - space) for search
738
+ if(p.sku)parts.push(p.sku.replace(/[.\- ]/g,''));
739
+ if(p.model)parts.push(p.model.replace(/[.\- ]/g,''));
740
  if(p.feats&&p.feats.length)parts.push(p.feats.join(' '));
741
  if(p.specs){Object.entries(p.specs).forEach(([k,v])=>{parts.push(k);parts.push(String(v))})}
742
  // AI semantic keywords based on product name