Sales Follow-up Dashboard

Due Today

0

Overdue

0

Active Pipeline Value

$0

Today's Follow-up List

    Pipeline by Status

    No follow-ups due today!

    '; return; } container.innerHTML = followupTasks.map(c => { const isOverdue = new Date(c.NextFollowUp) < today; return `
  • ${c.Name} (${c.Company})

    Last Contact: ${c.LastContact}
    ${formatCurrency(c.Value)}
  • ` }).join(''); } function renderStatusChart(activeContacts) { const statusCounts = activeContacts.reduce((acc, c) => { acc[c.Status] = (acc[c.Status] || 0) + 1; return acc; }, {}); const ctx = document.getElementById('sfd-status-chart').getContext('2d'); if(statusChart) statusChart.destroy(); statusChart = new Chart(ctx, { type: 'doughnut', data: { labels: Object.keys(statusCounts), datasets: [{ data: Object.values(statusCounts), backgroundColor: ['#0369a1', '#0ea5e9', '#60a5fa', '#f59e0b', '#64748b', '#94a3b8'] }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'bottom' } } } }); } function renderContactsTable() { const table = document.getElementById('contacts-table'); table.innerHTML = `Contact NameCompanyValue ($)StatusLast ContactNext Follow-upActions ${contactsData.sort((a,b)=>new Date(b.LastContact)-new Date(a.LastContact)).map(c => ` `).join('')} `; } function addContact() { const nextFollowUp = new Date(); nextFollowUp.setDate(nextFollowUp.getDate() + 7); contactsData.unshift({ id: Date.now(), Name: 'New Contact', Company: 'New Company', Value: 10000, Status: 'New', LastContact: new Date().toISOString().split('T')[0], NextFollowUp: nextFollowUp.toISOString().split('T')[0] }); renderAll(); } function handleTableEvents(e) { const target = e.target; if (!target) return; const id = parseInt(target.closest('tr')?.dataset.id); if (!id) return; if (target.classList.contains('remove-contact-btn')) { contactsData = contactsData.filter(c => c.id !== id); } else if (target.tagName === 'INPUT' || target.tagName === 'SELECT') { const key = target.dataset.key; const item = contactsData.find(c => c.id === id); if(item) item[key] = (target.type==='number')?parseFloat(target.value)||0:target.value; } renderAll(); } document.getElementById('sfd-add-contact-btn').addEventListener('click', addContact); document.getElementById('contacts-table').addEventListener('change', handleTableEvents); document.getElementById('contacts-table').addEventListener('click', handleTableEvents); function initialize() { const today = new Date("2025-07-08"); const createDate = (offsetDays) => { const d = new Date(today); d.setDate(today.getDate() - offsetDays); return d.toISOString().split('T')[0]; }; contactsData = [ { id: 1, Name: 'John Smith', Company: 'Innovate Corp (USA)', Value: 50000, Status: 'Nurturing', LastContact: createDate(10), NextFollowUp: createDate(0) }, { id: 2, Name: 'Jane Doe', Company: 'Data Insights LLC (USA)', Value: 75000, Status: 'Contacted', LastContact: createDate(5), NextFollowUp: createDate(0) }, { id: 3, Name: 'Alex Ray', Company: 'Global Tech (USA)', Value: 120000, Status: 'Nurturing', LastContact: createDate(20), NextFollowUp: createDate(3) }, { id: 4, Name: 'Brenda Miller', Company: 'PeopleFirst Inc (USA)', Value: 25000, Status: 'Unresponsive', LastContact: createDate(35), NextFollowUp: createDate(5) }, { id: 5, Name: 'Carlos Garcia', Company: 'SecureSys (USA)', Value: 90000, Status: 'Qualified', LastContact: createDate(8), NextFollowUp: createDate(-5) }, { id: 6, Name: 'Samantha Chen', Company: 'NextGen Solutions (USA)', Value: 65000, Status: 'Nurturing', LastContact: createDate(15), NextFollowUp: createDate(-8) }, ]; renderAll(); } initialize(); });
    Scroll to Top