1const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/AutomationsView-D5qubJzu.js","assets/index-BQSuW3M2.js","assets/index-7FVZiXie.css","assets/skeleton-BarAKMLu.js","assets/useEventCatalogue-B1_3NkSj.js","assets/AutomationDetail-BJOU3dcn.js","assets/AdminNewsletter-DMR-uRem.js","assets/calendar-clock-C4w1TAtF.js"])))=>i.map(i=>d[i]); 2import{c as Te,bC as nt,bD as me,bE as rt,bF as at,bG as it,j as t,aJ as he,br as g,u as O,K as se,s as N,aW as V,P as L,b3 as C,b6 as j,a9 as Q,L as ot,bg as dt,I as lt,ac as pe,ad as fe,ae as xe,af as ge,ag as J,bw as ne,r as x,B as w,n as Ee,az as ct,aX as re,aY as ae,aZ as ie,b1 as Ce,b2 as _e,b4 as q,b5 as Pe,Y as ee,J as Oe,bH as ut,bI as mt,o as ht,p as pt,q as ft,t as xt,v as gt,w as bt,x as yt,y as jt,aj as vt,bJ as Le,bK as Nt,_ as oe}from"./index-BQSuW3M2.js";import{S as v}from"./skeleton-BarAKMLu.js";const wt=Te("Ban",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m4.9 4.9 14.2 14.2",key:"1m5liu"}]]);const kt=Te("UserMinus",[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}],["line",{x1:"22",x2:"16",y1:"11",y2:"11",key:"1shjgl"}]]);var St=class extends nt{constructor(e,s){super(e,s)}bindMethods(){super.bindMethods(),this.fetchNextPage=this.fetchNextPage.bind(this),this.fetchPreviousPage=this.fetchPreviousPage.bind(this)}setOptions(e){super.setOptions({...e,behavior:me()})}getOptimisticResult(e){return e.behavior=me(),super.getOptimisticResult(e)}fetchNextPage(e){return this.fetch({...e,meta:{fetchMore:{direction:"forward"}}})}fetchPreviousPage(e){return this.fetch({...e,meta:{fetchMore:{direction:"backward"}}})}createResult(e,s){const{state:n}=e,r=super.createResult(e,s),{isFetching:a,isRefetching:i,isError:o,isRefetchError:m}=r,d=n.fetchMeta?.fetchMore?.direction,l=o&&d==="forward",f=a&&d==="forward",c=o&&d==="backward",h=a&&d==="backward";return{...r,fetchNextPage:this.fetchNextPage,fetchPreviousPage:this.fetchPreviousPage,hasNextPage:at(s,n.data),hasPreviousPage:rt(s,n.data),isFetchNextPageError:l,isFetchingNextPage:f,isFetchPreviousPageError:c,isFetchingPreviousPage:h,isRefetchError:m&&!l&&!c,isRefetching:i&&!f&&!h}}};function Re(e,s){return it(e,St)}function A(e,s){return!Number.isFinite(e)||!Number.isFinite(s)||s<=0||e<=0?0:Math.min(1,e/s)}const Fe=720*60*60*1e3,At=.02,D="â";function T(e){if(e==null||!Number.isFinite(e))return D;if(e<=0)return"0%";if(e>=1)return"100%";const s=e*100;return`${s>=1?s.toFixed(1):s.toFixed(2)}%`}function Tt(e){return e==null||!Number.isFinite(e)?D:e<=0?"0%":`${Math.round(Math.min(1,e)*100)}%`}function u(e){return new Intl.NumberFormat("en-GB").format(e)}const De=["all","scheduled","sending","automations","sent","drafts"],Et={all:"All",scheduled:"Scheduled",sending:"Sending",automations:"Automations",sent:"Sent",drafts:"Drafts"};function Ie(e){if(e.kind==="triggered")return"automations";switch(e.status){case"scheduled":return"scheduled";case"sending":return"sending";case"sent":return"sent";case"draft":return"drafts";default:return null}}function Ct(e,s){return s==="all"?[...e]:e.filter(n=>Ie(n)===s)}function _t(e){const s=Object.fromEntries(De.map(n=>[n,0]));s.all=e.length;for(const n of e){const r=Ie(n);r&&r!=="all"&&(s[r]+=1)}return s}function Pt(e){const s=e.finishedAt??e.startedAt??e.createdAt;if(!s)return null;const n=Date.parse(s);return Number.isFinite(n)?n:null}function Ot(e,s,n=Fe){const r=Pt(e);if(r===null)return!1;const a=s.getTime()-r;return a>=0&&a<=n}function Lt(e,s,n=Fe){const r=e.filter(b=>Ot(b,s,n));let a=0,i=0,o=0,m=0,d=0,l=0,f=0,c=!1,h=0;for(const b of r){const p=b.stats;a+=p.accepted,i+=p.delivered,o+=p.bounced,m+=p.complained,d+=p.unsubscribed,p.accepted>0&&(h+=1),b.tracking.opens&&(c=!0,l+=p.opened,f+=p.delivered)}return{campaigns:h,accepted:a,delivered:i,bounced:o,complained:m,unsubscribed:d,opened:l,deliveredOfAccepted:A(i,a),openedOfDelivered:c?A(l,f):null,unsubscribedOfDelivered:A(d,i)}}function Rt(e){const{attempted:s,queued:n}=e.stats;return A(s-n,s)}function $e(e){return e.status!=="sent"?!1:e.stats.rates.bouncedOfAccepted>=At}function Ft(e,s){return A(e,s)}const Dt={draft:{label:"Draft",className:"border-border bg-background text-muted-foreground"},scheduled:{label:"Scheduled",className:"border-border bg-secondary text-secondary-foreground"},sending:{label:"Sending",className:"border-primary/40 bg-primary/5 text-foreground"},sent:{label:"Sent",className:"border-border bg-secondary text-secondary-foreground"},paused:{label:"Paused",className:"border-border bg-secondary text-muted-foreground"},canceled:{label:"Canceled",className:"border-border bg-secondary text-muted-foreground"},failed:{label:"Failed",className:"border-destructive/40 bg-destructive/10 text-destructive"}},It={label:"Unknown state",className:"border-border bg-background text-muted-foreground"},be="rounded-full px-2.5 py-1 text-[11px] font-semibold transition-colors duration-200";function Me({campaign:e,className:s}){if($e(e)){const a=T(e.stats.rates.bouncedOfAccepted);return t.jsxs(he,{variant:"outline",title:`${e.stats.bounced} of ${e.stats.accepted} accepted messages bounced`,className:g(be,"border-destructive/40 bg-destructive/10 text-destructive",s),children:[a," bounced"]})}const n=Dt[e.status]??It,r=e.status==="sending"?`Sending ${Tt(Rt(e))}`:n.label;return t.jsx(he,{variant:"outline",className:g(be,n.className,s),children:r})}const ye=new Map;function te(e,s){const n=`${e??""}|${s?"y":"n"}`,r=ye.get(n);if(r)return r;const a={weekday:"short",day:"numeric",month:"short",hour:"2-digit",minute:"2-digit",...s?{year:"numeric"}:{},...e?{timeZone:e}:{}},i=new Intl.DateTimeFormat("en-GB",a);return ye.set(n,i),i}function $t(e){const s=typeof e=="string"?e.trim():"";if(s==="")return null;try{return te(s,!1),s}catch{return null}}function Mt(){try{return new Intl.DateTimeFormat().resolvedOptions().timeZone||null}catch{return null}}const qt=new Intl.DateTimeFormat("en-GB",{hour:"2-digit",minute:"2-digit"}),je=new Intl.RelativeTimeFormat("en-GB",{numeric:"auto"});function de(e){if(!e)return null;const s=Date.parse(e);return Number.isFinite(s)?new Date(s):null}function R(e,s,n=null){const r=de(e);if(!r)return null;const a=i=>te(n,!0).formatToParts(i).find(o=>o.type==="year")?.value;return te(n,a(r)!==a(s)).format(r)}function Bt(e,s){const n=de(e);if(!n)return null;const r=(n.getTime()-s.getTime())/1e3,a=[["year",365*24*3600],["month",720*3600],["day",24*3600],["hour",3600],["minute",60]];for(const[i,o]of a)if(Math.abs(r)>=o)return je.format(Math.round(r/o),i);return je.format(Math.round(r),"second")}function Ut(e){return e.status==="paused"&&e.stats.queued>0}function qe(e,s){const{stats:n}=e;switch(e.status){case"sending":{const r=de(e.startedAt);return{primary:r?`Started ${qt.format(r)}`:"Sending",secondary:`${u(n.queued)} still queued`,tone:"default"}}case"scheduled":{const r=$t(e.timezone)??Mt(),a=R(e.scheduledAt,s,r),i=Bt(e.scheduledAt,s);
2return{primary:a??"Scheduled",secondary:[r,i].filter(Boolean).join(" · ")||null,tone:"muted"}}case"sent":return{primary:R(e.finishedAt??e.startedAt,s)??"Sent",secondary:e.createdBy?`by ${e.createdBy}`:null,tone:"muted"};case"paused":return Ut(e)?{primary:"Held at the day's send ceiling",secondary:`${u(n.queued)} still queued · resumes when the day's allowance resets`,tone:"alert"}:{primary:`Paused ${R(e.finishedAt??e.startedAt,s)??""}`.trim(),secondary:"Nothing left queued",tone:"muted"};case"canceled":return{primary:`Canceled ${R(e.finishedAt,s)??""}`.trim(),secondary:n.queued>0?`${u(n.queued)} never sent`:null,tone:"muted"};case"failed":return{primary:`Stopped ${R(e.finishedAt??e.startedAt,s)??""}`.trim(),secondary:`${u(n.failed)} failed · needs a person, not a retry`,tone:"alert"};case"draft":return{primary:R(e.createdAt,s)??"Draft",secondary:"Never sent",tone:"muted"};default:return{primary:R(e.createdAt,s)??"â",secondary:`Status "${e.status}" is not one this screen knows`,tone:"alert"}}}const z={friends_family:"Friends and family (test group)",invited_pending:"Invited, never signed up",engaged_tenth:"Most recently confirmed tenth",engaged_half:"Most recently confirmed half",full:"Everyone on the list",all_users:"All registered users (not only subscribers)"};class Gt extends Error{partial;constructor(s){super(s.error),this.name="NewsletterPartialError",this.partial=s}}const zt=new Set(["spent","unreadable"]);function hn(e){return e.ceiling_refusal===void 0||!zt.has(e.ceiling_refusal)?[]:[...new Set([...e.not_delivered,...e.not_attempted])]}function Kt(e){if(!e||typeof e!="object")return null;const s=e;if(s.partial!==!0)return null;const n=r=>Array.isArray(r)?r.filter(a=>typeof a=="string"):[];return{error:typeof s.error=="string"?s.error:"Campaign stopped part-way",campaignId:typeof s.campaignId=="string"?s.campaignId:void 0,stats:s.stats,delivered:n(s.delivered),not_delivered:n(s.not_delivered),not_attempted:n(s.not_attempted),in_doubt:n(s.in_doubt),ceiling_refusal:typeof s.ceiling_refusal=="string"?s.ceiling_refusal:void 0,reasons:n(s.reasons),remedy:typeof s.remedy=="string"?s.remedy:void 0}}const _={subscribers:()=>["newsletter","subscribers"],templates:()=>["newsletter","templates"],chrome:(e,s,n)=>["newsletter","chrome",e,s,n??null],senderProfiles:()=>["newsletter","sender-profiles"],preview:(e,s)=>["newsletter","preview",e??null,[...s].sort()],campaigns:e=>["newsletter","campaigns",e],campaign:e=>["newsletter","campaign",e],campaignRecipients:(e,s)=>["newsletter","campaign-recipients",e,s]},Ht=120*1e3;function pn(){return O({queryKey:_.subscribers(),staleTime:Ht,queryFn:async()=>{const{data:e,error:s}=await N.functions.invoke("admin-newsletter?action=subscribers",{method:"GET"});if(s)throw new Error(await L(s));return e}})}function fn(){return O({queryKey:_.templates(),staleTime:1/0,queryFn:async()=>{const{data:e,error:s}=await N.functions.invoke("admin-newsletter?action=templates",{method:"GET"});if(s)throw new Error(await L(s));return e?.templates??[]}})}function xn(e,s,n,r){return O({queryKey:_.chrome(e,s,`${n??""}|${r??""}`),staleTime:1/0,queryFn:async()=>{const{data:a,error:i}=await N.functions.invoke("admin-newsletter",{body:{action:"chrome",subject:e,preheader:s,...n?{senderProfile:n}:{}}});if(i)throw new Error(await L(i));if(!a?.before||!a?.after)throw new Error("the preview shell came back incomplete");return a}})}function gn(){return O({queryKey:_.senderProfiles(),staleTime:6e4,queryFn:async()=>{const{data:e,error:s}=await N.functions.invoke("admin-email-gateway",{body:{action:"profiles"}});if(s)throw new Error(await L(s));return(e?.profiles??[]).filter(n=>n.stream==="bulk").map(n=>({name:String(n.name??""),fromName:String(n.fromName??""),fromAddress:String(n.fromAddress??""),isDefault:n.isDefault===!0,replyTo:String(n.replyTo??""),productName:String(n.productName??""),legalEntity:String(n.legalEntity??""),postalAddress:String(n.postalAddress??"")})).filter(n=>n.name!=="")}})}function bn(e,s){const n=!!e||s.length>0;return O({queryKey:_.preview(e,s),enabled:n,queryFn:async()=>{const{data:r,error:a}=await N.functions.invoke("admin-newsletter",{method:"POST",body:{action:"preview",segment:e,recipients:s}});if(a){const i=await V(a);throw new Error(i?.reason??(i?.error===void 0?null:String(i.error))??(a instanceof Error?a.message:String(a)))}return r}})}function yn(){return se({mutationFn:async e=>{if(!e.segment&&e.recipients.length===0)throw new Error("Choose a group or at least one recipient before sending.");const{data:s,error:n}=await N.functions.invoke("send-newsletter",{method:"POST",body:{subject:e.subject,preheader:e.preheader||void 0,content:e.content,contentText:e.contentText,...e.segment?{segment:e.segment}:{},...e.segmentLabel?{segmentLabel:e.segmentLabel}:{},recipients:e.recipients,trackingOpens:e.trackingOpens===!0,trackingClicks:e.trackingClicks===!0,...e.senderProfile?{senderProfile:e.senderProfile}:{}}});if(n){const r=await V(n),a=Kt(r);if(a)throw new Gt(a);const i=r;throw new Error(i?.reason??i?.reasons?.[0]??(i?.error===void 0?null:String(i.error))??(n instanceof Error?n.message:String(n)))}return s}})}const Be=10*1e3;function Ue(){return typeof document<"u"&&document.visibilityState==="visible"}function Wt(e){return Ue()&&e==="sending"?Be:!1}function Vt(e){return Ue()&&e?.some(s=>s.status==="sending")?Be:!1}function Qt(e,s){const n=new URLSearchParams({action:"campaigns"});for(const[r,a]of Object.entries(e))a==null||a===""||n.set(r,String(a));return n.toString()}function Yt(e={}){return O({queryKey:_.campaigns(e),refetchInterval:s=>Vt(s.state.data?.campaigns),queryFn:async()=>{const{data:s,error:n}=await N.functions.invoke(`admin-newsletter?${Qt(e)}`,{method:"GET"});if(n)throw new Error(await L(n));return s}})}function Zt(e){return O({queryKey:_.campaign(e??""),enabled:!!e,refetchInterval:s=>Wt(s.state.data?.campaign?.status),queryFn:async()=>{const s=new URLSearchParams({action:"campaign",id:e??""}),{data:n,error:r}=await N.functions.invoke(`admin-newsletter?${s.toString()}`,{method:"GET"});if(r)throw new Error(await L(r));return n}})}function Xt(e,s={}){return Re({queryKey:_.campaignRecipients(e??"",s),enabled:!!e,initialPageParam:null,getNextPageParam:n=>n.nextCursor,queryFn:async({pageParam:n})=>
2{const r=new URLSearchParams({action:"campaign-recipients",id:e??""});for(const[o,m]of Object.entries(s))m==null||m===""||r.set(o,String(m));n&&r.set("cursor",String(n));const{data:a,error:i}=await N.functions.invoke(`admin-newsletter?${r.toString()}`,{method:"GET"});if(i)throw new Error(await L(i));return a}})}const Jt={one_off:"One-off",scheduled:"Scheduled",triggered:"Automation",test:"Test"},es={default:"text-foreground",muted:"text-muted-foreground",alert:"text-destructive"};function ts(e){return e.segment?z[e.segment]??e.segment:"Named recipients"}function ve({value:e,kind:s}){const n=T(e);return t.jsx(j,{className:g("text-right text-xs tabular-nums",n===D?"text-muted-foreground":"text-foreground"),title:n===D?`${s} tracking was off for this campaign, so there is no number â not a zero`:void 0,children:n})}function ss({campaign:e,now:s,onOpen:n}){const r=qe(e,s),a=$e(e),{stats:i}=e,o=!!n;return t.jsxs(C,{className:g("transition-colors duration-150",o&&"cursor-pointer hover:bg-muted/50"),onClick:o?()=>n?.(e.id):void 0,children:[t.jsx(j,{className:"py-3 align-middle",children:t.jsxs("div",{className:"flex flex-col gap-0.5",children:[o?t.jsx("button",{type:"button",className:"w-fit text-left text-sm font-semibold text-foreground underline-offset-4 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",onClick:m=>{m.stopPropagation(),n?.(e.id)},children:e.name}):t.jsx("span",{className:"text-sm font-semibold text-foreground",children:e.name}),t.jsx("span",{className:"line-clamp-1 text-xs text-muted-foreground",title:e.subjectTemplate,children:e.subjectTemplate})]})}),t.jsx(j,{className:"text-xs text-muted-foreground",children:Jt[e.kind]??e.kind}),t.jsx(j,{className:"text-xs text-muted-foreground",children:ts(e)}),t.jsx(j,{children:t.jsxs("div",{className:"flex flex-col gap-0.5",children:[t.jsx("span",{className:g("text-xs",es[r.tone]),children:r.primary}),r.secondary&&t.jsx("span",{className:g("text-[11px]",r.tone==="alert"?"text-destructive":"text-muted-foreground"),children:r.secondary})]})}),t.jsx(j,{className:"text-right text-xs tabular-nums",children:u(i.accepted)}),t.jsx(j,{className:"text-right text-xs tabular-nums",children:t.jsxs("div",{className:"flex flex-col items-end gap-1",children:[t.jsxs("span",{children:[u(i.delivered)," ",t.jsx("span",{className:"text-muted-foreground",children:T(i.rates.deliveredOfAccepted)})]}),t.jsx("span",{className:"block h-1 w-20 overflow-hidden rounded-full bg-border",children:t.jsx("span",{className:g("block h-full origin-left rounded-full transition-transform duration-500 ease-out",a?"bg-destructive":"bg-primary"),style:{transform:`scaleX(${i.rates.deliveredOfAccepted??0})`}})}),i.bounced>0&&t.jsxs("span",{className:g("animate-in fade-in duration-300 text-[11px]",a?"text-destructive":"text-muted-foreground"),children:[u(i.bounced)," bounced"]})]})}),t.jsx(ve,{value:i.rates.openedOfDelivered,kind:"Open"}),t.jsx(ve,{value:i.rates.clickedOfDelivered,kind:"Click"}),t.jsx(j,{className:"text-right",children:t.jsx(Me,{campaign:e})})]})}function ns({budget:e}){if(!e)return t.jsxs("div",{className:"flex flex-col gap-1.5 rounded-xl border border-border bg-muted/40 p-4",children:[t.jsx("div",{className:"text-[11px] uppercase tracking-wide text-muted-foreground",children:"Today's budget"}),t.jsxs("div",{className:"flex items-center gap-2 text-sm font-medium text-muted-foreground",children:[t.jsx(Q,{className:"h-4 w-4 shrink-0","aria-hidden":"true"}),"Could not be read"]}),t.jsx("p",{className:"text-[11px] text-muted-foreground",children:"The day's count is unavailable, so how much is left is unknown."})]});const s=Ft(e.sentToday,e.ceiling);return t.jsxs("div",{className:"flex flex-col gap-2 rounded-xl border border-border bg-muted/40 p-4",children:[t.jsxs("div",{className:"flex items-baseline justify-between gap-2",children:[t.jsx("span",{className:"text-[11px] uppercase tracking-wide text-muted-foreground",children:"Today's budget"}),t.jsx("span",{className:"text-[11px] font-medium text-muted-foreground",children:"bulk stream"})]}),t.jsxs("div",{className:"text-2xl font-semibold tracking-tight",children:[u(e.sentToday),t.jsxs("span",{className:"ml-1 text-sm font-medium text-muted-foreground",children:["/ ",u(e.ceiling)]})]}),t.jsx("div",{role:"progressbar","aria-label":"Share of today's send budget used","aria-valuemin":0,"aria-valuemax":e.ceiling,"aria-valuenow":Math.min(e.sentToday,e.ceiling),"aria-valuetext":`${u(e.sentToday)} of ${u(e.ceiling)}`,className:"h-1.5 overflow-hidden rounded-full bg-border",children:t.jsx("div",{className:"h-full origin-left rounded-full bg-primary transition-transform duration-500 ease-out",style:{transform:`scaleX(${s})`}})})]})}function M({label:e,value:s,note:n,emphasis:r}){return t.jsxs("div",{className:"flex flex-col gap-1.5 rounded-xl border border-border p-4",children:[t.jsx("div",{className:"text-[11px] uppercase tracking-wide text-muted-foreground",children:e}),t.jsx("div",{className:r?"text-2xl font-semibold tracking-tight text-destructive":"text-2xl font-semibold tracking-tight",children:s}),t.jsx("div",{className:"text-[11px] text-muted-foreground",children:n})]})}const rs=.005,as="â",is=["Sent · last 30 days","Delivered","Opened","Unsubscribed","Today's budget"];function os({rollup:e,budget:s,loading:n,unavailable:r}){if(r)return t.jsx("section",{className:"grid gap-3 md:grid-cols-3 xl:grid-cols-5",children:is.map(i=>t.jsx(M,{label:i,value:as,note:"the history could not be read"},i))});if(n)return t.jsx("section",{className:"grid gap-3 md:grid-cols-3 xl:grid-cols-5",children:Array.from({length:5},(i,o)=>t.jsx(v,{className:"h-[104px] rounded-xl"},o))});const a=T(e.openedOfDelivered);return t.jsxs("section",{className:"grid gap-3 md:grid-cols-3 xl:grid-cols-5",children:[t.jsx(M,{label:"Sent · last 30 days",value:u(e.accepted),note:`across ${u(e.campaigns)} ${e.campaigns===1?"campaign":"campaigns"}`}),t.jsx(M,{label:"Delivered",value:T(e.deliveredOfAccepted),note:`${u(e.bounced)} bounced · ${u(e.complained)} complaints`}),t.jsx(M,{label:"Opened",value:a,note:a===D?"open tracking is off during the warm-up":"of delivered, not of sent · a weak signal"}),t.jsx(M,{label:"Unsubscribed",value:T(e.unsubscribedOfDelivered),emphasis:e.unsubscribedOfDelivered>=rs,note:`${u(e.unsubscribed)} ${e.unsubscribed===1?"person":"people"} · the line is 0.5%`}),t.jsx(ns,{budget:s}),t.jsx("p",{className:"col-span-full text-[11px] text-muted-foreground",children:"Across the campaigns listed below â the most recent page, not the whole account."})]})}const Y="any",Ge="all",ds={q:"",segment:Y,range:"90"},ls=[{value:"30",label:"Last 30 days"},{value:"90",label:"Last 90 days"},{value:"365",label:"Last 12 months"},{value:Ge,label:"All time"}];function cs(e,s){const n=new Set;for(const r of e)r.segment&&n.add(r.segment);return s!==Y&&n.add(s),[...n].map(r=>({value:r,label:z[r]??r}))}
2function us({value:e,onChange:s,campaigns:n}){const r=cs(n,e.segment);return t.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[t.jsxs("div",{className:"relative",children:[t.jsx(ot,{htmlFor:"campaign-search",className:"sr-only",children:"Search campaigns"}),t.jsx(dt,{className:"pointer-events-none absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground","aria-hidden":"true"}),t.jsx(lt,{id:"campaign-search",type:"search",value:e.q,placeholder:"Search subject or name",className:"h-8 w-56 pl-8 text-xs",onChange:a=>s({...e,q:a.target.value})})]}),t.jsxs(pe,{value:e.segment,onValueChange:a=>s({...e,segment:a}),children:[t.jsx(fe,{className:"h-8 w-44 text-xs","aria-label":"Filter by audience",children:t.jsx(xe,{})}),t.jsxs(ge,{children:[t.jsx(J,{value:Y,children:"Audience: any"}),r.map(a=>t.jsx(J,{value:a.value,children:a.label},a.value))]})]}),t.jsxs(pe,{value:e.range,onValueChange:a=>s({...e,range:a}),children:[t.jsx(fe,{className:"h-8 w-36 text-xs","aria-label":"Filter by date",children:t.jsx(xe,{})}),t.jsx(ge,{children:ls.map(a=>t.jsx(J,{value:a.value,children:a.label},a.value))})]})]})}function ms(e,s){const n=s.q.trim().toLowerCase();return e.filter(r=>s.segment!==Y&&r.segment!==s.segment?!1:n?r.name.toLowerCase().includes(n)||r.subjectTemplate.toLowerCase().includes(n):!0)}function hs(e,s){if(e===Ge)return;const n=Number(e);if(!(!Number.isFinite(n)||n<=0))return new Date(s.getTime()-n*24*60*60*1e3).toISOString()}const ps=.001,ze={attempted:"Attempted",accepted:"Accepted",delivered:"Delivered",opened:"Opened",clicked:"Clicked"},fs={opened:"open tracking was off for this campaign",clicked:"click tracking was off for this campaign"};function xs(e){const{attempted:s,accepted:n,delivered:r,opened:a,clicked:i,rates:o}=e,m=[{key:"attempted",count:s,share:A(s,s),shareOf:"attempted"},{key:"accepted",count:n,share:A(n,s),shareOf:"attempted"},{key:"delivered",count:r,share:o.deliveredOfAccepted,shareOf:"accepted"},{key:"opened",count:a,share:o.openedOfDelivered,shareOf:"delivered"},{key:"clicked",count:i,share:o.clickedOfDelivered,shareOf:"delivered"}];let d=1;return m.map(({key:l,count:f,share:c,shareOf:h})=>{const b=c!==null;let p=null;return b&&(p=Math.min(A(f,s),d),d=p),{key:l,label:ze[l],count:f,share:c,shareOf:h,width:p,absence:b?null:fs[l]??"not measured"}})}function gs(e){return e.rates.complainedOfAccepted>=ps}function bs(e){const s=`the hard/soft split is not recorded yet · ${e.bounced} bounced in total`;return[{key:"hard_bounces",label:"Hard bounces",count:e.bouncedHard,share:null,note:e.bouncedHard===null?s:"suppressed automatically",alarming:!1},{key:"soft_bounces",label:"Soft bounces",count:e.bouncedSoft,share:null,note:e.bouncedSoft===null?s:"retried, then dropped",alarming:!1},{key:"complaints",label:"Spam complaints",count:e.complained,share:e.rates.complainedOfAccepted,note:"the 0.10% line is the one that matters",alarming:gs(e)},{key:"unsubscribed",label:"Unsubscribed",count:e.unsubscribed,share:e.rates.unsubscribedOfDelivered,note:"recorded by the footer link, not by tracking",alarming:!1}]}const ys={unsubscribed:"unsubscribed between scheduling and sending",suppressed:"on the suppression list from an earlier hard bounce or complaint",frequency_capped:"held back by the frequency cap",render_failed:"the message could not be rendered for this address",invalid_address:"not a deliverable email address",not_a_subscriber:"not on the subscriber list",not_eligible:"on the list, but not eligible for this audience",unspecified:"refused without a reason being recorded"};function G(e){return e.replace(/\s+/g," ").trim().slice(0,80)}function Ke(e){const s=G(e).toLowerCase(),n=ys[s];return n||`refused for a reason this screen does not recognise (${G(e)||"no reason recorded"})`}function He(e){const s=G(e),n=s.toLowerCase();return n==="invalid_address"?"not a deliverable email address":n.startsWith("suppressed")?"the gateway found this address on the suppression list":n.startsWith("mode:paused")?"the email gateway was paused, so nothing left the system":n.startsWith("mode:guarded")?"the gateway is in guarded mode and this address is not allowlisted":n.startsWith("mode:")?`held by the gateway's sending mode (${s})`:`held by a gateway rule this screen does not recognise (${s||"no rule recorded"})`}function Ne(e,s){return Object.entries(e??{}).map(([n,r])=>({token:n,count:r,sentence:s(n)})).sort((n,r)=>r.count-n.count||n.token.localeCompare(r.token))}const js=new Intl.DateTimeFormat("en-GB",{hour:"2-digit",minute:"2-digit"}),vs=new Intl.DateTimeFormat("en-GB",{day:"numeric",month:"short"}),Ns=new Intl.DateTimeFormat("en-GB",{day:"numeric",month:"short",hour:"2-digit",minute:"2-digit"});function ws(e){const s=e.map(a=>a.delivered+a.opened+a.clicked),n=s.reduce((a,i)=>i>a?i:a,0),r=e.length>0&&Date.parse(e[e.length-1].bucket)-Date.parse(e[0].bucket)>=2880*60*1e3;return e.map((a,i)=>{const o=new Date(a.bucket),m=Number.isFinite(o.getTime());
2return{bucket:a.bucket,label:m?r?vs.format(o):js.format(o):"â",fullLabel:m?Ns.format(o):"â",delivered:a.delivered,opened:a.opened,clicked:a.clicked,total:s[i],deliveredShare:A(a.delivered,n),openedShare:A(a.opened,n),clickedShare:A(a.clicked,n)}})}function ks(e){return e.provisional?{final:!1,text:"Delivery finishes within minutes; opens and complaints keep arriving for two days. This reading is provisional until 72 hours after the last message went out."}:e.accepted===0?{final:!0,text:"No message was accepted for delivery, so there is nothing further to arrive. These numbers are final because the campaign stopped, not because a send has aged out."}:{final:!0,text:"More than 72 hours have passed since the last message went out, so these numbers are final."}}const Ss={sent:"Sent",delivered:"Delivered",opened:"Opened",clicked:"Clicked",bounced:"Bounced",complained:"Complained",unsubscribed:"Unsubscribed"},As=new Set(["bounced","complained"]);function We(e){const s=e.skipReason??"";if(e.state==="skipped")return{label:"Not sent",detail:Ke(s),tone:"alert",at:null};if(e.state==="withheld"||e.state==="redirected")return{label:e.state==="withheld"?"Withheld":"Redirected",detail:He(s),tone:"alert",at:null};if(e.state==="failed")return{label:"Failed",detail:G(s)||"the provider refused it without saying why",tone:"alert",at:null};if(!e.lastEvent)return{label:e.state==="queued"?"Queued":"No events yet",detail:null,tone:"muted",at:null};const n=e.lastEvent.type;return{label:Ss[n]??G(n),detail:null,tone:As.has(n)?"alert":"default",at:e.lastEvent.at}}const Ts=["name","kind","status","subject_template","audience","created_at","started_at","finished_at","created_by","accepted","delivered","bounced","complained","opened","clicked","unsubscribed","delivered_of_accepted","opened_of_delivered","clicked_of_delivered"],Es=/^[=+\-@\t\r]/;function Ve(e){if(e==null)return"";const s=String(e),n=Es.test(s)?`'${s}`:s;return/[",\n\r]/.test(n)?`"${n.replace(/"/g,'""')}"`:n}function Cs(e){const s=[Ts.join(",")];for(const n of e){const r=n.stats;s.push([n.name,n.kind,n.status,n.subjectTemplate,n.segment?z[n.segment]??n.segment:"Named recipients",n.createdAt,n.startedAt,n.finishedAt,n.createdBy,r.accepted,r.delivered,r.bounced,r.complained,r.opened,r.clicked,r.unsubscribed,T(r.rates.deliveredOfAccepted),T(r.rates.openedOfDelivered),T(r.rates.clickedOfDelivered)].map(Ve).join(","))}return`${s.join(` 3`)} 4`}function _s(e){return`newsletter-campaigns-${e.toISOString().slice(0,10)}.csv`}const Ps=["email","state","skip_reason","refusal","subject","subject_is_template","sent_at","last_event","last_event_at"];function Os(e,s){const n=[Ps.join(",")];for(const r of e){const a=We(r),i=r.renderedSubject;n.push([r.email,r.state,r.skipReason,a.detail,i??s,i?"no":"yes",r.sentAt,r.lastEvent?.type??null,r.lastEvent?.at??null].map(Ve).join(","))}return`${n.join(` 5`)} 6`}const H=[{key:"campaign",label:"Campaign",className:"w-[26%] min-w-[220px]"},{key:"type",label:"Type",className:"w-[9%]"},{key:"audience",label:"Audience",className:"w-[13%]"},{key:"when",label:"When",className:"w-[16%]"},{key:"sent",label:"Sent",className:"w-[7%] text-right"},{key:"delivered",label:"Delivered",className:"w-[12%] text-right"},{key:"opened",label:"Opened",className:"w-[7%] text-right"},{key:"clicked",label:"Clicked",className:"w-[7%] text-right"},{key:"status",label:"Status",className:"w-[9%] text-right"}];function Ls(){return t.jsx(t.Fragment,{children:Array.from({length:5},(e,s)=>t.jsx(C,{children:H.map(n=>t.jsx(j,{className:g("py-3",n.className),children:t.jsx(v,{className:g("h-4",n.className.includes("text-right")?"ml-auto w-10":"w-4/5")})},n.key))},s))})}async function Rs(e,s){const n=new URLSearchParams({action:"campaigns",cursor:s});e&&n.set("from",e);const{data:r,error:a}=await N.functions.invoke(`admin-newsletter?${n.toString()}`,{method:"GET"});if(a)throw new Error(await L(a));return r}function Fs(e,s){const n=new Set,r=[];for(const a of[...e,...s.flatMap(i=>i.campaigns)])n.has(a.id)||(n.add(a.id),r.push(a));return r}function Ds({onOpenCampaign:e,onNewCampaign:s,onOpenAutomations:n}){const{toast:r}=ne(),[a,i]=x.useState("all"),[o,m]=x.useState(ds),d=x.useMemo(()=>hs(o.range,new Date),[o.range]),l=Yt(x.useMemo(()=>({from:d}),[d])),f=l.data?.nextCursor??null,c=`${d??"all"}|${f??""}
6`,[h,b]=x.useState(null),p=Re({queryKey:["newsletter","campaigns-older",d??null,f],enabled:f!==null&&h===c,initialPageParam:f??"",getNextPageParam:y=>y.nextCursor,queryFn:({pageParam:y})=>Rs(d,String(y))}),k=x.useMemo(()=>h===c?p.data?.pages??[]:[],[h,c,p.data?.pages]),S=h===c&&p.data!==void 0?p.hasNextPage:f!==null,ue=h===c&&p.isFetching,Xe=x.useCallback(()=>{h!==c?b(c):p.data===void 0?p.refetch():p.fetchNextPage()},[h,c,p]),E=x.useMemo(()=>Fs(l.data?.campaigns??[],k),[l.data?.campaigns,k]),I=x.useMemo(()=>l.dataUpdatedAt?new Date(l.dataUpdatedAt):new Date,[l.dataUpdatedAt]),F=x.useMemo(()=>ms(Ct(E,a),o),[E,a,o]),Je=x.useMemo(()=>_t(E),[E]),et=x.useMemo(()=>Lt(E,I),[E,I]),tt=x.useCallback(()=>{if(F.length===0){r({title:"Nothing to export",description:"This filter matches no campaigns."});return}const y=new Blob([Cs(F)],{type:"text/csv;charset=utf-8"}),$=URL.createObjectURL(y),X=document.createElement("a");X.href=$,X.download=_s(I),X.click(),URL.revokeObjectURL($)},[F,I,r]),K=l.isLoading,Z=l.isError&&!l.data,st=E.length>0&&F.length===0;return t.jsxs("div",{className:"space-y-5",children:[t.jsxs("header",{className:"flex flex-wrap items-start justify-between gap-4",children:[t.jsxs("div",{className:"space-y-1",children:[t.jsx("h1",{className:"text-xl font-semibold tracking-tight",children:"Email Campaigns"}),t.jsx("p",{className:"text-sm text-muted-foreground",children:"Every campaign this account has sent, is sending, or will send. A send cannot be recalled."})]}),t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsxs(w,{variant:"outline",size:"sm",onClick:tt,children:[t.jsx(Ee,{className:"mr-2 h-4 w-4"}),"Export CSV"]}),n?t.jsx(w,{size:"sm",variant:"outline",onClick:n,className:"transition-colors duration-150",children:"Automations"}):null,t.jsxs(w,{size:"sm",onClick:s,children:[t.jsx(ct,{className:"mr-2 h-4 w-4"}),"New campaign"]})]})]}),t.jsx(os,{rollup:et,budget:l.data?.budget??null,loading:K,unavailable:l.isError&&!l.data}),t.jsxs("section",{className:"flex flex-wrap items-center justify-between gap-3 border-b border-border",children:[t.jsx("div",{role:"tablist","aria-label":"Campaign status",className:"flex gap-1",children:De.map(y=>{const $=y===a;return t.jsxs("button",{type:"button",role:"tab","aria-selected":$,onClick:()=>i(y),className:g("h-9 border-b-2 px-3 text-[13px] transition-colors duration-150",$?"border-primary font-semibold text-foreground":"border-transparent font-medium text-muted-foreground hover:text-foreground"),children:[Et[y]," ",t.jsx("span",{className:"font-normal text-muted-foreground",children:u(Je[y])})]},y)})}),t.jsx("div",{className:"pb-2",children:t.jsx(us,{value:o,onChange:m,campaigns:E})})]}),l.isError&&t.jsxs(re,{variant:"destructive",children:[t.jsx(Q,{className:"h-4 w-4"}),t.jsx(ae,{children:"Could not read the campaign history"}),t.jsxs(ie,{className:"space-y-2",children:[t.jsx("p",{children:l.error.message}),t.jsx(w,{variant:"outline",size:"sm",onClick:()=>l.refetch(),children:"Try again"})]})]}),t.jsx("section",{className:"overflow-hidden rounded-xl border border-border",children:t.jsxs(Ce,{children:[t.jsx(_e,{children:t.jsx(C,{className:"bg-muted/50 hover:bg-muted/50",children:H.map(y=>t.jsx(q,{className:g("h-9 text-[11px] uppercase tracking-wide text-muted-foreground",y.className),children:y.label},y.key))})}),t.jsx(Pe,{className:"animate-in fade-in-0 duration-300 ease-out",children:K?t.jsx(Ls,{}):Z?t.jsx(C,{className:"hover:bg-transparent",children:t.jsx(j,{colSpan:H.length,className:"py-12 text-center text-sm text-muted-foreground",children:"The campaign history could not be read, so there is nothing to list. This is not an empty account."})}):F.length>0?F.map(y=>t.jsx(ss,{campaign:y,now:I,onOpen:e},y.id)):t.jsx(C,{className:"hover:bg-transparent",children:t.jsx(j,{colSpan:H.length,className:"py-12 text-center",children:st?t.jsxs("div",{className:"space-y-1",children:[t.jsx("p",{className:"text-sm font-medium",children:"No campaigns match this filter"}),t.jsxs("p",{className:"text-xs text-muted-foreground",children:[u(E.length)," campaigns are hidden by the tab, the search or the audience."]})]}):t.jsxs("div",{className:"space-y-1",children:[t.jsx("p",{className:"text-sm font-medium",children:"No campaigns yet"}),t.jsx("p",{className:"mx-auto max-w-md text-xs text-muted-foreground",children:"The history starts with the first send after this feature shipped. Campaigns sent before it have no record here and never will."})]})})})},K?"loading":Z?"unreadable":"ready")]})}),S&&!Z&&t.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3 rounded-lg border border-border px-4 py-3 text-xs text-muted-foreground animate-in fade-in-0 duration-300 ease-out",children:[t.jsxs("p",{children:["Showing the ",u(E.length)," most recent campaigns in this range. Older ones exist: the tabs, the totals, the filters and the export cover only what is loaded until they are."]}),t.jsxs(w,{variant:"outline",size:"sm",onClick:Xe,disabled:ue,children:[ue&&t.jsx(ee,{className:"mr-2 h-4 w-4 animate-spin"}),"Load older campaigns"]})]}),p.isError&&h===c&&t.jsxs("p",{className:"text-xs text-destructive animate-in fade-in-0 duration-300 ease-out",children:["Could not read older campaigns: ",p.error.message]}),t.jsxs("p",{className:"flex items-center gap-2 text-[11px] text-muted-foreground",children:[l.isFetching&&!K&&t.jsx(ee,{className:"h-3 w-3 animate-spin","aria-hidden":"true"}),"Rates are a share of ",t.jsx("strong",{className:"font-semibold",children:"delivered"}),", never of attempted â a bounced address cannot open anything. Open rate is a weak signal wherever a mail client prefetches images; clicks are the number to act on."]})]})}const Is={forecast:(e,s,n,r,a)=>["newsletter","forecast",e??null,[...s].sort(),n,r,a]};async function Qe(e){const s=await V(e);return s?.reason??(s?.error===void 0?null:String(s.error))??(e instanceof Error?e.message:String(e))}
6class Ye extends Error{sentCount;constructor(s,n){super(s),this.name="AlreadySendingError",this.sentCount=n}}function jn(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"}catch{return"UTC"}}function vn(e){const s=n=>String(n).padStart(2,"0");return`${e.getFullYear()}-${s(e.getMonth()+1)}-${s(e.getDate())}T${s(e.getHours())}:${s(e.getMinutes())}`}function Nn(){const e=Oe();return se({mutationFn:async s=>{const{draft:n,when:r}=s;if(!n.segment&&n.recipients.length===0)throw new Error("Choose a group or at least one recipient before scheduling.");const{data:a,error:i}=await N.functions.invoke("admin-newsletter",{method:"POST",body:{action:"schedule",...s.campaignId?{campaignId:s.campaignId}:{},name:s.name,kind:"newsletter",subjectTemplate:n.subject,preheaderTemplate:n.preheader??"",htmlTemplate:n.content,textTemplate:n.contentText,...n.segment?{segment:n.segment}:{},...n.senderProfile?{senderProfile:n.senderProfile}:{},namedRecipients:n.recipients,scheduledAt:r.at,timezone:r.timezone,quietHours:r.quietHours===!0,trackingOpens:n.trackingOpens===!0,trackingClicks:n.trackingClicks===!0}});if(i)throw new Error(await Qe(i));return a},onSuccess:()=>{e.invalidateQueries({queryKey:["newsletter","campaigns"]})}})}function le(e){const s=Oe();return se({mutationFn:async n=>{const{data:r,error:a}=await N.functions.invoke("admin-newsletter",{method:"POST",body:{action:e,campaignId:n.campaignId}});if(a){const i=await V(a),o=i?.reason??(i?.error===void 0?null:String(i.error))??(a instanceof Error?a.message:String(a));throw typeof i?.sentCount=="number"&&i.sentCount>0?new Ye(o,i.sentCount):new Error(o)}return r},onSuccess:(n,r)=>{s.invalidateQueries({queryKey:_.campaign(r.campaignId)}),s.invalidateQueries({queryKey:["newsletter","campaigns"]})}})}const $s=()=>le("cancel"),Ms=()=>le("stop"),qs=()=>le("resume");function wn(e,s,n){const r=n?.quietHours===!0;return O({queryKey:Is.forecast(e,s,n?.at??"",n?.timezone??"",r),enabled:n!==void 0&&n.at!==""&&n.timezone!=="",queryFn:async()=>{const a=new URLSearchParams({action:"forecast",at:n?.at??"",tz:n?.timezone??""});r&&a.set("quiet","true"),e&&a.set("segment",e);for(const m of s)a.append("recipient",m);const{data:i,error:o}=await N.functions.invoke(`admin-newsletter?${a.toString()}`,{method:"GET"});if(o)throw new Error(await Qe(o));return i.forecast}})}function Bs(e){return e==="scheduled"||e==="draft"?"cancel":e==="sending"?"stop":e==="paused"||e==="failed"?"resume":null}const W={cancel:{label:"Cancel",title:"Cancel this campaign?",body:"It is queued and nothing has been delivered. Cancelling takes it out of the queue for good â there is no un-cancel, and a new send is a new campaign with its own statistics.",confirm:"Cancel the campaign",Icon:wt},stop:{label:"Stop",title:"Stop this campaign?",body:"It is sending right now. What has already been delivered stays delivered and cannot be recalled; nothing further goes out.",confirm:"Stop sending",Icon:mt},resume:{label:"Resume",title:"Put this campaign back in the queue?",body:"It paused at the daily ceiling. Resuming queues it for its scheduled time, and the dispatcher picks it up on its next tick.",confirm:"Resume",Icon:ut}},Us="Its last run failed before it finished, so it closed without delivering to everyone. Resuming puts it back in the queue and the dispatcher retries only the recipients it still owes â the people it already reached are not mailed a second time.";function Gs(e,s){return e==="resume"&&s==="failed"?Us:W[e].body}function zs({campaignId:e,status:s}){const{toast:n}=ne(),[r,a]=x.useState(null),[i,o]=x.useState(null),m=$s(),d=Ms(),l=qs(),f=Bs(s);if(f===null)return null;const c=W[f].Icon,h=m.isPending||d.isPending||l.isPending,b=W[r??f],p=async k=>{const ce=k==="cancel"?m:k==="stop"?d:l;try{const S=await ce.mutateAsync({campaignId:e});a(null),o(null),n({title:k==="resume"?"Back in the queue":"Stopped",description:k==="resume"?"It will be picked up at its scheduled time.":"Nothing further will go out."+(typeof S.sentCount=="number"&&S.sentCount>0?` ${S.sentCount.toLocaleString("en-GB")} already went and cannot be recalled.`:"")}
6)}catch(S){if(S instanceof Ye){o(S.sentCount),a("stop");return}a(null),n({title:"That did not work",description:S instanceof Error?S.message:String(S),variant:"destructive"})}};return t.jsxs(t.Fragment,{children:[t.jsxs(w,{variant:f==="resume"?"outline":"destructive",size:"sm",disabled:h,onClick:()=>{o(null),a(f)},children:[t.jsx(c,{className:"mr-1.5 h-3.5 w-3.5","aria-hidden":"true"}),W[f].label]}),t.jsx(ht,{open:r!==null,onOpenChange:k=>{k||a(null)},children:t.jsxs(pt,{children:[t.jsxs(ft,{children:[t.jsx(xt,{children:b.title}),t.jsxs(gt,{children:[i!==null&&t.jsxs("span",{className:"mb-2 block font-medium text-foreground",children:[i.toLocaleString("en-GB")," ",i===1?"message has":"messages have"," already been delivered, so this can no longer be cancelled."]}),Gs(r??f,s)]})]}),t.jsxs(bt,{children:[t.jsx(yt,{disabled:h,children:"Leave it"}),t.jsx(jt,{disabled:h,onClick:k=>{k.preventDefault(),p(r??f)},children:b.confirm})]})]})})]})}function Ks({step:e}){const s=e.width===null;return t.jsxs("div",{className:"space-y-1.5",children:[t.jsxs("div",{className:"flex items-baseline justify-between gap-3",children:[t.jsx("span",{className:"text-[13px] font-medium text-foreground",children:e.label}),t.jsxs("span",{className:"flex items-baseline gap-2 tabular-nums",children:[t.jsx("span",{className:"text-[13px] font-semibold text-foreground",children:u(e.count)}),t.jsxs("span",{className:"text-right text-xs text-muted-foreground",title:e.absence??void 0,children:[t.jsx("span",{className:"inline-block w-14",children:T(e.share)}),t.jsx("span",{className:"ml-1 inline-block w-[4.5rem] text-left text-[11px] opacity-70",children:e.key===e.shareOf?"":`of ${ze[e.shareOf].toLowerCase()}`})]})]})]}),t.jsx("div",{className:"h-2 overflow-hidden rounded-full bg-muted",children:!s&&t.jsx("div",{className:"h-full rounded-full bg-primary transition-[width] duration-500 ease-out",style:{width:`${(e.width??0)*100}%`}})}),e.absence&&t.jsx("p",{className:"text-[11px] text-muted-foreground",children:e.absence})]})}function Hs({tile:e}){const s=e.count===null?D:u(e.count);return t.jsxs("div",{className:"space-y-1 rounded-lg border border-border p-3",children:[t.jsx("div",{className:"text-[11px] uppercase tracking-wide text-muted-foreground",children:e.label}),t.jsxs("div",{className:"flex items-baseline gap-2",children:[t.jsx("span",{className:g("text-lg font-semibold tabular-nums tracking-tight",e.alarming?"text-destructive":"text-foreground"),children:s}),e.share!==null&&t.jsx("span",{className:g("text-xs tabular-nums",e.alarming?"text-destructive":"text-muted-foreground"),children:T(e.share)})]}),t.jsx("p",{className:g("text-[11px]",e.alarming?"text-destructive":"text-muted-foreground"),children:e.note})]})}function Ws({stats:e}){const s=xs(e),n=bs(e);return t.jsxs("section",{"aria-labelledby":"funnel-heading",className:"space-y-4 rounded-xl border border-border p-5",children:[t.jsxs("header",{className:"space-y-0.5",children:[t.jsx("h2",{id:"funnel-heading",className:"text-sm font-semibold",children:"Delivery funnel"}),t.jsx("p",{className:"text-[11px] text-muted-foreground",children:"Each step against the stage it is measured from"})]}),t.jsx("div",{className:"space-y-3",children:s.map(r=>t.jsx(Ks,{step:r},r.key))}),t.jsx("div",{className:"grid gap-2 sm:grid-cols-2 xl:grid-cols-4",children:n.map(r=>t.jsx(Hs,{tile:r},r.key))}),t.jsxs("p",{className:"text-[11px] leading-relaxed text-muted-foreground",children:["Open and click rates are a share of"," ",t.jsx("strong",{className:"font-semibold",children:"delivered"}),", never of attempted â a bounced address cannot open anything. Opens are inflated wherever a mail client prefetches images, so a person reading and a machine fetching look identical; clicks are the number to act on."]})]})}const we=[{key:"delivered",label:"Delivered",swatch:"bg-primary"},{key:"opened",label:"Opened",swatch:"bg-primary/50"}
6,{key:"clicked",label:"Clicked",swatch:"bg-foreground/70"}];function Vs({timeline:e,stats:s}){const n=ws(e),r=ks(s);return t.jsxs("section",{"aria-labelledby":"timeline-heading",className:"space-y-4 rounded-xl border border-border p-5",children:[t.jsxs("header",{className:"flex flex-wrap items-center justify-between gap-3",children:[t.jsx("h2",{id:"timeline-heading",className:"text-sm font-semibold",children:"Events over time"}),t.jsx("ul",{className:"flex flex-wrap items-center gap-3",children:we.map(a=>t.jsxs("li",{className:"flex items-center gap-1.5 text-[11px] text-muted-foreground",children:[t.jsx("span",{"aria-hidden":"true",className:g("h-2 w-2 rounded-sm",a.swatch)}),a.label]},a.key))})]}),n.length===0?t.jsx("p",{className:"rounded-lg bg-muted/40 px-3 py-6 text-center text-xs text-muted-foreground",children:s.delivered>0||s.opened>0||s.clicked>0?"No per-event timing is stored for this campaign, so there is nothing to plot. The counts above are unaffected â they are read from the recipients, not from the event log.":"Nothing has been delivered, opened or clicked yet. Events appear here as the provider reports them."}):t.jsxs(t.Fragment,{children:[t.jsx("div",{"aria-hidden":"true",className:"flex h-32 items-end gap-1 overflow-x-auto",children:n.map(a=>t.jsxs("div",{className:"flex h-full min-w-[10px] flex-1 flex-col justify-end gap-px",title:`${a.label} â ${u(a.delivered)} delivered, ${u(a.opened)} opened, ${u(a.clicked)} clicked`,children:[t.jsx("div",{className:"rounded-t-sm bg-foreground
6/70 transition-[height] duration-500 ease-out",style:{height:`${a.clickedShare*100}%`}}),t.jsx("div",{className:"bg-primary/50 transition-[height] duration-500 ease-out",style:{height:`${a.openedShare*100}%`}}),t.jsx("div",{className:"rounded-b-sm bg-primary transition-[height] duration-500 ease-out",style:{height:`${a.deliveredShare*100}%`}})]},a.bucket))}),t.jsxs("table",{className:"sr-only",children:[t.jsx("caption",{children:"Delivered, opened and clicked per time bucket"}),t.jsx("thead",{children:t.jsxs("tr",{children:[t.jsx("th",{scope:"col",children:"When"}),we.map(a=>t.jsx("th",{scope:"col",children:a.label},a.key))]})}),t.jsx("tbody",{children:n.map(a=>t.jsxs("tr",{children:[t.jsx("th",{scope:"row",children:a.fullLabel}),t.jsx("td",{children:a.delivered}),t.jsx("td",{children:a.opened}),t.jsx("td",{children:a.clicked})]},a.bucket))})]}),t.jsxs("div",{className:"flex items-center justify-between text-[11px] text-muted-foreground",children:[t.jsx("span",{children:n[0]?.label}),t.jsx("span",{children:n[n.length-1]?.label})]})]}),t.jsxs("p",{className:g("text-[11px] leading-relaxed",r.final?"text-muted-foreground":"text-foreground"),children:[t.jsx("strong",{className:"font-semibold",children:r.final?"Final.":"Provisional."})," ",r.text]})]})}const Qs=new Intl.DateTimeFormat("en-GB",{day:"numeric",month:"short",hour:"2-digit",minute:"2-digit"});function Ys(e){if(!e)return"â";const s=Date.parse(e);return Number.isFinite(s)?Qs.format(new Date(s)):"â"}const Zs={default:"text-foreground",muted:"text-muted-foreground",alert:"text-destructive"};function Xs(e){return[{key:"all",label:"All",count:e.attempted},{key:"bounced",label:"Bounced",state:"bounced",count:e.bounced},{key:"complained",label:"Complained",state:"complained",count:e.complained},{key:"skipped",label:"Not sent",state:"skipped",count:e.skipped}]}function Js({row:e,template:s}){return e.renderedSubject?t.jsx("span",{className:"line-clamp-1 text-xs text-foreground",children:e.renderedSubject}):t.jsxs("div",{className:"flex flex-col gap-0.5",children:[t.jsx("span",{className:"line-clamp-1 text-xs text-muted-foreground",children:s}),t.jsx("span",{className:"text-[11px] text-muted-foreground",children:"the template · not rendered per person yet"})]})}function en({campaignId:e,subjectTemplate:s,stats:n}){const{toast:r}=ne(),[a,i]=x.useState("all"),o=Xs(n),m=o.find(c=>c.key===a)?.state,d=Xt(e,x.useMemo(()=>m?{state:m}:{},[m])),l=x.useMemo(()=>(d.data?.pages??[]).flatMap(c=>c.recipients),[d.data?.pages]),f=()=>{if(l.length===0){r({title:"Nothing to export",description:"No recipients are loaded for this filter."});return}const c=new Blob([Os(l,s)],{type:"text/csv;charset=utf-8"}),h=URL.createObjectURL(c),b=document.createElement("a");b.href=h,b.download=`campaign-${e}-recipients.csv`,b.click(),URL.revokeObjectURL(h)};return t.jsxs("section",{"aria-labelledby":"recipients-heading",className:"space-y-3 rounded-xl border border-border p-5",children:[t.jsxs("header",{className:"flex flex-wrap items-center justify-between gap-3",children:[t.jsx("h2",{id:"recipients-heading",className:"text-sm font-semibold",children:"Recipients"}),t.jsxs(w,{variant:"outline",size:"sm",onClick:f,disabled:l.length===0,children:[t.jsx(Ee,{className:"mr-2 h-4 w-4","aria-hidden":"true"}),"Export ",u(l.length)," ",l.length===1?"recipient":"recipients"]})]}),t.jsx("div",{role:"group","aria-label":"Recipient filter",className:"flex flex-wrap gap-2",children:o.map(c=>{const h=c.key===a;return t.jsxs("button",{type:"button","aria-pressed":h,onClick:()=>i(c.key),className:g("rounded-full border px-3 py-1 text-xs transition-colors duration-150",h?"border-primary bg-primary/10 font-semibold text-foreground":"border-border text-muted-foreground hover:text-foreground"),children:[c.label," ",t.jsx("span",{className:"tabular-nums",children:u(c.count)})]},c.key)})}),d.isError&&t.jsxs(re,{variant:"destructive",children:[t.jsx(Q,{className:"h-4 w-4"}),t.jsx(ae,{children:"Could not read the recipients"}),t.jsxs(ie,{className:"space-y-2",children:[t.jsx("p",{children:d.error.message}),t.jsx(w,{variant:"outline",size:"sm",onClick:()=>d.refetch(),children:"Try again"})]})]}),t.jsx("div",{className:"overflow-hidden rounded-lg border border-border",children:t.jsxs(Ce,{children:[t.jsx(_e,{children:t.jsxs(C,{className:"bg-muted/50 hover:bg-muted/50",children:[t.jsx(q,{className:"h-9 w-[30%] text-[11px] uppercase tracking-wide text-muted-foreground",children:"Address"}),t.jsx(q,{className:"h-9 w-[34%] text-[11px] uppercase tracking-wide text-muted-foreground",children:"Rendered subject"}),t.jsx(q,{className:"h-9 w-[22%] text-[11px] uppercase tracking-wide text-muted-foreground",children:"Last event"}),t.jsx(q,{className:"h-9 w-[14%] text-[11px] uppercase tracking-wide text-muted-foreground",children:"When"})]})}),t.jsx(Pe,{className:"animate-in fade-in-0 duration-300 ease-out",children:d.isLoading?Array.from({length:4},(c,h)=>t.jsx(C,{children:Array.from({length:4},(b,p)=>t.jsx(j,{className:"py-3",children:t.jsx(v,{className:"h-4 w-4/5"})},p))},h)):l.length===0?t.jsx(C,{className:"hover:bg-transparent",children:t.jsx(j,{colSpan:4,className:"py-10 text-center text-xs text-muted-foreground",children:d.isError?"The recipients could not be read, so this list is not showing them.":"No recipients in this filter."})}):l.map(c=>{const h=We(c);return t.jsxs(C,{children:[t.jsx(j,{className:"py-2.5 font-mono text-xs text-foreground",children:c.email}),t.jsx(j,{className:"py-2.5",children:t.jsx(Js,{row:c,template:s})}),t.jsx(j,{className:"py-2.5",children:t.jsxs("div",{className:"flex flex-col gap-0.5",children:[t.jsx("span",{className:g("text-xs",Zs[h.tone]),children:h.label}),h.detail&&t.jsx("span",{className:"text-[11px] text-muted-foreground",children:h.detail})]})}),t.jsx(j,{className:"py-2.5 text-xs tabular-nums text-muted-foreground",children:Ys(h.at)})]},c.email)})},d.isLoading?"loading":"ready")]})}),d.hasNextPage&&t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsxs(w,{variant:"outline",size:"sm",onClick:()=>d.fetchNextPage(),disabled:d.isFetchingNextPage,children:[d.isFetchingNextPage&&t.jsx(ee,{className:"mr-2 h-3 w-3 animate-spin","aria-hidden":"true"}),"Load more"]}),t.jsxs("span",{className:"text-[11px] text-muted-foreground",children:[u(l.length)," of"," ",u(o.find(c=>c.key===a)?.count??n.attempted)," loaded â the export writes what is loaded."]})]})]})}function tn({subjectTemplate:e,preheaderTemplate:s,htmlTemplate:n}){return t.jsxs("section",{"aria-labelledby":"sent-heading",className:"space-y-3 rounded-xl border border-border p-5",children:[t.jsxs("header",{className:"flex items-center gap-2",children:[t.jsx(vt,{className:"h-4 w-4 text-muted-foreground","aria-hidden":"true"}),t.jsx("h2",{id:"sent-heading",className:"text-sm font-semibold",children:"What was sent"})]}),t.jsxs("div",{className:"overflow-hidden rounded-lg border border-border",children:[t.jsxs("div",{className:"space-y-0.5 border-b border-border bg-muted/40 px-3 py-2",children:[t.jsx("p",{className:"line-clamp-2 text-xs font-semibold text-foreground",children:e||"No subject recorded"}),s&&t.jsx("p",{className:"line-clamp-1 text-[11px] text-muted-foreground",children:s})]}),n?t.jsx("iframe",{sandbox:"",referrerPolicy:"no-referrer",srcDoc:n,title:"The message as it was sent",className:"h-[320px] w-full bg-background"}):t.jsx("p",{className:"px-3 py-8 text-center text-xs text-muted-foreground",children:"No HTML body is stored for this campaign."})]}),t.jsx("p",{className:"text-[11px] leading-relaxed text-muted-foreground",children:"This is the stored template, not one person's copy. Nothing is rendered per recipient yet; when it is, each recipient row keeps the values it was rendered with."})]})}function ke({label:e,rows:s}){return t.jsx("ul",{"aria-label":e,className:"space-y-1.5",children:s.map(n=>t.jsxs("li",{className:"flex gap-2 text-xs leading-relaxed text-foreground",children:[t.jsx("span",{className:"shrink-0 font-semibold tabular-nums",children:u(n.count)}),t.jsxs("span",{className:"text-muted-foreground",children:["· ",n.sentence]})]},n.token))})}function sn({stats:e}
6){const s=e.withheld+e.redirected;if(e.skipped<=0&&s<=0)return null;const n=Ne(e.skippedByReason,Ke),r=Ne(e.heldByRule,He);return t.jsxs("section",{"aria-labelledby":"skipped-heading",className:"space-y-4 rounded-xl border border-border p-5",children:[t.jsxs("header",{className:"flex items-center gap-2",children:[t.jsx(kt,{className:"h-4 w-4 text-muted-foreground","aria-hidden":"true"}),t.jsx("h2",{id:"skipped-heading",className:"text-sm font-semibold",children:e.skipped>0?`Not sent to ${u(e.skipped)} ${e.skipped===1?"person":"people"}`:"Held before sending"})]}),e.skipped>0&&(n.length>0?t.jsx(ke,{label:"Refusals",rows:n}):t.jsx("p",{className:"text-xs text-muted-foreground",children:"No reason was recorded for these refusals."})),s>0&&t.jsxs("div",{className:"space-y-1.5 border-t border-border pt-3",children:[t.jsxs("p",{className:"text-[11px] font-medium uppercase tracking-wide text-muted-foreground",children:["Held by the email gateway · ",u(s)]}),t.jsx(ke,{label:"Gateway holds",rows:r}),t.jsxs("p",{className:"text-[11px] leading-relaxed text-muted-foreground",children:["A hold is the gateway's own configuration, not a decision about these addresses.",e.redirected>0&&t.jsxs(t.Fragment,{children:[" ",u(e.redirected)," went to the redirect inbox instead of the recipient."]})]})]}),t.jsx("p",{className:"text-[11px] leading-relaxed text-muted-foreground",children:"Every refusal is kept with its reason, on the success path too â an address someone ticked and the sender declined has to appear in what they read."})]})}function nn({detail:e}){const{campaign:s,stats:n}=e,r=[["Campaign",s.id],["Kind",s.kind],["Audience",s.segment?z[s.segment]??s.segment:`${u(s.namedRecipients.length)} named`],["Accepted",u(n.accepted)],["Still queued",u(n.queued)],["Refused by provider",u(n.failed)],["Held by gateway",u(n.withheld+n.redirected)],["Tracking",`opens ${s.tracking.opens?"on":"off"} · clicks ${s.tracking.clicks?"on":"off"}`],["Quiet hours",s.quietHours?"respected":"not applied"],["Timezone",s.timezone??"not recorded"]];return t.jsxs("section",{"aria-labelledby":"record-heading",className:"space-y-3 rounded-xl border border-border p-5",children:[t.jsx("h2",{id:"record-heading",className:"text-sm font-semibold",children:"Send record"}),t.jsx("dl",{className:"space-y-1.5",children:r.map(([a,i])=>t.jsxs("div",{className:"flex items-baseline justify-between gap-3",children:[t.jsx("dt",{className:"text-[11px] text-muted-foreground",children:a}),t.jsx("dd",{className:"truncate font-mono text-[11px] text-foreground",children:i})]},a))}),n.unaccounted>0&&t.jsxs("p",{className:"text-[11px] text-destructive",children:[u(n.unaccounted)," recipient rows are in a state this build does not know. The funnel above does not account for them."]}),t.jsx("p",{className:"text-[11px] leading-relaxed text-muted-foreground",children:"Batch and retry counts and the idempotency key are not on this record yet â the dispatcher that owns them arrives with scheduled sending."})]})}function rn(){return t.jsxs("div",{className:"space-y-5",role:"status","aria-busy":"true",children:[t.jsx("p",{className:"sr-only",children:"Loading this campaign."}),t.jsx(v,{className:"h-8 w-40"}),t.jsx(v,{className:"h-20 w-full rounded-xl"}),t.jsxs("div",{className:"grid gap-5 xl:grid-cols-[minmax(0,1fr)_380px]",children:[t.jsxs("div",{className:"space-y-5",children:[t.jsx(v,{className:"h-[320px] w-full rounded-xl"}),t.jsx(v,{className:"h-[220px] w-full rounded-xl"})]}),t.jsxs("div",{className:"space-y-5",children:[t.jsx(v,{className:"h-[260px] w-full rounded-xl"}),t.jsx(v,{className:"h-[160px] w-full rounded-xl"})]})]})]})}function an({campaignId:e,onBack:s}){const n=Zt(e),r=n.data,a=x.useMemo(()=>n.dataUpdatedAt?new Date(n.dataUpdatedAt):new Date,[n.dataUpdatedAt]),i=t.jsxs(w,{variant:"ghost",size:"sm",className:"-ml-2 text-muted-foreground transition-colors duration-150 hover:text-foreground",onClick:s,children:[t.jsx(Le,{className:"mr-2 h-4 w-4","aria-hidden":"true"}),"Campaigns"]});if(n.isLoading)return t.jsxs("div",{className:"space-y-4",children:[i,t.jsx(rn,{})]});if(n.isError||!r)return t.jsxs("div",{className:"space-y-4",children:[i,t.jsxs(re,{variant:"destructive",children:[t.jsx(Q,{className:"h-4 w-4"}),t.jsx(ae,{children:"Could not read this campaign"}),t.jsxs(ie,{className:"space-y-2",children:[t.jsx("p",{children:n.isError?n.error.message:"No campaign with this id was returned."}),t.jsx(w,{variant:"outline",size:"sm",onClick:()=>n.refetch(),children:"Try again"})]})]})]});const{campaign:o,stats:m,timeline:d}=r,l=qe(o,a);return t.jsxs("div",{className:"space-y-5 animate-in fade-in-0 duration-300 ease-out",children:[i,t.jsxs("header",{className:"flex flex-wrap items-start justify-between gap-4",children:[t.jsxs("div",{className:"space-y-1",children:[t.jsx("h1",{className:"text-xl font-semibold tracking-tight",children:o.name}),t.jsxs("p",{className:"text-xs text-muted-foreground",children:[l.primary,l.secondary?` · ${l.secondary}
6`:""," · audience"," ",o.segment?z[o.segment]??o.segment:"named recipients",", resolved at send time"]}),t.jsxs("p",{className:"text-xs text-muted-foreground",children:["Subject template:"," ",t.jsx("span",{className:"text-foreground",children:o.subjectTemplate})]})]}),t.jsxs("div",{className:"flex shrink-0 items-center gap-2",children:[t.jsx(Me,{campaign:o}),t.jsx(zs,{campaignId:e,status:o.status})]})]}),t.jsxs("div",{className:"grid gap-5 xl:grid-cols-[minmax(0,1fr)_380px]",children:[t.jsxs("div",{className:"space-y-5",children:[t.jsx(Ws,{stats:m}),t.jsx(Vs,{timeline:d,stats:m}),t.jsx(en,{campaignId:e,subjectTemplate:o.subjectTemplate,stats:m})]}),t.jsxs("div",{className:"space-y-5",children:[t.jsx(tn,{subjectTemplate:o.subjectTemplate,preheaderTemplate:o.preheaderTemplate,htmlTemplate:o.htmlTemplate}),t.jsx(sn,{stats:m}),t.jsx(nn,{detail:r})]})]})]})}const on=x.lazy(()=>oe(()=>import("./AutomationsView-D5qubJzu.js"),__vite__mapDeps([0,1,2,3,4])).then(e=>({default:e.AutomationsView}))),dn=x.lazy(()=>oe(()=>import("./AutomationDetail-BJOU3dcn.js"),__vite__mapDeps([5,1,2,3,4])).then(e=>({default:e.AutomationDetail})));function Se(){return t.jsxs("div",{className:"space-y-3",children:[t.jsx(v,{className:"h-8 w-48"}),t.jsx(v,{className:"h-16 w-full rounded-lg"}),t.jsx(v,{className:"h-16 w-full rounded-lg"})]})}const ln=x.lazy(()=>oe(()=>import("./AdminNewsletter-DMR-uRem.js").then(e=>e.A),__vite__mapDeps([6,1,2,3,7])).then(e=>({default:e.AdminNewsletter}))),cn=e=>t.jsx(an,{...e}),P="view",B="campaign",U="automation";function Ze(e,s){const n=e.get(P);if(n==="compose")return{kind:"compose"};if(n==="automations")return{kind:"automations"};if(n==="automation")return{kind:"automation",id:e.get(U)??void 0};if(n==="campaign"){const r=e.get(B);if(r&&s)return{kind:"campaign",id:r}}return{kind:"campaigns"}}function Ae({renderCampaign:e}={}){const[s,n]=Nt(),r=e??cn,a=Ze(s,!!r),i=d=>{const l=new URLSearchParams(s);l.delete(B),l.delete(U),d.kind==="campaigns"?l.delete(P):d.kind==="compose"?l.set(P,"compose"):d.kind==="automations"?l.set(P,"automations"):d.kind==="automation"?(l.set(P,"automation"),d.id&&l.set(U,d.id)):(l.set(P,"campaign"),l.set(B,d.id)),n(l)},o=()=>{const d=new URLSearchParams(s);d.delete(P),d.delete(B),d.delete(U),n(d,{replace:!0})},m=()=>{const d=new URLSearchParams(s);d.set(P,"automations"),d.delete(U),d.delete(B),n(d,{replace:!0})};return a.kind==="campaign"&&r?t.jsx(t.Fragment,{children:r({campaignId:a.id,onBack:o})}):a.kind==="automations"?t.jsx(x.Suspense,{fallback:t.jsx(Se,{}),children:t.jsx(on,{onNew:()=>i({kind:"automation"}),onOpen:d=>i({kind:"automation",id:d})})}):a.kind==="automation"?t.jsx(x.Suspense,{fallback:t.jsx(Se,{}),children:t.jsx(dn,{triggerId:a.id,onBack:m})}):a.kind==="compose"?t.jsxs("div",{className:"flex h-full flex-col gap-4",children:[t.jsxs(w,{variant:"ghost",size:"sm",className:"-ml-2 text-muted-foreground transition-colors duration-150 hover:text-foreground",onClick:o,children:[t.jsx(Le,{className:"mr-2 h-4 w-4"}),"Campaigns"]}),t.jsx(x.Suspense,{fallback:t.jsxs("div",{className:"space-y-4",children:[t.jsx(v,{className:"h-8 w-56"}),t.jsx(v,{className:"h-[420px] w-full rounded-xl"})]}),children:t.jsx(ln,{showHeading:!1})})]}):t.jsx(Ds,{onNewCampaign:()=>i({kind:"compose"}),onOpenAutomations:()=>i({kind:"automations"}),onOpenCampaign:r?d=>i({kind:"campaign",id:d}):void 0})}const kn=Object.freeze(Object.defineProperty({__proto__:null,NewsletterShell:Ae,default:Ae,viewFromParams:Ze},Symbol.toStringTag,{value:"Module"}));export{Gt as N,z as S,gn as a,jn as b,xn as c,pn as d,fn as e,bn as f,yn as g,Nn as h,kn as i,hn as r,wn as u,vn as w};
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.