1import{ai as P,o as l,A as Q,al as O,a4 as L,am as K,U as y,a5 as U,j as n,C as b,G as p,$ as W,T as a,X as w,D as _,L as $,O as G,E as T,ap as E,ag as J,I as X,a7 as Y,F as Z,Z as V,W as ee}from"./index-dE8a1mPK.js";import{I as ne}from"./IconPlus-B47PY1MC.js";import{I as se}from"./IconFlame-BMTS6eFH.js";import{I as te}from"./IconUserOff-CVzBARaR.js";import{T as s}from"./Table-5ftamFSf.js";import{I as re}from"./IconTrash-DIXYcrq7.js";import{T as le}from"./Textarea-BtbUvWWM.js";import{S as ae}from"./Switch-Bm85N10X.js";import"./get-env-uyVen0u2.js";import"./InputsGroupFieldset-C0syow2C.js";function oe(o){return o?new Date(o).toLocaleDateString(void 0,{month:"short",day:"numeric",year:"numeric"}):"â"}const N={"opt-out":"red",manual:"gray",bounced:"orange",burn:"red"},ie={"opt-out":"Opt-out",manual:"Manual",bounced:"Bounced",burn:"Burn â account-killer"};function ye(){var z;const o=P(),[d,R]=l.useState(""),[M,u]=l.useState(!1),[i,k]=l.useState(""),[S,v]=l.useState(""),[C,q]=l.useState(!1),[c,A]=l.useState(null),{data:r,isLoading:F}=Q({queryKey:["blocklist"],queryFn:()=>y.listBlocklist()});function h(e){return[...new Set(String(e||"").split(/[\s,]+/).map(t=>t.replace(/^@/,"").trim().toLowerCase()).filter(Boolean))]}const B=O({mutationFn:async()=>{const e=h(i);if(!e.length)throw new Error("Paste at least one handle");const t=S.trim(),g=C?"burn":"manual",m=await Promise.allSettled(e.map(f=>y.addBlocklist({handle:f,note:t,reason:g}))),I=m.filter(f=>f.status==="fulfilled").length,H=m.length-I;return{added:I,failed:H,total:e.length}},onSuccess:({added:e,failed:t,total:g})=>{const m=t>0?`Added ${e} of ${g} â ${t} failed`:`Added ${e} ${e===1?"handle":"handles"} to blocklist`;K.show({color:t>0?"yellow":"green",message:m}),k(""),v(""),u(!1),o.invalidateQueries({queryKey:["blocklist"]})},onError:e=>L(e)}),x=O({mutationFn:e=>y.removeBlocklist(e),onSuccess:(e,t)=>{U(`@${t} removed`),o.invalidateQueries({queryKey:["blocklist"]})},onError:e=>L(e)}),j=((r==null?void 0:r.entries)||[]).filter(e=>c&&e.reason!==c?!1:d.trim()?e.handle.includes(d.toLowerCase().replace(/^@/,"")):!0),D=((r==null?void 0:r.entries)||[]).reduce((e,t)=>(e[t.reason]=(e[t.reason]||0)+1,e),{});return n.jsxs(b,{gap:"lg",children:[n.jsxs(p,{justify:"space-between",wrap:"wrap",children:[n.jsxs("div",{children:[n.jsx(W,{order:2,children:"Blocklist"}),n.jsx(a,{c:"dimmed",size:"sm",mt:2,children:"Handles here will never be DM'd by any campaign or co-pilot reply. Opt-outs are auto-detected from inbound DMs."})]}),n.jsx(w,{leftSection:n.jsx(ne,{size:14}),onClick:()=>u(!0),children:"Add handle"})]}),n.jsxs(_,{withBorder:!0,padding:"md",children:[n.jsxs(p,{justify:"space-between",mb:"sm",wrap:"wrap",gap:"xs",children:[n.jsx($,{placeholder:"Search handle",leftSection:n.jsx(G,{size:14}),value:d,onChange:e=>R(e.currentTarget.value),style:{flex:1,maxWidth:320}}),n.jsxs(p,{gap:4,wrap:"wrap",children:[n.jsxs(T,{variant:c?"light":"filled",color:"dark",style:{cursor:"pointer",textTransform:"none"},onClick:()=>A(null),children:["All · ",((z=r==null?void 0:r.entries)==null?void 0:z.length)||0]}),Object.entries(D).map(([e,t])=>n.jsxs(T,{variant:c===e?"filled":"light",color:N[e]||"gray",style:{cursor:"pointer",textTransform:"none"},onClick:()=>A(c===e?null:e),leftSection:e==="burn"?n.jsx(se,{size:10}):null,children:[ie[e]||e," · ",t]},e))]}),n.jsxs(a,{size:"sm",c:"dimmed",children:[j.length," shown"]})]}),F?n.jsx(E,{py:"xl",children:n.jsx(J,{size:32})}):j.length===0?n.jsx(E,{py:"xl",children:n.jsxs(b,{align:"center",gap:6,children:[n.jsx(te,{size:28,stroke:1.5,color:"var(--mantine-color-gray-6)"}),n.jsx(a,{c:"dimmed",children:d?"No matches.":"Your blocklist is empty."})]})}):n.jsxs(s,{children:[n.jsx(s.Thead,{children:n.jsxs(s.Tr,{children:[n.jsx(s.Th,{children:"Handle"}),n.jsx(s.Th,{children:"Reason"}),n.jsx(s.Th,{children:"Source"}),n.jsx(s.Th,{children:"Note"}),n.jsx(s.Th,{children:"Added"}),n.jsx(s.Th,{})]})}),n.jsx(s.Tbody,{children:j.map(e=>n.jsxs(s.Tr,{children:[n.jsx(s.Td,{children:n.jsxs(X,{component:Y,to:`/prospects/${e.handle}`,children:["@",e.handle]})}),n.jsx(s.Td,{children:n.jsx(T,{color:N[e.reason]||"gray",variant:"light",size:"sm",children:e.reason})}),n.jsx(s.Td,{children:n.jsx(a,{size:"sm",c:"dimmed",children:e.source})}),n.jsx(s.Td,{children:n.jsx(a,{size:"sm",c:"dimmed",lineClamp:2,title:e.note,children:e.note||"â"})}),n.jsx(s.Td,{children:oe(e.addedAt)}),n.jsx(s.Td,{children:n.jsx(Z,{variant:"subtle",color:"red",onClick:()=>x.mutate(e.handle),loading:x.isPending&&x.variables===e.handle,"aria-label":`Remove @${e.handle}`,children:n.jsx(re,{size:14})})})]},e.handle))})]})]}),n.jsx(V,{opened:M,onClose:()=>u(!1),title:"Add to blocklist",centered:!0,size:"md",children:n.jsxs(b,{children:[n.jsx(le,{label:"Handles",description:"One or many â commas, spaces, or newlines all work. Leading @ optional.",placeholder:`alice, bob, @carol 2dave`,value:i,onChange:e=>k(e.currentTarget.value),autosize:!0,minRows:3,maxRows:10,required:!0}),(()=>{const e=h(i);return e.length>0?n.jsxs(a,{size:"xs",c:"dimmed",children:[e.length," unique handle",e.length===1?"":"s"," ready: ",e.slice(0,8).map(t=>`@${t}`).join(", "),e.length>8?"â¦":""]}):null})(),n.jsx($,{label:"Note (applied to all)",placeholder:"Why are they blocked? (optional)",value:S,onChange:e=>v(e.currentTarget.value)}),n.jsx(ee,{multiline:!0,w:320,withArrow:!0,label:'Burn = "this handle has gotten an account banned before, never approach them from any account in my pool." Use when you know they reported / banned one of your accounts.',children:n.jsx(ae,{label:"Mark as burn (account-killer)",description:"Same effect as a regular block, but flagged distinctly so you can review burns separately.",checked:C,onChange:e=>q(e.currentTarget.checked),color:"red"})}),n.jsxs(p,{justify:"flex-end",children:[n.jsx(w,{variant:"default",onClick:()=>u(!1),children:"Cancel"}),n.jsxs(w,{onClick:()=>B.mutate(),disabled:!h(i).length,loading:B.isPending,children:["Add",(()=>{const e=h(i).length;return e>1?` (${e})`:""})()]})]})]})})]})}export{ye 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.