Upload src/app.js

#6
by bep40 - opened
Files changed (1) hide show
  1. src/app.js +45 -14
src/app.js CHANGED
@@ -127,7 +127,7 @@ const chatMessages = /** @type {HTMLElement} */ ($("#chat-messages"));
127
  const chatInput = /** @type {HTMLInputElement} */ ($("#chat-input"));
128
  const chatSendBtn = /** @type {HTMLButtonElement} */ ($("#chat-send-btn"));
129
  const chatCloseBtn = /** @type {HTMLButtonElement} */ ($("#chat-close-btn"));
130
- const chatResizeHandle = /** @type {HTMLElement} */ ($("#chat-resize-handle"));
131
  const chatAvatarSelect = /** @type {HTMLSelectElement} */ ($("#chat-avatar-select"));
132
  const settingsAvatarSelect = /** @type {HTMLSelectElement} */ ($("#settings-avatar-select"));
133
 
@@ -644,17 +644,19 @@ async function loadVaistudioProducts(loadMore = false) {
644
  }
645
  }
646
 
647
- async function searchP(q) {
648
- if (!q || !q.trim()) { _lastSearchResults = []; vaistudioCurrentSearch = ""; if (vaistudioAllProducts.length > 0 && vaistudioProductsLoaded) { renderPaginated(vaistudioAllProducts); if (vaistudioCount) vaistudioCount.textContent = vaistudioAllProducts.length + " sản phẩm"; } return; }
649
- vaistudioCurrentSearch = q.trim();
650
- if (vaistudioProducts) { vaistudioProducts.innerHTML = ""; vaistudioProducts.style.display = "block"; }
651
- if (vaistudioCount) vaistudioCount.textContent = "Đang tìm...";
652
- try {
653
- const resp = await fetch("/api/vaix/search?q=" + encodeURIComponent(q.trim())); const json = await resp.json();
654
- _lastSearchResults = (json.results || []).map(r => r.product); renderPaginated(_lastSearchResults);
655
- if (vaistudioCount) vaistudioCount.textContent = _lastSearchResults.length + " kết quả";
656
- if (!_lastSearchResults.length) clientSearch(q);
657
- } catch (err) { clientSearch(q); }
 
 
658
  }
659
 
660
  function clientSearch(q) { const norm=_sd(q),terms=norm.split(/\s+/).filter(t=>t.length>1); const r=vaistudioAllProducts.filter(p=>{const s=[_sd(p.title_clean||""),_sd(p.sku||""),_sd(p.brand||""),_sd(p.category||"")].join(" "); return terms.every(t=>s.includes(t));}); _lastSearchResults=r; renderPaginated(r); if(vaistudioCount) vaistudioCount.textContent=r.length+" kết quả"; }
@@ -667,9 +669,38 @@ function initVAISTUDIO() {
667
  const cb = document.getElementById("vaistudio-close"); if (cb) cb.addEventListener("click", () => { vaistudioPanelOpen = false; vaistudioPanel.classList.remove("open"); vaistudioToggle.classList.remove("active"); });
668
  const rb = document.getElementById(VAISTUDIO_RETRY_ID); if (rb) rb.addEventListener("click", () => { vaistudioProductsLoaded = false; vaistudioVisibleCount = 0; vaistudioAllProducts = []; if (vaistudioLoading) vaistudioLoading.classList.remove("hidden"); if (vaistudioErrorEl) vaistudioErrorEl.style.display = "none"; loadVaistudioProducts(); });
669
  const si = document.getElementById("vaix-search"); if (si) { let st = null; si.addEventListener("input", () => { if (st) clearTimeout(st); st = setTimeout(() => searchP(si.value), 300); }); si.addEventListener("keydown", (e) => { if (e.key === "Enter") { if (st) clearTimeout(st); searchP(si.value); } }); }
670
- window.vaistudio = { send: (a,d={}) => { if (a==="navigate"&&d.page==="products") { vaistudioCurrentSearch="";_lastSearchResults=[];loadVaistudioProducts();if(!vaistudioPanelOpen) vaistudioToggle.click();return{success:true};} if(a==="search") return searchP(d.query)||Promise.resolve(); return{success:false}; }, open:()=>{if(!vaistudioPanelOpen) vaistudioToggle.click();}, close:()=>{if(vaistudioPanelOpen) vaistudioToggle.click();}, isOpen:()=>vaistudioPanelOpen, products:()=>vaistudioAllProducts, search:(q)=>searchP(q) };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
671
  }
 
672
  async function vaistudioOpenCatalog(cat) { if(!vaistudioProductsLoaded) await loadVaistudioProducts(); if(!vaistudioPanelOpen) vaistudioToggle.click(); return{success:true,message:"Opened"+(cat?": "+cat:"")}; }
673
  async function vaistudioOpenProduct(pid) { if(!vaistudioProductsLoaded) await loadVaistudioProducts(); if(!vaistudioPanelOpen) vaistudioToggle.click(); return{success:true,message:"Opened product "+pid}; }
674
  async function vaistudioSearch(query) { if(!vaistudioProductsLoaded) await loadVaistudioProducts(); await searchP(query); if(!vaistudioPanelOpen) vaistudioToggle.click(); return{success:true,message:"Searching: "+query}; }
675
- async function vaistudioNavigate(page) { if(!vaistudioProductsLoaded) await loadVaistudioProducts(); if(page==="products"){vaistudioCurrentSearch="";_lastSearchResults=[];renderPaginated(vaistudioAllProducts);} if(!vaistudioPanelOpen) vaistudioToggle.click(); return{success:true,message:"Navigated to "+page}; }
 
127
  const chatInput = /** @type {HTMLInputElement} */ ($("#chat-input"));
128
  const chatSendBtn = /** @type {HTMLButtonElement} */ ($("#chat-send-btn"));
129
  const chatCloseBtn = /** @type {HTMLButtonElement} */ ($("#chat-close-btn"));
130
+ const chatResizeHandle = /** @type {HTMLElement} */ ($("#chatResizeHandle"));
131
  const chatAvatarSelect = /** @type {HTMLSelectElement} */ ($("#chat-avatar-select"));
132
  const settingsAvatarSelect = /** @type {HTMLSelectElement} */ ($("#settings-avatar-select"));
133
 
 
644
  }
645
  }
646
 
647
+ function searchP(q) {
648
+ return new Promise((resolve) => {
649
+ if (!q || !q.trim()) { _lastSearchResults = []; vaistudioCurrentSearch = ""; if (vaistudioAllProducts.length > 0 && vaistudioProductsLoaded) { renderPaginated(vaistudioAllProducts); if (vaistudioCount) vaistudioCount.textContent = vaistudioAllProducts.length + " sản phẩm"; } resolve(); return; }
650
+ vaistudioCurrentSearch = q.trim();
651
+ if (vaistudioProducts) { vaistudioProducts.innerHTML = ""; vaistudioProducts.style.display = "block"; }
652
+ if (vaistudioCount) vaistudioCount.textContent = "Đang tìm...";
653
+ fetch("/api/vaix/search?q=" + encodeURIComponent(q.trim())).then(r => r.json()).then(json => {
654
+ _lastSearchResults = (json.results || []).map(r => r.product); renderPaginated(_lastSearchResults);
655
+ if (vaistudioCount) vaistudioCount.textContent = _lastSearchResults.length + " kết quả";
656
+ if (!_lastSearchResults.length) clientSearch(q);
657
+ resolve();
658
+ }).catch(() => { clientSearch(q); resolve(); });
659
+ });
660
  }
661
 
662
  function clientSearch(q) { const norm=_sd(q),terms=norm.split(/\s+/).filter(t=>t.length>1); const r=vaistudioAllProducts.filter(p=>{const s=[_sd(p.title_clean||""),_sd(p.sku||""),_sd(p.brand||""),_sd(p.category||"")].join(" "); return terms.every(t=>s.includes(t));}); _lastSearchResults=r; renderPaginated(r); if(vaistudioCount) vaistudioCount.textContent=r.length+" kết quả"; }
 
669
  const cb = document.getElementById("vaistudio-close"); if (cb) cb.addEventListener("click", () => { vaistudioPanelOpen = false; vaistudioPanel.classList.remove("open"); vaistudioToggle.classList.remove("active"); });
670
  const rb = document.getElementById(VAISTUDIO_RETRY_ID); if (rb) rb.addEventListener("click", () => { vaistudioProductsLoaded = false; vaistudioVisibleCount = 0; vaistudioAllProducts = []; if (vaistudioLoading) vaistudioLoading.classList.remove("hidden"); if (vaistudioErrorEl) vaistudioErrorEl.style.display = "none"; loadVaistudioProducts(); });
671
  const si = document.getElementById("vaix-search"); if (si) { let st = null; si.addEventListener("input", () => { if (st) clearTimeout(st); st = setTimeout(() => searchP(si.value), 300); }); si.addEventListener("keydown", (e) => { if (e.key === "Enter") { if (st) clearTimeout(st); searchP(si.value); } }); }
672
+
673
+ // Expose all VAISTUDIO state on window.vaistudio so browser console / tools can access it
674
+ window.vaistudio = {
675
+ send: (a,d={}) => {
676
+ if (a==="navigate" && d.page==="products") {
677
+ vaistudioCurrentSearch="";_lastSearchResults=[];loadVaistudioProducts();if(!vaistudioPanelOpen) vaistudioToggle.click();return{success:true};
678
+ }
679
+ if(a==="search") return searchP(d.query)||Promise.resolve();
680
+ return{success:false};
681
+ },
682
+ open: () => { if(!vaistudioPanelOpen) vaistudioToggle.click(); },
683
+ close: () => { if(vaistudioPanelOpen) vaistudioToggle.click(); },
684
+ isOpen: () => vaistudioPanelOpen,
685
+ products: () => vaistudioAllProducts,
686
+ search: (q) => searchP(q),
687
+ // Pagination state — these were previously module-scoped only
688
+ vaistudioCurrentPage: vaistudioCurrentPage,
689
+ vaistudioTotalProducts: vaistudioTotalProducts,
690
+ vaistudioTotalPages: vaistudioTotalPages,
691
+ vaistudioVisibleCount: vaistudioVisibleCount,
692
+ vaistudioCurrentSearch: vaistudioCurrentSearch,
693
+ vaistudioProductsLoaded: vaistudioProductsLoaded,
694
+ vaistudioAllProducts: vaistudioAllProducts,
695
+ _lastSearchResults: _lastSearchResults,
696
+ // Methods
697
+ _loadMoreProducts: () => loadVaistudioProducts(true),
698
+ _resetPage: () => { vaistudioCurrentPage = 0; vaistudioAllProducts = []; vaistudioProductsLoaded = false; if(vaistudioLoading) vaistudioLoading.classList.remove("hidden"); loadVaistudioProducts(false); },
699
+ _reload: () => { vaistudioProductsLoaded = false; if(vaistudioLoading) vaistudioLoading.classList.remove("hidden"); loadVaistudioProducts(false); },
700
+ };
701
  }
702
+
703
  async function vaistudioOpenCatalog(cat) { if(!vaistudioProductsLoaded) await loadVaistudioProducts(); if(!vaistudioPanelOpen) vaistudioToggle.click(); return{success:true,message:"Opened"+(cat?": "+cat:"")}; }
704
  async function vaistudioOpenProduct(pid) { if(!vaistudioProductsLoaded) await loadVaistudioProducts(); if(!vaistudioPanelOpen) vaistudioToggle.click(); return{success:true,message:"Opened product "+pid}; }
705
  async function vaistudioSearch(query) { if(!vaistudioProductsLoaded) await loadVaistudioProducts(); await searchP(query); if(!vaistudioPanelOpen) vaistudioToggle.click(); return{success:true,message:"Searching: "+query}; }
706
+ async function vaistudioNavigate(page) { if(!vaistudioProductsLoaded) await loadVaistudioProducts(); if(page==="products"){vaistudioCurrentSearch="";_lastSearchResults=[];renderPaginated(vaistudioAllProducts);} if(!vaistudioPanelOpen) vaistudioToggle.click(); return{success:true,message:"Navigated to "+page}; }