const qs=(s,el=document)=>el.querySelector(s); const qsa=(s,el=document)=>[...el.querySelectorAll(s)]; let state={cond:'ALL', q:'', currency:'USD'}; function money(x,c){try{return new Intl.NumberFormat(undefined,{style:'currency',currency:c||'USD'}).format(x||0);}catch(e){return (c||'$')+' '+(x||0).toFixed?.(2);} } function setCond(which){ state.cond=which; qsa('.chip').forEach(b=>b.classList.toggle('active', b.dataset.cond===which)); search(); } function skeleton(){ qs('#stats').innerHTML = `
${Array.from({length:6}).map(()=>`
`).join('')}
`; qs('#out').innerHTML = `
${Array.from({length:8}).map(()=>`
`).join('')}
`; } function renderStats(s){ if(!s||!s.count){ qs('#stats').innerHTML=''; return; } qs('#stats').innerHTML = `
Average
${money(s.avg,state.currency)}
Median
${money(s.median,state.currency)}
Min
${money(s.min,state.currency)}
Max
${money(s.max,state.currency)}
Trimmed Avg
${money(s.trimmed_avg,state.currency)}
Count
${(s.count||0).toLocaleString()}
`; } function renderItems(list){ const out=qs('#out'); if(!list||!list.length){ out.innerHTML='
No results. If you are on Sandbox, try Production for live data.
'; return; } out.innerHTML = `
${list.map(r=>`
${r.image? `\"\"`:'No image'}
${(r.title||'').replace(/[<>]/g,'')}
${money(r.price, r.currency)}
${(r.condition||'').replace(/_/g,' ')}
`).join('')}
`; } async function runApi(params){ const u=new URL(location.href); u.search=''; Object.entries(params).forEach(([k,v])=>u.searchParams.set(k,v)); const res=await fetch(u.toString(),{headers:{'Accept':'application/json'}}); return res.json(); } async function search(skipLog=false){ const q = qs('#q').value.trim(); const cond = state.cond; qs('#err').style.display='none'; if(!q){ qs('#stats').innerHTML=''; qs('#out').innerHTML='
Type a search to begin.
'; return; } skeleton(); try{ const params={api:'1', q}; if(skipLog) params['from']='popular'; if(cond&&cond!=='ALL') params['cond']=cond; const j=await runApi(params); if(!j.ok){ qs('#err').textContent=j.error||'Request failed'; qs('#err').style.display='block'; return; } state.currency=j.currency||state.currency; renderStats(j.stats); renderItems(j.items); if(j.note){ qs('#tip').innerHTML = j.note; } try{ await refreshPopular(); }catch(_){} } catch(e){ qs('#err').textContent='Network error: '+e.message; qs('#err').style.display='block'; } } async function imageSearch(file){ if(!file) return; qs('#err').style.display='none'; skeleton(); try{ const u=new URL(location.href); u.search=''; u.searchParams.set('api','image'); const fd=new FormData(); fd.append('photo', file); const res=await fetch(u.toString(),{ method:'POST', body: fd }); const j=await res.json(); if(!j.ok){ qs('#err').textContent=j.message||j.error||'Image search failed'; qs('#err').style.display='block'; return; } if (j.suggestedQuery) { qs('#q').value = j.suggestedQuery; const newUrl = new URL(window.location.href); newUrl.searchParams.set('q', j.suggestedQuery); if (state.cond && state.cond !== 'ALL') newUrl.searchParams.set('cond', state.cond); else newUrl.searchParams.delete('cond'); history.replaceState(null, '', newUrl.toString()); } state.currency=j.currency||state.currency; renderStats(j.stats); renderItems(j.items); if(j.note){ qs('#tip').textContent=j.note; } try{ await refreshPopular(); }catch(_){} }catch(e){ qs('#err').textContent='Upload error: '+e.message; qs('#err').style.display='block'; } } qs('#go').addEventListener('click', ()=> search()); qs('#q').addEventListener('keydown', e=>{ if(e.key==='Enter'){ e.preventDefault(); search(); }}); qsa('.chip').forEach(b=> b.addEventListener('click', ()=> setCond(b.dataset.cond))); // Upload button → hidden file input qs('#uploadBtn').addEventListener('click', ()=> qs('#photo').click()); qs('#photo').addEventListener('change', (e)=> imageSearch(e.target.files[0])); // Camera button → dedicated camera input (rear camera hint) const camBtn = qs('#cameraBtn'); const camInput = qs('#cameraInput'); if (camBtn && camInput) { camBtn.addEventListener('click', ()=> { camInput.setAttribute('accept','image/*'); camInput.setAttribute('capture','environment'); // hint: rear camera camInput.click(); }); camInput.addEventListener('change', (e)=> imageSearch(e.target.files[0])); } // Optional demo (?demo=lego) const demo=new URL(location.href).searchParams.get('demo'); if(demo){ qs('#q').value=demo; search(); } // ---- Theme handling ---- function applyTheme(mode){ const root = document.documentElement; if(mode === 'light'){ root.setAttribute('data-theme','light'); } else { root.removeAttribute('data-theme'); } const t = document.getElementById('themeToggle'); if (t) t.title = (root.getAttribute('data-theme')==='light') ? 'Switch to dark theme' : 'Switch to light theme'; } (function initTheme(){ const saved = localStorage.getItem('iwia_theme'); const prefersLight = window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches; const initial = saved || (prefersLight ? 'light' : 'dark'); applyTheme(initial); const setup = ()=>{ const btn = document.getElementById('themeToggle'); if(!btn) return; btn.addEventListener('click', ()=>{ const now = (document.documentElement.getAttribute('data-theme')==='light') ? 'dark' : 'light'; localStorage.setItem('iwia_theme', now); applyTheme(now); }); }; if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', setup, {once:true}); else setup(); })(); // ---- Popular buttons ---- async function refreshPopular(){ const el=document.getElementById('popular'); if(!el) return; try{ const u=new URL(location.href); u.search=''; u.searchParams.set('api','popular'); const r=await fetch(u.toString(),{headers:{'Accept':'application/json'}}); const j=await r.json(); if(j && j.ok && Array.isArray(j.terms) && j.terms.length){ el.innerHTML = 'Popular:' + j.terms.map(t=>``).join(''); return; } el.innerHTML=''; }catch(_){ el.innerHTML=''; } } // First load (function ensurePopularOnLoad(){ const run = ()=>{ try{ refreshPopular(); }catch(e){} }; if (document.readyState==='loading') document.addEventListener('DOMContentLoaded', run, {once:true}); else run(); })(); // Delegate clicks for popular buttons document.addEventListener('click', (e)=> { const btn = e.target.closest('.pbtn'); if(!btn) return; e.preventDefault(); const val = btn.dataset.q || btn.textContent.trim(); const input = document.getElementById('q'); if(input){ input.value = val; } if (typeof search === 'function') search(true); // skipLog=true so clicks don't count });