Order Management

Process and track your customer orders

Total Orders

0

+0%

Pending Orders

0

Needs Action

Shipped Today

0

On Time

Revenue Today

$0.00

+0%

#VM-2024-1847

2 hours ago

Pending

Organic Basmati Rice

Qty: 1 × $24.99

Turmeric Powder

Qty: 2 × $12.49

Customer: Sarah Johnson
Total: $49.97

#VM-2024-1846

4 hours ago

Shipped

Kashmiri Red Chili

Qty: 3 × $8.99

Customer: Raj Patel
Total: $26.97

#VM-2024-1845

6 hours ago

Delivered

Fresh Curry Leaves

Qty: 5 × $3.99

Customer: Maria Rodriguez
Total: $19.95
Showing 0 orders
...
`); this.showNotification('Label Generated', `Shipping label for order #${orderId}`, 'fas fa-print', 'success'); } catch (error) { console.error('Failed to print label:', error); this.showNotification('Error', 'Failed to generate shipping label', 'fas fa-exclamation-circle', 'error'); } } async exportOrders(format = 'csv') { try { this.showNotification('Export Started', 'Preparing order export...', 'fas fa-download', 'info'); const params = {}; if (this.filters.status) params.status_filter = this.filters.status; const orders = await API.getVendorOrders({ ...params, per_page: 1000 }); if (!orders.items || orders.items.length === 0) { this.showNotification('No Data', 'No orders to export', 'fas fa-info-circle', 'warning'); return; } // Generate CSV const headers = ['Order ID', 'Date', 'Customer', 'Status', 'Total', 'Items', 'Tracking']; const rows = orders.items.map(o => [ o.id, new Date(o.created_at).toLocaleDateString(), o.customer_name || 'N/A', o.status, o.total, o.items?.length || 0, o.tracking_number || '' ]); const csv = [headers, ...rows].map(row => row.join(',')).join('\n'); const blob = new Blob([csv], { type: 'text/csv' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `orders_export_${new Date().toISOString().split('T')[0]}.csv`; a.click(); URL.revokeObjectURL(url); this.showNotification('Export Complete', `${orders.items.length} orders exported`, 'fas fa-check', 'success'); } catch (error) { console.error('Failed to export orders:', error); this.showNotification('Error', 'Failed to export orders', 'fas fa-exclamation-circle', 'error'); } } async bulkProcess(orderIds, newStatus) { try { this.showNotification('Processing', `Updating ${orderIds.length} orders...`, 'fas fa-spinner', 'info'); // Try bulk API first, fallback to individual updates let result; try { result = await API.bulkUpdateVendorOrderStatus(orderIds, newStatus); } catch (bulkError) { // Fallback to individual updates if bulk endpoint not available console.warn('Bulk endpoint not available, falling back to individual updates'); const results = await Promise.allSettled( orderIds.map(id => API.updateVendorOrderStatus(id, newStatus)) ); result = { updated: results.filter(r => r.status === 'fulfilled').length, failed: results.filter(r => r.status === 'rejected').length }; } const succeeded = result.updated || 0; const failed = result.failed || 0; // Invalidate caches OrderCache.invalidate('orders'); OrderCache.delete('dashboard_stats'); if (failed > 0) { this.showNotification( 'Partial Success', `${succeeded} orders updated, ${failed} failed`, 'fas fa-exclamation-triangle', 'warning' ); } else { this.showNotification( 'Bulk Update Complete', `${succeeded} orders updated to ${newStatus}`, 'fas fa-check', 'success' ); } await this.loadOrders(true); await this.loadDashboardStats(); return { succeeded, failed }; } catch (error) { console.error('Failed to bulk update orders:', error); this.showNotification('Error', 'Failed to update orders', 'fas fa-exclamation-circle', 'error'); throw error; } } async bulkPrintLabels(orderIds) { try { this.showNotification('Preparing Labels', `Generating ${orderIds.length} shipping labels...`, 'fas fa-print', 'info'); // Try bulk API first, fallback to fetching individual orders let orders; try { const response = await API.generateBulkShippingLabels(orderIds); orders = response.labels || []; } catch (bulkError) { // Fallback to individual fetches console.warn('Bulk labels endpoint not available, falling back to individual fetches'); orders = await Promise.all(orderIds.map(id => this.getOrderDetails(id))); } // Generate combined labels document const labelWindow = window.open('', '_blank', 'width=800,height=600'); const labelsHTML = orders.map(order => `

IndianShopping.com

${order.tracking_number || 'N/A'}
Order ID: #${order.id}
Date: ${new Date(order.created_at).toLocaleDateString()}
Ship To:
${order.shipping_address?.name || 'Customer'}
${order.shipping_address?.line1 || ''}
${order.shipping_address?.city || ''}, ${order.shipping_address?.state || ''}
${order.shipping_address?.pincode || ''}
`).join(''); labelWindow.document.write(` Shipping Labels (${orders.length}) ${labelsHTML} `); this.showNotification('Labels Ready', `${orders.length} shipping labels generated`, 'fas fa-check', 'success'); } catch (error) { console.error('Failed to print bulk labels:', error); this.showNotification('Error', 'Failed to generate shipping labels', 'fas fa-exclamation-circle', 'error'); } } async bulkExport(orderIds) { try { const orders = await Promise.all(orderIds.map(id => this.getOrderDetails(id))); const headers = ['Order ID', 'Date', 'Customer', 'Status', 'Total', 'Tracking']; const rows = orders.map(o => [ o.id, new Date(o.created_at).toLocaleDateString(), o.customer_name || 'N/A', o.status, o.total, o.tracking_number || '' ]); const csv = [headers, ...rows].map(row => row.join(',')).join('\n'); const blob = new Blob([csv], { type: 'text/csv' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `selected_orders_${new Date().toISOString().split('T')[0]}.csv`; a.click(); URL.revokeObjectURL(url); this.showNotification('Export Complete', `${orders.length} orders exported`, 'fas fa-check', 'success'); } catch (error) { console.error('Failed to export selected orders:', error); this.showNotification('Error', 'Failed to export orders', 'fas fa-exclamation-circle', 'error'); } } async trackShipment(orderId) { try { const order = await this.getOrderDetails(orderId); if (order.tracking_number && order.carrier) { // Open tracking URL based on carrier const trackingUrls = { 'DTDC': `https://www.dtdc.in/tracking.asp?strCnno=${order.tracking_number}`, 'BlueDart': `https://www.bluedart.com/tracking?trackNo=${order.tracking_number}`, 'Delhivery': `https://www.delhivery.com/track/package/${order.tracking_number}`, 'FedEx': `https://www.fedex.com/apps/fedextrack/?tracknumbers=${order.tracking_number}`, 'default': `https://track.aftership.com/${order.tracking_number}` }; const url = trackingUrls[order.carrier] || trackingUrls['default']; window.open(url, '_blank'); this.showNotification('Tracking', `Opening tracking for ${order.carrier}`, 'fas fa-truck', 'info'); } else { this.showNotification('No Tracking', 'No tracking information available', 'fas fa-info-circle', 'warning'); } } catch (error) { console.error('Failed to track shipment:', error); this.showNotification('Error', 'Failed to load tracking info', 'fas fa-exclamation-circle', 'error'); } } async contactCustomer(orderId) { try { const order = await this.getOrderDetails(orderId); // Open email client or messaging interface if (order.customer_email) { window.location.href = `mailto:${order.customer_email}?subject=Regarding Order #${orderId}`; this.showNotification('Contact', 'Opening email client...', 'fas fa-envelope', 'info'); } else if (order.customer_phone) { window.location.href = `tel:${order.customer_phone}`; this.showNotification('Contact', 'Opening phone dialer...', 'fas fa-phone', 'info'); } else { this.showNotification('No Contact', 'No contact information available', 'fas fa-info-circle', 'warning'); } } catch (error) { console.error('Failed to contact customer:', error); this.showNotification('Error', 'Failed to load customer info', 'fas fa-exclamation-circle', 'error'); } } async requestReview(orderId) { try { const order = await this.getOrderDetails(orderId); // Note: Would need a backend endpoint for review requests // For now, simulate sending a review request email this.showNotification('Review Request', `Review request sent for order #${orderId}`, 'fas fa-star', 'success'); } catch (error) { console.error('Failed to request review:', error); this.showNotification('Error', 'Failed to send review request', 'fas fa-exclamation-circle', 'error'); } } async viewReceipt(orderId) { try { const order = await this.getOrderDetails(orderId); const receiptWindow = window.open('', '_blank', 'width=600,height=800'); receiptWindow.document.write(` Receipt - Order #${orderId}

IndianShopping.com

Order Receipt

Order ID: #${orderId}
Date: ${new Date(order.created_at).toLocaleDateString()}
Status: ${order.status}

Items

${(order.items || []).map(item => ` `).join('')}
ItemQtyPrice
${item.product_name || 'Product'} ${item.quantity} ₹${item.price?.toLocaleString('en-IN')}
Subtotal₹${(order.subtotal || order.total)?.toLocaleString('en-IN')}
Shipping₹${(order.shipping_cost || 0)?.toLocaleString('en-IN')}
Tax₹${(order.tax || 0)?.toLocaleString('en-IN')}
Total₹${order.total?.toLocaleString('en-IN')}
`); this.showNotification('Receipt', `Receipt generated for order #${orderId}`, 'fas fa-receipt', 'success'); } catch (error) { console.error('Failed to view receipt:', error); this.showNotification('Error', 'Failed to generate receipt', 'fas fa-exclamation-circle', 'error'); } } async loadOrderInsights() { try { // Fetch dashboard stats and financial data for insights const [dashboard, financial] = await Promise.all([ API.getVendorDashboard(), API.getVendorFinancialDashboard().catch(() => null) ]); // Update insights modal with real data const insightsModal = document.getElementById('order-insights-modal'); if (insightsModal && dashboard) { // Update stats in the modal const statElements = insightsModal.querySelectorAll('.text-2xl, .text-3xl'); // This would need specific element IDs for proper targeting } return { dashboard, financial }; } catch (error) { console.error('Failed to load order insights:', error); } } async exportInsightsReport() { try { const [dashboard, orders] = await Promise.all([ API.getVendorDashboard(), API.getVendorOrders({ per_page: 1000 }) ]); // Generate insights report const report = { generated_at: new Date().toISOString(), total_orders: dashboard.total_orders, pending_orders: dashboard.pending_orders, total_revenue: dashboard.total_revenue, active_products: dashboard.active_products, order_breakdown: this.calculateOrderBreakdown(orders.items || []) }; const blob = new Blob([JSON.stringify(report, null, 2)], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `order_insights_${new Date().toISOString().split('T')[0]}.json`; a.click(); URL.revokeObjectURL(url); this.showNotification('Report Exported', 'Order insights report downloaded', 'fas fa-download', 'success'); } catch (error) { console.error('Failed to export insights:', error); this.showNotification('Error', 'Failed to export insights report', 'fas fa-exclamation-circle', 'error'); } } calculateOrderBreakdown(orders) { const breakdown = {}; orders.forEach(order => { breakdown[order.status] = (breakdown[order.status] || 0) + 1; }); return breakdown; } renderOrders() { const gridContainer = document.getElementById('orders-grid'); const listContainer = document.getElementById('orders-list'); if (!gridContainer || !listContainer) return; if (this.orders.length === 0) { const emptyMessage = `

No Orders Found

Orders will appear here when customers place them.

`; gridContainer.innerHTML = emptyMessage; return; } // Render grid view gridContainer.innerHTML = this.orders.map(order => this.renderOrderCard(order)).join(''); // Render list view const listBody = listContainer.querySelector('tbody'); if (listBody) { listBody.innerHTML = this.orders.map(order => this.renderOrderRow(order)).join(''); } } renderOrderCard(order) { const statusColors = { 'PENDING': 'status-pending', 'CONFIRMED': 'status-confirmed', 'PROCESSING': 'status-processing', 'SHIPPED': 'status-shipped', 'OUT_FOR_DELIVERY': 'status-shipped', 'DELIVERED': 'status-delivered', 'CANCELLED': 'status-cancelled', 'RETURNED': 'status-returned' }; return `

#${order.id}

${new Date(order.created_at).toLocaleDateString()}

${order.status?.replace('_', ' ') || 'Unknown'}
Customer ${order.customer_name || 'N/A'}
Items ${order.items?.length || 0} items
Total ₹${order.total?.toLocaleString('en-IN') || '0'}
`; } renderOrderRow(order) { const statusColors = { 'PENDING': 'status-pending', 'CONFIRMED': 'status-confirmed', 'PROCESSING': 'status-processing', 'SHIPPED': 'status-shipped', 'OUT_FOR_DELIVERY': 'status-shipped', 'DELIVERED': 'status-delivered', 'CANCELLED': 'status-cancelled', 'RETURNED': 'status-returned' }; return ` #${order.id} ${new Date(order.created_at).toLocaleDateString()} ${order.customer_name || 'N/A'} ${order.status?.replace('_', ' ') || 'Unknown'} ₹${order.total?.toLocaleString('en-IN') || '0'}
`; } // ===================================================== // UI SETUP METHODS // ===================================================== setupTheme() { const themeToggle = document.getElementById('theme-toggle'); const currentTheme = localStorage.getItem('theme') || 'dark'; document.documentElement.className = currentTheme; this.updateThemeUI(currentTheme); themeToggle?.addEventListener('click', () => { const newTheme = document.documentElement.className === 'dark' ? 'light' : 'dark'; document.documentElement.className = newTheme; localStorage.setItem('theme', newTheme); this.updateThemeUI(newTheme); }); } updateThemeUI(theme) { document.body.className = 'min-h-screen transition-all duration-300'; } setupSearch() { const searchInput = document.getElementById('order-search'); let searchTimeout; searchInput?.addEventListener('input', (e) => { clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { this.filters.search = e.target.value; this.applyFilters(); }, 300); }); } setupFilters() { const filters = ['status-filter', 'priority-filter', 'date-filter']; filters.forEach(filterId => { const element = document.getElementById(filterId); element?.addEventListener('change', (e) => { const filterType = filterId.replace('-filter', ''); this.filters[filterType] = e.target.value; this.applyFilters(); }); }); window.clearFilters = () => { this.filters = { search: '', status: '', priority: '', date: '' }; document.getElementById('order-search').value = ''; document.getElementById('status-filter').value = ''; document.getElementById('priority-filter').value = ''; document.getElementById('date-filter').value = ''; this.applyFilters(); }; } setupViewToggle() { const gridViewBtn = document.getElementById('grid-view'); const listViewBtn = document.getElementById('list-view'); const gridContainer = document.getElementById('orders-grid'); const listContainer = document.getElementById('orders-list'); gridViewBtn?.addEventListener('click', () => { this.currentView = 'grid'; gridViewBtn.classList.add('bg-accent-600', 'text-white'); gridViewBtn.classList.remove('text-slate-400'); listViewBtn?.classList.remove('bg-accent-600', 'text-white'); listViewBtn?.classList.add('text-slate-400'); gridContainer?.classList.remove('hidden'); listContainer?.classList.add('hidden'); }); listViewBtn?.addEventListener('click', () => { this.currentView = 'list'; listViewBtn.classList.add('bg-accent-600', 'text-white'); listViewBtn.classList.remove('text-slate-400'); gridViewBtn?.classList.remove('bg-accent-600', 'text-white'); gridViewBtn?.classList.add('text-slate-400'); listContainer?.classList.remove('hidden'); gridContainer?.classList.add('hidden'); }); } setupBulkActions() { const bulkBtn = document.getElementById('bulk-actions-btn'); const bulkDropdown = document.getElementById('bulk-dropdown'); bulkBtn?.addEventListener('click', () => { bulkDropdown?.classList.toggle('hidden'); }); document.addEventListener('click', (e) => { if (!bulkBtn?.contains(e.target) && !bulkDropdown?.contains(e.target)) { bulkDropdown?.classList.add('hidden'); } }); // Wire bulk action functions to API window.bulkUpdateStatus = () => this.openBulkStatusModal(); window.bulkPrintLabels = () => { const orderIds = Array.from(this.selectedOrders); if (orderIds.length > 0) { this.bulkPrintLabels(orderIds); } }; window.bulkExport = () => { const orderIds = Array.from(this.selectedOrders); if (orderIds.length > 0) { this.bulkExport(orderIds); } }; window.bulkCancel = () => this.bulkAction('cancel'); } setupOrderSelection() { const selectAllCheckbox = document.getElementById('select-all'); selectAllCheckbox?.addEventListener('change', (e) => { const checkboxes = document.querySelectorAll('.order-checkbox'); checkboxes.forEach(checkbox => { checkbox.checked = e.target.checked; const orderId = checkbox.closest('.order-card, tr')?.dataset.orderId; if (orderId) { if (e.target.checked) { this.selectedOrders.add(orderId); } else { this.selectedOrders.delete(orderId); } } }); this.updateBulkActionsUI(); }); document.addEventListener('change', (e) => { if (e.target.classList.contains('order-checkbox')) { const orderId = e.target.closest('.order-card, tr')?.dataset.orderId; if (orderId) { if (e.target.checked) { this.selectedOrders.add(orderId); } else { this.selectedOrders.delete(orderId); } this.updateBulkActionsUI(); } } }); } setupModals() { // Wire modal handlers to API window.viewOrder = async (orderId) => { this.currentOrderId = orderId; await this.openOrderDetailsModal(); }; window.closeOrderDetailsModal = () => { const modal = document.getElementById('order-details-modal'); modal?.classList.add('hidden'); document.body.style.overflow = 'auto'; }; window.updateOrderStatus = (orderId) => { this.currentOrderId = orderId; this.openUpdateStatusModal(); }; window.closeUpdateStatusModal = () => { const modal = document.getElementById('update-status-modal'); modal?.classList.add('hidden'); document.body.style.overflow = 'auto'; }; window.confirmStatusUpdate = async () => { const newStatus = document.getElementById('new-status')?.value; const trackingNumber = document.getElementById('tracking-number')?.value; const carrier = document.getElementById('carrier')?.value || 'Standard'; if (newStatus === 'SHIPPED' && trackingNumber) { await this.shipOrder(this.currentOrderId, trackingNumber, carrier); } else if (newStatus) { await this.processOrder(this.currentOrderId, newStatus); } closeUpdateStatusModal(); }; window.closeBulkStatusModal = () => { const modal = document.getElementById('bulk-status-modal'); modal?.classList.add('hidden'); document.body.style.overflow = 'auto'; }; window.confirmBulkStatusUpdate = async () => { const newStatus = document.getElementById('bulk-new-status')?.value; if (newStatus && this.selectedOrders.size > 0) { await this.bulkProcess(Array.from(this.selectedOrders), newStatus); this.selectedOrders.clear(); this.updateBulkActionsUI(); } closeBulkStatusModal(); }; window.openOrderInsights = async () => { const modal = document.getElementById('order-insights-modal'); modal?.classList.remove('hidden'); document.body.style.overflow = 'hidden'; await this.loadOrderInsights(); }; window.closeOrderInsightsModal = () => { const modal = document.getElementById('order-insights-modal'); modal?.classList.add('hidden'); document.body.style.overflow = 'auto'; }; window.exportInsights = () => { this.exportInsightsReport(); closeOrderInsightsModal(); }; // Wire other action functions to API window.printShippingLabel = (orderId) => this.printLabel(orderId); window.trackShipment = (orderId) => this.trackShipment(orderId); window.contactCustomer = (orderId) => this.contactCustomer(orderId); window.requestReview = (orderId) => this.requestReview(orderId); window.viewReceipt = (orderId) => this.viewReceipt(orderId); window.refreshOrders = async () => { const button = document.querySelector('.fa-sync-alt')?.parentElement; button?.classList.add('loading-spinner'); OrderCache.clear(); await this.loadOrders(true); await this.loadDashboardStats(); button?.classList.remove('loading-spinner'); this.showNotification('Orders Refreshed', 'Order list updated with latest data', 'fas fa-sync-alt', 'success'); }; window.exportOrders = () => this.exportOrders(); // Status change tracking input document.getElementById('new-status')?.addEventListener('change', (e) => { const trackingInfo = document.getElementById('tracking-info'); if (e.target.value === 'SHIPPED') { trackingInfo?.classList.remove('hidden'); } else { trackingInfo?.classList.add('hidden'); } }); // Close modals on backdrop click document.addEventListener('click', (e) => { if (e.target.classList.contains('modal-backdrop')) { const modals = document.querySelectorAll('[id$="-modal"]'); modals.forEach(modal => modal.classList.add('hidden')); document.body.style.overflow = 'auto'; } }); } async openOrderDetailsModal() { const modal = document.getElementById('order-details-modal'); if (!modal) return; try { const order = await this.getOrderDetails(this.currentOrderId); // Update modal content with order details const modalBody = modal.querySelector('.modal-body'); if (modalBody) { modalBody.innerHTML = `

Order #${order.id}

${order.status?.replace('_', ' ')}

Customer

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

${order.customer_email || ''}

Order Date

${new Date(order.created_at).toLocaleString()}

Shipping Address

${order.shipping_address?.line1 || 'N/A'}
${order.shipping_address?.city || ''}, ${order.shipping_address?.state || ''}
${order.shipping_address?.pincode || ''}

Order Items

${(order.items || []).map(item => `

${item.product_name || 'Product'}

Qty: ${item.quantity}

₹${item.price?.toLocaleString('en-IN')}

`).join('')}
Total ₹${order.total?.toLocaleString('en-IN')}
${order.tracking_number ? `

Tracking

${order.carrier || 'Carrier'}: ${order.tracking_number}

` : ''}
`; } modal.classList.remove('hidden'); document.body.style.overflow = 'hidden'; } catch (error) { console.error('Failed to open order details:', error); } } openUpdateStatusModal() { const modal = document.getElementById('update-status-modal'); const orderIdSpan = document.getElementById('status-order-id'); if (orderIdSpan) orderIdSpan.textContent = `#${this.currentOrderId}`; modal?.classList.remove('hidden'); document.body.style.overflow = 'hidden'; } openBulkStatusModal() { if (this.selectedOrders.size === 0) { this.showNotification('No Selection', 'Please select orders to update status', 'fas fa-exclamation-triangle', 'warning'); return; } const modal = document.getElementById('bulk-status-modal'); const countSpan = document.getElementById('bulk-order-count'); if (countSpan) countSpan.textContent = this.selectedOrders.size; modal?.classList.remove('hidden'); document.body.style.overflow = 'hidden'; } setupAutoRefresh() { // Auto-refresh orders every 30 seconds setInterval(async () => { if (!document.hidden) { await this.loadDashboardStats(); } }, 30000); // Reload on visibility change document.addEventListener('visibilitychange', async () => { if (!document.hidden) { await this.loadOrders(true); await this.loadDashboardStats(); } }); } updateBulkActionsUI() { const count = this.selectedOrders.size; const countSpan = document.getElementById('selected-count'); const bulkBtn = document.getElementById('bulk-actions-btn'); if (countSpan) countSpan.textContent = count; if (bulkBtn) bulkBtn.disabled = count === 0; } bulkAction(action) { const count = this.selectedOrders.size; if (count === 0) return; if (action === 'cancel') { if (confirm(`Are you sure you want to cancel ${count} selected orders?`)) { this.bulkProcess(Array.from(this.selectedOrders), 'CANCELLED'); this.selectedOrders.clear(); this.updateBulkActionsUI(); } } document.getElementById('bulk-dropdown')?.classList.add('hidden'); } async applyFilters() { this.currentPage = 1; await this.loadOrders(true); const activeFilters = Object.values(this.filters).filter(f => f !== '').length; if (activeFilters > 0) { this.showNotification( 'Filters Applied', `${activeFilters} filter(s) active. Showing filtered results.`, 'fas fa-filter', 'info' ); } } showNotification(title, message, icon, type = 'info') { const colors = { info: 'from-blue-500 to-blue-600', success: 'from-green-500 to-green-600', warning: 'from-yellow-500 to-orange-500', error: 'from-red-500 to-red-600' }; const notification = document.createElement('div'); notification.className = `bg-gradient-to-r ${colors[type]} text-white p-4 rounded-lg shadow-xl animate-slide-in-right max-w-sm mb-2`; notification.innerHTML = `

${title}

${message}

`; const container = document.getElementById('notification-container'); container?.appendChild(notification); setTimeout(() => { notification.style.opacity = '0'; notification.style.transform = 'translateX(100%)'; setTimeout(() => notification.remove(), 300); }, 5000); } } // Initialize Order Manager when API client is ready window.addEventListener('load', async () => { // Wait for API client to be available if (typeof API === 'undefined') { console.error('API client not loaded. Please include api-client.js before this script.'); return; } try { const orderManager = new OrderManager(); window.orderManager = orderManager; // Expose for debugging // Show welcome notification after initial load setTimeout(() => { orderManager.showNotification( 'Order Dashboard Ready', 'Connected to API. Auto-refresh is active.', 'fas fa-shopping-cart', 'info' ); }, 1500); } catch (error) { console.error('Failed to initialize Order Manager:', error); } }); // Performance optimization let resizeTimeout; window.addEventListener('resize', () => { clearTimeout(resizeTimeout); resizeTimeout = setTimeout(() => { // Recalculate responsive elements if needed }, 250); }); // Global showToast function for compatibility with other components window.showToast = function(message, type = 'info') { if (window.orderManager) { const icons = { success: 'fas fa-check-circle', error: 'fas fa-exclamation-circle', warning: 'fas fa-exclamation-triangle', info: 'fas fa-info-circle' }; window.orderManager.showNotification( type.charAt(0).toUpperCase() + type.slice(1), message, icons[type] || 'fas fa-info-circle', type ); } else if (typeof showNotification === 'function') { showNotification(message, type); } else { console.log(`[${type.toUpperCase()}] ${message}`); } };