import {frame} from './ds/frame.js'; import {npubFrom} from './ds/env.js'; const app=document.querySelector('#app');const params=new URLSearchParams(location.search);const npub=npubFrom();const prefilledTable=params.get('table')||'';let merchant,quantities={},statusTimer; const esc=v=>String(v??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); function error(message){app.innerHTML=`
⌁

Just Works · Order

${esc(message)}

Use order.justworks.cash/?npub=npub1…
`} function productCard(item){return ``} function render(data){merchant=data;document.title=`Order ${data.merchant.name} · Just Works`;frame(app,{label:'Order',surface:'order',html:`

Order to table

What can we bring you?

Order from ${esc(data.merchant.name)} without waiting for the waiter.

↗
${esc(data.merchant.name)}Taking orders
${data.products.length?`

Merchant menu

${data.products.map(productCard).join('')}
`:''}

No account · no app · sent directly to this merchant

`});bind(data.products)} function bind(products){for(const item of products){quantities[item.id]=0;document.querySelector(`[data-plus="${CSS.escape(item.id)}"]`).onclick=()=>setQty(item.id,quantities[item.id]+1);document.querySelector(`[data-minus="${CSS.escape(item.id)}"]`).onclick=()=>setQty(item.id,quantities[item.id]-1)}document.querySelector('#orderForm').onsubmit=submit} function setQty(id,value){quantities[id]=Math.max(0,Math.min(20,value));document.querySelector(`[data-qty="${CSS.escape(id)}"]`).textContent=quantities[id]} const statusCopy={'new':{eyebrow:'Sent to the staff',title:'Your order is on its way.',body:'Waiting for the team to confirm it.',step:0},accepted:{eyebrow:'Confirmed by the staff',title:'They are preparing it.',body:'Your order has been accepted.',step:1},delivered:{eyebrow:'Coming to your table',title:'It is ready for you.',body:'The team is bringing it now.',step:2},closed:{eyebrow:'Order complete',title:'Just Works.',body:'Enjoy—and order again whenever you like.',step:3}}; function renderStatus(order){const state=statusCopy[order.status]||statusCopy['new'];const card=document.querySelector('#orderForm,.order-status-card');if(!card)return;card.outerHTML=`
✓
${esc(merchant.merchant.name)}Table ${order.table||order.table_number}
Live order status

${esc(state.eyebrow)}

${esc(state.title)}

${esc(state.body)}

Table ${order.table||order.table_number} · ${esc(order.id.toUpperCase())}
${['Sent','Staff confirmed','Coming to table'].map((label,index)=>`
${index${label}
`).join('')}
Add another order +
`} async function pollStatus(order){try{const response=await fetch(`/api/merchant-order-status?npub=${encodeURIComponent(npub)}&id=${encodeURIComponent(order.id)}`,{cache:'no-store'});if(response.ok){const latest=await response.json();if(latest.status!==order.status){order.status=latest.status;order.table=latest.table_number;renderStatus(order)}}}catch{}if(order.status!=='closed')statusTimer=setTimeout(()=>pollStatus(order),1500)} async function submit(event){event.preventDefault();const button=document.querySelector('#submit');button.disabled=true;button.innerHTML='Sending to staff…';const items=merchant.products.filter(item=>quantities[item.id]>0).map(item=>({id:item.id,name:item.name,qty:quantities[item.id]}));const response=await fetch('/api/merchant-orders',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({npub,table:Number(document.querySelector('#table').value),request:document.querySelector('#request').value,guest:document.querySelector('#guest').value,items})});const data=await response.json();if(!response.ok){button.disabled=false;button.innerHTML=`${esc(data.error||'Try again')} ↻`;return}renderStatus(data);pollStatus(data)} if(!npub)error('Add the merchant npub to order.');else fetch(`/api/order-merchant?npub=${encodeURIComponent(npub)}`,{cache:'no-store'}).then(async r=>{const data=await r.json();if(!r.ok)throw new Error(data.error||'Merchant unavailable');return data}).then(render).catch(e=>error(e.message));