Files
orion/app/modules/prospecting/static/admin/js/leads.js
Samir Boulahtit 6d6eba75bf
Some checks failed
CI / pytest (push) Failing after 48m31s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
CI / ruff (push) Successful in 11s
CI / validate (push) Successful in 23s
CI / dependency-scanning (push) Successful in 28s
feat(prospecting): add complete prospecting module for lead discovery and scoring
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>
2026-02-28 00:59:47 +01:00

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';
},
};
}