Welcome back. Reorder your approved gear in minutes — tap any product to choose sizes and quantities. Your invoice goes to .

Products
🔍
No products match your search.
Order Summary
No items added yet — tap a product above to add quantities. Your last order is one tap away in Order History.

Review your items, then request your Xero invoice. Payment is due within 30 days.

Add products above to request an invoice

Questions about your order? Email info@arrowsport.com.au

Order History
No previous orders found
0 items · $0.00

Invoice Request Submitted!

Your reorder request has been received and your Xero invoice will be emailed to your registered address.

Please allow a few minutes for the email to arrive. Production starts once payment is received.


`); win.document.close(); win.focus(); }; window.filterHistory = function(status, pill) { document.querySelectorAll('.history-filter-pill').forEach(p => p.classList.remove('active')); if (pill) pill.classList.add('active'); document.querySelectorAll('.invoice-summary-row').forEach(row => { const rowStatus = row.getAttribute('data-status'); let show = true; if (status === 'paid') show = rowStatus === 'paid'; else if (status === 'unpaid') show = rowStatus === 'unpaid'; row.style.display = show ? '' : 'none'; if (!show) { const match = row.getAttribute('onclick').match(/toggleInvoice\('([^']+)'/); const id = match ? match[1] : null; if (id) { document.querySelectorAll('[data-invoice-group="' + id + '"]').forEach(r => r.style.display = 'none'); document.querySelectorAll('[data-prod-group]').forEach(r => { if (r.getAttribute('data-prod-group').startsWith(id.replace('inv-', 'inv-prod-'))) r.style.display = 'none'; }); } } }); }; window.filterProducts = function(query) { const q = query.trim().toLowerCase(); const clearBtn = document.getElementById('product-search-clear'); const emptyMsg = document.getElementById('product-search-empty'); if (clearBtn) clearBtn.classList.toggle('visible', q.length > 0); let visibleCount = 0; currentProducts.forEach(product => { const card = document.getElementById('card-' + product.product_id); if (!card) return; const matches = !q || (product.product_name || '').toLowerCase().includes(q); card.style.display = matches ? '' : 'none'; if (matches) visibleCount++; }); if (emptyMsg) emptyMsg.style.display = visibleCount === 0 ? 'block' : 'none'; }; window.clearProductSearch = function() { const input = document.getElementById('product-search-input'); if (input) { input.value = ''; filterProducts(''); input.focus(); } }; window.portalStayLoggedIn = async function() { try { const res = await fetch(APPS_SCRIPT_URL, { method: 'POST', headers: { 'Content-Type': 'text/plain' }, body: JSON.stringify({ action: 'login', password: currentPassword }) }); const data = await res.json(); if (data.success) { localStorage.setItem('arrowsport_session', JSON.stringify({ password: currentPassword, expiry: Date.now() + (8 * 60 * 60 * 1000) })); startSessionTimer(); const b = document.getElementById('session-warning-banner'); if (b) b.classList.remove('visible'); } } catch(e) {} }; window.portalReorderFromHistory = function(invoiceId, event) { if (event) event.stopPropagation(); const rows = (window._currentHistory || []).filter(r => r.xero_invoice_id === invoiceId); if (!rows.length) return; const skipped = []; // Reset current order currentProducts.forEach(p => { orderData[p.product_id] = p.sizes && p.sizes.length > 0 ? {} : 0; }); rows.forEach(row => { const product = currentProducts.find(p => p.product_id === row.product_id); if (!product) { skipped.push(row.product_name); return; } const qty = parseInt(row.qty) || 0; if (qty <= 0) return; if (product.sizes && product.sizes.length > 0) { const size = row.Size || row.size; if (!size || size === '—') return; if (!orderData[product.product_id]) orderData[product.product_id] = {}; orderData[product.product_id][size] = (orderData[product.product_id][size] || 0) + qty; } else { orderData[product.product_id] = (parseInt(orderData[product.product_id]) || 0) + qty; } }); if (currentClub) localStorage.setItem('arrowsport_draft_' + currentClub.club_id, JSON.stringify(orderData)); updateAllCardBadges(); updateSummary(); switchTab('place-order'); if (skipped.length > 0) { const unique = [...new Set(skipped)]; setTimeout(() => alert(`Order loaded from ${invoiceId}.\n\nNote: The following products are no longer in your catalog and were skipped:\n• ${unique.join('\n• ')}`), 300); } }; window.portalExportCSV = function() { try { if (!window._currentHistory || window._currentHistory.length === 0) { alert("No history available to export."); return; } let csv = "Order Date,Invoice,Payment Status,Product,Size,Quantity,Line Total (ex GST)\n"; window._currentHistory.forEach(row => { const date = row.timestamp ? new Date(row.timestamp).toLocaleDateString('en-AU') : 'Unknown'; const inv = `"${row.xero_invoice_id || ''}"`; const pStatusObj = window._currentPaymentStatus && window._currentPaymentStatus[row.xero_invoice_id]; const pStatus = pStatusObj ? pStatusObj.status : 'UNKNOWN'; // Bulletproof string replacements in case data is null const prodStr = String(row.product_name || 'Unknown Product'); const prod = `"${prodStr.replace(/"/g, '""')}"`; const sizeStr = String(row.Size || row.size || '—'); const size = `"${sizeStr.replace(/"/g, '""')}"`; const qty = row.qty || 0; const total = row.line_total || 0; csv += `${date},${inv},"${pStatus}",${prod},${size},${qty},${total}\n`; }); const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); const link = document.createElement("a"); link.href = URL.createObjectURL(blob); // Fallback club name just in case const clubName = (currentClub && currentClub.name) ? currentClub.name : 'Club'; link.download = `Order_History_${clubName.replace(/\s+/g, '_')}.csv`; document.body.appendChild(link); link.click(); document.body.removeChild(link); } catch (error) { console.error("CSV Export Error: ", error); alert("There was an error generating the CSV. Please try again or check the browser console."); } }; // Export SINGLE Invoice CSV Logic window.portalExportSingleCSV = function(invoiceId, event) { if (event) event.stopPropagation(); // Stops the row from expanding when clicking the button try { const rowsToExport = window._currentHistory.filter(r => r.xero_invoice_id === invoiceId); if (rowsToExport.length === 0) return; let csv = "Order Date,Invoice,Payment Status,Product,Size,Quantity,Line Total (ex GST)\n"; rowsToExport.forEach(row => { const date = row.timestamp ? new Date(row.timestamp).toLocaleDateString('en-AU') : 'Unknown'; const inv = `"${row.xero_invoice_id || ''}"`; const pStatusObj = window._currentPaymentStatus && window._currentPaymentStatus[row.xero_invoice_id]; const pStatus = pStatusObj ? pStatusObj.status : 'UNKNOWN'; const prodStr = String(row.product_name || 'Unknown Product'); const prod = `"${prodStr.replace(/"/g, '""')}"`; const sizeStr = String(row.Size || row.size || '—'); const size = `"${sizeStr.replace(/"/g, '""')}"`; const qty = row.qty || 0; const total = row.line_total || 0; csv += `${date},${inv},"${pStatus}",${prod},${size},${qty},${total}\n`; }); const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); const link = document.createElement("a"); link.href = URL.createObjectURL(blob); const clubName = (currentClub && currentClub.name) ? currentClub.name : 'Club'; link.download = `Invoice_${invoiceId}_${clubName.replace(/\s+/g, '_')}.csv`; document.body.appendChild(link); link.click(); document.body.removeChild(link); } catch (error) { console.error("Single CSV Export Error: ", error); } }; })();