bep40 commited on
Commit
512a45a
·
verified ·
1 Parent(s): 7c7fa8b

Upload index.html

Browse files
Files changed (1) hide show
  1. index.html +73 -186
index.html CHANGED
@@ -695,213 +695,78 @@ catLoaded=true;
695
  function initCatTabs(){
696
  let tabs=document.getElementById('catTabs');
697
  if(!tabs||!CAT_LIST.length)return;
698
- tabs.innerHTML=CAT_LIST.map((c,i)=>`<button class="ctab" onclick="loadCatalogue(${i})" style="padding:8px 18px;border-radius:10px;border:2px solid ${i===0?'var(--p)':'var(--gl)'};background:${i===0?'var(--p)':'#fff'};color:${i===0?'#fff':'var(--d)'};font-size:.78rem;font-weight:600;cursor:pointer;font-family:inherit;transition:all .2s">${c.name} <span style="opacity:.5;font-weight:400">${c.pages.length}p</span></button>`).join('');
699
  }
700
 
701
  function loadCatalogue(idx){
702
  activeCat=idx;
703
- catPage=1;
704
- document.querySelectorAll('.ctab').forEach((t,i)=>{
705
- t.style.background=i===idx?'var(--p)':'#fff';
706
- t.style.color=i===idx?'#fff':'var(--d)';
707
- t.style.borderColor=i===idx?'var(--p)':'var(--gl)';
708
- });
709
- renderCatPages();
710
- }
711
-
712
- function renderCatPages(){
713
- let c=CAT_LIST[activeCat];
714
  if(!c)return;
715
- let total=c.pages.length;
716
- let totalPages=Math.ceil(total/CAT_PER_PAGE);
717
- if(catPage>totalPages)catPage=totalPages;
718
- let start=(catPage-1)*CAT_PER_PAGE;
719
- let items=c.pages.slice(start,start+CAT_PER_PAGE);
720
-
721
- let container=document.getElementById('catContent');
722
- // Pagination
723
- let pagHtml='';
724
- if(totalPages>1){
725
- pagHtml=`<div style="display:flex;justify-content:center;gap:6px;margin-top:20px;flex-wrap:wrap">`;
726
- pagHtml+=`<button onclick="catPage--;renderCatPages();window.scrollTo({top:document.getElementById('catContent').offsetTop-80,behavior:'smooth'})" style="padding:8px 14px;border:2px solid var(--gl);border-radius:8px;background:#fff;cursor:pointer;font-family:inherit;font-weight:600;font-size:.8rem" ${catPage<=1?'disabled style="opacity:.3;padding:8px 14px;border:2px solid var(--gl);border-radius:8px;background:#fff;cursor:default;font-family:inherit;font-weight:600;font-size:.8rem"':''}><i class="fas fa-chevron-left"></i></button>`;
727
- pagHtml+=`<span style="padding:8px 14px;font-size:.82rem;font-weight:600;color:var(--g)">Trang ${catPage}/${totalPages} (${total} trang catalogue)</span>`;
728
- pagHtml+=`<button onclick="catPage++;renderCatPages();window.scrollTo({top:document.getElementById('catContent').offsetTop-80,behavior:'smooth'})" style="padding:8px 14px;border:2px solid var(--gl);border-radius:8px;background:#fff;cursor:pointer;font-family:inherit;font-weight:600;font-size:.8rem" ${catPage>=totalPages?'disabled style="opacity:.3;padding:8px 14px;border:2px solid var(--gl);border-radius:8px;background:#fff;cursor:default;font-family:inherit;font-weight:600;font-size:.8rem"':''}><i class="fas fa-chevron-right"></i></button>`;
729
- pagHtml+=`</div>`;
730
- }
731
-
732
- container.innerHTML=`
733
- <div style="background:#fff;border-radius:20px;padding:24px;box-shadow:0 2px 16px rgba(0,0,0,.06)">
734
- <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;flex-wrap:wrap;gap:10px">
735
- <div><h3 style="font-size:1.2rem;font-weight:800;color:var(--d)"><i class="fas fa-book-open" style="color:var(--a);margin-right:8px"></i>${c.name}</h3>
736
- <p style="color:var(--g);font-size:.8rem;margin-top:4px">${c.desc} — ${total} trang</p></div>
737
- </div>
738
- ${pagHtml}
739
- <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px;margin-top:16px">
740
- ${items.map((img,i)=>{let pgNum=start+i+1;return`<div style="position:relative;border-radius:12px;overflow:hidden;border:2px solid var(--gl);cursor:pointer;transition:all .2s" onmouseover="this.style.borderColor='var(--p)';this.style.transform='translateY(-2px)';this.style.boxShadow='0 8px 20px rgba(0,0,0,.1)'" onmouseout="this.style.borderColor='var(--gl)';this.style.transform='';this.style.boxShadow=''" onclick="openCatImage('${img.replace(/'/g,"\\'")}')">
741
- <img src="${img}" alt="Trang ${pgNum}" loading="lazy" style="width:100%;display:block">
742
- <div style="position:absolute;top:8px;left:8px;background:var(--p);color:#fff;padding:3px 10px;border-radius:6px;font-size:.7rem;font-weight:700">Trang ${pgNum}</div>
743
- <div style="position:absolute;bottom:8px;right:8px;background:rgba(0,0,0,.5);color:#fff;width:30px;height:30px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:.75rem"><i class="fas fa-search-plus"></i></div>
744
- </div>`}).join('')}
745
- </div>
746
- ${pagHtml}
747
  </div>`;
748
- }
749
-
750
- function openCatImage(src){
751
- let overlay=document.createElement('div');
752
- overlay.style.cssText='position:fixed;inset:0;background:rgba(0,0,0,.9);z-index:500;display:flex;align-items:center;justify-content:center;padding:20px;cursor:zoom-out;backdrop-filter:blur(6px)';
753
- overlay.onclick=()=>overlay.remove();
754
- overlay.innerHTML=`<img src="${src}" style="max-width:95%;max-height:95%;object-fit:contain;border-radius:8px;box-shadow:0 10px 40px rgba(0,0,0,.4)"><button style="position:absolute;top:20px;right:20px;width:40px;height:40px;border:none;background:rgba(255,255,255,.15);color:#fff;border-radius:10px;font-size:1.2rem;cursor:pointer" onclick="event.stopPropagation();this.parentElement.remove()"><i class="fas fa-times"></i></button>`;
755
- document.body.appendChild(overlay);
756
- }
757
-
758
-
759
- // ===== CATALOGUE SEARCH (OCR text index) =====
760
- let catOcrData=null;
761
- let catSearchMode=false;
762
-
763
- function loadCatOcr(){
764
- if(catOcrData)return Promise.resolve();
765
- return fetch('catalogue_ocr.json').then(r=>r.ok?r.json():null).then(d=>{catOcrData=d}).catch(()=>{catOcrData=null});
766
  }
767
 
768
  function searchCatalogue(){
769
- let q=document.getElementById('catSearch').value.trim().toLowerCase();
770
- let countEl=document.getElementById('catSearchCount');
771
- if(!q){
772
- catSearchMode=false;
773
- countEl.textContent='';
774
- renderCatPages();
775
- return;
776
- }
777
- catSearchMode=true;
778
- if(!catOcrData){
779
- loadCatOcr().then(()=>searchCatalogue());
780
- countEl.textContent='Đang tải...';
781
- return;
782
- }
783
- // Search through OCR texts
784
  let results=[];
785
- for(let ci=0;ci<CAT_LIST.length;ci++){
786
- let ocr=catOcrData&&catOcrData[ci]?catOcrData[ci].texts:[];
787
- let pages=CAT_LIST[ci].pages;
788
- for(let pi=0;pi<pages.length;pi++){
789
- let txt=(ocr[pi]||'').toLowerCase();
790
- if(txt.includes(q)){
791
- results.push({catIdx:ci,catName:CAT_LIST[ci].name,pageIdx:pi,pageNum:pi+1,img:pages[pi],text:ocr[pi]||''});
792
- }
793
- }
794
- }
795
- countEl.textContent=results.length?results.length+' trang':'Không tìm thấy';
796
- renderCatSearchResults(results,q);
797
- }
798
-
799
- function renderCatSearchResults(results,q){
800
- let container=document.getElementById('catContent');
801
- if(!results.length){
802
- container.innerHTML=`<div style="text-align:center;padding:50px;color:var(--g)"><i class="fas fa-search" style="font-size:2.5rem;opacity:.3;display:block;margin-bottom:14px"></i><h3 style="font-size:1rem;font-weight:700;color:var(--d);margin-bottom:6px">Không tìm thấy "${q}"</h3><p style="font-size:.85rem">Thử từ khóa khác hoặc xóa bộ lọc</p></div>`;
803
- return;
804
- }
805
- // Hide tabs selection when showing search results
806
- container.innerHTML=`
807
- <div style="background:#fff;border-radius:20px;padding:24px;box-shadow:0 2px 16px rgba(0,0,0,.06)">
808
- <div style="margin-bottom:16px"><h3 style="font-size:1.1rem;font-weight:700;color:var(--d)"><i class="fas fa-search" style="color:var(--a);margin-right:8px"></i>${results.length} trang chứa "${q}"</h3></div>
809
- <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px">
810
- ${results.map(r=>`<div style="position:relative;border-radius:12px;overflow:hidden;border:2px solid var(--gl);cursor:pointer;transition:all .2s" onmouseover="this.style.borderColor='var(--p)';this.style.transform='translateY(-2px)'" onmouseout="this.style.borderColor='var(--gl)';this.style.transform=''" onclick="openCatImage('${r.img.replace(/'/g,"\\'")}')">
811
- <img src="${r.img}" alt="" loading="lazy" style="width:100%;display:block">
812
- <div style="position:absolute;top:8px;left:8px;background:var(--p);color:#fff;padding:3px 10px;border-radius:6px;font-size:.68rem;font-weight:700">${r.catName} — Trang ${r.pageNum}</div>
813
- <div style="position:absolute;bottom:0;left:0;right:0;background:linear-gradient(transparent,rgba(0,0,0,.7));padding:10px 12px 8px;color:#fff;font-size:.72rem;line-height:1.4">${highlightText(r.text.substring(0,120),q)}...</div>
814
- </div>`).join('')}
815
- </div>
816
- </div>`;
817
- }
818
-
819
- function highlightText(text,q){
820
- let re=new RegExp('('+q.replace(/[.*+?^${}()|[\]\\]/g,'\\$&')+')','gi');
821
- return text.replace(re,'<mark style="background:var(--al);color:var(--d);padding:1px 2px;border-radius:2px">$1</mark>');
822
  }
823
 
824
- // ===== MAIN SEARCH → CATALOGUE OCR RESULTS =====
825
  function renderMainCatSearch(){
826
- let container=document.getElementById('catSearchResults');
827
- if(!container)return;
828
- let q=S.q;
829
- if(!q||q.length<2){container.innerHTML='';return;}
830
- // Ensure OCR data and catalogue list are loaded
831
- if(!catOcrData){
832
- loadCatOcr().then(()=>{
833
- if(!CAT_LIST.length){
834
- fetch('catalogues.json').then(r=>r.json()).then(data=>{CAT_LIST=data;renderMainCatSearch()});
835
- }else{renderMainCatSearch()}
836
- });
837
- return;
838
- }
839
- if(!CAT_LIST.length){
840
- fetch('catalogues.json').then(r=>r.json()).then(data=>{CAT_LIST=data;renderMainCatSearch()});
841
- return;
842
- }
843
- let ql=nVN(q);
844
  let results=[];
845
- for(let ci=0;ci<CAT_LIST.length;ci++){
846
- let ocr=catOcrData&&catOcrData[ci]?catOcrData[ci].texts:[];
847
- let pages=CAT_LIST[ci].pages;
848
- for(let pi=0;pi<pages.length;pi++){
849
- let txt=nVN(ocr[pi]||'');
850
- if(txt.includes(ql)){
851
- results.push({catIdx:ci,catName:CAT_LIST[ci].name,pageIdx:pi,pageNum:pi+1,img:pages[pi],text:ocr[pi]||''});
852
- }
853
- }
854
- }
855
- if(!results.length){container.innerHTML='';return;}
856
- let shown=results.slice(0,8);
857
- let moreCount=results.length-shown.length;
858
- container.innerHTML=`
859
- <div style="margin-top:24px;background:#fff;border-radius:var(--r);padding:20px;box-shadow:0 2px 12px rgba(0,0,0,.06)">
860
- <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:14px;flex-wrap:wrap;gap:8px">
861
- <h3 style="font-size:.95rem;font-weight:700;color:var(--d);display:flex;align-items:center;gap:8px">
862
- <i class="fas fa-book-open" style="color:var(--a)"></i> Tìm thấy trong Catalogue: <strong style="color:var(--p)">${results.length} trang</strong>
863
- </h3>
864
- ${results.length>8?`<button onclick="showPage('catalogue');document.getElementById('catSearch').value='${q.replace(/'/g,"\\'")}';setTimeout(searchCatalogue,300)" style="padding:6px 16px;border:2px solid var(--p);border-radius:8px;background:#fff;color:var(--p);font-size:.78rem;font-weight:600;cursor:pointer;font-family:inherit">Xem tất cả ${results.length} trang <i class="fas fa-arrow-right" style="margin-left:4px"></i></button>`:''}
865
- </div>
866
- <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px">
867
- ${shown.map(r=>`<div style="position:relative;border-radius:10px;overflow:hidden;border:2px solid var(--gl);cursor:pointer;transition:all .2s;aspect-ratio:1.4" onmouseover="this.style.borderColor='var(--p)';this.style.transform='translateY(-2px)'" onmouseout="this.style.borderColor='var(--gl)';this.style.transform=''" onclick="openCatImage('${r.img.replace(/'/g,"\\'")}')">
868
- <img src="${r.img}" alt="" loading="lazy" style="width:100%;height:100%;object-fit:cover">
869
- <div style="position:absolute;top:6px;left:6px;background:var(--p);color:#fff;padding:2px 8px;border-radius:5px;font-size:.6rem;font-weight:700">${r.catName} — Trang ${r.pageNum}</div>
870
- <div style="position:absolute;bottom:0;left:0;right:0;background:linear-gradient(transparent,rgba(0,0,0,.75));padding:8px 10px 6px;color:#fff;font-size:.65rem;line-height:1.3">${highlightText(r.text.substring(0,100),q)}...</div>
871
- </div>`).join('')}
872
- </div>
873
- ${moreCount>0?`<div style="text-align:center;margin-top:12px"><button onclick="showPage('catalogue');document.getElementById('catSearch').value='${q.replace(/'/g,"\\'")}';setTimeout(searchCatalogue,300)" style="padding:8px 20px;border:none;background:var(--p);color:#fff;border-radius:8px;font-size:.8rem;font-weight:600;cursor:pointer;font-family:inherit">+${moreCount} trang khác trong Catalogue <i class="fas fa-arrow-right" style="margin-left:4px"></i></button></div>`:''}
874
- </div>`;
875
  }
876
 
877
- // ===== NAVIGATION =====
878
- let currentPage='products';
879
-
880
  function showPage(page){
881
- currentPage=page;
882
- document.querySelectorAll('.page-section').forEach(s=>s.classList.remove('active'));
883
- document.querySelectorAll('.nav-tab').forEach(t=>t.classList.remove('active'));
884
  let el=document.getElementById('page-'+page);
885
- if(el)el.classList.add('active');
886
- let tab=document.querySelector(`.nav-tab[data-page="${page}"]`);
887
- if(tab)tab.classList.add('active');
888
- if(page==='products'){
889
- document.getElementById('page-products').classList.add('active');
890
- document.getElementById('listView').style.display='';
891
- document.getElementById('detailView').classList.remove('show');
892
- document.getElementById('detailView').innerHTML='';
893
- document.querySelector('.hero').style.display='';
894
- }else{
895
- document.getElementById('detailView').classList.remove('show');
896
- document.getElementById('detailView').innerHTML='';
897
- document.querySelector('.hero').style.display='none';
898
- }
899
- if(page==='catalogue'&&!catLoaded){
900
- loadCatalogueData();
901
- }
902
  window.scrollTo({top:0,behavior:'smooth'});
903
  }
904
 
 
 
 
 
905
 
906
  // ===== CART =====
907
  let cart=JSON.parse(localStorage.getItem('malloca_cart')||'[]');
@@ -1055,8 +920,30 @@ goBack();
1055
  showPage('products');resetAll();
1056
  }
1057
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1058
  // Init on load
1059
  document.addEventListener('DOMContentLoaded',()=>{
 
1060
  initCatalogue();
1061
  updateCartBadge();
1062
  });
 
695
  function initCatTabs(){
696
  let tabs=document.getElementById('catTabs');
697
  if(!tabs||!CAT_LIST.length)return;
698
+ tabs.innerHTML=CAT_LIST.map((c,i)=>`<button class="pgb${i===0?' active':''}" onclick="loadCatalogue(${i})" style="white-space:nowrap">${c.title}</button>`).join('');
699
  }
700
 
701
  function loadCatalogue(idx){
702
  activeCat=idx;
703
+ let c=CAT_LIST[idx];
 
 
 
 
 
 
 
 
 
 
704
  if(!c)return;
705
+ // Update active tab
706
+ let tabBtns=document.querySelectorAll('#catTabs .pgb');
707
+ tabBtns.forEach((b,i)=>b.classList.toggle('active',i===idx));
708
+ let content=document.getElementById('catContent');
709
+ if(!content)return;
710
+ let pages=c.pages||[];
711
+ let totalPages=pages.length;
712
+ let totalPagesDisplay=totalPages;
713
+ let pageHtml=`<div style="text-align:center;margin-bottom:16px">
714
+ <div style="font-size:.85rem;color:var(--g)">${c.desc||''} — <strong>${totalPagesDisplay}</strong> trang</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
715
  </div>`;
716
+ pageHtml+=`<div style="display:flex;flex-direction:column;gap:16px;align-items:center">`;
717
+ pageHtml+=pages.map(pg=>`<div style="width:100%;max-width:900px"><img src="grob_img/${pg.file}" alt="${pg.title||'Page'}" style="width:100%;border-radius:12px;box-shadow:0 2px 12px rgba(0,0,0,.1)" loading="lazy"><div style="text-align:center;font-size:.75rem;color:var(--g);margin-top:6px">Trang ${pg.page||''}</div></div>`).join('');
718
+ pageHtml+=`</div>`;
719
+ content.innerHTML=pageHtml;
720
+ window.scrollTo({top:0,behavior:'smooth'});
 
 
 
 
 
 
 
 
 
 
 
 
 
721
  }
722
 
723
  function searchCatalogue(){
724
+ let q=document.getElementById('catSearch').value.trim();
725
+ if(!q){loadCatalogue(activeCat);document.getElementById('catSearchCount').textContent='';return}
726
+ let nq=nVN(q);
 
 
 
 
 
 
 
 
 
 
 
 
727
  let results=[];
728
+ CAT_LIST.forEach(c=>{
729
+ (c.pages||[]).forEach(pg=>{
730
+ let text=nVN((pg.ocr||'')+' '+(pg.title||''));
731
+ if(text.includes(nq))results.push({cat:c.title,page:pg});
732
+ });
733
+ });
734
+ document.getElementById('catSearchCount').textContent=results.length+' kết quả';
735
+ let content=document.getElementById('catContent');
736
+ if(!results.length){content.innerHTML='<div class="empty" style="padding:40px"><i class="fas fa-search"></i><h3>Không tìm thấy trong catalogue</h3></div>';return}
737
+ content.innerHTML=`<div style="display:flex;flex-direction:column;gap:16px;align-items:center">`+results.map(r=>`<div style="width:100%;max-width:900px"><div style="font-size:.8rem;color:var(--p);font-weight:700;margin-bottom:6px">${r.cat} — Trang ${r.page.page||''}</div><img src="grob_img/${r.page.file}" alt="${r.page.title||'Page'}" style="width:100%;border-radius:12px;box-shadow:0 2px 12px rgba(0,0,0,.1)" loading="lazy"></div>`).join('')+`</div>`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
738
  }
739
 
 
740
  function renderMainCatSearch(){
741
+ let q=document.getElementById('q').value.trim();
742
+ let csr=document.getElementById('catSearchResults');
743
+ if(!csr)return;
744
+ if(!q){csr.innerHTML='';return}
745
+ let nq=nVN(q);
 
 
 
 
 
 
 
 
 
 
 
 
 
746
  let results=[];
747
+ CAT_LIST.forEach(c=>{
748
+ (c.pages||[]).forEach(pg=>{
749
+ let text=nVN((pg.ocr||'')+' '+(pg.title||''));
750
+ if(text.includes(nq))results.push({cat:c.title,page:pg});
751
+ });
752
+ });
753
+ if(!results.length){csr.innerHTML='';return}
754
+ csr.innerHTML=`<div style="margin-top:24px;padding-top:24px;border-top:2px solid var(--gl)"><h3 style="font-size:1rem;font-weight:700;margin-bottom:12px"><i class="fas fa-book-open" style="color:var(--a);margin-right:8px"></i>Kết quả trong Catalogue (${results.length})</h3><div style="display:flex;flex-wrap:wrap;gap:12px">`+results.slice(0,6).map(r=>`<div style="width:200px;cursor:pointer" onclick="showPage('catalogue');document.getElementById('catSearch').value='${document.getElementById('q').value.replace(/'/g,"\\'")}';searchCatalogue();"><img src="grob_img/${r.page.file}" style="width:100%;border-radius:8px;border:2px solid var(--gl)" loading="lazy"><div style="font-size:.7rem;color:var(--g);margin-top:4px">${r.cat}</div></div>`).join('')+`</div></div>`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
755
  }
756
 
 
 
 
757
  function showPage(page){
758
+ document.querySelectorAll('.page-section').forEach(el=>el.classList.remove('active'));
759
+ document.querySelectorAll('.nav-tab').forEach(el=>el.classList.toggle('active',el.dataset.page===page));
 
760
  let el=document.getElementById('page-'+page);
761
+ if(el){el.classList.add('active');}
762
+ if(page==='catalogue'&&!catLoaded){loadCatalogueData();}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
763
  window.scrollTo({top:0,behavior:'smooth'});
764
  }
765
 
766
+ function initCatalogue(){
767
+ // catalogue loads on demand
768
+ }
769
+
770
 
771
  // ===== CART =====
772
  let cart=JSON.parse(localStorage.getItem('malloca_cart')||'[]');
 
920
  showPage('products');resetAll();
921
  }
922
 
923
+ // Parse URL query params on load for direct search URLs
924
+ function parseUrlParams(){
925
+ let params=new URLSearchParams(location.search);
926
+ let q=params.get('q')||params.get('search')||'';
927
+ if(q){
928
+ document.getElementById('q').value=q;
929
+ S.q=q;
930
+ S.pg=1;
931
+ }
932
+ let cat=params.get('cat');
933
+ if(cat){S.cat=cat;}
934
+ let brand=params.get('brand');
935
+ if(brand){S.brand=brand;}
936
+ let page=params.get('page');
937
+ if(page){S.pg=parseInt(page)||1;}
938
+ let sort=params.get('sort');
939
+ if(sort){S.sort=sort;document.getElementById('ss').value=sort;}
940
+ let p=params.get('p');
941
+ if(p==='list'){S.view='l';document.getElementById('gb').classList.remove('active');document.getElementById('lb').classList.add('active');}
942
+ }
943
+
944
  // Init on load
945
  document.addEventListener('DOMContentLoaded',()=>{
946
+ parseUrlParams();
947
  initCatalogue();
948
  updateCartBadge();
949
  });