@@ -5,7 +5,6 @@ import { requireProjectAccess } from "@/lib/lx/currentSite";
55import { env } from "@/lib/env" ;
66import { LeadFinder } from "@/components/leads/lead-finder" ;
77import { LeadActions } from "@/components/leads/lead-actions" ;
8- import { CampaignPanel , type CampaignSummary } from "@/components/leads/campaign-panel" ;
98import { SenderAddress } from "@/components/leads/sender-address" ;
109import { MailboxConnect , type ConnectedMailbox } from "@/components/leads/mailbox-connect" ;
1110import { SeedLogins } from "@/components/leads/seed-logins" ;
@@ -14,7 +13,7 @@ import { RepliesPanel, type ReplyRow } from "@/components/leads/replies-panel";
1413import { ContactsPanel } from "@/components/leads/contacts-panel" ;
1514import { IntentPanel , type IntentSignalRow } from "@/components/leads/intent-panel" ;
1615import { contactNiches } from "@/lib/outreach/contactsExport" ;
17- import { campaignFunnels , projectFunnel } from "@/lib/outreach/funnel" ;
16+ import { projectFunnel } from "@/lib/outreach/funnel" ;
1817import { listSeedCredentials , type StoredSeedCredential } from "@/lib/outreach/seedCredentials" ;
1918import { RefreshLeads } from "@/components/leads/refresh-leads" ;
2019import { loadAddressSettings } from "@/lib/outreach/postalAddress" ;
@@ -74,7 +73,7 @@ export default async function LeadsPage({
7473 // project pages work. It also keeps outreach_sends unwritable from a
7574 // browser, so the record of what was sent stays honest.
7675 const supabase = serviceClient ( ) ;
77- const [ { data : prospectData } , { data : sendData } , { data : campaignData } ] = await Promise . all ( [
76+ const [ { data : prospectData } , { data : sendData } ] = await Promise . all ( [
7877 supabase
7978 . from ( "outreach_prospects" )
8079 . select (
@@ -89,51 +88,10 @@ export default async function LeadsPage({
8988 . eq ( "project_id" , projectId )
9089 . order ( "sent_at" , { ascending : false } )
9190 . limit ( 10 ) ,
92- supabase
93- . from ( "outreach_campaigns" )
94- . select (
95- "id, name, active, auto_send, daily_send_limit, max_score, queries, seed_urls, last_run_at, last_run_note, auth_required_hosts, pitch_mode, pitch_intro, pitch_ask, pitch_facts, scan_prospects, min_intent, sells_description, angle, sender_name, reply_to" ,
96- )
97- . eq ( "project_id" , projectId )
98- . order ( "updated_at" , { ascending : false } )
99- . limit ( 10 ) ,
10091 ] ) ;
10192
10293 const prospects = ( prospectData as ProspectRow [ ] | null ) ?? [ ] ;
10394 const sends = ( sendData as SendRow [ ] | null ) ?? [ ] ;
104- const campaignRows = ( campaignData as ( CampaignSummary & { id : string } ) [ ] | null ) ?? [ ] ;
105-
106- // Recent ticks per campaign. last_run_note holds only the newest line, so
107- // without this there is no way to see that a campaign has been erroring for
108- // an hour, or that it has never found anything at all.
109- const { data : runData } = await supabase
110- . from ( "outreach_campaign_runs" )
111- . select ( "campaign_id, ran_at, summary, ok, errors" )
112- . in ( "campaign_id" , campaignRows . map ( ( c ) => c . id ) )
113- . order ( "ran_at" , { ascending : false } )
114- . limit ( 60 ) ;
115-
116- const runsByCampaign = new Map < string , CampaignSummary [ "runs" ] > ( ) ;
117- for ( const r of ( runData as Record < string , unknown > [ ] | null ) ?? [ ] ) {
118- const key = r . campaign_id as string ;
119- const list = runsByCampaign . get ( key ) ?? [ ] ;
120- if ( list . length >= 8 ) continue ;
121- list . push ( {
122- ran_at : r . ran_at as string ,
123- summary : ( r . summary as string ) ?? "" ,
124- ok : ( r . ok as boolean ) ?? true ,
125- errors : Array . isArray ( r . errors ) ? ( r . errors as string [ ] ) : [ ] ,
126- } ) ;
127- runsByCampaign . set ( key , list ) ;
128- }
129-
130- const campaigns : CampaignSummary [ ] = campaignRows . map ( ( c ) => ( {
131- ...c ,
132- pitch_facts : Array . isArray ( c . pitch_facts ) ? c . pitch_facts : [ ] ,
133- auth_required_hosts : Array . isArray ( c . auth_required_hosts ) ? c . auth_required_hosts : [ ] ,
134- runs : runsByCampaign . get ( c . id ) ?? [ ] ,
135- } ) ) ;
136-
13795 const byStatus = new Map < string , number > ( ) ;
13896 for ( const p of prospects ) byStatus . set ( p . status , ( byStatus . get ( p . status ) ?? 0 ) + 1 ) ;
13997
@@ -152,7 +110,6 @@ export default async function LeadsPage({
152110 projectId,
153111 ownerId : access . userId ,
154112 } ) ;
155- const canSendLive = Boolean ( addressSettings . address ) ;
156113
157114 // The org's default email sender, when it's a connected mailbox rather than
158115 // an API-key provider — that's what the connect panel reflects back.
@@ -162,12 +119,10 @@ export default async function LeadsPage({
162119 . eq ( "id" , projectId )
163120 . maybeSingle ( ) ;
164121 const orgId = ( projectRow ?. organization_id as string | null ) ?? null ;
165- // Measured outcomes, project-wide and per campaign. Both read the same
166- // tables the pipeline already writes, so this costs two queries rather than
167- // any new bookkeeping.
168- const [ funnel , perCampaignFunnel , contacts ] = await Promise . all ( [
122+ // Measured outcomes, read from the same tables the pipeline already writes,
123+ // so this costs a query rather than any new bookkeeping.
124+ const [ funnel , contacts ] = await Promise . all ( [
169125 projectFunnel ( projectId ) ,
170- campaignFunnels ( projectId ) ,
171126 contactNiches ( projectId ) ,
172127 ] ) ;
173128
@@ -195,17 +150,6 @@ export default async function LeadsPage({
195150 let seedCredentials : StoredSeedCredential [ ] = [ ] ;
196151 if ( orgId ) seedCredentials = await listSeedCredentials ( orgId ) ;
197152
198- // Hosts any campaign in this project is parked on, waiting for a sign-in.
199- const waitingHosts = [
200- ...new Set (
201- campaigns . flatMap ( ( c ) =>
202- Array . isArray ( ( c as { auth_required_hosts ?: string [ ] } ) . auth_required_hosts )
203- ? ( ( c as { auth_required_hosts ?: string [ ] } ) . auth_required_hosts as string [ ] )
204- : [ ] ,
205- ) ,
206- ) ,
207- ] ;
208-
209153 let mailbox : ConnectedMailbox | null = null ;
210154 if ( orgId ) {
211155 const { data : senderRow } = await supabase
@@ -249,11 +193,9 @@ export default async function LeadsPage({
249193
250194 < LeadFinder projectId = { projectId } />
251195
252- < CampaignPanel projectId = { projectId } campaigns = { campaigns } canSendLive = { canSendLive } />
253-
254196 < IntentPanel signals = { intentSignals } />
255197
256- < FunnelPanel project = { funnel } campaigns = { perCampaignFunnel } />
198+ < FunnelPanel project = { funnel } campaigns = { [ ] } />
257199
258200 < RepliesPanel replies = { replies } />
259201
@@ -266,7 +208,7 @@ export default async function LeadsPage({
266208
267209 < SeedLogins
268210 projectId = { projectId }
269- waitingHosts = { waitingHosts }
211+ waitingHosts = { [ ] }
270212 credentials = { seedCredentials }
271213 />
272214
@@ -284,8 +226,7 @@ export default async function LeadsPage({
284226
285227 { prospects . length === 0 ? (
286228 < p className = "mt-4 text-sm text-[var(--color-muted)]" >
287- Nothing yet. Search for businesses above, or set up a campaign to keep the funnel full on
288- its own.
229+ Nothing yet. Search for businesses above.
289230 </ p >
290231 ) : (
291232 < ul className = "mt-4 divide-y divide-[var(--color-border)]" >
0 commit comments