Some checks failed
Migrates scanning pipeline from marketing-.lu-domains app into Orion module. Supports digital (domain scan) and offline (manual capture) lead channels with enrichment, scoring, campaign management, and interaction tracking. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
108 lines
3.7 KiB
JavaScript
108 lines
3.7 KiB
JavaScript
// 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';
|
|
},
|
|
};
|
|
}
|