PageSourceSearch

https://founder-spark-63.lovable.app/assets/Newsletter-DhEae52p.js

js founder-spark-63.lovable.app collected 2026-10-03 03:32:01 UTC 59,225 bytes, 42 lines download raw bytes

1import{b as B,u as P,c as E,j as e}from"./query-_koPiPsI.js";import{r as x,L as hs,f as ps}from"./react-vendor-h1rQ_Bae.js";import{c as fs,C as S,n as ve,H as gs,k as $,G as Ne,B as g,L as I,s as y,g as c,a7 as js,S as Ye,aN as bs,M as Ve,ai as ws,O as W,I as U,y as ys,N as vs,w as Ns,T as _s,a as Ss,b as Oe,V as ge,Z as qs,d as Ue,F as Ie,J as Cs,D as je,h as be,i as we,j as ye,x as Ke,o as ze,p as Qe,q as Re,ah as ks,av as We}from"./index-Dq2zLArw.js";import{T as Je}from"./TiptapEditor-y1HQpIhc.js";import{S as Es}from"./shield-alert-BIB5GtN7.js";import{S as re}from"./switch-CyEfQhNS.js";import{S as Fs,a as Ts,b as As,c as Ps,d as Be}from"./select-S0HS5dUY.js";import{A as _e,a as Se,b as qe,c as Ce,d as ke,e as Ee,f as Fe,g as Te}from"./alert-dialog-DEwTsyDm.js";import{L as Ds}from"./lock-CB21B3PI.js";import{P as Ae}from"./plus-BKP-C_hU.js";import{U as Ze}from"./users-B5SvTFTu.js";import{T as Pe}from"./trash-2-DwNrObEE.js";import{G as $s}from"./grip-vertical-s3_ZjWHt.js";import{C as Ls}from"./chevron-up-Dbq7Df3-.js";import{E as Ms}from"./eye-DeaWVGHm.js";import{S as Os}from"./save-bi9ogCha.js";import"./ui-radix-CKwvnS8F.js";import"./supabase-DL6nu9mS.js";import"./charts-Xu79y1bN.js";import"./motion-nVmI7L5T.js";import"./index-CnMJwqSh.js";import"./image-B61r9cSd.js";import"./link-CKRegxtG.js";import"./square-check-big-Bl-6BMjG.js";import"./quote-Cc7kmDa5.js";import"./minus-PALHGxhy.js";import"./mouse-pointer-click-B3fjeOvo.js";/**
2 * @license lucide-react v0.462.0 - ISC
3 *
4 * This source code is licensed under the ISC license.
5 * See the LICENSE file in the root directory of this source tree.
6 */const Us=fs("Library",[["path",{d:"m16 6 4 14",key:"ji33uf"}],["path",{d:"M12 6v14",key:"1n7gus"}],["path",{d:"M8 8v12",key:"1gg7y9"}],["path",{d:"M4 4v16",key:"6qkkli"}]]);function te(r){return`${(r*100).toFixed(2)}%`}function He(r,n,t){return r>=t?"text-red-600":r>=n?"text-amber-600":"text-emerald-600"}function Is(){const r=B(),{data:n,isLoading:t}=P({queryKey:["newsletter-sender-health"],queryFn:async()=>{const{data:j,error:b}=await y.rpc("get_my_newsletter_health");if(b)throw b;return j},refetchInterval:6e4}),o=E({mutationFn:async()=>{const{data:j,error:b}=await y.rpc("request_newsletter_unpause");if(b)throw b;return j},onSuccess:j=>{j?.success&&j.unpaused?(c.success("Sending resumed. Bounce/spam rates are back under threshold."),r.invalidateQueries({queryKey:["newsletter-sender-health"]})):j?.error==="rates_still_above_threshold"?c.error(`Still above threshold — bounce ${te(j.bounce_rate??0)}, spam ${te(j.complaint_rate??0)}. Wait for the 7-day window to roll off or clean your list.`):c.error("Could not unpause.")},onError:j=>{c.error(j?.message??"Failed to request unpause")}});if(t||!n||n.error)return null;const d=!!n.paused_at,p=n.quota_cap>0?n.quota_today/n.quota_cap*100:0;return e.jsx(S,{className:"border-border",children:e.jsxs(ve,{className:"p-4",children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[d?e.jsx(Es,{className:"h-4 w-4 text-red-600"}):e.jsx(gs,{className:"h-4 w-4 text-emerald-600"}),e.jsx("span",{className:"text-sm font-semibold",children:"Sender health"})]}),d?e.jsx($,{variant:"destructive",className:"text-xs",children:"Paused"}):e.jsx($,{variant:"outline",className:"text-xs border-emerald-600/40 text-emerald-700",children:"Active"})]}),d&&e.jsxs("div",{className:"mb-3 rounded-md border border-red-200 bg-red-50 p-3 text-xs text-red-800",children:[e.jsxs("div",{className:"flex items-start gap-2 mb-2",children:[e.jsx(Ne,{className:"h-3.5 w-3.5 mt-0.5 shrink-0"}),e.jsx("span",{children:n.pause_reason??"Sender paused to protect deliverability."})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(g,{size:"sm",variant:"outline",className:"h-7 text-xs",onClick:()=>o.mutate(),disabled:o.isPending,children:[o.isPending?e.jsx(I,{className:"h-3 w-3 mr-1 animate-spin"}):null,"Request unpause"]}),e.jsx("span",{className:"text-[11px] text-red-700/70",children:"Only succeeds if rates are back under threshold."})]})]}),e.jsxs("div",{className:"grid grid-cols-3 gap-3 text-xs",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-muted-foreground",children:"Today"}),e.jsxs("div",{className:"font-semibold",children:[n.quota_today,e.jsxs("span",{className:"text-muted-foreground",children:[" / ",n.quota_cap]})]}),e.jsx("div",{className:"mt-1 h-1 w-full rounded bg-muted overflow-hidden",children:e.jsx("div",{className:"h-full bg-foreground",style:{width:`${Math.min(100,p)}%`}})})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-muted-foreground",children:"Bounce rate (7d)"}),e.jsx("div",{className:`font-semibold ${He(n.bounce_rate,.02,.05)}`,children:te(n.bounce_rate)}),e.jsxs("div",{className:"text-[10px] text-muted-foreground",children:[n.bounces_count," / ",n.sends_count]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-muted-foreground",children:"Spam rate (7d)"}),e.jsx("div",{className:`font-semibold ${He(n.complaint_rate,.001,.003)}`,children:te(n.complaint_rate)}),e.jsxs("div",{className:"text-[10px] text-muted-foreground",children:[n.complaints_count," / ",n.sends_count]})]})]})]})})}function Ks(){const{data:r,isLoading:n}=P({queryKey:["newsletter-campaigns"],queryFn:async()=>{const{data:t,error:o}=await y.rpc("get_my_newsletter_campaigns",{p_limit:20});if(o)throw o;return t||[]},refetchInterval:6e4});return e.jsxs(S,{className:"p-6",children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsx("h2",{className:"text-xl font-bold",children:"Campaign performance"}),e.jsx("span",{className:"text-xs text-muted-foreground",children:"Per-send delivery breakdown"})]}),n?e.jsxs("div",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:[e.jsx(I,{className:"w-3.5 h-3.5 animate-spin"}
6)," Loading campaigns…"]}):!r||r.length===0?e.jsx("p",{className:"text-sm text-muted-foreground",children:"No campaigns yet. Once you send your first newsletter, delivery stats per send will show up here."}):e.jsx("div",{className:"space-y-2 max-h-[420px] overflow-y-auto",children:r.map(t=>{const o=Math.max(t.recipients-t.delivered-t.bounced-t.complained,0),d=t.recipients>0?Math.round(t.bounced/t.recipients*1e3)/10:0;return e.jsxs("div",{className:"p-3 rounded-lg border",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3 mb-2",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"font-medium truncate",children:t.subject||"(no subject)"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:new Date(t.sent_at).toLocaleString()})]}),e.jsxs($,{variant:"secondary",className:"shrink-0 text-xs",children:[t.recipients," sent"]})]}),e.jsxs("div",{className:"flex flex-wrap gap-1.5 text-xs",children:[e.jsxs("span",{className:"px-2 py-0.5 rounded-full bg-green-500/10 text-green-700 dark:text-green-400",children:[t.delivered," delivered"]}),t.bounced>0&&e.jsxs("span",{className:"px-2 py-0.5 rounded-full bg-destructive/10 text-destructive",children:[t.bounced," bounced (",d,"%)"]}),t.complained>0&&e.jsxs("span",{className:"px-2 py-0.5 rounded-full bg-amber-500/10 text-amber-700 dark:text-amber-400",children:[t.complained," spam reports"]}),o>0&&e.jsxs("span",{className:"px-2 py-0.5 rounded-full bg-muted text-muted-foreground",children:[o," pending events"]})]})]},t.campaign_id)})})]})}const _=y,Ge=[{name:"The Answer Drift Wake-Up",description:"Wake subscribers up to what AI models actually say about their space.",steps:[{subject:"What does AI think you are?",content:`<p>Most founders have never asked ChatGPT what it says about them. Try this prompt today: <em>"Who is {your name}, founder of {your company}?"</em></p><p>The answer is almost never what you'd expect. That gap is your competitive advantage — if you close it before your competitors do.</p>`,send_after_value:1,send_after_unit:"days"},{subject:"3 signals AI models use to identify you",content:"<p>Schema markup. Consistent bios across owned surfaces. Interlinked pillar articles. That's the entity graph.</p><p>Missing any one of them and models blend you with someone else who shares your name or niche.</p>",send_after_value:3,send_after_unit:"days"},{subject:"How to fix it in one afternoon",content:"<p>Publish one pillar article. Interlink it from your homepage. Add Person JSON-LD. Done.</p><p>ThoughtForge does the pillar + schema for you in one publish.</p>",send_after_value:7,send_after_unit:"days"}]},{name:"The GEO Score Reveal",description:"Teach subscribers what GEO is and why their score matters.",steps:[{subject:"Score your homepage in 60 seconds",content:"<p>GEO (Generative Engine Optimization) scores how well AI models can extract, cite, and reason with your content.</p><p>Most sites score under 40/100. Yours probably does too — and that's fixable.</p>",send_after_value:1,send_after_unit:"days"},{subject:"The 5 things models look for",content:"<p>Clear H1s, definitional first sentences, structured lists, FAQ blocks, and inline citations. Miss one and your score drops 15 points.</p>",send_after_value:3,send_after_unit:"days"},{subject:"From 32 to 87 in two weeks",content:"<p>A founder we work with went from a 32 GEO score to 87 by rewriting 4 pages using ThoughtForge's checklist. Their Perplexity citations 3x'd.</p>",send_after_value:7,send_after_unit:"days"}]},{name:"The AEO Verdict",description:"Show subscribers exactly how AI answers questions their buyers ask.",steps:[{subject:"3 questions your buyers ask AI",content:`<p>Right now, your future customers are asking ChatGPT things like "What's the best X for Y?" — and getting an answer that names someone else.</p><p>What are those 3 questions in your niche?</p>`,send_after_value:1,send_after_unit:"days"},{subject:"How to become the default answer",content:"<p>Write the definitive article for each question. Structure it so models can extract the answer in one paragraph. Add FAQs. Interlink.</p>",send_after_value:3,send_after_unit:"days"},{subject:"The compounding effect",content:"<p>Once you're the default answer, you compound. Every new person asking gets you first. That's the moat.</p>",send_after_value:7,send_after_unit:"days"}]},{name:"The Citation Compounder",description:"Explain why AI citations compound and how to earn them.",steps:[{subject:"One article, 6 months of citations",content:"<p>A well-structured article keeps getting cited by ChatGPT, Perplexity, and Claude — long after you publish. Traffic never showed up on Google, but citations kept coming.</p>",send_after_value:1,send_after_unit:"days"},{subject:"What makes an article citable",content:'<p>Specificity. Data. Named entities. Clear definitions. The stuff SEO writers strip out to "read easier."</p>',send_after_value:3,send_after_unit:"days"},{subject:"Your citation flywheel",content:"<p>Publish → get cited → cited-in-answer drives visits → visits drive more content → more citations. ThoughtForge automates the top of the loop.</p>",send_after_value:7,send_after_unit:"days"}]},{name:"The Case Study Drop",description:"Prove the moat with a real founder story and s
6oft CTA.",steps:[{subject:"0 → 47 AI citations in 60 days",content:"<p>Meet a founder who went from zero AI citations to 47 in two months. No SEO team. No paid ads. Just ThoughtForge + a weekly publishing cadence.</p>",send_after_value:1,send_after_unit:"days"},{subject:"Their exact playbook",content:"<p>Week 1: audit + pillar 1. Week 2: pillar 2 + interlinking. Week 3: FAQ + schema. Week 4: distribute. Repeat.</p>",send_after_value:3,send_after_unit:"days"},{subject:"Try it free for 7 days",content:"<p>Get the same setup for your site. 7-day trial, no card up front.</p>",send_after_value:7,send_after_unit:"days"}]}],R=2;function zs(){const r=B(),{tier:n}=js(),t=bs(n),[o,d]=x.useState(null),[p,j]=x.useState(null),{data:b,isLoading:q}=P({queryKey:["newsletter-sequences"],queryFn:async()=>{const{data:{user:i}}=await y.auth.getUser();if(!i)return[];const{data:k,error:v}=await _.from("newsletter_sequences").select("*").eq("author_id",i.id).order("created_at",{ascending:!1});if(v)throw v;return k}}),u=!t&&(b?.length??0)>=R,f=E({mutationFn:async()=>{const{data:{user:i}}=await y.auth.getUser();if(!i)throw new Error("Not authenticated");if(!t&&(b?.length??0)>=R)throw new Error(`Forge is capped at ${R} sequences. Upgrade to Forge Pro for unlimited.`);const{data:k,error:v}=await _.from("newsletter_sequences").insert({author_id:i.id,name:"Untitled sequence",trigger_type:"new_subscriber",is_active:!1,auto_enroll:!0}).select().single();if(v)throw v;return k},onSuccess:i=>{r.invalidateQueries({queryKey:["newsletter-sequences"]}),d(i.id)},onError:i=>c.error(i.message)}),w=E({mutationFn:async i=>{const{data:{user:k}}=await y.auth.getUser();if(!k)throw new Error("Not authenticated");if(!t&&(b?.length??0)>=R)throw new Error(`Forge is capped at ${R} sequences. Upgrade to Forge Pro for unlimited.`);const{data:v,error:L}=await _.from("newsletter_sequences").insert({author_id:k.id,name:i.name,description:i.description,trigger_type:"new_subscriber",is_active:!1,auto_enroll:!0}).select().single();if(L)throw L;const A=i.steps.map((h,N)=>({...h,sequence_id:v.id,position:N})),{error:l}=await _.from("newsletter_sequence_steps").insert(A);if(l)throw l;return v},onSuccess:i=>{r.invalidateQueries({queryKey:["newsletter-sequences"]}),d(i.id),c.success("Starter sequence added. Edit and activate when ready.")},onError:i=>c.error(i.message)}),C=E({mutationFn:async({id:i,next:k})=>{const{error:v}=await _.from("newsletter_sequences").update({is_active:k}).eq("id",i);if(v)throw v},onSuccess:()=>r.invalidateQueries({queryKey:["newsletter-sequences"]}),onError:i=>c.error(i.message)}),F=E({mutationFn:async i=>{const{error:k}=await _.from("newsletter_sequences").delete().eq("id",i);if(k)throw k},onSuccess:()=>{r.invalidateQueries({queryKey:["newsletter-sequences"]}),c.success("Sequence deleted"),j(null)},onError:i=>c.error(i.message)});return o?e.jsx(Rs,{id:o,onBack:()=>d(null)}):e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4 flex-wrap",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-2xl font-bold",children:"Sequences"}),e.jsx("p",{className:"text-sm text-muted-foreground mt-1 max-w-xl",children:"Set up drip campaigns that automatically send to new subscribers. Prepare valuable content in advance — every new signup gets the sequence you built."}),!t&&e.jsxs("p",{className:"text-xs text-muted-foreground mt-2",children:["Forge: ",b?.length??0,"/",R," sequences used ·"," ",e.jsx(hs,{to:"/pricing",className:"text-primary hover:underline",children:"Upgrade to Forge Pro for unlimited"})]})]}),e.jsxs(g,{onClick:()=>f.mutate(),disabled:f.isPending||u,title:u?"Upgrade to Forge Pro for unlimited sequences":void 0,children:[u?e.jsx(Ds,{className:"w-4 h-4 mr-2"}):e.jsx(Ae,{className:"w-4 h-4 mr-2"}),"New sequence"]})]}),q?e.jsxs("div",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:[e.jsx(I,{className:"w-4 h-4 animate-spin"})," Loading…"]}):(b||[]).length===0?e.jsxs(e.Fragment,{children:[e.jsxs(S,{className:"p-8 text-center border-dashed",children:[e.jsx(Ye,{className:"w-8 h-8 mx-auto mb-3 text-primary"}),e.jsx("h3",{className:"font-medium mb-1",children:"No sequences yet"}),e.jsx("p",{className:"text-sm text-muted-foreground mb-4",children:"Start from a founder-moat template below, or build your own."}),e.jsxs(g,{onClick:()=>f.mutate(),disabled:f.isPending,children:[e.jsx(Ae,{className:"w-4 h-4 mr-2"})," Build from scratch"]})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-semibold uppercase tracking-wide text-muted-foreground mb-3",children:"Founder-moat starter templates"}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-3",children:Ge.map(i=>e.jsxs(S,{className:"p-4 hover:border-primary/50 transition",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3 mb-2",children:[e.jsx("h4",{className:"font-medium",children:i.name}),e.jsxs($,{variant:"secondary",className:"shrink-0 text-xs",children:[i.steps.length," emails"]})]}),e.jsx("p",{className:"text-sm text-muted-foreground mb-3",children:i.description}),e.jsx(g,{size:"sm",variant:"outline",onClick:()=>w.mutate(i),disabled:w.isPending,children:"Use this template"})]},i.name))})]})]}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-3",children:b.map(i=>e.jsx(Qs,{seq:i,onEdit:()=>d(i.id),onToggle:k=>C.mutate({id:i.id,next:k}),onDelete:()=>j(i.id)},i.id))}),e.jsxs("details",{className:"mt-6",children:[e.jsx("summary",{className:"text-sm font-medium cursor-pointer text-muted-foreground hover:text-foreground",children:"+ Add another starter template"}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-3 mt-3",children:Ge.map(i=>e.jsxs(S,{className:"p-4",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3 mb-2",children:[e.jsx("h4",{className:"font-medium text-sm",children:i.name}),e.jsx($,{variant:"secondary",className:"shrink-0 text-xs",children:i.steps.length})]}),e.jsx("p",{className:"text-xs text-muted-foreground mb-3",children:i.description}),e.jsx(g,{size:"sm",variant:"outline",onClick:()=>w.mutate(i),disabled:w.isPending,children:"Add"})]},i.name))})]})]}),e.jsx(_e,{open:!!p,onOpenChange:i=>!i&&j(null),children:e.jsxs(Se,{children:[e.jsxs(qe,{children:[e.jsx(Ce,{children:"Delete this sequence?"}),e.jsx(ke,{children:"Enrollments and send history for this sequence will also be removed. Existing subscribers stay on your list."})]}),e.jsxs(Ee,{children:[e.jsx(Fe,{children:"Cancel"}),e.jsx(Te,{onClick:()=>p&&F.mutate(p),children:"Delete"})]})]})})]})}function Qs({seq:r,onEdit:n,onToggle:t,onDelete:o}){const{data:d}=P({queryKey:["seq-counts",r.id],queryFn:async()=>{const[{count:p},{count:j}]=await Promise.all([_.from("newsletter_sequence_steps").select("id",{count:"exact",head:!0}).eq("sequence_id",r.id),_.from("newsletter_sequence_enrollments").select("id",{count:"exact",head:!0}).eq("sequence_id",r.id).eq("status","active")]);return{steps:p||0,active:j||0}}});return e.jsxs(S,{className:"p-4",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3 mb-3",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("button",{onClick:n,className:"text-left w-full",children:e.jsx("h3",{className:"font-medium truncate hover:text-primary transition",children:r.name})}),r.description&&e.jsx("p",{className:"text-xs text-muted-foreground line-clamp-2 mt-1",children:r.description})]}),e.jsx("div",{className:"flex items-center gap-1 shrink-0",children:e.jsx(re,{checked:r.is_active,onCheckedChange:t})})]}),e.jsxs("div",{className:"flex items-center gap-2 flex-wrap text-xs",children:[e.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-muted",children:[e.jsx(Ve,{className:"w-3 h-3"})," ",d?.steps??0," steps"]}),e.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-muted",children:[e.jsx(Ze,{className:"w-3 h-3"})," ",d?.active??0," enrolled"]}),r.is_active?e.jsx($,{className:"text-xs",children:"Active"}):e.jsx($,{variant:"secondary",className:"text-xs",children:"Draft"})]}),e.jsxs("div",{className:"flex items-center gap-2 mt-3",children:[e.jsx(g,{size:"sm",variant:"outline",onClick:n,children:"Edit"}),e.jsx(g,{size:"sm",variant:"ghost",onClick:o,className:"text-destructive hover:text-destructive",children:e.jsx(Pe,{className:"w-4 h-4"})})]})]})}function Rs({id:r,onBack:n}){const t=B(),{data:o,isLoading:d}=P({queryKey:["seq",r],queryFn:async()=>{const{data:l,error:h}=await _.from("newsletter_sequences").select("*").eq("id",r).single();if(h)throw h;return l}}),{data:p,isLoading:j}=P({queryKey:["seq-steps",r],queryFn:async()=>{const{data:l,error:h}=await _.from("newsletter_sequence_steps").select("*").eq("sequence_id",r).order("position");if(h)throw h;return l}}),{data:b}=P({queryKey:["seq-enroll",r],queryFn:async()=>{const{data:l,error:h}=await _.from("newsletter_sequence_enrollments").select("id, subscriber_id, status, current_step").eq("sequence_id",r);
6if(h)throw h;return l}}),[q,u]=x.useState(""),[f,w]=x.useState(""),[C,F]=x.useState(!0);x.useState(()=>{}),o&&q===""&&o.name!==""&&(u(o.name),w(o.description||""),F(o.auto_enroll));const i=E({mutationFn:async()=>{const{error:l}=await _.from("newsletter_sequences").update({name:q.trim()||"Untitled sequence",description:f.trim()||null,auto_enroll:C}).eq("id",r);if(l)throw l},onSuccess:()=>{t.invalidateQueries({queryKey:["seq",r]}),t.invalidateQueries({queryKey:["newsletter-sequences"]}),c.success("Saved")},onError:l=>c.error(l.message)}),k=E({mutationFn:async l=>{if(l&&(!p||p.length===0))throw new Error("Add at least one step before activating");const{error:h}=await _.from("newsletter_sequences").update({is_active:l}).eq("id",r);if(h)throw h},onSuccess:()=>t.invalidateQueries({queryKey:["seq",r]}),onError:l=>c.error(l.message)}),v=E({mutationFn:async()=>{const l=(p||[]).length,{error:h}=await _.from("newsletter_sequence_steps").insert({sequence_id:r,position:l,subject:"New email subject",content:"<p>Write your email here.</p>",send_after_value:l===0?1:2,send_after_unit:"days"});if(h)throw h},onSuccess:()=>t.invalidateQueries({queryKey:["seq-steps",r]}),onError:l=>c.error(l.message)}),L=E({mutationFn:async l=>{const{error:h}=await _.from("newsletter_sequence_steps").delete().eq("id",l);if(h)throw h},onSuccess:()=>t.invalidateQueries({queryKey:["seq-steps",r]}),onError:l=>c.error(l.message)}),A=E({mutationFn:async({a:l,b:h})=>{const N=999e3+l.position,H=await _.from("newsletter_sequence_steps").update({position:N}).eq("id",l.id);if(H.error)throw H.error;const Z=await _.from("newsletter_sequence_steps").update({position:l.position}).eq("id",h.id);if(Z.error)throw Z.error;const M=await _.from("newsletter_sequence_steps").update({position:h.position}).eq("id",l.id);if(M.error)throw M.error},onSuccess:()=>t.invalidateQueries({queryKey:["seq-steps",r]}),onError:l=>c.error(l.message)});return d||!o?e.jsxs("div",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:[e.jsx(I,{className:"w-4 h-4 animate-spin"})," Loading…"]}):e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3 flex-wrap",children:[e.jsxs(g,{variant:"ghost",size:"sm",onClick:n,children:[e.jsx(ws,{className:"w-4 h-4 mr-1"})," Back to sequences"]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"text-sm text-muted-foreground",children:o.is_active?"Active":"Draft"}),e.jsx(re,{checked:o.is_active,onCheckedChange:l=>k.mutate(l)})]})]}),e.jsxs(S,{className:"p-5 space-y-4",children:[e.jsxs("div",{children:[e.jsx(W,{htmlFor:"seq-name",children:"Sequence name"}),e.jsx(U,{id:"seq-name",value:q,onChange:l=>u(l.target.value),className:"mt-1.5"})]}),e.jsxs("div",{children:[e.jsx(W,{htmlFor:"seq-desc",children:"Description (optional)"}),e.jsx(ys,{id:"seq-desc",value:f,onChange:l=>w(l.target.value),rows:2,className:"mt-1.5",placeholder:"What is this sequence about?"})]}),e.jsxs("div",{className:"flex items-start justify-between gap-3 pt-2 border-t",children:[e.jsxs("div",{children:[e.jsx(W,{children:"Auto-enroll new subscribers"}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1 max-w-lg",children:"Every new subscriber automatically joins this sequence starting from step 1. Turn off to enroll subscribers manually from the Enrolled panel below."})]}),e.jsx(re,{checked:C,onCheckedChange:F})]}),e.jsx("div",{className:"flex justify-end",children:e.jsx(g,{size:"sm",onClick:()=>i.mutate(),disabled:i.isPending,children:"Save changes"})})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsx("h3",{className:"text-lg font-semibold",children:"Emails in this sequence"}),e.jsxs(g,{size:"sm",variant:"outline",onClick:()=>v.mutate(),disabled:v.isPending,children:[e.jsx(Ae,{className:"w-4 h-4 mr-1"})," Add email"]})]}),j?e.jsxs("div",{className:"text-sm text-muted-foreground",children:[e.jsx(I,{className:"w-4 h-4 animate-spin inline mr-1"})," Loading…"]}):(p||[]).length===0?e.jsx(S,{className:"p-6 border-dashed text-center text-sm text-muted-foreground",children:'No emails yet. Click "Add email" above to start building your sequence.'}):e.jsx("div",{className:"space-y-3",children:p.map((l,h)=>e.jsx(Ws,{step:l,index:h,total:p.length,onDelete:()=>L.mutate(l.id),onMoveUp:()=>h>0&&A.mutate({a:l,b:p[h-1]}),onMoveDown:()=>h<p.length-1&&A.mutate({a:l,b:p[h+1]})},l.id))})]}),e.jsx(Bs,{sequenceId:r,enrolled:b||[]})]})}function Ws({step:r,index:n,total:t,onDelete:o,onMoveUp:d,onMoveDown:p}
6){const j=B(),[b,q]=x.useState(r.subject),[u,f]=x.useState(r.content),[w,C]=x.useState(r.send_after_value),[F,i]=x.useState(r.send_after_unit),[k,v]=x.useState(!1),[L,A]=x.useState(!1),l=E({mutationFn:async()=>{const{error:N}=await _.from("newsletter_sequence_steps").update({subject:b.trim()||"(no subject)",content:u,send_after_value:Math.max(1,Number(w)||1),send_after_unit:F}).eq("id",r.id);if(N)throw N},onSuccess:()=>{j.invalidateQueries({queryKey:["seq-steps",r.sequence_id]}),A(!1),c.success(`Email ${n+1} saved`)},onError:N=>c.error(N.message)}),h=n===0?`Sends ${w} ${F} after signup`:`Sends ${w} ${F} after previous email`;return e.jsx(S,{className:"p-4",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsxs("div",{className:"flex flex-col items-center pt-1 gap-1",children:[e.jsx($s,{className:"w-4 h-4 text-muted-foreground"}),e.jsxs("span",{className:"text-xs font-mono text-muted-foreground",children:["#",n+1]})]}),e.jsxs("div",{className:"flex-1 min-w-0 space-y-3",children:[e.jsxs("div",{className:"flex items-start justify-between gap-2",children:[e.jsxs("button",{className:"text-left flex-1 min-w-0",onClick:()=>v(N=>!N),children:[e.jsx("div",{className:"font-medium truncate",children:b||"(no subject)"}),e.jsxs("div",{className:"text-xs text-muted-foreground flex items-center gap-1 mt-0.5",children:[e.jsx(vs,{className:"w-3 h-3"})," ",h]})]}),e.jsxs("div",{className:"flex items-center gap-1 shrink-0",children:[e.jsx(g,{size:"icon",variant:"ghost",onClick:d,disabled:n===0,children:e.jsx(Ls,{className:"w-4 h-4"})}),e.jsx(g,{size:"icon",variant:"ghost",onClick:p,disabled:n===t-1,children:e.jsx(Ns,{className:"w-4 h-4"})}),e.jsx(g,{size:"icon",variant:"ghost",onClick:o,className:"text-destructive hover:text-destructive",children:e.jsx(Pe,{className:"w-4 h-4"})})]})]}),k&&e.jsxs("div",{className:"space-y-3 pt-2 border-t",children:[e.jsxs("div",{children:[e.jsx(W,{className:"text-xs",children:"Subject"}),e.jsx(U,{value:b,onChange:N=>{q(N.target.value),A(!0)},className:"mt-1"})]}),e.jsxs("div",{children:[e.jsx(W,{className:"text-xs",children:"Body"}),e.jsx("div",{className:"mt-1",children:e.jsx(Je,{content:u,onChange:N=>{f(N),A(!0)}})})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(W,{className:"text-xs shrink-0",children:"Send after"}),e.jsx(U,{type:"number",min:1,value:w,onChange:N=>{C(Number(N.target.value)),A(!0)},className:"w-24 h-9"}),e.jsxs(Fs,{value:F,onValueChange:N=>{i(N),A(!0)},children:[e.jsx(Ts,{className:"w-32 h-9",children:e.jsx(As,{})}),e.jsxs(Ps,{children:[e.jsx(Be,{value:"hours",children:"Hours"}),e.jsx(Be,{value:"days",children:"Days"})]})]}),e.jsx("span",{className:"text-xs text-muted-foreground",children:n===0?"after signup":"after previous email"})]}),e.jsx("div",{className:"flex justify-end",children:e.jsx(g,{size:"sm",onClick:()=>l.mutate(),disabled:!L||l.isPending,children:l.isPending?"Saving…":L?"Save email":"Saved"})})]})]})]})})}function Bs({sequenceId:r,enrolled:n}){const t=B(),{data:o}=P({queryKey:["all-subs-for-seq"],queryFn:async()=>{const{data:{user:u}}=await y.auth.getUser();if(!u)return[];const{data:f,error:w}=await y.from("newsletter_subscribers").select("id, email, name, status").eq("author_id",u.id).eq("status","active").order("subscribed_at",{ascending:!1});if(w)throw w;return f}}),d=new Map(n.map(u=>[u.subscriber_id,u])),p=E({mutationFn:async({subscriberId:u,exclude:f})=>{const w=d.get(u);if(f&&w){const{error:C}=await _.from("newsletter_sequence_enrollments").update({status:"excluded",updated_at:new Date().toISOString()}).eq("id",w.id);if(C)throw C}else if(f&&!w){const{error:C}=await _.from("newsletter_sequence_enrollments").insert({sequence_id:r,subscriber_id:u,status:"excluded",current_step:0,next_send_at:null});if(C)throw C}else if(!f&&w){const C=new Date(Date.now()+6e4).toISOString(),{error:F}=await _.from("newsletter_sequence_enrollments").update({status:"active",current_step:0,next_send_at:C,updated_at:new Date().toISOString()}).eq("id",w.id);if(F)throw F}},onSuccess:()=>{t.invalidateQueries({queryKey:["seq-enroll",r]}),t.invalidateQueries({queryKey:["seq-counts",r]})},onError:u=>c.error(u.message)}),j=n.filter(u=>u.status==="active").length,b=n.filter(u=>u.status==="excluded").length,q=n.filter(u=>u.status==="completed").length;return e.jsxs(S,{className:"p-5",children:[e.jsxs("div",{className:"flex items-center justify-between mb-3 gap-3 flex-wrap",children:[e.jsx("h3",{className:"text-lg font-semibold",children:"Enrolled subscribers"}),e.jsxs("div",{className:"flex items-center gap-2 text-xs",children:[e.jsxs($,{variant:"secondary",children:[j," active"]}),e.jsxs($,{variant:"secondary",children:[q," completed"]}),e.jsxs($,{variant:"secondary",children:[b," excluded"]})]})]}),e.jsx("p",{className:"text-xs text-muted-foreground mb-4",children:"Untick any subscriber you don't want to re
6ceive this sequence (e.g. paying customers). You can re-enroll them anytime."}),!o||o.length===0?e.jsx("p",{className:"text-sm text-muted-foreground",children:"No active subscribers yet."}):e.jsx("div",{className:"max-h-[420px] overflow-y-auto -mx-2 divide-y",children:o.map(u=>{const f=d.get(u.id);f?.status;const w=!f||f.status==="active"||f.status==="completed";return e.jsxs("label",{className:"flex items-center gap-3 px-2 py-2 hover:bg-muted/50 rounded cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:w,onChange:C=>p.mutate({subscriberId:u.id,exclude:!C.target.checked}),className:"w-4 h-4"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"text-sm truncate",children:u.name||u.email}),u.name&&e.jsx("div",{className:"text-xs text-muted-foreground truncate",children:u.email})]}),f&&e.jsxs("span",{className:"text-xs text-muted-foreground shrink-0",children:[f.status==="active"&&`on step ${f.current_step+1}`,f.status==="completed"&&"completed",f.status==="excluded"&&"excluded",f.status==="bounced"&&"bounced",f.status==="unsubscribed"&&"unsubscribed"]})]},u.id)})})]})}const Hs=["free","guarantee","guaranteed","winner","winning","cash","earn $","double your","risk-free","100%","act now","limited time","urgent","click here","buy now","best price","amazing","miracle","secret","no obligation","no cost","no fees","deal","lowest price"];function Gs(r){const n=[],t=(r||"").trim();if(!t)return n;t.length<10?n.push({id:"too-short",severity:"info",message:"Short subjects (<10 chars) can look spammy. Aim for 30–60 chars."}):t.length>70&&n.push({id:"too-long",severity:"warn",message:`Subject is ${t.length} chars — most inboxes truncate after ~60.`});const o=t.replace(/[^a-zA-Z]/g,"");o.length>6&&o.replace(/[^A-Z]/g,"").length/o.length>.6&&n.push({id:"all-caps",severity:"warn",message:"Mostly UPPERCASE — major spam-filter signal. Use sentence case."}),/[!?]{2,}/.test(t)&&n.push({id:"punctuation",severity:"warn",message:"Avoid repeated !!! or ??? — strong spam signal."});const d=(t.match(/!/g)||[]).length;d>=3&&n.push({id:"many-exclam",severity:"warn",message:`Contains ${d} exclamation marks — keep it to 0–1.`});const p=t.match(/[\u{1F300}-\u{1FAFF}\u{2600}-\u{27BF}]/gu)||[];p.length>=3&&n.push({id:"many-emoji",severity:"warn",message:`Contains ${p.length} emoji — 0–1 is plenty for deliverability.`});const j=t.toLowerCase(),b=Hs.filter(q=>j.includes(q));return b.length>0&&n.push({id:"spam-words",severity:"warn",message:`Contains spam-trigger phrase${b.length>1?"s":""}: ${b.slice(0,3).map(q=>`"${q}"`).join(", ")}.`}),(/\$\$+/.test(t)||/\b\$\d/.test(t)&&/free|earn|win/i.test(t))&&n.push({id:"money",severity:"warn",message:"Money + urgency phrasing trips many spam filters."}),n}function Nt(){const r=ps(),n=B(),[t,o]=x.useState(""),[d,p]=x.useState(""),[j,b]=x.useState(!1),[q,u]=x.useState(""),[f,w]=x.useState(!1),[C,F]=x.useState(!1),[i,k]=x.useState("all"),[v,L]=x.useState([]),[A,l]=x.useState(null),[h,N]=x.useState(!1),[H,Z]=x.useState(0),[M,Xe]=x.useState("active"),[X,es]=x.useState(""),[ss,ae]=x.useState(!1),[ts,ne]=x.use
6State(null),[ie,ee]=x.useState(""),le=x.useMemo(()=>Gs(t),[t]),{data:rs}=P({queryKey:["newsletter-sender-health"],queryFn:async()=>{const{data:s,error:a}=await y.rpc("get_my_newsletter_health");if(a)throw a;return s},refetchInterval:6e4}),oe=!!rs?.paused_at;x.useEffect(()=>{const s=localStorage.getItem("newsletter-draft");if(s){const a=JSON.parse(s);o(a.subject||""),p(a.content||"")}},[]),x.useEffect(()=>{(t||d)&&localStorage.setItem("newsletter-draft",JSON.stringify({subject:t,content:d}))},[t,d]);const De=()=>{localStorage.removeItem("newsletter-draft"),o(""),p(""),l(null)},as=s=>{o(s.title),p(s.content||""),l(s.id),F(!1),c.success("Article loaded! Edit and send when ready.")},{data:O,isLoading:ce}=P({queryKey:["newsletter-subscribers"],queryFn:async()=>{const{data:{user:s}}=await y.auth.getUser();if(!s)throw new Error("Not authenticated");const{data:a,error:m}=await y.from("newsletter_subscribers").select("*").eq("author_id",s.id).order("subscribed_at",{ascending:!1});if(m)throw m;return a}}),{data:D,refetch:ns}=P({queryKey:["newsletter-profile"],queryFn:async()=>{const{data:{user:s}}=await y.auth.getUser();if(!s)return null;const{data:a}=await y.from("profiles").select("username, full_name, newsletter_enabled, newsletter_reply_to_email, newsletter_double_opt_in, newsletter_signature").eq("id",s.id).single();return{...a||{},auth_email:s.email}}}),G=D?.newsletter_reply_to_email||D?.auth_email||"",de=D?.full_name||"Newsletter",$e=D?.newsletter_signature&&String(D.newsletter_signature).trim()||`Best,
7${de}`,is=async s=>{const{data:{user:a}}=await y.auth.getUser();if(!a)return;const{error:m}=await y.from("profiles").update({newsletter_double_opt_in:s}).eq("id",a.id);if(m){c.error(`Couldn't update preference: ${m.message}`);return}c.success(s?"Double opt-in enabled":"Double opt-in disabled"),ns()},Y=D?.username?`${window.location.origin}/user/${D.username}`:null,ls=async()=>{Y&&(await navigator.clipboard.writeText(Y),c.success("Signup link copied"))},K=x.useMemo(()=>(O||[]).filter(s=>s.status==="active"),[O]).filter(s=>!(i!=="all"&&s.source!==i||v.length>0&&!(Array.isArray(s.tags)?s.tags:[]).some(m=>v.includes(m)))),Le=x.useMemo(()=>{const s=new Set;return(O||[]).forEach(a=>{(Array.isArray(a.tags)?a.tags:[]).forEach(m=>{m&&s.add(m)})}),Array.from(s).sort()},[O]),V=x.useMemo(()=>{const s={active:0,bounced:0,complained:0,unsubscribed:0};return(O||[]).forEach(a=>{s[a.status]!==void 0&&s[a.status]++}),s},[O]),Me=x.useMemo(()=>{const s=X.trim().toLowerCase();return(O||[]).filter(a=>a.status!==M?!1:s?a.email?.toLowerCase().includes(s)||a.name?.toLowerCase().includes(s):!0)},[O,M,X]),{data:J}=P({queryKey:["newsletter-sends"],queryFn:async()=>{const{data:{user:s}}=await y.auth.getUser();if(!s)return[];const{data:a,error:m}=await y.from("newsletter_sends").select("*").eq("sent_by",s.id).order("sent_at",{ascending:!1}).limit(10);if(m)throw m;return a}}),{data:ue}=P({queryKey:["newsletter-templates"],queryFn:async()=>{const{data:s,error:a}=await y.from("newsletter_templates").select("*").order("created_at",{ascending:!1});if(a)throw a;return s}}),{data:se}=P({queryKey:["published-articles"],queryFn:async()=>{const{data:{user:s}}=await y.auth.getUser();if(!s)throw new Error("Not authenticated");const{data:a,error:m}=await y.from("posts").select("id, title, content, excerpt, featured_image_url, slug, published_at").eq("author_id",s.id).eq("status","published").order("published_at",{ascending:!1}).limit(20);if(m)throw m;return a}}),z=E({mutationFn:async()=>{const{data:s,error:a}=await y.functions.invoke("send-newsletter",{body:{subject:t,content:d,source_post_id:A,source_filter:i,tag_filter:v}});if(a)throw a;if(s&&s.success===!1){const m=new Error(s.error||"Send failed");throw m.errorCode=s.errorCode,m.payload=s,m}return s},onSuccess:()=>{c.success("Newsletter sent successfully"),De(),n.invalidateQueries({queryKey:["newsletter-sends"]}),n.invalidateQueries({queryKey:["newsletter-sender-health"]})},onError:s=>{s?.errorCode==="SENDER_PAUSED"?(c.error("Sending is paused. See sender health above."),n.invalidateQueries({queryKey:["newsletter-sender-health"]})):c.error(s.message||"Failed to send newsletter"),We("newsletter_send_failure",s.message||"Failed to send newsletter",{subject:t,errorCode:s?.errorCode})}}),me=E({mutationFn:async s=>{const{data:a,error:m}=await y.functions.invoke("send-newsletter",{body:{subject:`[TEST] ${t}`,content:`${d}
8
9---
10This is a test email.`,test_email:s}});if(m)throw m;if(a&&a.success===!1){const T=new Error(a.error||"Test send failed");throw T.errorCode=a.errorCode,T}return a},onSuccess:()=>{c.success("Test email sent! Check your inbox."),u("")},onError:s=>{c.error(s.message||"Failed to send test email"),We("newsletter_test_failure",s.message||"Failed to send test email")}}),os=E({mutationFn:async s=>{const{error:a}=await y.from("newsletter_subscribers").update({status:"unsubscribed",unsubscribed_at:new Date().toISOString()}).eq("id",s);if(a)throw a},onSuccess:()=>{c.success("Subscriber removed"),n.invalidateQueries({queryKey:["newsletter-subscribers"]}
10)},onError:()=>{c.error("Failed to remove subscriber")}}),xe=E({mutationFn:async({id:s,tags:a})=>{const{error:m}=await y.from("newsletter_subscribers").update({tags:a}).eq("id",s);if(m)throw m},onSuccess:()=>{c.success("Tags updated"),ne(null),ee(""),n.invalidateQueries({queryKey:["newsletter-subscribers"]})},onError:s=>c.error(s?.message||"Failed to update tags")}),he=E({mutationFn:async()=>{const{data:{user:s}}=await y.auth.getUser();if(!s)throw new Error("Not authenticated");const{error:a,count:m}=await y.from("newsletter_subscribers").delete({count:"exact"}).eq("author_id",s.id).eq("status","bounced");if(a)throw a;return m||0},onSuccess:s=>{c.success(`Removed ${s} bounced subscriber${s===1?"":"s"}`),n.invalidateQueries({queryKey:["newsletter-subscribers"]})},onError:s=>{c.error(s?.message||"Failed to clean bounced list")}}),cs=()=>{if(!t||!d){c.error("Please fill in subject and content");return}if(!K||K.length===0){c.error("No active subscribers to send to");return}Z(K.length),N(!0)},ds=()=>{if(!q){c.error("Please enter a test email address");return}if(!t||!d){c.error("Please fill in subject and content");return}me.mutate(q)},us=(s=!1)=>{const a=A&&se?.find(fe=>fe.id===A),m=a?`${window.location.origin}/${a.slug}`:"",T=s&&a?`
11      <div style="margin-top: 32px; text-align: center;">
12        <a href="${m}"
13           style="display: inline-block; background-color: #000000; color: #ffffff; padding: 12px 28px; border-radius: 8px; text-decoration: none; font-weight: 600; font-size: 14px;">
14          Read Full Article →
15        </a>
16      </div>
17    `:"",Q=fe=>fe.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"),pe=Q($e).replace(/\n/g,"<br>"),xs=Q(de);return`
18      <div style="background-color: #f8f8f8; color-scheme: light; font-family: -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', Roboto, sans-serif;">
19        <div style="max-width: 560px; margin: 0 auto; padding: 48px 24px;">
20          <div style="background-color: #ffffff; border: 1px solid #e5e5e5; border-radius: 12px; padding: 48px 40px;">
21            <p style="color: #333333; line-height: 1.7; margin: 0 0 24px 0; font-size: 15px;">Hi there,</p>
22            <div style="color: #333333; line-height: 1.8; font-size: 15px;">
23              ${d}
24            </div>
25            ${T}
26            <div style="margin-top: 32px; padding-top: 24px; border-top: 1px solid #e5e5e5;">
27              <p style="color: #666666; line-height: 1.6; margin: 0; font-size: 14px;">
28                ${pe}
29              </p>
30            </div>
31          </div>
32          <div style="text-align: center; margin-top: 32px;">
33            <p style="color: #999999; font-size: 12px; margin: 0 0 6px 0;">
34              You received this because you subscribed to ${xs}'s newsletter.
35            </p>
36            <a href="#" style="color: #666666; font-size: 12px; text-decoration: underline;">
37              Unsubscribe
38            </a>
39          </div>
40        </div>
41      </div>
42    `},ms=s=>{o(s.subject),p(s.content),w(!1),c.success("Template loaded")};return e.jsx("div",{className:"min-h-screen bg-background",children:e.jsxs("div",{className:"container mx-auto px-4 sm:px-6 py-6 sm:py-8 max-w-6xl",children:[e.jsxs("div",{className:"mb-6 sm:mb-8",children:[e.jsx(g,{variant:"ghost",onClick:()=>r("/dashboard"),className:"mb-4",children:"← Back to Dashboard"}),e.jsx("h1",{className:"text-3xl sm:text-4xl font-bold mb-2",children:"Newsletter"}),e.jsx("p",{className:"text-sm sm:text-base text-muted-foreground",children:"Compose and send newsletters to your subscribers"})]}),D&&D.newsletter_enabled===!1&&e.jsx(S,{className:"p-5 mb-6 border-dashed",children:e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-medium mb-1",children:"Your newsletter is off"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Turn it on in Profile to show the signup form on your public page and start sending."})]}),e.jsx(g,{onClick:()=>r("/profile"),variant:"outline",size:"sm",children:"Open Profile"})]})}),D?.newsletter_enabled&&!ce&&(K?.length||0)===0&&Y&&e.jsxs(S,{className:"p-5 mb-6",children:[e.jsx("h3",{className:"font-medium mb-1",children:"Your newsletter is live — share it"}),e.jsx("p",{className:"text-sm text-muted-foreground mb-3",children:"Send this 
42signup link to your audience to start collecting subscribers."}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(U,{value:Y,readOnly:!0,className:"font-mono text-sm"}),e.jsx(g,{type:"button",variant:"outline",size:"sm",onClick:ls,children:"Copy"}),e.jsx(g,{type:"button",variant:"outline",size:"sm",asChild:!0,children:e.jsx("a",{href:Y,target:"_blank",rel:"noreferrer",children:"Open"})})]})]}),D?.newsletter_enabled&&e.jsxs("div",{className:"mb-6 space-y-3",children:[e.jsx(Is,{}),e.jsxs(S,{className:"p-4 flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"font-medium text-sm",children:"Require email confirmation (double opt-in)"}),e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5",children:"New subscribers receive a confirm email and only join your list after they click. Protects deliverability and proves consent for GDPR/CAN-SPAM."})]}),e.jsx(re,{checked:!!D?.newsletter_double_opt_in,onCheckedChange:is})]})]}),e.jsxs(_s,{defaultValue:"compose",className:"w-full",children:[e.jsxs(Ss,{className:"mb-6",children:[e.jsxs(Oe,{value:"compose",children:[e.jsx(ge,{className:"w-4 h-4 mr-1.5"})," Compose"]}),e.jsxs(Oe,{value:"sequences",children:[e.jsx(qs,{className:"w-4 h-4 mr-1.5"})," Sequences"]})]}),e.jsxs(Ue,{value:"compose",children:[e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-3 sm:gap-4 mb-6 sm:mb-8",children:[e.jsx(S,{className:"p-6",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"p-2 rounded-lg bg-primary/10",children:e.jsx(Ze,{className:"w-5 h-5 text-primary"})}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Active Subscribers"}),e.jsx("p",{className:"text-2xl font-bold",children:ce?"...":K?.length||0})]})]})}),e.jsx(S,{className:"p-6",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"p-2 rounded-lg bg-accent/10",children:e.jsx(Ve,{className:"w-5 h-5 text-accent"})}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Newsletters Sent"}),e.jsx("p",{className:"text-2xl font-bold",children:J?.length||0})]})]})}),e.jsx(S,{className:"p-6",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"p-2 rounded-lg bg-green-500/10",children:e.jsx(ge,{className:"w-5 h-5 text-green-500"})}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Total Sent"}),e.jsx("p",{className:"text-2xl font-bold",children:J?.reduce((s,a)=>s+(a.recipient_count||0),0)||0})]})]})})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-6 sm:gap-8",children:[e.jsx("div",{children:e.jsxs(S,{className:"p-4 sm:p-6",children:[e.jsxs("div",{className:"flex flex-col sm:flex-row items-start sm:items-center justify-between mb-4 gap-2",children:[e.jsx("h2",{className:"text-xl sm:text-2xl font-bold",children:"Compose Newsletter"}),A&&e.jsxs($,{variant:"secondary",className:"flex items-center gap-2",children:[e.jsx(Ie,{className:"w-3 h-3"}),e.jsx("span",{className:"text-xs",children:"Loaded from article"})]})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("label",{className:"text-sm font-medium block",children:"Subject"}),t&&e.jsxs("span",{className:`text-xs ${t.length>70?"text-destructive":"text-muted-foreground"}`,children:[t.length," chars"]})]}),e.jsx(U,{placeholder:"Your newsletter subject...",value:t,onChange:s=>o(s.target.value)}),le.length>0&&e.jsx("ul",{className:"mt-2 space-y-1",children:le.map(s=>e.jsxs("li",{className:`text-xs flex items-start gap-1.5 ${s.severity==="warn"?"text-destructive":"text-muted-foreground"}`,children:[e.jsx(Ne,{className:"w-3 h-3 mt-0.5 shrink-0"}),e.jsx("span",{children:s.message})]},s.id))})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-sm font-medium mb-2 block",children:"Content"}),e.jsx("div",{className:"border rounded-lg overflow-hidden bg-card",children:e.jsx(Je,{content:d,onChange:p,placeholder:"Write your newsletter content here... Use the toolbar to format your text.",className:"min-h-[300px] p-4",aiAssistantEnabled:!1})}),e.jsxs("div",{className:"mt-2 rounded-md border border-dashed border-border bg-muted/30 px-3 py-2 text-xs text-muted-foreground",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3 flex-wrap",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsxs("div",{children:[e.jsx("span",{className:"font-medium text-foreground",children:"Auto signature:"})," ",e.jsx("span",{className:"whitespace-pre-line",children:$e})]}),e.jsxs("div",{children:[e.jsx("span",{className:"font-medium text-foreground",children:"Replies go to:"})," ",G?e.jsx("code",{children:G}):e.jsx("span",{className:"text-destructive",children:"not set — replies will be lost"})]})]}),e.jsx(g,{variant:"ghost",size:"sm",className:"h-7 px-2 text-xs",onClick:()=>r("/profile?section=newsletter"),children:"Edit in Profile"})]}),e.jsx("p",{className:"mt-1.5 text-[11px] text-muted-foreground
42/80",children:'Skip writing "Cheers!" or your name at the end — the signature above is appended automatically.'})]})]}),e.jsxs("div",{className:"flex gap-2 flex-wrap",children:[e.jsxs(g,{onClick:()=>F(!0),variant:"outline",className:"flex-1 min-w-[140px] sm:min-w-[120px]",children:[e.jsx(Ie,{className:"w-4 h-4 mr-2"}),e.jsx("span",{className:"text-xs sm:text-sm",children:"Load from Article"})]}),e.jsxs(g,{onClick:()=>w(!0),variant:"outline",className:"flex-1 min-w-[140px] sm:min-w-[120px]",children:[e.jsx(Us,{className:"w-4 h-4 mr-2"}),e.jsx("span",{className:"text-xs sm:text-sm",children:"Load Template"})]}),e.jsxs(g,{onClick:()=>b(!0),disabled:!d,variant:"outline",className:"flex-1 min-w-[100px] sm:min-w-[120px]",children:[e.jsx(Ms,{className:"w-4 h-4 mr-2"}),e.jsx("span",{className:"text-xs sm:text-sm",children:"Preview"})]}),e.jsxs(g,{onClick:De,disabled:!t&&!d,variant:"outline",className:"flex-1 min-w-[100px] sm:min-w-[120px]",children:[e.jsx(Os,{className:"w-4 h-4 mr-2"}),e.jsx("span",{className:"text-xs sm:text-sm",children:"Clear Draft"})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("label",{className:"text-sm font-medium block",children:"Send Test Email"}),e.jsxs("div",{className:"flex flex-col sm:flex-row gap-2",children:[e.jsx(U,{type:"email",placeholder:"[email protected]",value:q,onChange:s=>u(s.target.value),className:"flex-1"}),e.jsx(g,{onClick:ds,disabled:me.isPending||!t||!d||!q,variant:"outline",className:"w-full sm:w-auto",children:me.isPending?e.jsx(I,{className:"w-4 h-4 animate-spin"}):"Send Test"})]})]}),Le.length>0&&e.jsxs("div",{className:"space-y-2 border rounded-lg p-3 bg-muted/20",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("label",{className:"text-sm font-medium",children:"Send to"}),v.length>0&&e.jsxs("button",{type:"button",className:"text-xs text-muted-foreground hover:text-foreground underline",onClick:()=>L([]),children:["Clear (",v.length,")"]})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:v.length===0?"All active subscribers":`Only subscribers tagged: ${v.join(", ")}`}),e.jsx("div",{className:"flex gap-1.5 flex-wrap",children:Le.map(s=>{const a=v.includes(s);return e.jsx("button",{type:"button",onClick:()=>L(m=>m.includes(s)?m.filter(T=>T!==s):[...m,s]),className:`text-xs px-2.5 py-1 rounded-full border transition-colors ${a?"bg-foreground text-background border-foreground":"bg-background text-muted-foreground border-border hover:border-foreground
42/40"}`,children:s},s)})})]}),e.jsx(g,{onClick:cs,disabled:z.isPending||!t||!d||oe,className:"w-full",size:"lg",title:oe?"Sending paused — see sender health above":void 0,children:z.isPending?e.jsxs(e.Fragment,{children:[e.jsx(I,{className:"w-4 h-4 mr-2 animate-spin"}),"Sending..."]}):oe?e.jsx(e.Fragment,{children:"Sending paused"}):e.jsxs(e.Fragment,{children:["Send to ",K?.length||0," subscribers",e.jsx(ge,{className:"w-4 h-4 ml-2"})]})})]})]})}),e.jsxs("div",{className:"space-y-6",children:[e.jsxs(S,{className:"p-6",children:[e.jsxs("div",{className:"flex items-center justify-between mb-4 gap-2 flex-wrap",children:[e.jsx("h2",{className:"text-xl font-bold",children:"Subscribers"}),M==="bounced"&&V.bounced>0&&e.jsxs(g,{variant:"outline",size:"sm",disabled:he.isPending,onClick:()=>ae(!0),children:[he.isPending?e.jsx(I,{className:"w-3 h-3 mr-1 animate-spin"}):e.jsx(Ye,{className:"w-3 h-3 mr-1"}),"Clean ",V.bounced," bounced"]})]}),e.jsx("div",{className:"flex gap-1.5 mb-3 flex-wrap",children:["active","bounced","complained","unsubscribed"].map(s=>e.jsxs("button",{type:"button",onClick:()=>Xe(s),className:`text-xs px-2.5 py-1 rounded-full border transition-colors ${M===s?"bg-foreground text-background border-foreground":"bg-background text-muted-foreground border-border hover:border-foreground
42/40"}`,children:[s.charAt(0).toUpperCase()+s.slice(1)," (",V[s]||0,")"]},s))}),e.jsxs("div",{className:"relative mb-3",children:[e.jsx(Cs,{className:"absolute left-2.5 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted-foreground"}),e.jsx(U,{placeholder:"Search by email or name…",value:X,onChange:s=>es(s.target.value),className:"pl-8 h-9 text-sm"})]}),e.jsx("div",{className:"space-y-2 max-h-[300px] overflow-y-auto",children:ce?e.jsx("p",{className:"text-muted-foreground",children:"Loading..."}):Me.length>0?Me.map(s=>{const a=Array.isArray(s.tags)?s.tags:[],m=ts===s.id;return e.jsxs("div",{className:"flex flex-col gap-2 p-3 rounded-lg border",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"font-medium mb-0.5 truncate",children:s.email}),s.name&&e.jsx("p",{className:"text-sm text-muted-foreground truncate",children:s.name})]}),M==="active"&&e.jsx(g,{variant:"ghost",size:"sm",onClick:()=>os.mutate(s.id),title:"Unsubscribe",children:e.jsx(Pe,{className:"w-4 h-4"})})]}),e.jsxs("div",{className:"flex items-center gap-1.5 flex-wrap",children:[a.map(T=>e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded-full bg-muted text-muted-foreground border",children:T},T)),m?e.jsxs(e.Fragment,{children:[e.jsx(U,{autoFocus:!0,value:ie,onChange:T=>ee(T.target.value),placeholder:"tag1, tag2",className:"h-7 text-xs flex-1 min-w-[140px]",onKeyDown:T=>{if(T.key==="Enter"){const Q=ie.split(",").map(pe=>pe.trim()).filter(Boolean);xe.mutate({id:s.id,tags:Q})}else T.key==="Escape"&&(ne(null),ee(""))}}),e.jsx(g,{size:"sm",variant:"outline",className:"h-7 px-2 text-xs",disabled:xe.isPending,onClick:()=>{const T=ie.split(",").map(Q=>Q.trim()).filter(Boolean);xe.mutate({id:s.id,tags:T})},children:"Save"})]}):e.jsx("button",{type:"button",className:"text-[10px] text-muted-foreground hover:text-foreground underline",onClick:()=>{ne(s.id),ee(a.join(", "))},children:a.length===0?"+ add tags":"edit"})]})]},s.id)}):e.jsx("p",{className:"text-muted-foreground text-sm",children:X?`No matches in ${M}`:`No ${M} subscribers`})})]}),e.jsxs(S,{className:"p-6",children:[e.jsx("h2",{className:"text-xl font-bold mb-4",children:"Recent Sends"}),e.jsx("div",{className:"space-y-2 max-h-[300px] overflow-y-auto",children:J&&J.length>0?J.map(s=>e.jsxs("div",{className:"p-3 rounded-lg border",children:[e.jsx("p",{className:"font-medium",children:s.subject}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:[s.recipient_count," recipients • ",new Date(s.sent_at).toLocaleDateString()]})]},s.id)):e.jsx("p",{className:"text-muted-foreground text-sm",children:"No sends yet"})})]}),e.jsx(Ks,{})]})]}),e.jsx(je,{open:j,onOpenChange:b,children:e.jsxs(be,{className:"max-w-2xl max-h-[80vh] overflow-y-auto",children:[e.jsx(we,{children:e.jsx(ye,{children:"Email Preview"})}),e.jsxs("div",{className:"border rounded-lg overflow-hidden",style:{backgroundColor:"#f8f8f8",colorScheme:"light"},children:[e.jsxs("div",{className:"p-4 border-b",style:{backgroundColor:"#ffffff",color:"#111"},children:[e.jsx("p",{className:"text-xs",style:{color:"#666"},children:"Subject"}),e.jsx("p",{className:"font-semibold",style:{color:"#111"},children:t||"(no subject)"}),e.jsxs("p",{className:"text-xs mt-2",style:{color:"#666"},children:["From: ",de," <[email protected]> · Reply-to: ",G||"(not set)"]})]}),e.jsx("div",{dangerouslySetInnerHTML:{__html:us(!0)}})]})]})}),e.jsx(je,{open:f,onOpenChange:w,children:e.jsxs(be,{className:"max-w-4xl max-h-[90vh] overflow-y-auto",children:[e.jsxs(we,{children:[e.jsx(ye,{children:"Select a Template"}),e.jsx(Ke,{children:"Choose a template to start your newsletter"})]}),!ue||ue.length===0?e.jsx("div",{className:"text-center py-8",children:e.jsx("p",{className:"text-muted-foreground",children:"No templates available yet. Start from a blank newsletter to create your first one."})}):e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:ue.map(s=>e.jsxs(S,{className:"hover:shadow-lg transition-shadow cursor-pointer",onClick:()=>ms(s),children:[e.jsxs(ze,{children:[e.jsx(Qe,{className:"text-lg",children:s.name}),s.description&&e.jsx(Re,{children:s.description})]}),e.jsx(ve,{children:e.jsxs("div",{className:"space-y-2",children:[e.jsxs("p",{className:"text-sm text-muted-foreground",children:[e.jsx("strong",{children:"Subject:"})," ",s.subject]}),e.jsx("p",{className:"text-sm text-muted-foreground line-clamp-3",children:s.content})]})})]},s.id))})]})}),e.jsx(je,{open:C,onOpenChange:F,children:e.jsxs(be,{className:"max-w-4xl max-h-[90vh] overflow-y-auto",children:[e.jsxs(we,{children:[e.jsx(ye,{children:"Load from Published Article"}),e.jsx(Ke,{children:"Select an article to send as a newsletter. You can edit it before sending."})]}),!se||se.length===0?e.jsxs("div",{className:"text-center py-8",children:[e.jsx("p",{className:"text-muted-foreground mb-4",children:"No published articles yet."}),e.jsx(g,{onClick:()=>
42r("/dashboard"),children:"Write Your First Article"})]}):e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:se.map(s=>e.jsxs(S,{className:"hover:shadow-lg transition-shadow cursor-pointer group",onClick:()=>as(s),children:[s.featured_image_url&&e.jsx("div",{className:"relative h-40 overflow-hidden rounded-t-lg",children:e.jsx("img",{src:s.featured_image_url,alt:s.title,loading:"lazy",decoding:"async",className:"w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"})}),e.jsxs(ze,{children:[e.jsx(Qe,{className:"text-lg line-clamp-2",children:s.title}),e.jsxs(Re,{className:"flex items-center gap-2",children:[e.jsx(ks,{className:"w-4 h-4"}),new Date(s.published_at).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})]})]}),s.excerpt&&e.jsx(ve,{children:e.jsx("p",{className:"text-sm text-muted-foreground line-clamp-3",children:s.excerpt})})]},s.id))})]})})]}),e.jsx(Ue,{value:"sequences",children:e.jsx(zs,{})})]}),e.jsx(_e,{open:h,onOpenChange:N,children:e.jsxs(Se,{children:[e.jsxs(qe,{children:[e.jsx(Ce,{children:"Send newsletter?"}),e.jsx(ke,{asChild:!0,children:e.jsxs("div",{className:"space-y-3",children:[e.jsxs("p",{children:["This will send to ",e.jsx("strong",{children:H})," ",i!=="all"?`${i} `:"","subscriber",H!==1?"s":"",". This action cannot be undone."]}),e.jsxs("div",{className:"rounded-md border bg-muted/30 p-3 space-y-2",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] uppercase tracking-wide text-muted-foreground",children:"Subject"}),e.jsx("p",{className:"text-sm font-medium break-words",children:t})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] uppercase tracking-wide text-muted-foreground",children:"Preview"}),e.jsx("p",{className:"text-xs text-muted-foreground line-clamp-3",children:d.replace(/<[^>]+>/g,"").trim().slice(0,200)||"—"})]})]}),le.some(s=>s.severity==="warn")&&e.jsxs("div",{className:"text-xs text-destructive flex items-start gap-1.5",children:[e.jsx(Ne,{className:"w-3 h-3 mt-0.5 shrink-0"}),e.jsx("span",{children:"Subject has deliverability warnings — review before sending."})]}),G&&e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Replies will go to ",e.jsx("span",{className:"font-mono",children:G}),"."," ",e.jsx("button",{type:"button",className:"underline hover:text-foreground",onClick:()=>r("/profile?tab=newsletter"),children:"Change"})]})]})})]}),e.jsxs(Ee,{children:[e.jsx(Fe,{children:"Cancel"}),e.jsx(Te,{disabled:z.isPending,onClick:()=>{z.isPending||(z.mutate(),N(!1))},children:z.isPending?"Sending…":"Send Now"})]})]})}),e.jsx(_e,{open:ss,onOpenChange:ae,children:e.jsxs(Se,{children:[e.jsxs(qe,{children:[e.jsx(Ce,{children:"Remove bounced subscribers?"}),e.jsxs(ke,{children:["This permanently deletes ",V.bounced," subscriber",V.bounced===1?"":"s"," whose addresses bounced. They were already suppressed from future sends — this just tidies your list."]})]}),e.jsxs(Ee,{children:[e.jsx(Fe,{children:"Cancel"}),e.jsx(Te,{onClick:()=>{he.mutate(),ae(!1)},children:"Remove"})]})]})})]})})}export{Nt 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.