// static/admin/js/customers.js /** * Admin customer management page logic */ // Create logger for this module const customersLog = window.LogConfig?.createLogger('CUSTOMERS') || console; function adminCustomers() { return { // Inherit base layout state ...data(), // Page identifier currentPage: 'customers', // Loading states loading: true, loadingCustomers: false, // Error state error: '', // Data customers: [], vendors: [], stats: { total: 0, active: 0, inactive: 0, with_orders: 0, total_spent: 0, total_orders: 0, avg_order_value: 0 }, // Pagination page: 1, limit: 20, total: 0, skip: 0, // Filters filters: { search: '', is_active: '', vendor_id: '' }, // Computed: total pages get totalPages() { return Math.ceil(this.total / this.limit); }, async init() { customersLog.debug('Customers page initialized'); // Load vendors for filter dropdown await this.loadVendors(); // Load initial data await Promise.all([ this.loadCustomers(), this.loadStats() ]); this.loading = false; }, /** * Load vendors for filter dropdown */ async loadVendors() { try { const response = await apiClient.get('/admin/vendors?limit=100'); this.vendors = response.vendors || []; } catch (error) { customersLog.error('Failed to load vendors:', error); this.vendors = []; } }, /** * Load customers with current filters */ async loadCustomers() { this.loadingCustomers = true; this.error = ''; this.skip = (this.page - 1) * this.limit; try { const params = new URLSearchParams({ skip: this.skip.toString(), limit: this.limit.toString() }); if (this.filters.search) { params.append('search', this.filters.search); } if (this.filters.is_active !== '') { params.append('is_active', this.filters.is_active); } if (this.filters.vendor_id) { params.append('vendor_id', this.filters.vendor_id); } const response = await apiClient.get(`/admin/customers?${params}`); this.customers = response.customers || []; this.total = response.total || 0; } catch (error) { customersLog.error('Failed to load customers:', error); this.error = error.message || 'Failed to load customers'; this.customers = []; } finally { this.loadingCustomers = false; } }, /** * Load customer statistics */ async loadStats() { try { const params = new URLSearchParams(); if (this.filters.vendor_id) { params.append('vendor_id', this.filters.vendor_id); } const response = await apiClient.get(`/admin/customers/stats?${params}`); this.stats = response; } catch (error) { customersLog.error('Failed to load stats:', error); } }, /** * Reset pagination and reload */ async resetAndLoad() { this.page = 1; await Promise.all([ this.loadCustomers(), this.loadStats() ]); }, /** * Go to specific page */ goToPage(p) { this.page = p; this.loadCustomers(); }, /** * Get array of page numbers to display */ getPageNumbers() { const total = this.totalPages; const current = this.page; const maxVisible = 5; if (total <= maxVisible) { return Array.from({length: total}, (_, i) => i + 1); } const half = Math.floor(maxVisible / 2); let start = Math.max(1, current - half); let end = Math.min(total, start + maxVisible - 1); if (end - start < maxVisible - 1) { start = Math.max(1, end - maxVisible + 1); } return Array.from({length: end - start + 1}, (_, i) => start + i); }, /** * Toggle customer active status */ async toggleStatus(customer) { const action = customer.is_active ? 'deactivate' : 'activate'; if (!confirm(`Are you sure you want to ${action} this customer?`)) { return; } try { const response = await apiClient.patch(`/admin/customers/${customer.id}/toggle-status`); customer.is_active = response.is_active; // Update stats if (response.is_active) { this.stats.active++; this.stats.inactive--; } else { this.stats.active--; this.stats.inactive++; } customersLog.info(response.message); } catch (error) { customersLog.error('Failed to toggle status:', error); alert(error.message || 'Failed to toggle customer status'); } }, /** * Format currency for display */ formatCurrency(amount) { if (amount == null) return '-'; return new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(amount); }, /** * Format date for display */ formatDate(dateString) { if (!dateString) return '-'; try { const date = new Date(dateString); return date.toLocaleDateString('en-GB', { year: 'numeric', month: 'short', day: 'numeric' }); } catch { return dateString; } } }; }