PageSourceSearch

https://opentxt.ai/assets/AdminCampaignsPage-Bt6Dz8PJ.js

js opentxt.ai collected 2026-10-05 12:22:57 UTC 53,573 bytes, 1 lines download raw bytes

1import{$ as Tt,w as $,r as u,j as t,Z as Ot,aL as Ft,s as y,b6 as Pt,b7 as Ut,b8 as Bt,L as de,a7 as Qt,T as Zt,b3 as Wt,V as zt,u as Gt,g as ge,B as Me,R as Vt,be as Yt,ah as Xt,a2 as Ht,S as Ce,aa as bt,a8 as Jt,M as es,al as ts,aU as ss,I as as,a3 as ns,ac as wt}from"./index-CnpT2L3h.js";import{i as rs,F as is}from"./FastLaneBadge-C12zx4P1.js";import{f as ds,a as ls,B as os,D as cs,O as us}from"./OutsideWindowBadge-DJehOuvj.js";import{f as ms}from"./formatDistanceToNow-tGjf3qKA.js";import{S as ps}from"./StatusBadge-wCdBswH4.js";import{T as gs,a as fs,b as hs}from"./tabs-C8FxQGpl.js";import{B as xs}from"./badge-B_awFKIr.js";import{T as _s,a as ys,b as vt,c as J,d as bs,e as ee}from"./table-BwSZRhSE.js";import{c as It}from"./sms-segments-BVDsHy3d.js";import{L as ws}from"./lightbulb-BmCPay7a.js";import{U as vs}from"./user-x-C8nEUxrZ.js";import{R as Ns}from"./repeat-ysDRa9j0.js";import{I as js}from"./image-DTOEd4CT.js";import{P as Ss}from"./pencil-DquZRFZe.js";import{s as $e,f as dt}from"./format-B7vqQ0W_.js";import{s as ve}from"./subDays-CaWjBKZi.js";import{e as lt}from"./endOfDay-DsI-jOwi.js";import"./pause-C4lBdlm-.js";import"./play-B3J_hbK2.js";import"./hourglass-ByiKjbOj.js";import"./globe-CP0awkh7.js";import"./ban-RDoMJept.js";import"./circle-help-Dr1fK3Pi.js";import"./getRoundingMethod--2oHQwai.js";import"./en-US-D_dhEEMD.js";import"./differenceInCalendarMonths-ChX2-Hr_.js";import"./endOfMonth-BIoxjeR4.js";import"./addDays-BPV4c-4W.js";function Ts(){const d=Tt(),{data:o,isLoading:m}=$({queryKey:["admin-api-sends-today"],queryFn:async()=>{const{data:c,error:_}=await y.rpc("get_api_sends_today_cached",{_max_age_seconds:30});if(_)throw _;return c??[]},refetchInterval:15e3}),[x,h]=u.useState([]),[T,l]=u.useState(()=>Date.now());u.useEffect(()=>{const c=setInterval(()=>l(Date.now()),1e3);return()=>clearInterval(c)},[]),u.useEffect(()=>{let c=!1;const _=async()=>{const q=new Date(Date.now()-12e4).toISOString(),{data:B}=await y.from("api_sms_log").select("api_key_id, created_at").gte("created_at",q).not("status","in","(inbound,opt_out)").limit(3e3);!c&&B&&h(B)};_();const v=setInterval(_,1e4);return()=>{c=!0,clearInterval(v)}},[]),u.useEffect(()=>{const c=setInterval(()=>{d.invalidateQueries({queryKey:["admin-api-sends-today"]})},15e3);return()=>clearInterval(c)},[d]);const b=u.useMemo(()=>{const c=T,_=new Map;let v=0,q=0;for(const Y of x){const p=c-new Date(Y.created_at).getTime();if(!(p>12e4||p<-5e3)&&(q+=1,p<=6e4)){v+=1;const qe=Y.api_key_id||"unknown";_.set(qe,(_.get(qe)||0)+1)}}const B=Math.round(q/2);return{last60:v,perMin:B,perKey:_}},[x,T]),O=(o??[]).reduce((c,_)=>(c.sends+=Number(_.total_sends)||0,c.sent+=Number(_.sent)||0,c.failed+=Number(_.failed)||0,c.segments+=Number(_.segments)||0,c),{sends:0,sent:0,failed:0,segments:0});return t.jsxs("div",{className:"rounded-xl border bg-card shadow-sm",children:[t.jsxs("div",{className:"flex items-center justify-between px-3 py-2 border-b gap-2",children:[t.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[t.jsx("div",{className:"rounded-lg p-1.5 bg-primary/10 text-primary",children:t.jsx(Ot,{className:"h-4 w-4"})}),t.jsxs("div",{className:"min-w-0",children:[t.jsxs("div",{className:"text-sm font-semibold flex items-center gap-2 flex-wrap",children:["API Sends Today",b.last60>0?t.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full bg-success/10 text-success px-2 py-0.5 text-[10px] font-semibold",children:[t.jsx("span",{className:"h-1.5 w-1.5 rounded-full bg-success animate-pulse"}),"Sending now · ",b.perMin.toLocaleString(),"/min"]}):t.jsx("span",{className:"rounded-full bg-muted text-muted-foreground px-2 py-0.5 text-[10px] font-medium",children:"Idle"}),t.jsx(Ft,{to:"/admin/api-live",className:"text-[10px] text-primary underline",children:"Live view"})]}),t.jsx("div",{className:"text-[11px] text-muted-foreground",children:b.last60>0?`${b.last60.toLocaleString()} sent in the last 60s`:"Live traffic from API customers (ET day)"})]})]}),t.jsxs("div",{className:"text-right shrink-0",children:[t.jsx("div",{className:"text-lg font-bold leading-none",children:O.sends.toLocaleStr
1ing()}),t.jsxs("div",{className:"text-[11px] text-muted-foreground",children:[O.sent.toLocaleString()," sent · ",O.failed.toLocaleString()," failed · ",O.segments.toLocaleString()," seg"]})]})]}),t.jsx("div",{className:"p-2",children:m?t.jsx("div",{className:"text-xs text-muted-foreground px-2 py-3",children:"Loading…"}):!o||o.length===0?t.jsx("div",{className:"text-xs text-muted-foreground px-2 py-3",children:"No API sends yet today."}):t.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2",children:o.map(c=>t.jsxs("div",{className:"rounded-lg border bg-background/50 p-2 flex flex-col gap-0.5",children:[t.jsxs("div",{className:"flex items-center justify-between gap-2",children:[t.jsxs("div",{className:"text-sm font-medium truncate flex items-center gap-1.5",children:[(b.perKey.get(c.api_key_id)||0)>0&&t.jsx("span",{className:"h-1.5 w-1.5 rounded-full bg-success animate-pulse shrink-0"}),c.key_name||"Unnamed key"]}),t.jsxs("div",{className:"text-sm font-semibold tabular-nums flex items-center gap-1.5",children:[(b.perKey.get(c.api_key_id)||0)>0&&t.jsxs("span",{className:"text-[10px] font-medium text-success",children:["+",b.perKey.get(c.api_key_id),"/min"]}),Number(c.total_sends).toLocaleString()]})]}),c.user_email&&t.jsx("div",{className:"text-[11px] text-muted-foreground truncate",children:c.user_email}),t.jsxs("div",{className:"text-[11px] text-muted-foreground flex items-center justify-between gap-2",children:[t.jsxs("span",{children:[Number(c.sent).toLocaleString()," sent · ",Number(c.failed).toLocaleString()," failed"]}),t.jsx("span",{children:ms(new Date(c.last_sent_at),{addSuffix:!0})})]})]},c.api_key_id))})})]})}const Is={good:{icon:Qt,color:"text-success",bg:"bg-success/10 border-success/30",label:"Safe to resume"},warn:{icon:Zt,color:"text-warning",bg:"bg-warning/10 border-warning/30",label:"Fix first"},bad:{icon:Wt,color:"text-destructive",bg:"bg-destructive/10 border-destructive/30",label:"Do not resume as-is"},wait:{icon:zt,color:"text-muted-foreground",bg:"bg-muted border-border",label:"Wait"}},ks="No Carrier Confirmation (likely filtered/spam)",Ds="Carrier Never Confirmed (counted as failed)",Es="Carrier Spam Filter",Ls="Awaiting Carrier DLR",Ms="Queued (not yet sent)",Cs="Delivered (carrier confirmed)",$s=["Landline (Mobile-Only Block)","Landline / Unreachable","Number Doesn't Exist","Invalid Number","Phone Off / Unavailable"],qs=["Sender Not 10DLC-Registered","Sender Not Found","Outside Allowed Country"],As=["Compliance Blocked (pre-send)","Contact Unsubscribed"];function Nt(d,o){return o>0?Math.round(d/o*100):0}function Rs(d){const o=B=>{var Y;return Number(((Y=d.find(p=>p.category===B))==null?void 0:Y.error_count)||0)},m=B=>B.reduce((Y,p)=>Y+o(p),0),x=o(Cs),h=o(ks)+o(Ds),T=o(Es),l=m($s),b=m(qs);m(As);const O=o(Ls)+o(Ms),c=o("Unknown Error")+o("Other"),_=h+T+b+c,v=x+_,q=Nt(x,v);return v<25&&O>0?{severity:"wait",headline:"Too early to judge — receipts still landing",because:`Only ${v.toLocaleString()} messages have a carrier answer so far, with ${O.toLocaleString()} still open. Receipts can take up to 40 minutes.`,steps:["Give it up to an hour, then read this again.","Don't swap the number or rewrite yet — you'd be guessing."]}:b>0&&b>=_*.5?{severity:"warn",headline:"Sender problem, not a wording problem",because:`${Nt(b,_)}% of the failures are registration or sender errors — the carrier rejected the line, not the text.`,steps:["Swap the sending number for a registered line.","Leave the message exactly as it is — it was never judged.","Resume; it will re-test on the new number automatically."]}:l>0&&l>=(l+_)*.5?{severity:"good",headline:"It's the list, not the message",because:`${l.toLocaleString()} of these were landlines, disconnected, or invalid numbers. Real delivery on reachable phones is ${q}%.`,steps:["Keep the number and the message.","Clean the list of landlines before the next upload.","Resume as-is."]}:T>0&&T>=_*.3?{severity:"bad",headline:"Carrier is naming your wording as spam",because:`${T.toLocaleString()} messages came back with an explicit spam-filter reason. That's a content verdict, not bad luck.`,steps:["Rewrite the message — drop links, all-caps, money claims and urgency.","Swap the sending number too; this one is already flagged on this text.","Then resume — it will send a 200-message test before opening up."]}:q<45&&h>=_*.7?{severity:"bad",headline:"Wording problem — silent filtering",because:`${q}
1% delivered with ${h.toLocaleString()} messages accepted then never confirmed, and no carrier reason given. Silent drops at this scale mean the text is being filtered, not the line.`,steps:["Rewrite the message before anything else.","Change the sending number as well — a fresh number carrying the same filtered text usually burns within a day or two.","Resume; a 200-message test runs first and it re-pauses itself if it's still bad."]}:q<70?{severity:"warn",headline:"Borderline — soften the wording",because:`${q}% delivered. Not a burn, but below where this route normally runs (85–90%).`,steps:["Reword the opening line and remove any link or promo phrasing.","Keep the number for now — it isn't the weak link yet.","Resume and watch the 200-message test."]}:{severity:"good",headline:"Healthy — resume as-is",because:`${q}% delivered on ${v.toLocaleString()} answered messages. Nothing here points at the wording or the number.`,steps:["Resume as-is.","A 200-message test still runs first, so nothing goes out blind."]}}function Ks({campaignId:d,after:o}){const[m,x]=u.useState(!1),[h,T]=u.useState(!1),[l,b]=u.useState(null),O=async()=>{if(!l){T(!0);try{const v={_campaign_id:d};o&&(v._after=o);const{data:q,error:B}=await y.rpc("get_campaign_error_breakdown",v);if(B)throw B;b(Rs(q||[]))}catch(v){console.error("Suggestion failed:",v),b({severity:"wait",headline:"Couldn't read the delivery detail",because:"The breakdown didn't load, so there's nothing solid to base a call on.",steps:["Close this and try again in a moment."]})}finally{T(!1)}}},c=l?Is[l.severity]:null,_=c==null?void 0:c.icon;return t.jsxs(Pt,{open:m,onOpenChange:v=>{x(v),v&&O()},children:[t.jsx(Ut,{asChild:!0,children:t.jsxs("button",{onClick:v=>v.stopPropagation(),className:"h-6 px-2 inline-flex items-center gap-1 rounded-md border border-primary/40 bg-primary/10 text-primary text-[10px] font-medium hover:bg-primary/20 transition-colors",title:"What should I do with this campaign?",children:[t.jsx(ws,{className:"h-2.5 w-2.5"}),"Suggestion"]})}),t.jsxs(Bt,{className:"w-[22rem] p-0",align:"center",side:"bottom",onClick:v=>v.stopPropagation(),children:[t.jsxs("div",{className:"p-3 border-b",children:[t.jsx("p",{className:"text-sm font-semibold",children:"What to do before resuming"}),t.jsx("p",{className:"text-xs text-muted-foreground",children:"Read from this campaign's own carrier answers."})]}),h&&t.jsxs("p",{className:"text-xs text-muted-foreground text-center py-6 flex items-center justify-center gap-2",children:[t.jsx(de,{className:"h-3 w-3 animate-spin"})," Reading delivery detail…"]}),!h&&l&&c&&_&&t.jsxs("div",{className:"p-3 space-y-3",children:[t.jsxs("div",{className:`rounded-md border p-2 flex items-start gap-2 ${c.bg}`,children:[t.jsx(_,{className:`h-4 w-4 mt-0.5 shrink-0 ${c.color}`}),t.jsxs("div",{children:[t.jsx("p",{className:`text-xs font-semibold ${c.color}`,children:c.label}),t.jsx("p",{className:"text-xs font-medium",children:l.headline})]})]}),t.jsx("p",{className:"text-xs text-muted-foreground leading-snug",children:l.because}),t.jsx("div",{className:"space-y-1.5",children:l.steps.map((v,q)=>t.jsxs("div",{className:"flex gap-2 text-xs",children:[t.jsx("span",{className:"h-4 w-4 shrink-0 rounded-full bg-muted text-[10px] font-semibold flex items-center justify-center",children:q+1}),t.jsx("span",{className:"leading-snug",children:v})]},q))})]})]})]})}const Os=[{value:"all",label:"All"},{value:"active",label:"Active"},{value:"completed",label:"Completed"},{value:"paused",label:"Paused"},{value:"failed",label:"Failed"}],kt=[{value:"today",label:"Today"},{value:"yesterday",label:"Yesterday"},{value:"7d",label:"7 Days"},{value:"30d",label:"30 Days"},{value:"all",label:"All Time"}];function Dt(){return new Date(new Date().toLocaleString("en-US",{timeZone:"America/New_York"}))}function z(d){return new Date(new Date(d).toLocaleString("en-US",{timeZone:"America/New_York"}))}function we(d){const o=Dt(),m=d.match(/^day-(\d+)$/);if(m){const x=parseInt(m[1],10),h=$e(ve(o,x));return{start:h,end:lt(h)}}switch(d){case"today":return{start:$e(o),end:lt(o)};case"yesterday":{const x=$e(ve(o,1));return{start:x,end:lt(x)}}case"7d":return{start:$e(ve(o,7)),end:null};case"30d":return{start:$e(ve(o,30)),end:null};default:return{start:null,end:null}}}function Fs(d){const o=Dt();if(d==="today")return dt(o,"EEE, MMM d");
1if(d==="yesterday")return dt(ve(o,1),"EEE, MMM d");const m=d.match(/^day-(\d+)$/);if(m){const x=parseInt(m[1],10);return dt(ve(o,x),"EEE, MMM d")}return null}function jt(d){return d?kt.some(o=>o.value===d)||/^day-\d+$/.test(d):!1}function Ne(d,o=!1){var l;if(d!=null&&d.media_url)return 3;const m=typeof((l=d==null?void 0:d.templates)==null?void 0:l.body)=="string"?d.templates.body:"",x=Math.max(1,m?It(m).segments:1),h=d!=null&&d.ai_personalize?1:0,T=d!=null&&d.ai_personalize||o?2:1;return Math.max(T,x+h)}function St(d,o,m){var O;const x=o*Ne(d,(d==null?void 0:d._rowType)==="round"),h=Number((d==null?void 0:d.txtsUsed)??0),T=Number(m??0),l=Number(((O=d==null?void 0:d.stats)==null?void 0:O.sent)??0),b=o>0&&o===l;return Math.max(x,T,b?h:0)}function Ps(d,o){if(!d)return null;const m=d.match(/(\d+)% delivered[\s\S]*?(\d+)\/(\d+) failures suspicious/i);if(m)return{deliveryPct:Number(m[1]),suspicious:Number(m[2]),failed:Number(m[3])};const x=d.match(/(\d+)% of failures/i);if(!x||!o)return null;const h=Number(o.delivered??0),T=Number(o.failed??0),l=h+T;return{deliveryPct:l>0?Math.round(h/l*100):0,suspicious:Math.round(Number(x[1])/100*T),failed:T}}function Us(d,o,m){var l;if(!d.list_id)return null;const x=o==null?void 0:o[d.list_id];if(typeof x!="number")return null;const h=((l=m==null?void 0:m[d.id])==null?void 0:l.sent)??0,T=Math.max(0,x-h);return T<=0?0:T*Ne(d)}function fe({icon:d,label:o,value:m,color:x,subtitle:h}){return t.jsxs("div",{className:"rounded-xl border bg-card p-2 lg:p-3 flex flex-col xl:flex-col 2xl:flex-row items-start 2xl:items-center gap-1.5 2xl:gap-3 shadow-sm min-w-0",children:[t.jsx("div",{className:`rounded-lg p-1.5 lg:p-2 ${x} shrink-0`,children:t.jsx(d,{className:"h-3.5 w-3.5 lg:h-4 lg:w-4"})}),t.jsxs("div",{className:"min-w-0 w-full",children:[t.jsx("p",{className:"text-base lg:text-xl font-bold tabular-nums leading-tight",children:m.toLocaleString()}),t.jsxs("p",{className:"text-[10px] lg:text-xs text-muted-foreground truncate",children:[o,h&&t.jsx("span",{className:"ml-1 font-medium",children:h})]})]})]})}function _a(){const d=Tt(),[o]=Gt(),[m,x]=u.useState(o.get("search")||""),[h,T]=u.useState("all"),[l,b]=u.useState(jt(o.get("range"))?o.get("range"):"today");u.useState(null);const[O,c]=u.useState(!1),[_,v]=u.useState(null),[q,B]=u.useState(null),Y=u.useCallback(async e=>{v(e.id);try{let a=null;if(e.list_id){const[{count:g},E]=await Promise.all([y.from("list_leads").select("lead_id",{count:"exact",head:!0}).eq("list_id",e.list_id),(async()=>{const L=new Set;let M=0;for(;;){const{data:j}=await y.from("messages").select("lead_id").eq("campaign_id",e.id).range(M,M+999);if(!(j!=null&&j.length)||(j.forEach(Z=>Z.lead_id&&L.add(Z.lead_id)),j.length<1e3))break;M+=1e3}return L})()]);typeof g=="number"&&(a=Math.max(0,g-E.size))}if(a===0){await y.from("campaigns").update({status:"completed",paused_reason:null}).eq("id",e.id),ge.error(`Nothing left to send — every lead in this list already received a message from "${e.name}". Marked completed. Use Edit & Retry (new template) to message them again.`,{duration:8e3});return}const{data:n,error:s}=await y.from("campaigns").update({status:"running",paused_reason:null}).eq("id",e.id).select("id, status").maybeSingle();if(s)throw s;if(!n)throw new Error("Resume not applied — campaign not found");if(n.status!=="running")throw new Error(`Resume not confirmed — status is still "${n.status}"`);const{data:r,error:i}=await y.functions.invoke("execute-campaign",{body:{campaign_id:e.id,resume:!0}});if(i)throw i;if(r!=null&&r.error)throw new Error(r.error);(r==null?void 0:r.message)==="All leads already sent"||(r==null?void 0:r.sent)===0&&(r!=null&&r.success)&&!(r!=null&&r.testing)?ge.error("No leads were eligible — remaining leads are inside the 24h contact cooldown or already messaged. Campaign marked completed.",{duration:8e3}):ge.success(`Resuming "${e.name}"${a!==null?` — ${a.toLocaleString()} leads left`:""}…`)}catch(a){await y.from("campaigns").update({status:"paused",paused_reason:e.paused_reason}).eq("id",e.id),ge.error((a==null?void 0:a.message)||"Failed to resume")}finally{v(null),await d.invalidateQueries({queryKey:["admin-campaigns"]}),await d.refetchQueries({queryKey:["admin-campaigns"]})}},[d]);u.useEffect(()=>{const e=o.get("search")||"",a=o.get("range");x(n=>n===e?n:e),jt(a)&&b(n=>n===a?n:a)},[o]);const p=u.useMemo(()=>l==="today"||l==="yesterday"||/^day-\d+$/.test(l),[l]),qe=u.useCallback(async()=>{c(!0),await d.invalidateQueries({queryKey:["admin-campaigns"]}),await d.invalidateQueries({queryKey:["admin-campaign-stats"]}),await d.invalidateQueries({queryKey:["admin-campaign-costs"]}),await d.invalidateQueries({queryKey:["admin-campaign-message-segment-totals"]}),await d.invalidateQueries({queryKey:["admin-day-scoped-credit-entries"]}),await d.invalidateQueries({queryKey:["admin-campaigns-txts-used-direct"]}),await d.invalidateQueries({queryKey:["admin-all-drip-round-logs"]}),await d.invalidateQueries({queryKey:["admin-drip-live-stats"]}),await d.invalidateQueries({queryKey:["admin-all-round-optouts"]}),await d.invalidateQueries({queryKey:["admin-all-round-replies"]}),await d.invalidateQueries({queryKey:["admin-active-sent-counts"]}),await d.invalidateQueries({queryKey:["admin-drip-round-sent"]}),await d.invalidateQueries({queryKey:["admin-campaign-lead-counts"]}),await d.invalidateQueries({queryKey:["admin-campaigns-profiles"]}),await d.invalidateQueries({queryKey:["admin-day-scoped-round-stats"]}),await d.invalidateQueries({queryKey:["admin-day-scoped-replies"]}),await d.invalidateQueries({queryKey:["admin-day-scoped-optouts"]}),await d.invalidateQueries({queryKey:["admin-day-scoped-last-activity"]}),ge.success("Data refreshed"),c(!1)},[d]),{data:N,isLoading:Et}=$({queryKey:["admin-campaigns"],staleTime:15e3,refetchOnMount:"always",queryFn:async()=>{let a=[],n=0;for(;;){const{data:s,error:r}=await y.from("campaigns").select("*, lists:list_id(name), templates:template_id(body)").is("bulk_blast_id",null).order("created_at",{ascending:!1}).range(n,n+2e3-1);if(r)throw r;if(!s||s.length===0||(a=a.concat(s),s.length<2e3))break;n+=2e3}return a},refetchInterval:()=>document.hidden?!1:3e4,placeholderData:e=>e}),{data:le}=$({queryKey:["admin-campaigns-profiles"],queryFn:async()=>{const{data:e,error:a}=await y.from("profiles").select("user_id, name, email, display_name, company_name, fast_lane");if(a)throw a;const n={};
1return(e||[]).forEach(s=>{n[s.user_id]=s}),n},staleTime:3e4}),Ve=u.useMemo(()=>(N||[]).map(e=>e.id),[N]),{start:G,end:V}=u.useMemo(()=>we(l),[l]),{data:k}=$({queryKey:["admin-day-scoped-round-stats",l],enabled:p&&!!G&&!!V,staleTime:15e3,refetchInterval:()=>document.hidden?!1:3e4,refetchOnMount:"always",queryFn:async()=>{const{data:e,error:a}=await y.rpc("get_campaign_round_activity_in_range",{_since:G.toISOString(),_until:V.toISOString()});if(a)throw a;const n={};return(e||[]).forEach(s=>{const r=`${s.campaign_id}_r${s.round_number}`;n[r]={sent:Number(s.sent??0),delivered:Number(s.delivered??0),failed:Number(s.failed??0),unreachable:Number(s.unreachable??0)}}),n},placeholderData:e=>e}),F=u.useMemo(()=>{if(!N)return[];const{start:e,end:a}=we(l);if(!e)return Ve;const n=new Set;if(p){k&&Object.keys(k).forEach(s=>n.add(s.split("_r")[0]));for(const s of N)["sending","running","testing","scheduled"].includes(s.status)&&n.add(s.id);return[...n]}for(const s of N){if(["sending","running","testing","scheduled","paused"].includes(s.status)){
1n.add(s.id);continue}const r=z(s.schedule_start||s.created_at);if(r>=e&&(!a||r<=a)){n.add(s.id);continue}(s.drip_enabled||s.drip_current_round>0)&&n.add(s.id)}return[...n]},[N,Ve,l,p,k]),Ae=!p||!!k,{data:te}=$({queryKey:["admin-campaign-stats",F],enabled:F.length>0&&Ae,queryFn:async()=>{const{data:e,error:a}=await y.rpc("get_campaign_stats",{_campaign_ids:F});if(a)throw a;const n={};return(e||[]).forEach(s=>{n[s.campaign_id]={...s,opt_outs:Number(s.opt_outs??0),last_message_at:s.last_message_at||null}}),n},refetchInterval:()=>document.hidden?!1:6e4,staleTime:3e4,placeholderData:e=>e}),{data:Re}=$({queryKey:["admin-campaign-costs",F],enabled:F.length>0&&Ae,staleTime:15e3,queryFn:async()=>{const{data:e,error:a}=await y.rpc("get_campaign_credit_costs",{_campaign_ids:F});if(a)throw a;const n={};return(e||[]).forEach(s=>{n[s.campaign_id]=Number(s.total_cost)}),n},refetchInterval:()=>document.hidden?!1:3e4,placeholderData:e=>e}),{data:Ke}=$({queryKey:["admin-campaign-message-segment-totals",F],enabled:F.length>0&&Ae,staleTime:15e3,queryFn:async()=>{const{data:e,error:a}=await y.rpc("get_campaign_message_segment_totals",{_campaign_ids:F});if(a)throw a;const n={};return(e||[]).forEach(s=>{n[s.campaign_id]={totalSegments:Number(s.total_segments??0),billableSegments:Number(s.billable_segments??0),messageCount:Number(s.message_count??0)}}),n},refetchInterval:()=>document.hidden?!1:3e4,placeholderData:e=>e}),{data:je}=$({queryKey:["admin-bulk-blast-totals",l],staleTime:15e3,queryFn:async()=>{const{start:e,end:a}=we(l),{data:n,error:s}=await y.rpc("get_bulk_blast_admin_totals",{_from:e?e.toISOString():null,_to:a?a.toISOString():null});if(s)throw s;const r=(n==null?void 0:n[0])??{sent:0,delivered:0,failed:0};return{sent:Number(r.sent??0),delivered:Number(r.delivered??0),failed:Number(r.failed??0)}},refetchInterval:()=>document.hidden?!1:3e4,placeholderData:e=>e}),Ye=u.useMemo(()=>N?[...new Set(N.filter(e=>["testing","running","sending","paused"].includes(e.status)&&e.list_id).map(e=>e.list_id))]:[],[N]),Xe=u.useMemo(()=>N?N.filter(e=>["testing","running","sending"].includes(e.status)&&(!e.drip_enabled||e.drip_current_round===0)).map(e=>e.id):[],[N]),{data:Oe}=$({queryKey:["admin-active-sent-counts",Xe],enabled:Xe.length>0,staleTime:1e4,refetchInterval:()=>document.hidden?!1:1e4,queryFn:async()=>{const e={};for(const a of Xe){const{count:n,error:s}=await y.from("messages").select("id",{count:"exact",head:!0}).eq("campaign_id",a);s||(e[a]=n??0)}return e}}),P=u.useMemo(()=>{if(!N)return[];const e=new Set(F);return N.filter(a=>(a.drip_enabled||a.drip_current_round>0)&&e.has(a.id)).map(a=>a.id)},[N,F]),{data:Se}=$({queryKey:["admin-all-drip-round-logs",P],enabled:P.length>0,staleTime:15e3,refetchOnMount:"always",refetchInterval:()=>document.hidden?!1:3e4,queryFn:async()=>{const e=[];for(let n=0;n<P.length;n+=200){const s=P.slice(n,n+200),{data:r,error:i}=await y.from("drip_round_logs").select("campaign_id, round_number, messages_sent, sent_at, delivered, failed, replies, skipped_opted_out, skipped_responded, eligible_leads").in("campaign_id",s);if(i)throw i;r&&e.push(...r)}return e},placeholderData:e=>e}),{data:Q}=$({queryKey:["admin-drip-live-stats",P],enabled:P.length>0,staleTime:15e3,refetchOnMount:"always",refetchInterval:()=>document.hidden?!1:3e4,queryFn:async()=>{const{data:e,error:a}=await y.rpc("get_drip_round_live_stats",{_campaign_ids:P});if(a)throw a;const n=new Map;return e==null||e.forEach(s=>{n.set(`${s.campaign_id}_r${s.round_number}`,{delivered:Number(s.live_delivered),failed:Number(s.live_failed),unreachable:Number(s.live_unreachable??0),sent:Number(s.live_sent),lastSentAt:s.last_sent_at||void 0})}),n},placeholderData:e=>e}),{data:oe}=$({queryKey:["admin-all-round-optouts",P],enabled:P.length>0,staleTime:10*6e4,refetchInterval:!1,refetchOnWindowFocus:!1,queryFn:async()=>ds(P,3),placeholderData:e=>e}),Fe=oe==null?void 0:oe.map,{data:He}=$({queryKey:["admin-all-round-replies",P],enabled:P.length>0,staleTime:10*6e4,refetchInterval:!1,refetchOnWindowFocus:!1,queryFn:async()=>ls(P,3),placeholderData:e=>e}),Pe=He==null?void 0:He.map,Je=u.useMemo(()=>N?N.filter(e=>
1e.drip_current_round>0&&["running","sending","completed","testing"].includes(e.status)).map(e=>e.id):[],[N]),{data:ce}=$({queryKey:["admin-drip-round-sent",Je],enabled:Je.length>0,staleTime:15e3,refetchInterval:()=>document.hidden?!1:15e3,queryFn:async()=>{const{data:e,error:a}=await y.from("drip_round_logs").select("campaign_id, round_number, messages_sent, eligible_leads, skipped_responded, skipped_opted_out").in("campaign_id",Je).order("round_number",{ascending:!1});if(a)throw a;const n={};return(e||[]).forEach(s=>{if(!n[s.campaign_id]){const r=Math.max(0,Number(s.eligible_leads??0)),i=Math.max(0,Number(s.skipped_responded??0)),g=Math.max(0,Number(s.skipped_opted_out??0)),E=Math.max(0,r-i-g),L=Math.max(0,Number(s.messages_sent??0));n[s.campaign_id]={round:Number(s.round_number??0),sent:L,eligible:E}}}),n}}),{data:Te}=$({queryKey:["admin-campaign-lead-counts",Ye],enabled:Ye.length>0,staleTime:12e4,refetchInterval:()=>document.hidden?!1:12e4,queryFn:async()=>{const{data:e,error:a}=await y.rpc("get_list_lead_counts",{_list_ids:Ye});if(a)throw a;const n={};return(e||[]).forEach(s=>{n[s.list_id]=Number(s.lead_count??0)}),n},placeholderData:e=>e}),{data:et}=$({queryKey:["admin-day-scoped-last-activity",l],enabled:p&&!!G&&!!V&&Ve.length>0,staleTime:15e3,refetchInterval:()=>document.hidden?!1:3e4,queryFn:async()=>{const{data:e,error:a}=await y.rpc("get_campaign_activity_in_range",{_since:G.toISOString(),_until:V.toISOString()});if(a)throw a;const n={};return(e||[]).forEach(s=>{s.last_message_at&&(n[s.campaign_id]=s.last_message_at)}),n},placeholderData:e=>e}),{data:tt}=$({queryKey:["admin-day-scoped-credit-entries",l,F],enabled:p&&!!G&&!!V&&F.length>0&&Ae,staleTime:3e4,placeholderData:e=>e,queryFn:async()=>{const n=[];for(let s=0;s<F.length;s+=200){const r=F.slice(s,s+200);let i=0;for(;;){const{data:g,error:E}=await y.from("credit_ledger").select("related_campaign_id, created_at, change_amount, reason").in("related_campaign_id",r).gte("created_at",G.toISOString()).lte("created_at",V.toISOString()).order("created_at",{ascending:!0}).range(i,i+1e3-1);if(E)throw E;const L=g||[];if(n.push(...L.flatMap(M=>M.related_campaign_id?[{related_campaign_id:M.related_campaign_id,created_at:M.created_at,change_amount:M.change_amount,reason:M.reason}]:[])),L.length<1e3)break;i+=1e3}}return n}}),{data:Ue}=$({queryKey:["admin-campaigns-txts-used-direct",l],staleTime:3e4,placeholderData:e=>e,queryFn:async()=>{const{start:e,end:a}=we(l),{data:n,error:s}=await y.rpc("get_admin_txts_used_in_range",{_since:e?e.toISOString():null,_until:a?a.toISOString():null});if(s)throw s;return Number(n??0)},refetchInterval:()=>document.hidden?!1:12e4}),{data:he}=$({queryKey:["admin-day-scoped-replies",l],enabled:p&&!!G&&!!V,staleTime:3e4,refetchInterval:()=>document.hidden?!1:3e4,queryFn:async()=>{const{data:e,error:a}=await y.rpc("get_campaign_replies_in_range",{_since:G.toISOString(),_until:V.toISOString()});if(a)throw a;const n={};return(e||[]).forEach(s=>{n[`${s.campaign_id}_r${s.round_number}`]=Number(s.replies??0)}),n},placeholderData:e=>e}),{data:xe}=$({queryKey:["admin-day-scoped-optouts",l],enabled:p&&!!G&&!!V,staleTime:3e4,refetchInterval:()=>document.hidden?!1:3e4,queryFn:async()=>{const{data:e,error:a}=await y.rpc("get_campaign_optouts_in_range",{_since:G.toISOString(),_until:V.toISOString()});if(a)throw a;const n={};return(e||[]).forEach(s=>{n[`${s.campaign_id}_r${s.round_number}`]=Number(s.opt_outs??0)}),n},placeholderData:e=>e}),Lt=["[email protected]"],Mt=e=>{const a=Math.max(0,e.eligible_leads||0),n=Math.max(0,e.skipped_responded||0),s=Math.max(0,e.skipped_opted_out||0);return Math.max(0,a-n-s)},Ie=e=>Math.max(0,e.messages_sent||0),ue=u.useMemo(()=>{var a;if(!p||!et||!k)return;const e={};for(const n of Object.keys(k)){if((((a=k[n])==null?void 0:a.sent)??0)<=0)continue;const s=n.split("_r")[0],r=et[s];r&&(e[n]=r)}return e},[p,et,k]),me=u.useMemo(()=>{if(!p||!tt||P.length>0&&!Se)return;const e=new Map;for(const n of Se||[]){const s=e.get(n.campaign_id)||[];s.push({roundNumber:Number(n.round_number??0),sentAtMs:new Date(n.sent_at).getTime()}),e.set(n.campaign_id,s)}for(const n of e.values())n.sort((s,r)=>s.sentAtMs-r.sentAtMs);const a={};for(const n of tt){const s=e.get(n.related_campaign_id)||[],r=new Date(n.created_at).getTime();let i=0;for(const Z of s)if(Z.sentAtMs<=r)i=Z.roundNumber;else break;const g=n.reason||"",E=Number(n.change_amount??0),L=E<0&&(g.startsWith("
1Campaign message")||g.startsWith("MMS send")||g.startsWith("AI surcharge")),M=E>0&&g.startsWith("Reversal:")&&g.toLowerCase().includes("campaign");if(!L&&!M)continue;const j=`${n.related_campaign_id}_r${i}`;a[j]=Math.max(0,(a[j]??0)+-E)}return a},[p,tt,P.length,Se]),ke=u.useMemo(()=>{const e={};if(!N)return e;const a=N.filter(n=>n.status==="paused"&&n.list_id);if(a.length===0)return e;for(const n of a){let s=null;for(const r of N)r.id!==n.id&&(r.user_id!==n.user_id||r.list_id!==n.list_id||r.status!=="draft"&&(new Date(r.created_at)<=new Date(n.created_at)||(!s||new Date(r.created_at)>new Date(s.created_at))&&(s=r)));s&&(e[n.id]={name:s.name,created_at:s.created_at,status:s.status})}return e},[N]),_e=u.useMemo(()=>{var a,n,s,r;if(!N)return[];const e=[];for(const i of N){const g=le==null?void 0:le[i.user_id],E=(g==null?void 0:g.name)||(g==null?void 0:g.company_name)||(g==null?void 0:g.email)||"Unknown",L=(g==null?void 0:g.email)||"",M=((a=i.lists)==null?void 0:a.name)||"—";if(Lt.includes(L.toLowerCase())&&!["sending","running","testing","scheduled"].includes(i.status))continue;const j=(te==null?void 0:te[i.id])||{sent:0,delivered:0,failed:0,replies:0,opt_outs:0},Z=(Re==null?void 0:Re[i.id])??0,ye=((n=Ke==null?void 0:Ke[i.id])==null?void 0:n.totalSegments)??0,ae=Math.max(Z,ye),We=i.list_id?(Te==null?void 0:Te[i.list_id])??null:null,K=(()=>{const ne=(Se||[]).filter(f=>f.campaign_id===i.id).sort((f,S)=>f.round_number-S.round_number),W=new Set;return ne.filter(f=>W.has(f.round_number)?!1:(W.add(f.round_number),!0))})(),ze=(Fe==null?void 0:Fe[i.id])||{},Ge=(Pe==null?void 0:Pe[i.id])||{},X=!!((s=oe==null?void 0:oe.failedCampaignIds)!=null&&s.includes(i.id));if(K.length>0){const ne=(r=K[0])==null?void 0:r.sent_at,W=K.reduce((I,U)=>{const A=`${i.id}_r${U.round_number}`,w=Q==null?void 0:Q.get(A);return I+Math.max(Ie(U),Number((w==null?void 0:w.sent)??0))},0),f=K.reduce((I,U)=>{const A=`${i.id}_r${U.round_number}`,w=Q==null?void 0:Q.get(A),pe=Math.max(Ie(U),Number((w==null?void 0:w.sent)??0)),H=w?w.delivered:U.delivered||0;return I+Math.min(H,pe)},0),S=K.reduce((I,U)=>{const A=`${i.id}_r${U.round_number}`,w=Q==null?void 0:Q.get(A),pe=Math.max(Ie(U),Number((w==null?void 0:w.sent)??0)),H=Math.min(w?w.delivered:U.delivered||0,pe);return I+Math.min(w?w.failed:U.failed||0,Math.max(0,pe-H))},0),C=Math.max(0,(j.sent??0)-W),R=Math.min(Math.max(0,(j.delivered??0)-f),C),re=Math.min(Math.max(0,(j.failed??0)-S),Math.max(0,C-R)),Ee=X?-1:ze[0]??0,ie=Ge[0]??0,at=K.reduce((I,U)=>I+Ie(U)*Ne(i,!0),0),Le=i.paused_reason==="drip_paused"?"paused":C>0?"completed":i.status,Ct=z(i.schedule_start||i.created_at),ut=["sending","running","testing"].includes(Le)&&j.last_message_at?z(j.last_message_at):Ct;e.push({...i,_rowId:`${i.id}_blast`,_rowType:"blast",_roundNumber:0,_displayName:`${i.name}`,_displayDate:ut,_rangeDate:ut,stats:{sent:C,delivered:R,failed:re,replies:ie,opt_outs:Ee},lifetimeStats:j,userName:E,userEmail:L,listName:M,totalLeads:We,txtsUsed:ae>0?Math.max(0,ae-at):Ne(i)*C,currentRoundInfo:null,_effectiveStatus:Le,_optOutsUnknown:X,_errorAfter:null,_errorBefore:ne||null});for(const I of K){const U=`${i.id}_r${I.round_number}`,A=Q==null?void 0:Q.get(U),w=Math.max(Ie(I),Number((A==null?void 0:A.sent)??0)),pe=Mt(I),H=Math.min(A?A.delivered:I.delivered||0,w),mt=A?Math.min(A.unreachable,Math.max(0,w-H)):0,pt=A?Math.min(A.failed,Math.max(0,w-H-mt)):Math.min(I.failed||0,Math.max(0,w-H)),$t=Ge[I.round_number]??0,qt=X?-1:ze[I.round_number]??0,gt=I.round_number===i.drip_current_round,ft=H+pt>=w,nt=ce==null?void 0:ce[i.id],be=nt?{...nt,sent:Math.max(Number(nt.sent??0),w)}:null,ht=["running","sending","testing"].includes(i.status),At=gt&&ht&&!ft&&!!be&&be.eligible>0&&be.sent<be.eligible,xt=gt&&ht&&(At||!ft),Rt=xt&&be?be:null;let rt;xt?rt="sending":rt="completed";const Kt=z(I.sent_at),_t=A!=null&&A.lastSentAt?z(A.lastSentAt):Kt,yt=K.indexOf(I),it=yt<K.length-1?K[yt+1]:null;e.push({...i,_rowId:`${i.id}_r${I.round_number}`,_rowType:"round",_roundNumber:I.round_number,_displayName:`${i.name}`,_displayDate:_t,_rangeDate:_t,_roundLog:I,_targetLeads:pe,stats:{sent:w,delivered:H,failed:pt,unreachable:mt,replies:$t,opt_outs:qt},lifetimeStats:j,userName:E,userEmail:L,listName:M,totalLeads:pe,txtsUsed:w*Ne(i,!0),currentRoundInfo:Rt,_effectiveStatus:rt,_optOutsUnknown:X,_errorAfter:I.sent_at,_errorBefore:(it==null?void 0:it.sent_at)||null})}}else{const ne=j.sent??0,W=Oe==null?void 0:Oe[i.id],f=W!=null?Math.max(ne,W):ne,S=z(i.schedule_start||i.created_at),C=["sending","running","testing"].includes(i.status)&&j.last_message_at?z(j.last_message_at):S;e.push({...i,_rowId:i.id,_rowType:"campaign",_roundNumber:null,_displayName:i.name,_displayDate:C,_rangeDate:C,stats:W!=null?{...j,sent:f}:j,lifetimeStats:j,userName:E,userEmail:L,listName:M,totalLeads:We,txtsUsed:ae>0?ae:Ne(i)*f,currentRoundInfo:(ce==null?void 0:ce[i.id])||null,_effectiveStatus:i.paused_reason==="drip_paused"?"paused":i.status})}}return e}
1,[N,te,le,Te,Re,Ke,Se,Fe,Pe,ce,Oe,Q,oe]),De=e=>e._rowType==="round"?`${e.id}_r${e._roundNumber}`:e._rowType==="blast"?`${e.id}_r0`:`${e.id}_r0`,Be=u.useCallback((e,a,n)=>{if(e._rowType==="round"&&e._roundLog){const r=z(e._roundLog.sent_at);return r>=a&&r<=n}if(e._rowType==="blast"){const r=z(e.schedule_start||e.created_at);return r>=a&&r<=n}const s=z(e.schedule_start||e.created_at);return s>=a&&s<=n},[]),Qe=u.useCallback(e=>{var n;const a=De(e);return(((n=k==null?void 0:k[a])==null?void 0:n.sent)??0)>0},[k]),Ze=u.useCallback(e=>{if(p){const a=ue==null?void 0:ue[De(e)];if(a)return z(a)}return e._displayDate},[p,ue]),se=u.useMemo(()=>{let e=_e.filter(r=>{if(r.status==="draft"&&r._rowType==="campaign")return!1;const i=["sending","running","testing","scheduled"];return!(r._rowType==="blast"&&r.stats.sent===0&&!i.includes(r._effectiveStatus)||r._rowType==="round"&&r.stats.sent===0&&!i.includes(r._effectiveStatus))});const{start:a,end:n}=we(l);p&&a&&n?e=e.filter(r=>k?Qe(r):Be(r,a,n)):a&&(e=e.filter(r=>{const i=r._rangeDate??r._displayDate;return i>=a&&(!n||i<=n)}));const s=r=>r._effectiveStatus;if(h==="active"?e=e.filter(r=>["sending","running","testing","scheduled"].includes(s(r))):h==="completed"?e=e.filter(r=>s(r)==="completed"):h==="paused"?e=e.filter(r=>s(r)==="paused"):h==="failed"&&(e=e.filter(r=>s(r)==="failed")),m.trim()){const r=m.toLowerCase();e=e.filter(i=>i.userName.toLowerCase().includes(r)||i.userEmail.toLowerCase().includes(r)||i.id.toLowerCase().includes(r)||i.name.toLowerCase().includes(r)||i.listName.toLowerCase().includes(r))}return[...e].sort((r,i)=>{const g=M=>M._effectiveStatus==="sending"||M._effectiveStatus==="testing",E=g(r),L=g(i);return E!==L?E?-1:1:Ze(i).getTime()-Ze(r).getTime()})},[_e,h,m,l,p,k,Qe,Be,Ze]),ot=u.useMemo(()=>new Set(se.map(e=>e.id)).size,[se]),D=u.useMemo(()=>{const e={sends:se.length,campaigns:0,sent:0,delivered:0,failed:0,replies:0,opt_outs:0,txtsUsed:0};return e.campaigns=ot,p&&k?se.forEach(a=>{const n=De(a),s=k[n];s&&(e.sent+=s.sent,e.delivered+=s.delivered,e.failed+=s.failed),e.txtsUsed+=St(a,(s==null?void 0:s.sent)??0,me==null?void 0:me[n]),e.replies+=(he==null?void 0:he[n])??0,e.opt_outs+=(xe==null?void 0:xe[n])??0}):se.forEach(a=>{e.sent+=a.stats.sent,e.delivered+=a.stats.delivered,e.failed+=a.stats.failed,e.replies+=a.stats.replies??0,e.opt_outs+=Math.max(0,a.stats.opt_outs??0),e.txtsUsed+=a.txtsUsed??0}),Ue!=null&&Ue>0&&(e.txtsUsed=Math.max(e.txtsUsed,Ue)),je&&(e.sent+=je.sent,e.delivered+=je.delivered,e.failed+=je.failed),e},[se,p,k,me,he,xe,ot,Ue,je]),ct=u.useMemo(()=>{const{start:e,end:a}=we(l);let n;p&&e&&a?n=_e.filter(r=>k?Qe(r):Be(r,e,a)):e?n=_e.filter(r=>{const i=r._rangeDate??r._displayDate;return i>=e&&(!a||i<=a)}):n=_e,n=n.filter(r=>{if(r.status==="draft"&&r._rowType==="campaign")return!1;const i=["sending","running","testing","scheduled"];return!(r._rowType==="blast"&&r.stats.sent===0&&!i.includes(r._effectiveStatus)||r._rowType==="round"&&r.stats.sent===0&&!i.includes(r._effectiveStatus))});const s={all:n.length,active:0,completed:0,paused:0,failed:0};return n.forEach(r=>{const i=r._effectiveStatus;["sending","running","testing","scheduled"].includes(i)?s.active++:i==="completed"?s.completed++:i==="paused"?s.paused++:i==="failed"&&s.failed++}),s},[_e,l,p,k,Qe,Be]),st=D.sent>0?Math.round(D.delivered/(D.delivered+D.failed||1)*100):0;return t.jsxs("div",{className:"p-4 md:p-6 space-y-5",children:[t.jsxs("div",{className:"flex flex-col sm:flex-row gap-3 items-start sm:items-center justify-between",children:[t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx("h1",{className:"text-2xl font-bold",children:"All Campaigns"}),t.jsx(Me,{size:"icon",variant:"ghost",className:"h-8 w-8",onClick:qe,disabled:O,children:t.jsx(Vt,{className:`h-4 w-4 ${O?"animate-spin":""}`})})]}),t.jsxs("div",{className:"flex items-center gap-1.5 flex-wrap",children:[kt.map(e=>t.jsx(Me,{size:"sm",variant:l===e.value?"default":"outline",className:"h-8 text-xs",onClick:()=>b(e.value),children:e.label},e.value)),p&&t.jsxs("div",{className:"flex items-center gap-0.5 ml-1 border-l pl-2",children:[t.jsx(Me,{variant:"ghost",size:"icon",className:"h-7 w-7",disabled:l==="today",onClick:()=>
1{if(l==="yesterday")b("today");else{const e=l.match(/^day-(\d+)$/);if(e){const a=parseInt(e[1],10)-1;a<=0?b("today"):b(a===1?"yesterday":`day-${a}`)}}},children:t.jsx(Yt,{className:"h-4 w-4"})}),t.jsx("span",{className:"text-xs text-muted-foreground min-w-[56px] text-center font-medium",children:Fs(l)}),t.jsx(Me,{variant:"ghost",size:"icon",className:"h-7 w-7",onClick:()=>{if(l==="today")b("yesterday");else if(l==="yesterday")b("day-2");else{const e=l.match(/^day-(\d+)$/);b(`day-${e?parseInt(e[1],10)+1:2}`)}},children:t.jsx(Xt,{className:"h-4 w-4"})})]})]})]}),t.jsx(os,{adminMode:!0,dateFilter:l}),l==="today"&&t.jsx(Ts,{}),t.jsxs("div",{className:"grid grid-cols-2 sm:grid-cols-4 xl:grid-cols-8 gap-2 lg:gap-3",children:[t.jsx(fe,{icon:Ht,label:"Sends",value:D.sends,color:"bg-primary/10 text-primary",subtitle:`(${D.campaigns} campaigns)`}),t.jsx(fe,{icon:Ce,label:"Total Sent",value:D.sent,color:"bg-muted text-foreground"}),t.jsx(fe,{icon:bt,label:"Delivered",value:D.delivered,color:"bg-success/10 text-success"}),t.jsx(fe,{icon:Jt,label:"Filtered / Failed",value:D.failed,color:"bg-warning/10 text-warning"}),t.jsx(fe,{icon:es,label:"Replies",value:D.replies,color:"bg-primary/10 text-primary"}),t.jsx(fe,{icon:vs,label:"Opt-Outs",value:D.opt_outs,subtitle:D.delivered>0?`(${(D.opt_outs/D.delivered*100).toFixed(1)}%)`:void 0,color:`${D.delivered>0&&D.opt_outs/D.delivered>.03?"bg-destructive/10 text-destructive":D.delivered>0&&D.opt_outs/D.delivered>.01?"bg-warning/10 text-warning":"bg-muted text-muted-foreground"}`}),t.jsx(fe,{icon:ts,label:"TXTs Used",value:D.txtsUsed,color:"bg-accent text-accent-foreground"}),t.jsxs("div",{className:"rounded-xl border bg-card p-2 lg:p-3 flex flex-col xl:flex-col 2xl:flex-row items-start 2xl:items-center gap-1.5 2xl:gap-3 shadow-sm min-w-0",children:[t.jsx("div",{className:`rounded-lg p-1.5 lg:p-2 shrink-0 ${st>=75?"bg-success/10 text-success":st>=50?"bg-warning/10 text-warning":"bg-destructive/10 text-destructive"}`,children:t.jsx(bt,{className:"h-3.5 w-3.5 lg:h-4 lg:w-4"})}),t.jsxs("div",{className:"min-w-0 w-full",children:[t.jsxs("p",{className:"text-base lg:text-xl font-bold tabular-nums leading-tight",children:[st,"%"]}),t.jsx("p",{className:"text-[10px] lg:text-xs text-muted-foreground truncate",children:"Delivery Rate"})]})]})]}),t.jsxs("div",{className:"flex flex-col sm:flex-row gap-3 items-start sm:items-center justify-between",children:[t.jsx(gs,{value:h,onValueChange:T,children:t.jsx(fs,{children:Os.map(e=>t.jsxs(hs,{value:e.value,className:"gap-1.5",children:[e.label,ct[e.value]>0&&t.jsx(xs,{variant:"secondary",className:"h-5 min-w-5 text-[10px] px-1.5",children:ct[e.value]})]},e.value))})}),t.jsxs("div",{className:"relative w-full sm:w-64",children:[t.jsx(ss,{className:"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground"}),t.jsx(as,{placeholder:"Search user, campaign, list…",className:"pl-9",value:m,onChange:e=>x(e.target.value)})]})]}),Et&&!N?t.jsx("div",{className:"space-y-3",children:Array.from({length:8}).map((e,a)=>t.jsx(ns,{className:"h-12 w-full"},a))}):se.length===0?t.jsx("p",{className:"text-sm text-muted-foreground py-8 text-center",children:"No campaigns found."}):t.jsx("div",{className:"rounded-lg border overflow-auto",style:{WebkitOverflowScrolling:"touch"},children:t.jsxs(_s,{className:"min-w-[900px]",children:[t.jsx(ys,{children:t.jsxs(vt,{children:[t.jsx(J,{className:"w-[140px]",children:"User"}),t.jsx(J,{className:"w-[180px]",children:"Campaign / List"}),t.jsx(J,{className:"text-center w-[80px]",children:"Type"}),t.jsx(J,{className:"text-center w-[100px]",children:"Delivery"}),t.jsx(J,{className:"text-center w-[90px]",children:"Responses"}),t.jsx(J,{className:"text-center w-[70px]",children:"Opt-Outs"}),t.jsx(J,{className:"text-center w-[70px]",children:"TXTs Used"}),t.jsx(J,{className:"text-center w-[80px]",children:"Status"}),t.jsx(J,{className:"w-[80px]",children:"Date"})]})}),t.jsx(bs,{children:se.map(e=>{var W;const a=e._effectiveStatus,n=["sending","running","testing"].includes(a);Ze(e);const s=De(e),r=p&&k?k[s]:null,i=r?r.sent:e.stats.sent||0,g=r?r.delivered:e.stats.delivered||0,E=r?r.failed:e.stats.failed||0,L=r?r.unreachable??0:e.stats.unreachable||0,M=g+E+L,j=g+E,Z=Math.max(0,i-M),ye=j>0?Math.round(g/j*100):0,ae=p&&he?he[s]??0:e.stats.replies??0,We=p&&xe?xe[s]??0:e.stats.opt_outs??0,K=r?g:e.stats.delivered||0,ze=i>0&&Z>0,Ge=me==null?void 0:me[s],X=r?St(e,r.sent,Ge):e.txtsUsed??0,ne=e._rowType==="round"?t.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-semibold bg-primary/15 border border-primary/30 text-primary",children:[t.jsx(Ns,{className:"h-3 w-3"}),"Round ",e._roundNumber]}
1):e._rowType==="blast"?t.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-semibold bg-muted border text-muted-foreground",children:[t.jsx(Ce,{className:"h-3 w-3"}),"Blast"]}):e.drip_enabled?t.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-semibold bg-muted border text-muted-foreground",children:[t.jsx(Ce,{className:"h-3 w-3"}),"Blast"]}):t.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-semibold bg-muted border text-muted-foreground",children:[t.jsx(Ce,{className:"h-3 w-3"}),"Blast"]});return t.jsxs(vt,{className:e._rowType==="round"?"bg-primary/[0.02]":"",children:[t.jsx(ee,{children:t.jsxs("div",{className:"min-w-0",children:[t.jsxs("div",{className:"flex items-center gap-1.5 flex-wrap",children:[t.jsx("p",{className:"text-sm font-medium truncate",children:e.userName}),rs(e.user_id,(W=le==null?void 0:le[e.user_id])==null?void 0:W.fast_lane)&&t.jsx(is,{})]}),t.jsx("p",{className:"text-[10px] text-muted-foreground truncate",children:e.userEmail})]})}),t.jsx(ee,{children:t.jsxs("div",{className:"min-w-0",children:[t.jsx("p",{className:"text-sm font-semibold truncate",children:e.name}),t.jsx("p",{className:"text-[10px] text-muted-foreground truncate",children:e.listName})]})}),t.jsx(ee,{className:"text-center",children:t.jsxs("div",{className:"flex items-center justify-center gap-1.5 flex-wrap",children:[ne,(e.ai_personalize||e._rowType==="round")&&t.jsx("span",{className:"inline-flex items-center gap-0.5 rounded-full px-1.5 py-0.5 text-[9px] font-semibold bg-violet-500/15 border border-violet-500/30 text-violet-600 dark:text-violet-400",title:"AI Anti-Spam: messages are uniquely reworded",children:"🤖 AI"}),e.media_url&&t.jsxs("span",{className:"inline-flex items-center gap-0.5 rounded-full px-1.5 py-0.5 text-[9px] font-semibold bg-accent/15 border border-accent/30 text-accent-foreground",title:"MMS campaign — image attached, billed 3 TXTs/send",children:[t.jsx(js,{className:"h-2.5 w-2.5"})," MMS"]})]})}),t.jsx(ee,{className:"text-center",children:i>0?t.jsxs("div",{className:"flex flex-col items-center gap-0.5",children:[t.jsx(cs,{campaignId:e.id,deliveryPct:ye,after:e._errorAfter,before:e._errorBefore,colorClass:`font-medium ${ye>=80?"text-success":ye>=50?"text-warning":"text-destructive"}`,children:t.jsxs("span",{children:[ye,"%"]})}),t.jsxs("span",{className:"text-muted-foreground text-xs",children:[g,"/",j,L>0?` · ${L} bad #s`:""]}),Z>0&&t.jsxs("span",{className:"flex items-center gap-0.5 text-[9px] text-warning font-medium",children:[t.jsx(de,{className:"h-2 w-2 animate-spin"}),Z," pending"]}),!n&&Z===0&&i>0&&t.jsxs("span",{className:"flex items-center gap-0.5 text-[9px] text-success font-medium",children:[t.jsx(wt,{className:"h-2 w-2"})," Final"]})]}):ze?t.jsxs("div",{className:"flex flex-col items-center gap-0.5",children:[t.jsxs("span",{className:"flex items-center gap-1 text-xs text-muted-foreground",children:[t.jsx(de,{className:"h-3 w-3 animate-spin"})," Awaiting…"]}),t.jsxs("span",{className:"text-muted-foreground text-xs",children:["Sent ",i]})]}):n?t.jsxs("span",{className:"flex items-center justify-center gap-1 text-xs text-muted-foreground",children:[t.jsx(de,{className:"h-3 w-3 animate-spin"})," Awaiting…"]}):t.jsx("span",{className:"text-muted-foreground",children:"—"})}),t.jsx(ee,{className:"text-center",children:ae>0||K>0?(()=>{const f=K>0?K:i,S=f>0?ae/f:0;return t.jsxs("div",{className:"flex flex-col items-center",children:[t.jsx("span",{className:"font-medium",children:ae}),t.jsx("span",{className:"text-muted-foreground text-xs",children:f>0?`${Math.round(S*100)}%`:""})]})})():t.jsx("span",{className:"text-muted-foreground",children:"—"})}),t.jsx(ee,{className:"text-center",children:(()=>{const f=We;if(f<0||!p&&e._optOutsUnknown)return t.jsx("span",{className:"text-muted-foreground",title:"Still calculating",children:"—"});const S=K>0?K:i>0?i:1,C=f/S*100,R=C>3?"text-destructive":C>1?"text-warning":f>0?"text-success":"text-muted-foreground";return t.jsxs("div",{className:"flex flex-col items-center",children:[t.jsxs("span",{className:`font-medium ${R}`,children:[C.toFixed(1),"%"]}),t.jsxs("span",{className:`text-[10px] ${R} opacity-70`,children:["(",f,")"]})]})})()}),t.jsx(ee,{className:"text-center tabular-nums",children:X>
10?t.jsx("span",{className:"font-medium",children:X.toLocaleString()}):t.jsx("span",{className:"text-muted-foreground",children:"—"})}),t.jsx(ee,{className:"text-center",children:t.jsxs("div",{className:"flex flex-col items-center gap-1",children:[t.jsxs("div",{className:"flex items-center gap-1",children:[t.jsx(ps,{status:a}),(a==="running"||a==="sending")&&e._rowType!=="round"&&t.jsx("button",{title:"Pause campaign",disabled:q===e.id,onClick:async f=>{f.stopPropagation(),B(e.id);try{const{data:S,error:C}=await y.from("campaigns").update({status:"paused",paused_reason:"paused_by_admin"}).eq("id",e.id).select("id, status").maybeSingle();if(C)throw C;if(!S)throw new Error("Pause not applied — no permission or campaign not found");if(S.status!=="paused")throw new Error(`Pause not confirmed — status is still "${S.status}"`);const{data:R}=await y.from("campaigns").select("status").eq("id",e.id).maybeSingle();if((R==null?void 0:R.status)!=="paused")throw new Error("Campaign re-started itself — try again");await d.invalidateQueries({queryKey:["admin-campaigns"]}),await d.refetchQueries({queryKey:["admin-campaigns"]}),ge.success(`Paused "${e.name}" — confirmed`)}catch(S){ge.error(S.message||"Failed to pause")}finally{B(null)}},className:"h-4 w-4 rounded-sm border border-destructive/40 bg-destructive/10 text-destructive hover:bg-destructive hover:text-destructive-foreground text-[9px] font-bold leading-none flex items-center justify-center transition-colors disabled:opacity-50",children:q===e.id?"…":"P"})]}),(a==="running"||a==="sending"||a==="scheduled")&&t.jsx(us,{}),(a==="paused"||a==="failed")&&e.paused_reason&&t.jsx("span",{className:`text-[10px] font-medium ${e.paused_reason==="paused_by_user"?"text-warning":"text-destructive"} max-w-[160px] text-center leading-tight`,title:e.paused_reason,children:(()=>{const f=Ps(e.paused_reason,te==null?void 0:te[e.id]);if(f){const S=Us(e,Te,te);return`${f.deliveryPct}% delivered · ${f.suspicious}/${f.failed} failures suspicious${S!==null?` · ${S.toLocaleString()} TXTs waiting`:""}`}return e.paused_reason==="paused_by_user"?"Paused by user":e.paused_reason==="paused_by_admin"||e.paused_reason==="manually_paused"||/^manually paused/i.test(e.paused_reason)?"Paused by admin":e.paused_reason.toLowerCase().includes("credit")?"Low Credits":e.paused_reason.toLowerCase().includes("no eligible leads")?"All leads filtered (72h cooldown)":e.paused_reason})()}),a==="paused"&&e._rowType!=="round"&&(ke[e.id]?t.jsxs("span",{className:"text-[10px] font-medium text-muted-foreground max-w-[160px] text-center leading-tight flex items-center gap-1 justify-center",title:`Superseded by "${ke[e.id].name}" (${ke[e.id].status}) launched ${new Date(ke[e.id].created_at).toLocaleString("en-US",{timeZone:"America/New_York"})}`,children:[t.jsx(Ss,{className:"h-2.5 w-2.5"}),"Edited & resent"," ",new Date(ke[e.id].created_at).toLocaleTimeString("en-US",{timeZone:"America/New_York",hour:"numeric",minute:"2-digit",hour12:!0})]}):t.jsxs("div",{className:"flex items-center gap-1",children:[t.jsxs(Me,{size:"sm",variant:"outline",className:"h-6 text-[10px] px-2 gap-1",disabled:_===e.id,onClick:f=>{f.stopPropagation(),Y(e)},children:[_===e.id?t.jsx(de,{className:"h-2.5 w-2.5 animate-spin"}):t.jsx(Ce,{className:"h-2.5 w-2.5"}),_===e.id?"Resuming…":"Resume"]}),t.jsx(Ks,{campaignId:e.id,after:e.test_window_start??null})]})),a==="scheduled"&&e.schedule_start&&t.jsxs("span",{className:"text-[10px] text-muted-foreground whitespace-nowrap",children:[new Date(e.schedule_start).toLocaleDateString("en-US",{timeZone:"America/New_York",month:"numeric",day:"numeric",year:"numeric"})," ",new Date(e.schedule_start).toLocaleTimeString("en-US",{timeZone:"America/New_York",hour:"numeric",minute:"2-digit",hour12:!0})]}),n&&(()=>{var re;const f=((re=e.templates)==null?void 0:re.body)||"",S=f?It(f).segments:1,C=S>1?` · ${S} seg`:"",R=e.currentRoundInfo;if(R){const Ee=e._targetLeads??R.eligible,ie=Math.max(Ee,R.sent),at=ie>0?Math.min(100,Math.max(3,R.sent/ie*100)):50,Le=X||R.sent*S;return t.jsxs(t.Fragment,{children:[t.jsx("div",{className:"h-1.5 w-20 rounded-full bg-muted overflow-hidden",children:t.jsx("div",{className:"h-full rounded-full bg-primary transition-all duration-700 ease-out",style:{width:`${at}%`}})}),t.jsxs("span",{className:"text-[10px] font-medium text-muted-foreground whitespace-nowrap flex items-center gap-1",children:[t.jsx(de,{className:"h-2.5 w-2.5 animate-spin"}
1)," Sent ",R.sent.toLocaleString(),"/",ie.toLocaleString(),Le>0&&t.jsxs("span",{className:"text-primary",children:["· ",Le.toLocaleString()," TXTs",C]})]})]})}if(e.totalLeads!=null&&e.totalLeads>0){const Ee=Math.min(100,Math.max(3,e.stats.sent/e.totalLeads*100)),ie=X||(e.stats.sent||0)*S;return t.jsxs(t.Fragment,{children:[t.jsx("div",{className:"h-1.5 w-20 rounded-full bg-muted overflow-hidden",children:t.jsx("div",{className:"h-full rounded-full bg-primary transition-all duration-700 ease-out",style:{width:`${Ee}%`}})}),t.jsxs("span",{className:"text-[10px] font-medium text-muted-foreground whitespace-nowrap flex items-center gap-1",children:[t.jsx(de,{className:"h-2.5 w-2.5 animate-spin"})," Sent ",e.stats.sent.toLocaleString(),"/",e.totalLeads.toLocaleString(),ie>0&&t.jsxs("span",{className:"text-primary",children:["· ",ie.toLocaleString()," TXTs",C]})]})]})}return t.jsxs("span",{className:"text-[10px] font-medium text-muted-foreground whitespace-nowrap flex items-center gap-1",children:[t.jsx(de,{className:"h-2.5 w-2.5 animate-spin"})," Sending…"]})})(),e._rowType==="round"&&e._roundLog&&e._roundLog.skipped_responded>0&&t.jsx("div",{className:"flex flex-col items-center gap-0.5 text-[9px] text-muted-foreground",children:t.jsxs("span",{className:"flex items-center gap-0.5",children:[t.jsx(wt,{className:"h-2.5 w-2.5 text-success"}),e._roundLog.skipped_responded," replied"]})})]})}),t.jsx(ee,{className:"text-xs text-muted-foreground whitespace-nowrap",children:(()=>{const S=(p?ue==null?void 0:ue[De(e)]:null)||(e._rowType==="round"&&e._roundLog?e._roundLog.sent_at:null)||e.schedule_start||e.created_at,C=new Date(S).getTime(),R=Date.now()-C,re=Math.floor(R/6e4);return re<1?"Just now":re<60?`${re}m ago`:new Date(S).toLocaleString("en-US",{timeZone:"America/New_York",month:"short",day:"numeric",hour:"numeric",minute:"2-digit",hour12:!0})+" ET"})()})]},e._rowId)})})]})})]})}export{_a as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.