88
99import { useCallback , useEffect , useState } from "react" ;
1010import Link from "next/link" ;
11+ import AccountSelect , { type AccountOption } from "@/components/account-select" ;
1112
1213interface Campaign {
1314 id : string ;
@@ -19,6 +20,10 @@ interface Campaign {
1920 dmMessage : string ;
2021 isActive : boolean ;
2122 wholeWordMatch : boolean ;
23+ instagramAccount : {
24+ username : string ;
25+ instagramId : string ;
26+ } ;
2227 reportShareSlug : string | null ;
2328 reportShareEnabled : boolean ;
2429 reportUrl : string | null ;
@@ -43,18 +48,33 @@ interface Campaign {
4348
4449export default function CampaignsPage ( ) {
4550 const [ automations , setAutomations ] = useState < Campaign [ ] > ( [ ] ) ;
51+ const [ accounts , setAccounts ] = useState < AccountOption [ ] > ( [ ] ) ;
52+ const [ selectedAccountId , setSelectedAccountId ] = useState ( "all" ) ;
4653 const [ loading , setLoading ] = useState ( true ) ;
4754
4855 const fetchAutomations = useCallback ( async ( ) => {
4956 try {
50- const res = await fetch ( "/api/automations" ) ;
57+ const params = new URLSearchParams ( ) ;
58+ if ( selectedAccountId !== "all" ) {
59+ params . set ( "instagramAccountId" , selectedAccountId ) ;
60+ }
61+ const res = await fetch ( `/api/automations${ params . size ? `?${ params } ` : "" } ` ) ;
5162 const data = await res . json ( ) ;
5263 if ( data . success ) setAutomations ( data . data ) ;
5364 } catch ( err ) {
5465 console . error ( "Failed to fetch campaigns:" , err ) ;
5566 } finally {
5667 setLoading ( false ) ;
5768 }
69+ } , [ selectedAccountId ] ) ;
70+
71+ useEffect ( ( ) => {
72+ fetch ( "/api/dashboard/stats" )
73+ . then ( ( res ) => res . json ( ) )
74+ . then ( ( payload ) => {
75+ if ( payload . success ) setAccounts ( payload . data . instagramAccounts ?? [ ] ) ;
76+ } )
77+ . catch ( console . error ) ;
5878 } , [ ] ) ;
5979
6080 useEffect ( ( ) => {
@@ -64,6 +84,11 @@ export default function CampaignsPage() {
6484 return ( ) => window . clearTimeout ( timer ) ;
6585 } , [ fetchAutomations ] ) ;
6686
87+ function handleAccountChange ( accountId : string ) {
88+ setLoading ( true ) ;
89+ setSelectedAccountId ( accountId ) ;
90+ }
91+
6792 async function toggleActive ( id : string , isActive : boolean ) {
6893 try {
6994 await fetch ( `/api/automations?id=${ id } ` , {
@@ -121,21 +146,30 @@ export default function CampaignsPage() {
121146 return (
122147 < div className = "space-y-6" >
123148 { /* Header */ }
124- < div className = "flex items-center justify-between" >
149+ < div className = "flex flex-col gap-4 sm:flex-row sm: items-end sm: justify-between" >
125150 < div >
126151 < p className = "text-sm text-muted" >
127152 { automations . length } campaign{ automations . length !== 1 ? "s" : "" }
128153 </ p >
129154 </ div >
130- < Link
131- href = "/campaigns/new"
132- className = "inline-flex items-center gap-2 px-4 py-2.5 rounded-xl bg-gradient-to-r from-indigo-500 to-violet-500 text-sm font-semibold text-white shadow-lg shadow-indigo-500/20 hover:shadow-xl hover:shadow-indigo-500/30 hover:scale-[1.02] active:scale-[0.98] transition-all"
133- >
134- < svg className = "w-4 h-4" fill = "none" viewBox = "0 0 24 24" strokeWidth = { 2 } stroke = "currentColor" >
135- < path strokeLinecap = "round" strokeLinejoin = "round" d = "M12 4.5v15m7.5-7.5h-15" />
136- </ svg >
137- New Campaign
138- </ Link >
155+ < div className = "flex flex-col gap-3 sm:flex-row sm:items-end" >
156+ { accounts . length > 1 && (
157+ < AccountSelect
158+ accounts = { accounts }
159+ value = { selectedAccountId }
160+ onChange = { handleAccountChange }
161+ />
162+ ) }
163+ < Link
164+ href = "/campaigns/new"
165+ className = "inline-flex items-center gap-2 px-4 py-2.5 rounded-xl bg-gradient-to-r from-indigo-500 to-violet-500 text-sm font-semibold text-white shadow-lg shadow-indigo-500/20 hover:shadow-xl hover:shadow-indigo-500/30 hover:scale-[1.02] active:scale-[0.98] transition-all"
166+ >
167+ < svg className = "w-4 h-4" fill = "none" viewBox = "0 0 24 24" strokeWidth = { 2 } stroke = "currentColor" >
168+ < path strokeLinecap = "round" strokeLinejoin = "round" d = "M12 4.5v15m7.5-7.5h-15" />
169+ </ svg >
170+ New Campaign
171+ </ Link >
172+ </ div >
139173 </ div >
140174
141175 { /* Empty state */ }
@@ -167,6 +201,9 @@ export default function CampaignsPage() {
167201 < div className = "flex-1 min-w-0" >
168202 < div className = "flex items-center gap-3 mb-3" >
169203 < h3 className = "text-base font-semibold truncate" > { auto . name } </ h3 >
204+ < span className = "shrink-0 rounded-full border border-border px-2 py-0.5 text-xs text-muted" >
205+ @{ auto . instagramAccount . username }
206+ </ span >
170207 < span
171208 className = { `text-xs px-2 py-0.5 rounded-full font-medium ${
172209 auto . isActive
0 commit comments