Coffee Grounds
Pilot App
`); w.document.close() }; $('#export_json').onclick=()=>download('coffee-data.json',JSON.stringify({requests:state.requests,shops:state.shops,pricing:state.pricing,security:state.security},null,2)); $('#export_csv').onclick=()=>download('coffee-data.csv',toCSV(state.requests)); $('#reset_all').onclick=()=>{ if(confirm('Reset ALL data?')){ ['requests','shops','pricing','security','firstRun'].forEach(k=>localStorage.removeItem(NS+k)); alert('Data cleared. Reloading.'); location.reload() } }; $('#add_shop').onclick=()=>{ const v=$('#new_shop').value.trim(); if(!v) return; if(!state.shops.includes(v)) state.shops.push(v); save('shops',state.shops); render() }; $$('#shops_list .li').forEach((el,i)=>{ const name=state.shops[i]; let timer=null; el.addEventListener('touchstart',()=>{ timer=setTimeout(()=>{ if(confirm('Delete shop \"'+name+'\"?')){ state.shops.splice(i,1); save('shops',state.shops); render() } },600) }); el.addEventListener('touchend',()=>clearTimeout(timer)); el.addEventListener('click',()=>{ const nn=prompt('Rename shop',name); if(nn&&nn.trim()){ state.shops[i]=nn.trim(); save('shops',state.shops); render() } }) }); $('#import_file').onchange=(e)=>{ const f=e.target.files[0]; if(!f) return; const r=new FileReader(); r.onload=()=>{ try{ const d=JSON.parse(r.result); if(Array.isArray(d.requests)) state.requests=d.requests; if(Array.isArray(d.shops)) state.shops=d.shops; if(d.pricing&&typeof d.pricing==='object') state.pricing=d.pricing; if(d.security&&typeof d.security==='object') state.security=d.security; save('requests',state.requests); save('shops',state.shops); save('pricing',state.pricing); save('security',state.security); alert('Import complete.'); render() }catch(_){ alert('Invalid JSON.') } }; r.readAsText(f) } } } $$('.tab').forEach(b=>b.onclick=()=>setTab(b.dataset.tab)); $('#shareBtn').onclick=async()=>{ try{ if(navigator.share){ await navigator.share({title:'Coffee Grounds Pilot App',text:'Single-file MVP',url:location.href}) } else { await navigator.clipboard.writeText(location.href); alert('Link copied.') } }catch(_){}}; render(); applyDeepLink(); })();