// static/admin/js/leads.js const leadsLog = window.LogConfig.createLogger('prospecting-leads'); function leadsList() { return { ...data(), currentPage: 'leads', leads: [], loading: true, error: null, // Filters minScore: 0, filterTier: '', filterChannel: '', filterIssue: '', filterHasEmail: '', // Pagination pagination: { page: 1, per_page: 20, total: 0, pages: 0 }, async init() { await I18n.loadModule('prospecting'); if (window._leadsListInit) return; window._leadsListInit = true; if (window.PlatformSettings) { this.pagination.per_page = await window.PlatformSettings.getRowsPerPage(); } leadsLog.info('Leads list initializing'); await this.loadLeads(); }, async loadLeads() { this.loading = true; this.error = null; try { const params = new URLSearchParams({ page: this.pagination.page, per_page: this.pagination.per_page, }); if (this.minScore > 0) params.set('min_score', this.minScore); if (this.filterTier) params.set('lead_tier', this.filterTier); if (this.filterChannel) params.set('channel', this.filterChannel); if (this.filterIssue) params.set('reason_flag', this.filterIssue); if (this.filterHasEmail) params.set('has_email', this.filterHasEmail); const response = await apiClient.get('/admin/prospecting/leads?' + params); this.leads = response.items || []; this.pagination.total = response.total || 0; this.pagination.pages = response.pages || 0; } catch (err) { this.error = err.message; leadsLog.error('Failed to load leads', err); } finally { this.loading = false; } }, async exportCSV() { try { const params = new URLSearchParams(); if (this.minScore > 0) params.set('min_score', this.minScore); if (this.filterTier) params.set('lead_tier', this.filterTier); if (this.filterChannel) params.set('channel', this.filterChannel); const url = '/admin/prospecting/leads/export/csv?' + params; window.open('/api/v1' + url, '_blank'); Utils.showToast('CSV export started', 'success'); } catch (err) { Utils.showToast('Export failed: ' + err.message, 'error'); } }, sendCampaign(lead) { window.location.href = '/admin/prospecting/prospects/' + lead.id + '#campaigns'; }, goToPage(page) { this.pagination.page = page; this.loadLeads(); }, tierBadgeClass(tier) { const classes = { top_priority: 'text-red-700 bg-red-100 dark:text-red-100 dark:bg-red-700', quick_win: 'text-orange-700 bg-orange-100 dark:text-orange-100 dark:bg-orange-700', strategic: 'text-blue-700 bg-blue-100 dark:text-blue-100 dark:bg-blue-700', low_priority: 'text-gray-700 bg-gray-100 dark:text-gray-100 dark:bg-gray-700', }; return classes[tier] || classes.low_priority; }, scoreColor(score) { if (score == null) return 'text-gray-400'; if (score >= 70) return 'text-red-600'; if (score >= 50) return 'text-orange-600'; if (score >= 30) return 'text-blue-600'; return 'text-gray-600'; }, }; }