From b1a2468382f1c183aa69d077251a7f2dd74bf531 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Bajpai Date: Mon, 22 Jun 2026 12:14:31 +0530 Subject: [PATCH] feat: filter campaign leads by tag --- frontend/campaign-builder.html | 95 ++++++++++++++++++++++++++++------ 1 file changed, 78 insertions(+), 17 deletions(-) diff --git a/frontend/campaign-builder.html b/frontend/campaign-builder.html index 25f873b..7bf1712 100644 --- a/frontend/campaign-builder.html +++ b/frontend/campaign-builder.html @@ -1243,6 +1243,7 @@ let activeTab = 'sequence'; let availableLeads = []; let selectedLeadIds = new Set(); + let selectedLeadTagFilter = ''; let aiComposerStep = null; let aiConversation = []; let aiLatestDraft = null; @@ -1305,6 +1306,24 @@ return `${value.slice(0, limit)}...`; } + function getUniqueLeadTags() { + const tagsById = new Map(); + availableLeads.forEach(lead => { + (lead.tags || []).forEach(tag => { + if (!tag?.id) return; + tagsById.set(String(tag.id), tag); + }); + }); + return [...tagsById.values()].sort((a, b) => String(a.name || '').localeCompare(String(b.name || ''))); + } + + function getFilteredLeads() { + if (!selectedLeadTagFilter) return availableLeads; + return availableLeads.filter(lead => + (lead.tags || []).some(tag => String(tag.id) === String(selectedLeadTagFilter)) + ); + } + async function loadEmailTemplates() { try { const res = await fetchWithAuth('/email-templates/'); @@ -1561,15 +1580,20 @@ function renderLeadsTab() { const canvas = document.getElementById('canvas'); - const rows = availableLeads.map(lead => { - const checked = selectedLeadIds.has(lead.id) ? 'checked' : ''; + const filteredLeads = getFilteredLeads(); + const tags = getUniqueLeadTags(); + const rows = filteredLeads.map(lead => { + const leadId = String(lead.id); + const checked = selectedLeadIds.has(leadId) ? 'checked' : ''; + const tagNames = (lead.tags || []).map(tag => `${escapeHtml(tag.name)}`).join(''); return ` - - ${lead.first_name || ''} ${lead.last_name || ''} - ${lead.email} - ${lead.phone || '-'} - ${lead.company || '-'} + + ${escapeHtml(lead.first_name || '')} ${escapeHtml(lead.last_name || '')} + ${escapeHtml(lead.email || '')} + ${escapeHtml(lead.phone || '-') || '-'} + ${escapeHtml(lead.company || '-') || '-'} + ${tagNames || '-'} `; }).join(''); @@ -1580,24 +1604,42 @@
Select leads for this campaign
${selectedLeadIds.size} selected +
+
+ + +
+
+
+ + +
+
+
+ ${rows || ` -
- + Name Email Phone CompanyTags
-

No leads found in your organization.

+
+

${selectedLeadTagFilter ? 'No leads match this tag filter.' : 'No leads found in your organization.'}

Go to Import Leads @@ -1612,20 +1654,41 @@
Select leads for this campaign
`; + const tagFilter = document.getElementById('lead-tag-filter'); + if (tagFilter) { + tagFilter.addEventListener('change', (e) => { + selectedLeadTagFilter = e.target.value; + renderLeadsTab(); + }); + } + const selectAll = document.getElementById('select-all-leads'); if (selectAll) { - selectAll.checked = availableLeads.length > 0 && selectedLeadIds.size === availableLeads.length; + selectAll.checked = availableLeads.length > 0 && availableLeads.every(lead => selectedLeadIds.has(String(lead.id))); selectAll.addEventListener('change', (e) => { - selectedLeadIds = new Set(); - if (e.target.checked) availableLeads.forEach(lead => selectedLeadIds.add(lead.id)); + if (e.target.checked) availableLeads.forEach(lead => selectedLeadIds.add(String(lead.id))); + else selectedLeadIds.clear(); + renderLeadsTab(); + }); + } + + const selectAllFiltered = document.getElementById('select-all-filtered-leads'); + if (selectAllFiltered) { + selectAllFiltered.checked = filteredLeads.length > 0 && filteredLeads.every(lead => selectedLeadIds.has(String(lead.id))); + selectAllFiltered.addEventListener('change', (e) => { + if (e.target.checked) { + filteredLeads.forEach(lead => selectedLeadIds.add(String(lead.id))); + } else { + filteredLeads.forEach(lead => selectedLeadIds.delete(String(lead.id))); + } renderLeadsTab(); }); } canvas.querySelectorAll('.lead-select').forEach(input => { input.addEventListener('change', (e) => { - if (e.target.checked) selectedLeadIds.add(e.target.value); - else selectedLeadIds.delete(e.target.value); + if (e.target.checked) selectedLeadIds.add(String(e.target.value)); + else selectedLeadIds.delete(String(e.target.value)); document.getElementById('selected-leads-count').textContent = `${selectedLeadIds.size} selected`; }); }); @@ -2759,5 +2822,3 @@

Launch campaign

- -