Put Order on Hold

Reason
Notes (optional)

Report Problem

Issue Type
Details
📦 Pack Station No order loaded
Queue
📦
Ready to Pack
Scan an order barcode or load the next order from the queue
' + '
Order ' + orderNum + '
' + '
' + '

📦 Packing Slip

Order ' + orderNum + '
' + '
Date: ' + dateStr + '
Time: ' + timeStr + '
Merchant: ' + merchant + '
' + '
' + '
Ship To
' + addrLines.join('
') + '
' + '
Package Info
' + '
' + packageName + 'Box Type
' + '
' + dimL + 'x' + dimW + 'x' + dimH + 'L×W×H (cm)
' + '
' + weight + 'Weight (kg)
' + '
' + '
' + '' + itemRows + '
#SKUProductQty
Total:' + totalQty + '
' + '
Packer Notes
' + '
JLog Fulfillment — Order ' + orderNum + 'Printed ' + dateStr + ' ' + timeStr + '
' + '
'; var win = window.open('', '_blank'); if (win) { win.document.write(html); win.document.close(); } } // ===== MARK AS PACKED ===== function markAsPacked() { if (!currentOrder) return; var btn = document.getElementById('packBtn'); btn.disabled = true; btn.innerHTML = ' Packing...'; var weight = parseFloat(document.getElementById('weightInput').value); var length = parseInt(document.getElementById('dimL').value) || 0; var width = parseInt(document.getElementById('dimW').value) || 0; var height = parseInt(document.getElementById('dimH').value) || 0; var packageType = document.getElementById('boxPreset').value === 'custom' ? 'custom' : 'box'; api('/api/fulfillment/orders/' + currentOrder.id + '/pack', { method: 'POST', body: { weight: weight, length: length, width: width, height: height, packageType: packageType } }).then(function() { flashGreen(); beepAllDone(); if (navigator.vibrate) navigator.vibrate(200); toast('Order #' + (currentOrder.orderNumber || '') + ' packed!', 'rgba(46,232,158,.9)'); // Remove from queue if (queueIdx >= 0 && queueIdx < queue.length) { queue.splice(queueIdx, 1); } // Auto-advance if (queue.length > 0) { if (queueIdx >= queue.length) queueIdx = queue.length - 1; setTimeout(function() { loadOrder(queue[queueIdx].id); }, 800); } else { currentOrder = null; items = []; document.getElementById('orderState').style.display = 'none'; document.getElementById('emptyState').style.display = 'block'; document.getElementById('headerOrderLabel').textContent = 'All done!'; updateNav(); // Reload queue to check for new orders loadQueue(); } }).catch(function(e) { toast('Pack failed: ' + (e.message || e), '#b91c1c'); btn.disabled = false; btn.innerHTML = '\u2713 Mark as Packed'; }); } // ===== HOLD ===== function openHoldModal() { document.getElementById('holdModal').classList.add('open'); } function closeHoldModal() { document.getElementById('holdModal').classList.remove('open'); } function submitHold() { if (!currentOrder) return; var reason = document.getElementById('holdReason').value; var notes = document.getElementById('holdNotes').value.trim(); var full = reason + (notes ? ': ' + notes : ''); api('/api/fulfillment/orders/' + currentOrder.id + '/hold', { method: 'POST', body: { reason: full } }).then(function() { toast('Order placed on hold', 'var(--ps-amber)'); closeHoldModal(); // Remove from queue and advance if (queueIdx >= 0) queue.splice(queueIdx, 1); if (queue.length > 0) { if (queueIdx >= queue.length) queueIdx = queue.length - 1; loadOrder(queue[queueIdx].id); } else { resetToEmpty(); } }).catch(function(e) { toast('Hold failed: ' + (e.message || e), '#b91c1c'); }); } // ===== PROBLEM ===== function openProblemModal() { document.getElementById('problemModal').classList.add('open'); } function closeProblemModal() { document.getElementById('problemModal').classList.remove('open'); } function submitProblem() { if (!currentOrder) return; var type = document.getElementById('problemType').value; var notes = document.getElementById('problemNotes').value.trim(); var full = type + (notes ? ': ' + notes : ''); // Use hold endpoint with problem prefix api('/api/fulfillment/orders/' + currentOrder.id + '/hold', { method: 'POST', body: { reason: 'PROBLEM: ' + full } }).then(function() { toast('Problem reported — order on hold', '#b91c1c'); closeProblemModal(); if (queueIdx >= 0) queue.splice(queueIdx, 1); if (queue.length > 0) { if (queueIdx >= queue.length) queueIdx = queue.length - 1; loadOrder(queue[queueIdx].id); } else { resetToEmpty(); } }).catch(function(e) { toast('Report failed: ' + (e.message || e), '#b91c1c'); }); } // ===== NAV ===== function updateNav() { var prevBtn = document.getElementById('prevBtn'); var nextBtn = document.getElementById('nextBtn'); var label = document.getElementById('navLabel'); prevBtn.disabled = queueIdx <= 0; nextBtn.disabled = queueIdx >= queue.length - 1; if (currentOrder && queueIdx >= 0) { label.innerHTML = '#' + esc(currentOrder.orderNumber || '???') + '(' + (queueIdx + 1) + ' of ' + queue.length + ' remaining)'; } else if (queue.length > 0) { label.textContent = queue.length + ' orders in queue'; } else { label.textContent = 'Queue empty'; } } function resetToEmpty() { currentOrder = null; items = []; queueIdx = -1; document.getElementById('orderState').style.display = 'none'; document.getElementById('emptyState').style.display = 'block'; document.getElementById('headerOrderLabel').textContent = 'No order loaded'; updateNav(); } // ===== SWIPE GESTURES ===== (function() { var startX = 0, startY = 0, swiping = false; document.addEventListener('touchstart', function(e) { startX = e.touches[0].clientX; startY = e.touches[0].clientY; swiping = true; }, { passive: true }); document.addEventListener('touchend', function(e) { if (!swiping) return; swiping = false; var dx = e.changedTouches[0].clientX - startX; var dy = e.changedTouches[0].clientY - startY; if (Math.abs(dx) < 80 || Math.abs(dy) > Math.abs(dx) * 0.5) return; if (dx > 0 && queueIdx > 0) loadPrevOrder(); else if (dx < 0 && queueIdx < queue.length - 1) loadNextFromNav(); }, { passive: true }); })(); // ===== INIT ===== document.addEventListener('DOMContentLoaded', function() { loadQueue().then(function() { // Check URL params for direct order load var params = new URLSearchParams(window.location.search); var orderId = params.get('order'); if (orderId) { loadOrder(orderId); } }); });