1import{o as l,al as k,a4 as T,U as u,a5 as I,j as e,X as m,Z as J,C as y,T as S,L as O,D as E,G as g,as as V,A as z,$ as W,E as ee,a0 as $,aa as K,F as te,ae}from"./index-dE8a1mPK.js";import{I as se}from"./IconFlask-Q5Q6JTza.js";import{T as ne}from"./Textarea-BtbUvWWM.js";import{A as re}from"./AccountPicker-M2R_QSt1.js";import{a as oe,c as F,f as ie}from"./draftStorage-BA_l97c0.js";import{u as ce}from"./useDraftAutosave-BRfAYMIp.js";import{I as le}from"./IconArrowLeft-cAVPTBNq.js";import{I as de}from"./IconDeviceFloppy-DgEyIcAH.js";import{S as L}from"./Select-DebRlW67.js";import{I as ue}from"./IconPlus-B47PY1MC.js";import{I as pe}from"./IconTrash-DIXYcrq7.js";import{N as me}from"./NumberInput-EbCp_odp.js";import{S as he}from"./Switch-Bm85N10X.js";import"./get-env-uyVen0u2.js";import"./Checkbox-CVTqs_Fd.js";import"./InputsGroupFieldset-C0syow2C.js";import"./CheckIcon-DkMc45y2.js";import"./OptionsDropdown-wonErrz5.js";function ge({accountId:x,templateId:s,sampleVars:i,disabled:p}){const[b,o]=l.useState(!1),[h,f]=l.useState(""),[v,d]=l.useState(""),C=k({mutationFn:()=>u.previewTemplate({templateId:s,vars:{handle:h.replace(/^@/,""),...i||{}}}),onSuccess:a=>d(a.text||""),onError:a=>T(a)}),r=k({mutationFn:()=>u.sendTestDm(x,{recipientHandle:h.replace(/^@/,"").trim(),text:v.trim()}),onSuccess:()=>{I("Test DM sent â check the recipient's inbox."),o(!1)},onError:a=>T(a)}),j=async()=>{if(o(!0),d(""),s){const a=await u.previewTemplate({templateId:s,vars:{handle:"tester",...i||{}}}).catch(()=>null);a!=null&&a.text&&d(a.text)}};return e.jsxs(e.Fragment,{children:[e.jsx(m,{variant:"default",leftSection:e.jsx(se,{size:14}),onClick:j,disabled:p,title:p?"Pick an account + template first":"Send one real DM to verify everything works",children:"Send test"}),e.jsx(J,{opened:b,onClose:()=>o(!1),title:"Send test DM",centered:!0,size:"md",children:e.jsxs(y,{children:[e.jsx(S,{size:"sm",c:"dimmed",children:"Sends one real DM via this account. A successful send means cookies + proxy + template + account caps all work â your campaign will dispatch fine. Use your own handle or a throwaway test account as the recipient."}),e.jsx(O,{label:"Recipient handle",description:"The DM lands in their inbox immediately.",placeholder:"yourhandle",value:h,onChange:a=>{f(a.currentTarget.value),s&&C.mutate()},required:!0}),e.jsx(ne,{label:"Message preview",description:s?"Rendered from the template with the recipient as {handle}. Edit before sending if you want.":"No template attached â type the test message directly.",value:v,onChange:a=>d(a.currentTarget.value),autosize:!0,minRows:3,maxRows:8,required:!0}),e.jsx(E,{withBorder:!0,padding:"xs",bg:"rgba(0,0,0,0.02)",children:e.jsx(S,{size:"xs",c:"dimmed",children:"Tip: send to your own handle so you can immediately confirm formatting on X."})}),e.jsxs(g,{justify:"flex-end",children:[e.jsx(m,{variant:"default",onClick:()=>o(!1),children:"Cancel"}),e.jsx(m,{onClick:()=>r.mutate(),loading:r.isPending,disabled:!x||!h.trim()||!v.trim(),children:"Send test"})]})]})})]})}const w="campaign:dm-outreach";function Pe(){var G,X;const x=V(),s=l.useMemo(()=>oe(w),[]),i=(s==null?void 0:s.value)||{},[p,b]=l.useState(i.name||""),[o,h]=l.useState(i.accountIds||[]),[f,v]=l.useState(i.accountGroup||""),[d,C]=l.useState(i.listId||null),[r,j]=l.useState(i.steps&&i.steps.length?i.steps:[{templateId:null,delayHours:0}]),[a,P]=l.useState(!!i.approvalMode);ce(w,{name:p,accountIds:o,accountGroup:f,listId:d,steps:r,approvalMode:a},{isEmpty:t=>!t.name.trim()&&!t.accountIds.length&&!t.listId&&t.steps.every(n=>!n.templateId)&&!t.approvalMode});const{data:M}=z({queryKey:["accounts"],queryFn:()=>u.listAccounts()}),{data:D}=z({queryKey:["lists"],queryFn:()=>u.listLists()}),{data:A}=z({queryKey:["templates","dm"],queryFn:()=>u.listTemplates("dm")}),q=()=>({listId:d,steps:r}),R=k({mutationFn:async()=>(await u.createCampaign({type:"dm-outreach",name:p,accountIds:o,accountGroup:f,approvalMode:a,config:q()})).id,onSuccess:()=>{I("Campaign saved as draft"),F(w),x("/campaigns")},onError:t=>T(t)}),N=k({mutationFn:async()=>{const t=await u.createCampaign({type:"dm-outreach",name:p,accountIds:o,accountGroup:f,approvalMode:a,config:q()}),n=await u.startCampaign(t.id);return{id:t.id,...n}},onSuccess:t=>{I(`Campaign started â ${t.scheduled||0} DMs queued`),F(w),x("/campaigns")},onError:t=>T(t)}),Q=r.length&&r.every(t=>t.templateId),B=p.trim()&&o.length&&d&&Q;function H(t,n){j(r.map((c,Z)=>Z===t?{...c,...n}:c))}function U(){j([...r,{templateId:null,delayHours:48}])}function _(t){r.length!==1&&j(r.filter((n,c)=>c!==t))}const Y=((M==null?void 0:M.accounts)||[]).filter(t=>t.status==="active");return e.jsxs(y,{gap:"md",children:[e.jsxs(g,{children:[e.jsx(m,{variant:"subtle",leftSection:e.jsx(le,{size:14}),onClick:()=>
1x("/campaigns"),children:"Back"}),e.jsx(W,{order:2,children:"New DM Outreach campaign"}),(s==null?void 0:s.ts)&&e.jsxs(ee,{color:"blue",variant:"light",leftSection:e.jsx(de,{size:12}),children:["Resumed from ",ie(s.ts)]})]}),e.jsx(E,{withBorder:!0,p:"lg",children:e.jsxs(y,{gap:"md",children:[e.jsx(O,{label:"Campaign name",placeholder:"Q1 Shopify outreach",value:p,onChange:t=>b(t.currentTarget.value)}),e.jsx(re,{label:"Accounts to send from",description:"Multi-account campaigns rotate sends round-robin and respect each account's caps. Pick a group to grab every account in it at once.",value:o,group:f,onGroupChange:v,onChange:h,mode:"multi"}),Y.length===0&&e.jsx($,{color:"yellow",icon:e.jsx(K,{size:16}),children:"No active X accounts. Connect one by signing into x.com with the extension installed."}),e.jsx(L,{label:"Prospect list",placeholder:"Pick a list",value:d,onChange:C,data:((D==null?void 0:D.lists)||[]).map(t=>({value:t.id,label:`${t.name} (${t.handleCount||0})`})),searchable:!0,clearable:!0}),e.jsxs(y,{gap:"xs",children:[e.jsxs(g,{justify:"space-between",children:[e.jsxs(y,{gap:2,children:[e.jsx(S,{fw:600,size:"sm",children:"DM sequence"}),e.jsx(S,{size:"xs",c:"dimmed",children:"Step 1 sends immediately. Follow-ups send after the delay if the prospect hasn't replied."})]}),e.jsx(m,{size:"xs",variant:"light",leftSection:e.jsx(ue,{size:14}),onClick:U,children:"Add follow-up"})]}),r.map((t,n)=>e.jsx(E,{withBorder:!0,p:"sm",children:e.jsxs(y,{gap:"xs",children:[e.jsxs(g,{justify:"space-between",children:[e.jsx(S,{size:"sm",fw:600,children:n===0?"Step 1 â initial":`Step ${n+1} â follow-up`}),n>0&&e.jsx(te,{variant:"subtle",color:"red",onClick:()=>_(n),children:e.jsx(pe,{size:14})})]}),e.jsxs(g,{grow:!0,align:"flex-start",children:[e.jsx(L,{label:"Template",placeholder:"Pick a template",value:t.templateId,onChange:c=>H(n,{templateId:c}),data:((A==null?void 0:A.templates)||[]).map(c=>({value:c.id,label:c.name})),searchable:!0,clearable:!0}),n>0&&e.jsx(me,{label:"Delay (hours)",description:"From the previous step",value:t.delayHours,onChange:c=>H(n,{delayHours:Number(c)||0}),min:0,max:720})]})]})},n))]}),e.jsx(he,{label:"Approval mode",description:"Off (default): DMs send as soon as they're due. On: each DM waits for manual approval in History.",checked:a,onChange:t=>P(t.currentTarget.checked)}),e.jsx($,{color:"orange",icon:e.jsx(K,{size:16}),variant:"light",children:"Mass DMs on X carry account-suspension risk. The pacing engine spaces sends, respects per-account daily caps and working hours, and randomizes timing â but you assume responsibility for compliance with X's automation policies."}),e.jsxs(g,{justify:"space-between",wrap:"wrap",gap:"xs",children:[e.jsx(ge,{accountId:o[0]||null,templateId:((G=r[0])==null?void 0:G.templateId)||null,disabled:!o.length||!((X=r[0])!=null&&X.templateId)}),e.jsxs(g,{gap:"xs",children:[(s==null?void 0:s.ts)&&e.jsx(m,{variant:"subtle",color:"gray",onClick:()=>{F(w),b(""),h([]),C(null),j([{templateId:null,delayHours:0}]),P(!1),I("Draft discarded")},children:"Discard draft"}),e.jsx(m,{variant:"default",onClick:()=>R.mutate(),disabled:!B,loading:R.isPending,children:"Save as draft"}),e.jsx(m,{leftSection:e.jsx(ae,{size:16}),onClick:()=>N.mutate(),disabled:!B,loading:N.isPending,children:"Create & start"})]})]})]})})]})}export{Pe 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.