1import{b as je,u as A,c as de,j as e}from"./vendor-query-CmR8e8UI.js";import{k as ke,r as b,L as Ne}from"./vendor-react-CtvgsDZ3.js";import{l as U}from"./lists-CMQd9Q9B.js";import{s as z,i as Se,h,B as p,L as I,K as _e,k as ue,g as J,X as we}from"./index-B50KUD3M.js";import{P as Le}from"./PageHeader-A6CBw4Vp.js";import{I as De}from"./InfoDot-DD69Qk7O.js";import{B as g}from"./badge-BqknQmtB.js";import{P as Ce}from"./progress-D2ie3gkc.js";import{T as Be,a as qe,b as O,e as S,c as Ae,d as k}from"./table-CFvcCRnq.js";import{D as Ke,a as Re,b as Pe,c as Te,f as Ee,e as Qe}from"./dialog-DUHCd5JD.js";import{B as Fe,g as Ue}from"./BuyCreditsDialog-Ch5SxOSK.js";import{A as Oe}from"./arrow-left-CBlt0ZNp.js";import"./vendor-supabase-GlODc1dO.js";import"./vendor-charts-MzEwy637.js";import"./popover-CAVfmKyj.js";import"./index-DotgDK9r.js";import"./index-vlVzEKL-.js";import"./info-FvD5yPlr.js";import"./index-D90OnMJA.js";import"./arrow-right-DFcOBxG5.js";import"./check-zxk8COol.js";async function $(r,s){const{data:n,error:c}=await z.functions.invoke(r,{body:s});if(c){let i=c.message;try{const u=c.context;if(u&&typeof u.text=="function"){const m=await u.text();try{const N=JSON.parse(m);i=N.error||N.message||m||i}catch{i=m||i}}}catch{}throw new Error(i)}if(n&&typeof n=="object"&&"ok"in n&&n.ok===!1){const i="error"in n?String(n.error||"Request failed"):"Request failed";throw new Error(i)}return n}const K={startScan:async(r,s={})=>$("bouncify-start-scan",{list_id:r,mark_as_scanned:s.markAsScanned??!1}),testKey:async()=>$("bouncify-test-key",{}),pollJob:async r=>$("bouncify-poll-job",{job_id:r}),latestJobsByList:async r=>{if(!r.length)return{};const{data:s,error:n}=await z.from("bouncify_jobs").select("*").in("list_id",r).order("created_at",{ascending:!1});if(n)throw n;const c={};for(const i of s??[])c[i.list_id]||(c[i.list_id]=i);return c},listCounts:async r=>{const s={deliverable:0,rejected:0,unscanned:0};for(const n of["deliverable","rejected","unscanned"]){const{count:c}=await z.from("subscriber_lists").select("subscriber_id",{count:"exact",head:!0}).eq("list_id",r).eq("deliverability",n);s[n]=c??0}return s}},$e=({deliverability:r,result:s,scanning:n})=>n&&r==="unscanned"?e.jsxs(g,{variant:"secondary",className:"gap-1",children:[e.jsx(I,{className:"size-3 animate-spin"})," Scan in progress"]}):r==="deliverable"?e.jsxs(g,{className:"bg-emerald-600 hover:bg-emerald-600 text-white",title:s??"",children:["Deliverable",s&&s!=="deliverable"?` · ${s}`:""]}):r==="rejected"?e.jsxs(g,{variant:"destructive",title:s??"",children:["Rejected",s&&s!=="undeliverable"?` · ${s}`:""]}):e.jsx(g,{variant:"outline",className:"text-muted-foreground",children:"Unscanned"}),Me=r=>{switch(r){case"deliverable":return{deliverability:"deliverable",bouncifyResult:"deliverable"};case"accept_all":return{deliverability:"deliverable",bouncifyResult:"accept-all"};case"undeliverable":return{deliverability:"rejected",bouncifyResult:"undeliverable"};case"unknown":return{deliverability:"rejected",bouncifyResult:"unknown"};case"unscanned":return{deliverability:"unscanned"};case"legacy_deliverable":return{deliverability:"deliverable"};case"legacy_rejected":return{deliverability:"rejected"}}},R={deliverable:"Deliverable",accept_all:"Accept-all",undeliverable:"Undeliverable",unknown:"Unknown",unscanned:"Unscanned",legacy_deliverable:"Deliverable",legacy_rejected:"Rejected"},ze={good:"text-emerald-700 dark:text-emerald-400",risky:"text-amber-700 dark:text-amber-400",bad:"text-destructive",muted:"text-muted-foreground"},M=({label:r,value:s,tone:n,note:c,active:i,onClick:u})=>e.jsxs("button",{type:"button",onClick:u,"aria-pressed":i,className:J("rounded-lg border bg-card p-4 text-left transition hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",n==="risky"&&"border-amber-300/70 bg-amber-50/40 dark:border-amber-900/50 dark:bg-amber-950/20",i&&"ring-2 ring-primary border-primary"),children:[e.jsx("div",{className:J("text-xl font-bold tabular-nums tracking-tight",ze[n]),children:s.toLocaleString()}),e.jsx("div",{className:"mt-0.5 text-xs font-medium text-muted-foreground",children:r}),c&&e.jsx("div",{className:"mt-1 text-[11px] leading-tight text-amber-700 dark:text-amber-500",children:c})]}),xs=()=>{var se,te,ae,ne,re,ie,le;const{id:r}=ke(),s=Number(r),n=je(),{isAdmin:c}=Se(),[i,u]=b.useState(1),[m,N]=b.useState(null),V=10,P=A({queryKey:["list",s],queryFn:()=>U.get(s),enabled:!!s}),t=(se=A({queryKey:["bouncify-jobs",String(s)],queryFn:()=>K.latestJobsByList([s]),enabled:!!s,refetchInterval:a=>{const o=a.state.data,f=o==null?void 0:o[s];return(f==null?void 0:f.status)==="pending"||(f==null?void 0:f.status)==="processing"?8e3:!1},staleTime:3e4}).data)==null?void 0:se[s],v=(t==null?void 0:t.status)==="pending"||(t==null?void 0:t.status)==="processing",_=(t==null?void 0:t.status)==="completed",y=_?m:null,me=y?Me(y):{},T=A({queryKey:["list-subscribers",s,i,y],queryFn:()=>U.subscribersInList(s,{page:i,per_page:V,...me}),enabled:!!s}),xe=A({queryKey:["list-scan-meta",s],queryFn:()=>U.scanMeta(s),enabled:!!s}),w=a=>{N(o=>o===a?null:a),u(1)},H=b.useRef(t==null?void 0:t.status);b.useEffect(()=>{const a=H.current;if(t!=null&&t.status&&a!==t.status&&(t.status==="completed"?(n.invalidateQueries({queryKey:["list-subscribers",s]}),n.invalidateQueries({queryKey:["list-scan-meta",s]}),h.success("Deliverability scan complete")):t.status==="failed"&&h.error(t.error||"Deliverability scan failed",{duration:6e3}),H.current=t.status),!t||!v)return;const o=setInterval(()=>{K.pollJob(t.id).catch(()=>{}).finally(()=>n.invalidateQueries({queryKey:["bouncify-jobs",String(s)]}))},1e4);return()=>clearInterval(o)},[t,v,n,s]);const fe=de({mutationFn:({markAsScanned:a})=>K.startScan(s,{markAsScanned:a}),onSuccess:(a,o)=>{h.success(o.markAsScanned?"List marked as scanned":"Deliverability scan started"),n.invalidateQueries({queryKey:["bouncify-jobs",String(s)]})},onError:a=>h.error(a.message||"Scan failed to start",{duration:6e3})}),[ge,L]=b.useState(!1),[be,X]=b.useState(!1),[d,E]=b.useState(null),he=()=>{E(null),L(!0),Ue().then(E).catch(()=>E(0))},Q=de({mutationFn:()=>K.testKey(),onSuccess:a=>{var f,ce,oe;const o=(f=a.results)==null?void 0:f.find(j=>j.ok);if(a.ok&&o){const j=(ce=o.credits)==null?void 0:ce.credits_remaining;
1h.success(j!=null?`Bouncify key OK â ${j.toLocaleString()} credits remaining (${o.secret})`:`Bouncify key OK (${o.secret})`,{duration:6e3})}else{const j=a.error||((oe=a.results)==null?void 0:oe.map(F=>`${F.secret}: ${F.status} ${F.message}`).join(" ⢠"))||"Unknown error";h.error(`Bouncify key test failed: ${j}`,{duration:8e3})}},onError:a=>h.error(a.message||"Key test failed",{duration:8e3})}),Y=((te=T.data)==null?void 0:te.results)??[],D=((ae=T.data)==null?void 0:ae.total)??0,x=((ne=P.data)==null?void 0:ne.subscriber_count)??0,C=Math.max(1,Math.ceil(D/V)),G=t&&t.total>0?Math.round(t.progress/t.total*100):0,l=(t==null?void 0:t.summary)??{},W=_&&("total"in l||"accept_all"in l||"undeliverable"in l||"unknown"in l||"deliverable_total"in l),B=((re=xe.data)==null?void 0:re.last_scanned_at)??null,q=(t==null?void 0:t.credits_spent)??null,pe=l.total??x,Z=l.other??0,ee=l.unscanned??0,ve=()=>t?t.status==="failed"?e.jsx(g,{variant:"outline",className:"text-muted-foreground",title:t.error??"",children:"Scan failed"}):v?e.jsxs(g,{variant:"secondary",className:"gap-1",children:[e.jsx(I,{className:"size-3 animate-spin"})," Scanning ",G,"%"]}):e.jsx(g,{className:"bg-emerald-600 hover:bg-emerald-600 text-white",children:"Scan complete"}):e.jsx(g,{variant:"outline",className:"text-muted-foreground",children:"Unscanned"}),ye=[{key:"deliverable",tone:"good",value:l.deliverable??0},{key:"accept_all",tone:"risky",value:l.accept_all??0,note:"Risky for cold domains"},{key:"undeliverable",tone:"bad",value:l.undeliverable??0},{key:"unknown",tone:"muted",value:l.unknown??0}];return e.jsxs("div",{children:[e.jsxs(Ne,{to:"/lists",className:"inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground mb-3",children:[e.jsx(Oe,{className:"size-4"})," Back to Lists"]}),e.jsx(Le,{title:((ie=P.data)==null?void 0:ie.name)??"List",description:((le=P.data)==null?void 0:le.description)||`${x.toLocaleString()} subscribers`,actions:e.jsxs("div",{className:"flex flex-wrap gap-2",children:[c&&e.jsxs(p,{variant:"outline",disabled:Q.isPending,onClick:()=>Q.mutate(),children:[Q.isPending?e.jsx(I,{className:"animate-spin"}):e.jsx(_e,{}),"Test API key"]}),e.jsxs(p,{disabled:v||x===0,onClick:he,children:[e.jsx(ue,{})," Deliverability Scan"]})]})}),e.jsx(Ke,{open:ge,onOpenChange:L,children:e.jsxs(Re,{className:"sm:max-w-md",children:[e.jsxs(Pe,{children:[e.jsxs(Te,{children:["Verify ",x.toLocaleString()," contacts"]}),e.jsxs(Ee,{children:["Uses about ",x.toLocaleString()," credits. 1 credit = 1 email; duplicates and invalid addresses are removed free, so you may be charged less."]})]}),e.jsxs("div",{className:"rounded-lg border p-3 text-sm",children:["Your balance:"," ",e.jsx("span",{className:"font-semibold",children:d===null?"â¦":d.toLocaleString()})," ","credits",d!==null&&d<x&&e.jsxs("span",{className:"text-destructive",children:[" â ",(x-d).toLocaleString()," short"]})]}),e.jsx(Qe,{children:d!==null&&d>=x?e.jsxs(p,{onClick:()=>{L(!1),fe.mutate({markAsScanned:!1})},children:[e.jsx(ue,{})," Verify now"]}):e.jsx(p,{disabled:d===null,onClick:()=>{L(!1),X(!0)},children:"Buy credits"})})]})}),e.jsx(Fe,{open:be,onOpenChange:X,needed:d!==null?Math.max(0,x-d):void 0}),e.jsxs("div",{className:"rounded-lg border bg-card p-4 mb-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("div",{className:"text-sm font-medium",children:"Deliverability scan"}),e.jsxs(De,{label:"About deliverability buckets",children:[e.jsx("p",{className:"mb-1 font-medium text-foreground",children:"Verification buckets"}),e.jsxs("ul",{className:"space-y-1",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"Deliverable"})," â safe to send."]}),e.jsxs("li",{children:[e.jsx("strong",{children:"Accept-all"})," â the domain accepts every address, so it can't be verified. Risky for cold domains; fine for warm, engaged contacts."]}),e.jsxs("li",{children:[e.jsx("strong",{children:"Undeliverable"})," â the mailbox rejected verification. Don't send."]}),e.jsxs("li",{children:[e.jsx("strong",{children:"Unknown"})," â verification was inconclusive."]})]})]})]}),ve()]}),v&&e.jsxs("div",{className:"space-y-1",children:[e.jsx(Ce,{value:G}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:[t.progress.toLocaleStr
1ing()," / ",t.total.toLocaleString()," processed"]})]}),_&&W&&e.jsxs("div",{className:"space-y-3",children:[e.jsx("div",{className:"grid grid-cols-2 gap-3 sm:grid-cols-4",children:ye.map(a=>e.jsx(M,{label:R[a.key],value:a.value,tone:a.tone,note:a.note,active:m===a.key,onClick:()=>w(a.key)},a.key))}),e.jsxs("div",{className:"flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground",children:[e.jsxs("span",{className:"font-medium text-foreground",children:[pe.toLocaleString()," verified"]}),ee>0&&e.jsxs("button",{type:"button",onClick:()=>w("unscanned"),className:J("underline-offset-2 hover:text-foreground hover:underline",m==="unscanned"&&"font-medium text-foreground underline"),children:["· ",ee.toLocaleString()," not scanned"]}),Z>0&&e.jsxs("span",{children:["· ",Z.toLocaleString()," other"]}),B&&e.jsxs("span",{children:["· Scanned ",new Date(B).toLocaleString()]}),q!=null&&e.jsxs("span",{children:["· ",q.toLocaleString()," credits used"]}),l.sums_ok===!1&&e.jsx("span",{className:"text-destructive",children:"· counts don't reconcile â re-scan"})]})]}),_&&!W&&e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-3 max-w-md",children:[e.jsx(M,{label:R.legacy_deliverable,value:l.deliverable??0,tone:"good",active:m==="legacy_deliverable",onClick:()=>w("legacy_deliverable")}),e.jsx(M,{label:R.legacy_rejected,value:l.rejected??0,tone:"bad",active:m==="legacy_rejected",onClick:()=>w("legacy_rejected")})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground",children:[e.jsx("span",{children:"Accept-all and unknown breakdown appears after the next scan."}),B&&e.jsxs("span",{children:["· Scanned ",new Date(B).toLocaleString()]}),q!=null&&e.jsxs("span",{children:["· ",q.toLocaleString()," credits used"]})]})]})]}),y&&e.jsxs("div",{className:"mb-2 flex items-center gap-2 text-sm",children:[e.jsxs("span",{className:"text-muted-foreground",children:["Showing ",e.jsx("span",{className:"font-medium text-foreground",children:R[y]})," · ",D.toLocaleString()," ",D===1?"contact":"contacts"]}),e.jsxs(p,{variant:"ghost",size:"sm",className:"h-7 gap-1 px-2",onClick:()=>N(null),children:[e.jsx(we,{className:"size-3.5"})," Clear filter"]})]}),e.jsx("div",{className:"rounded-lg border bg-card",children:e.jsxs(Be,{children:[e.jsx(qe,{children:e.jsxs(O,{children:[e.jsx(S,{children:"Email"}),e.jsx(S,{children:"Name"}),e.jsx(S,{children:"Status"}),e.jsx(S,{children:"Deliverability"}),e.jsx(S,{children:"Added"})]})}),e.jsxs(Ae,{children:[Y.map(a=>e.jsxs(O,{children:[e.jsx(k,{className:"font-medium",children:a.email}),e.jsx(k,{className:"text-muted-foreground",children:a.name||"â"}),e.jsx(k,{children:e.jsx(g,{variant:"outline",children:a.status})}),e.jsx(k,{children:e.jsx($e,{deliverability:a.deliverability,result:a.bouncify_result,scanning:v})}),e.jsx(k,{className:"text-xs text-muted-foreground",children:new Date(a.added_at).toLocaleDateString()})]},a.id)),!Y.length&&!T.isLoading&&e.jsx(O,{children:e.jsx(k,{colSpan:5,className:"text-center text-muted-foreground py-8",children:y?"No contacts match this filter.":"No subscribers in this list."})})]})]})}),C>1&&e.jsxs("div",{className:"flex items-center justify-between mt-4 text-sm",children:[e.jsxs("div",{className:"text-muted-foreground",children:["Page ",i," of ",C," · ",D.toLocaleString()," subscribers"]}
1),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(p,{variant:"outline",size:"sm",disabled:i<=1,onClick:()=>u(a=>Math.max(1,a-1)),children:"Previous"}),e.jsx(p,{variant:"outline",size:"sm",disabled:i>=C,onClick:()=>u(a=>Math.min(C,a+1)),children:"Next"})]})]})]})};export{xs 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.