import { useMemo, useState } from 'react'; import { Link } from 'react-router'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faPenToSquare, faFileImport } from '@fortawesome/pro-duotone-svg-icons'; import { Tabs, TabList, Tab, TabPanel } from '@/components/application/tabs/tabs'; import { CampaignCard } from '@/components/campaigns/campaign-card'; import { CampaignEditSlideout } from '@/components/campaigns/campaign-edit-slideout'; import { LeadImportWizard } from '@/components/campaigns/lead-import-wizard'; import { Button } from '@/components/base/buttons/button'; import { useCampaigns } from '@/hooks/use-campaigns'; import { useLeads } from '@/hooks/use-leads'; import { useData } from '@/providers/data-provider'; import { formatCurrency } from '@/lib/format'; import type { Campaign, CampaignStatus } from '@/types/entities'; type TabConfig = { id: string; label: string; status: CampaignStatus | undefined; }; const tabs: TabConfig[] = [ { id: 'all', label: 'All', status: undefined }, { id: 'active', label: 'Active', status: 'ACTIVE' }, { id: 'paused', label: 'Paused', status: 'PAUSED' }, { id: 'completed', label: 'Completed', status: 'COMPLETED' }, { id: 'draft', label: 'Drafts', status: 'DRAFT' }, ]; export const CampaignsPage = () => { const [activeTab, setActiveTab] = useState('all'); const [editCampaign, setEditCampaign] = useState(null); const [importOpen, setImportOpen] = useState(false); const { refresh } = useData(); const selectedTab = tabs.find((t) => t.id === activeTab) ?? tabs[0]; const { campaigns, ads } = useCampaigns({ status: selectedTab.status }); const { campaigns: allCampaigns } = useCampaigns(); const { leads } = useLeads(); const activeCount = allCampaigns.filter((c) => c.campaignStatus === 'ACTIVE').length; const totalSpent = allCampaigns.reduce((sum, c) => sum + (c.amountSpent?.amountMicros ?? 0), 0); const subtitle = `${allCampaigns.length} campaigns \u00b7 ${activeCount} active \u00b7 ${formatCurrency(totalSpent)} total spend`; // Index leads by campaignId for fast per-campaign lookups const leadsByCampaign = useMemo(() => { const map = new Map(); for (const lead of leads) { if (lead.campaignId) { const existing = map.get(lead.campaignId); if (existing) { existing.push(lead); } else { map.set(lead.campaignId, [lead]); } } } return map; }, [leads]); // Index ads by campaignId const adsByCampaign = useMemo(() => { const map = new Map(); for (const ad of ads) { if (ad.campaignId) { const existing = map.get(ad.campaignId); if (existing) { existing.push(ad); } else { map.set(ad.campaignId, [ad]); } } } return map; }, [ads]); // Tab badges const tabBadges: Record = useMemo(() => ({ all: allCampaigns.length, active: allCampaigns.filter((c) => c.campaignStatus === 'ACTIVE').length, paused: allCampaigns.filter((c) => c.campaignStatus === 'PAUSED').length, completed: allCampaigns.filter((c) => c.campaignStatus === 'COMPLETED').length, draft: allCampaigns.filter((c) => c.campaignStatus === 'DRAFT').length, }), [allCampaigns]); return (

Campaigns

{subtitle}

setActiveTab(String(key))}> ({ id: tab.id, label: tab.label, badge: tabBadges[tab.id] > 0 ? tabBadges[tab.id] : undefined, }))} > {(item) => ( )} {tabs.map((tab) => (
{campaigns.map((campaign) => (
))} {campaigns.length === 0 && (

No campaigns match this filter.

)}
))}
{editCampaign && ( { if (!open) setEditCampaign(null); }} campaign={editCampaign} onSaved={refresh} /> )}
); };