๐Ÿ”ฅ
RODEO GRUB
Food Booth
๐Ÿ›’ $0.00
0
โ†
Your Order
๐Ÿค 
WHAT'S YOUR NAME?
So we can call you when your order is ready
$0.00
0 items

Tap or Insert Your
Payment Card

on the Moneris terminal

Waiting for payment...

Order Placed!
Your Order Number
00
Listen for your number! ๐Ÿ“ข
Pickup at the counter

Starting new order...

โ†
Condiments
Extras
Item added!
Demo:
+ (total / 100).toFixed(2); document.getElementById('payItems').textContent = getCartCount() + ' item' + (getCartCount() > 1 ? 's' : ''); goToScreen('payment'); sendToMoneris(total); } async function sendToMoneris(amountInCents) { const orderId = `FOOD-${Date.now()}-${Math.random().toString(36).substr(2,6)}`; console.log(`[Moneris] Purchase: $${(amountInCents/100).toFixed(2)} | Order: ${orderId}`); /* // ===== PRODUCTION: Moneris Go Cloud API ===== const MONERIS_CLOUD_URL = 'https://gatewayt.moneris.com/gocloud/api'; const subtotal = getSubtotal(); const tax = Math.round(subtotal * TAX_RATE); const requestBody = { "request": { "command": "purchase", "totalAmount": amountInCents.toString(), "subtotalAmount": subtotal.toString(), "orderId": orderId, "ecrNo": "2", // Different ECR number from bar kiosk "storeId": "YOUR_STORE_ID", "apiToken": "YOUR_API_TOKEN", "terminalId": "YOUR_TERMINAL_ID", "taxes": [{ "taxName": "HST", "taxAmount": tax.toString(), "taxRate": "13.00" }] } }; try { const response = await fetch(MONERIS_CLOUD_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(requestBody) }); const data = await response.json(); if (data.response && data.response.responseCode === '000') { onPaymentSuccess(data.response); } else { onPaymentFailed(data.response?.message || 'Transaction declined'); } } catch (error) { console.error('[Moneris] Error:', error); onPaymentFailed('Connection error. Please try again.'); } */ } function onPaymentSuccess() { orderCounter++; const orderNum = String(orderCounter).padStart(2, '0'); document.getElementById('orderNumber').textContent = orderNum; // Build summary const lines = cart.map(entry => { const item = MENU.find(i => i.id === entry.id); return `${entry.qty}ร— ${item.name}`; }); document.getElementById('orderSummaryText').textContent = lines.join(' ยท '); goToScreen('success'); // Send order to kitchen display system sendOrderToKitchen(orderNum); // Reset countdown animation const fill = document.getElementById('cdFill'); fill.style.animation = 'none'; fill.offsetHeight; fill.style.animation = 'cd 8s linear forwards'; successTimeout = setTimeout(() => { resetKiosk(); }, 8000); } async function sendOrderToKitchen(orderNum) { const items = cart.map(entry => { const item = MENU.find(i => i.id === entry.id); const modNames = Object.keys(entry.mods).filter(k => entry.mods[k]).map(k => { const c = CONDIMENTS.find(m => m.key === k); const e = EXTRAS.find(m => m.key === k); return c ? c.name : e ? e.name : k; }); return { name: item.name, emoji: item.emoji || '', qty: entry.qty, price: (item.price + entry.modCost) / 100, notes: modNames.length > 0 ? modNames.join(', ') : '' }; }); const subtotal = getSubtotal() / 100; const tax = subtotal * TAX_RATE; const total = subtotal + tax; try { await fetch(API_URL + '/kitchen/orders', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ customerName: 'Kiosk #' + orderNum, items, subtotal: subtotal.toFixed(2), tax: tax.toFixed(2), total: total.toFixed(2), source: 'kiosk', paymentRef: 'FOOD-' + Date.now() }) }); console.log('[Kitchen] Order #' + orderNum + ' sent to kitchen display'); } catch (err) { console.warn('[Kitchen] Failed to send order:', err.message); } } function onPaymentFailed(msg) { alert('Payment failed: ' + msg); goToScreen('order'); } // ===== NAVIGATION ===== function goToScreen(id) { if (successTimeout) { clearTimeout(successTimeout); successTimeout = null; } document.querySelectorAll('.screen').forEach(s => s.classList.remove('active')); setTimeout(() => { document.getElementById('screen-' + id).classList.add('active'); }, 50); if (id === 'order') renderOrderScreen(); } function resetKiosk() { cart = []; updateCartUI(); renderMenu(); goToScreen('menu'); } // ===== TOAST ===== function showToast(msg) { const t = document.getElementById('toast'); t.textContent = msg; t.classList.add('show'); setTimeout(() => t.classList.remove('show'), 1500); } // ===== DEMO ===== function simulatePaySuccess() { if (document.getElementById('screen-payment').classList.contains('active')) { onPaymentSuccess(); } } function simulatePayFail() { if (document.getElementById('screen-payment').classList.contains('active')) { onPaymentFailed('Card declined โ€” insufficient funds'); } } // ===== INIT ===== (async function init() { // Show loading state const grid = document.getElementById('menuGrid'); if (grid) grid.innerHTML = '
Loading menu...
'; // Load menu from API await loadMenuFromAPI(); // Build category tabs const tabsEl = document.getElementById('catTabs'); tabsEl.innerHTML = CATEGORIES.map((c, i) => `
${c.label}
` ).join(''); // Set tax label from config document.getElementById('taxLabel').textContent = TAX_LABEL; document.getElementById('taxPct').textContent = Math.round(TAX_RATE * 100) + '%'; renderMenu(); })();