// API base URL const API_BASE_URL = '/api'; // Selected orders for actions let selectedOrders = new Set(); // Show toast notification function showToast(message, type = 'success') { const toast = document.createElement('div'); toast.className = `fixed bottom-4 right-4 px-6 py-3 rounded-lg shadow-lg text-white ${ type === 'success' ? 'bg-green-600' : 'bg-red-600' } transform translate-y-0 opacity-100 transition-all duration-300`; toast.textContent = message; document.body.appendChild(toast); setTimeout(() => { toast.style.transform = 'translateY(100%)'; toast.style.opacity = '0'; setTimeout(() => toast.remove(), 300); }, 3000); } // Show loading state function setLoading(isLoading) { const buttons = document.querySelectorAll('button'); buttons.forEach(button => { if (isLoading) { button.disabled = true; button.classList.add('opacity-50', 'cursor-not-allowed'); } else { button.disabled = false; button.classList.remove('opacity-50', 'cursor-not-allowed'); } }); } // Fetch orders from the API async function fetchOrders() { try { setLoading(true); const searchRange = document.getElementById('searchRange').value; const openOnly = document.getElementById('openOnly').checked; const response = await fetch(`${API_BASE_URL}/orders?search_range=${searchRange}&open_only=${openOnly}`); if (!response.ok) { throw new Error('Failed to fetch orders'); } const orders = await response.json(); displayOrders(orders); showToast('Orders loaded successfully'); } catch (error) { showToast('Error fetching orders: ' + error.message, 'error'); } finally { setLoading(false); } } // Display orders in the UI function displayOrders(orders) { const ordersList = document.getElementById('ordersList'); ordersList.innerHTML = ''; if (!orders || orders.length === 0) { ordersList.innerHTML = '
No orders found
'; return; } orders.forEach(order => { const orderCard = document.createElement('div'); orderCard.className = `bg-gray-700 rounded-lg shadow-sm p-4 border border-gray-600 hover:shadow-md transition-shadow cursor-pointer ${ selectedOrders.has(order.orderNumber) ? 'ring-2 ring-blue-500' : '' }`; orderCard.dataset.orderId = order.orderNumber; orderCard.innerHTML = `

#${order.orderNumber || 'N/A'}

${order.buyerName || 'N/A'}

${order.orderStatus || 'Unknown'}

${order.orderDate ? new Date(order.orderDate).toLocaleString() : 'N/A'}

$${order.totalAmount ? order.totalAmount.toFixed(2) : '0.00'}

`; ordersList.appendChild(orderCard); // Add click event listener to the order card orderCard.addEventListener('click', () => { const orderId = orderCard.dataset.orderId; if (selectedOrders.has(orderId)) { selectedOrders.delete(orderId); orderCard.classList.remove('ring-2', 'ring-blue-500'); } else { selectedOrders.add(orderId); orderCard.classList.add('ring-2', 'ring-blue-500'); } }); }); } // Select all orders on the page function selectAllOrders() { const orderCards = document.querySelectorAll('[data-order-id]'); const allSelected = orderCards.length > 0 && Array.from(orderCards).every(card => selectedOrders.has(card.dataset.orderId)); orderCards.forEach(card => { const orderId = card.dataset.orderId; if (allSelected) { selectedOrders.delete(orderId); card.classList.remove('ring-2', 'ring-blue-500'); } else { selectedOrders.add(orderId); card.classList.add('ring-2', 'ring-blue-500'); } }); showToast(allSelected ? 'All orders deselected' : 'All orders selected'); } // Generate pull sheets async function generatePullSheets() { try { const orderIds = Array.from(selectedOrders); if (orderIds.length === 0) { showToast('Please select at least one order', 'error'); return; } setLoading(true); const response = await fetch(`${API_BASE_URL}/orders/generate-pull-sheets`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ order_ids: orderIds }) }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.detail || 'Failed to generate pull sheets'); } showToast('Pull sheets generated successfully'); } catch (error) { showToast('Error generating pull sheets: ' + error.message, 'error'); } finally { setLoading(false); } } // Generate packing slips async function generatePackingSlips() { try { const orderIds = Array.from(selectedOrders); if (orderIds.length === 0) { showToast('Please select at least one order', 'error'); return; } setLoading(true); const response = await fetch(`${API_BASE_URL}/orders/generate-packing-slips`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ order_ids: orderIds }) }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.detail || 'Failed to generate packing slips'); } showToast('Packing slips generated successfully'); } catch (error) { showToast('Error generating packing slips: ' + error.message, 'error'); } finally { setLoading(false); } } // Generate address labels async function generateAddressLabels() { try { const orderIds = Array.from(selectedOrders); if (orderIds.length === 0) { showToast('Please select at least one order', 'error'); return; } const labelType = document.getElementById('labelType').value; setLoading(true); const response = await fetch(`${API_BASE_URL}/orders/generate-address-labels`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ order_ids: orderIds, label_type: labelType }) }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.detail || 'Failed to generate address labels'); } showToast('Address labels generated successfully'); } catch (error) { showToast('Error generating address labels: ' + error.message, 'error'); } finally { setLoading(false); } } // Show return labels modal function showReturnLabelsModal() { const modal = document.getElementById('returnLabelsModal'); modal.classList.remove('hidden'); modal.classList.add('flex'); } // Close return labels modal function closeReturnLabelsModal() { const modal = document.getElementById('returnLabelsModal'); modal.classList.remove('flex'); modal.classList.add('hidden'); } // Submit return labels request async function submitReturnLabels() { try { const numberOfLabels = document.getElementById('numberOfLabels').value; if (!numberOfLabels || numberOfLabels < 1) { showToast('Please enter a valid number of labels', 'error'); return; } setLoading(true); const response = await fetch(`${API_BASE_URL}/orders/generate-return-labels`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ number_of_labels: parseInt(numberOfLabels) }) }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.detail || 'Failed to generate return labels'); } showToast('Return labels generated successfully'); closeReturnLabelsModal(); } catch (error) { showToast('Error generating return labels: ' + error.message, 'error'); } finally { setLoading(false); } } // Generate return labels (opens modal) function generateReturnLabels() { showReturnLabelsModal(); } // Show Pirate Ship label modal function showPirateShipModal() { const modal = document.getElementById('pirateShipModal'); modal.classList.remove('hidden'); modal.classList.add('flex'); } // Close Pirate Ship label modal function closePirateShipModal() { const modal = document.getElementById('pirateShipModal'); modal.classList.remove('flex'); modal.classList.add('hidden'); // Reset file input document.getElementById('pirateShipFile').value = ''; } // Submit Pirate Ship label async function submitPirateShipLabel() { try { const fileInput = document.getElementById('pirateShipFile'); const file = fileInput.files[0]; if (!file) { showToast('Please select a PDF file', 'error'); return; } if (file.type !== 'application/pdf') { showToast('Please select a valid PDF file', 'error'); return; } setLoading(true); const formData = new FormData(); formData.append('file', file); const response = await fetch(`${API_BASE_URL}/orders/print-pirate-ship-label`, { method: 'POST', body: formData }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.detail || 'Failed to print Pirate Ship label'); } showToast('Pirate Ship label printed successfully'); closePirateShipModal(); } catch (error) { showToast('Error printing Pirate Ship label: ' + error.message, 'error'); } finally { setLoading(false); } } // Show set labels modal function showSetLabelsModal() { const modal = document.getElementById('setLabelsModal'); modal.classList.remove('hidden'); modal.classList.add('flex'); fetchAvailableSets(); // Add event listener for search input const searchInput = document.getElementById('setSearch'); searchInput.addEventListener('input', filterSets); } // Close set labels modal function closeSetLabelsModal() { const modal = document.getElementById('setLabelsModal'); modal.classList.remove('flex'); modal.classList.add('hidden'); // Clear search input document.getElementById('setSearch').value = ''; } // Filter sets based on search input function filterSets() { const searchTerm = document.getElementById('setSearch').value.toLowerCase(); const setItems = document.querySelectorAll('#setLabelsList > div'); setItems.forEach(item => { const label = item.querySelector('label'); const text = label.textContent.toLowerCase(); if (text.includes(searchTerm)) { item.style.display = 'flex'; } else { item.style.display = 'none'; } }); } // Fetch available sets from the API async function fetchAvailableSets() { try { setLoading(true); const response = await fetch(`${API_BASE_URL}/set-labels/available-sets`); if (!response.ok) { throw new Error('Failed to fetch available sets'); } const sets = await response.json(); displayAvailableSets(sets); } catch (error) { showToast('Error fetching available sets: ' + error.message, 'error'); } finally { setLoading(false); } } // Display available sets in the modal function displayAvailableSets(sets) { const setList = document.getElementById('setLabelsList'); setList.innerHTML = ''; if (!sets || sets.length === 0) { setList.innerHTML = '
No sets available
'; return; } // Sort sets alphabetically by name sets.sort((a, b) => a.name.localeCompare(b.name)); sets.forEach(set => { const setItem = document.createElement('div'); setItem.className = 'flex items-center p-2 hover:bg-gray-600 rounded-lg cursor-pointer'; setItem.innerHTML = ` `; setList.appendChild(setItem); }); // Trigger initial filter in case there's text in the search box filterSets(); } // Submit set labels request async function submitSetLabels() { try { const selectedSets = Array.from(document.querySelectorAll('#setLabelsList input[type="checkbox"]:checked')) .map(checkbox => checkbox.id.replace('set-', '')); if (selectedSets.length === 0) { showToast('Please select at least one set', 'error'); return; } setLoading(true); const response = await fetch(`${API_BASE_URL}/set-labels/generate`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ sets: selectedSets }) }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.detail || 'Failed to generate set labels'); } showToast('Set labels generated successfully'); closeSetLabelsModal(); } catch (error) { showToast('Error generating set labels: ' + error.message, 'error'); } finally { setLoading(false); } } // Load orders when page loads document.addEventListener('DOMContentLoaded', () => { fetchOrders(); // Add event listeners for search range and open only checkbox document.getElementById('searchRange').addEventListener('change', fetchOrders); document.getElementById('openOnly').addEventListener('change', fetchOrders); });