1import{v as F,c as H,r as i,j as e,B as x,E as q,z as pt,S as _,F as Le,M as gt,g as qt,h as Te,b as Ht,a as Vt,k as Yt,t as oe,d as et,l as Gt,T as tt,L as Jt,p as st}from"./index-_aijvlUq.js";import{c as D,R as Kt}from"./RecipientRoles-Dnrpkk2i.js";import{m as Xt}from"./members-I3UAoZ9P.js";import{P as Zt}from"./PageHeader-DCofr6qo.js";import{I as K}from"./Input-ysTyZFq5.js";import{M as at}from"./Menu-CATQC14B.js";import{C as Ae}from"./ConfirmDialog-CODvETNM.js";import{E as he}from"./EmptyState-CPGKooqj.js";import{U as Qt}from"./UpgradePrompt-CWmCKX75.js";import{O as es}from"./orgRoles-D1oGgqrm.js";import{T as ts}from"./Tabs-CGDUdv1I.js";import"./downscaleImage-qyGK-a3D.js";import"./Badge-DJIi163x.js";const P={getConfigs(){return F.get("/weekly-digest/config")},getConfig(a){return F.get(`/weekly-digest/config/${a}`)},saveConfig(a,r){return F.put(`/weekly-digest/config/${a}`,r)},approverCandidates(){return F.get("/weekly-digest/approver-candidates")},getPreview(a){return F.get(`/weekly-digest/preview/${a}`,{timeout:12e4})},getInputs(a){return F.get(`/weekly-digest/inputs/${a}`)},addInput(a,r){return F.post(`/weekly-digest/inputs/${a}`,{bodyText:r})},editInput(a,r){return F.put(`/weekly-digest/input/${a}`,{bodyText:r})},setInputExcluded(a,r){return F.put(`/weekly-digest/input/${a}/excluded`,{excluded:r})}};function nt(a){if(!a)return"";const r=new Date(a);return Number.isNaN(r.getTime())?String(a).slice(0,10):r.toLocaleDateString("en-US",{weekday:"short",month:"short",day:"numeric"})+" "+r.toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"})}function ss({ensembleId:a}){const r=H(d=>d.showError),n=H(d=>d.showSuccess),[l,c]=i.useState(null),[u,v]=i.useState(!1),[C,p]=i.useState(null),[w,h]=i.useState(""),[j,I]=i.useState(""),[E,A]=i.useState(!1),k=i.useCallback(()=>{P.getInputs(a).then(c).catch(()=>c({digest:null,inputs:[]}))},[a]);if(i.useEffect(()=>{k()},[k]),!l)return null;const g=l.inputs||[],L=g.filter(d=>!d.excludedAt).length;async function X(d){if(w.trim()){A(!0);try{await P.editInput(d.id,w.trim()),n("Reply updated"),p(null),k()}catch(O){r(O?.message||q)}finally{A(!1)}}}async function T(d){A(!0);try{await P.setInputExcluded(d.id,!d.excludedAt),n(d.excludedAt?"Reply restored â back in the digest":"Reply excluded from the digest"),k()}catch(O){r(O?.message||q)}finally{A(!1)}}async function te(){if(j.trim()){A(!0);try{await P.addInput(a,j.trim()),n("Note added to this weekâs digest inputs"),I(""),k()}catch(d){r(d?.message||q)}finally{A(!1)}}}return e.jsxs("div",{className:"mt-3 border-t border-gray-100 pt-3",children:[e.jsxs("button",{type:"button",onClick:()=>v(!u),className:"flex items-center gap-2 text-sm font-medium text-gray-700 hover:text-band-700",children:[e.jsx("span",{children:"Replies collected"}),e.jsx("span",{className:`inline-flex px-2 py-0.5 rounded-full text-xs font-semibold ${L>0?"bg-band-50 text-band-700":"bg-gray-100 text-gray-500"}`,children:L}),l.digest?.status&&e.jsx("span",{className:"text-xs text-gray-400 font-normal",children:l.digest.status==="collecting"?"collecting now":l.digest.status}),e.jsx("span",{className:"text-gray-400",children:u?"â´":"â¾"})]}),u&&e.jsxs("div",{className:"mt-3 space-y-3",children:[!l.digest&&e.jsx("p",{className:"text-xs text-gray-400",children:"No digest in progress yet â replies appear here once the input request goes out."}),g.length===0&&l.digest&&e.jsxs("p",{className:"text-xs text-gray-400",children:["No replies yet for the week of ",String(l.digest.weekStart||"").slice(0,10),"."]}),g.map(d=>e.jsxs("div",{className:`rounded-lg border p-3 ${d.excludedAt?"border-gray-200 bg-gray-50 opacity-70":"border-gray-200 bg-white"}`,children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap text-xs text-gray-500",children:[e.jsx("span",{className:"font-semibold text-gray-800",children:d.senderName||d.senderEmail}),e.jsx("span",{children:nt(d.receivedAt)}),d.source==="manual"&&e.jsx("span",{className:"inline-flex px-2 py-0.5 rounded-full text-[10px] font-semibold bg-blue-100 text-blue-800",children:"Typed in-app"}),d.editedAt&&e.jsxs("span",{className:"inline-flex px-2 py-0.5 rounded-full text-[10px] font-semibold bg-amber-100 text-amber-800",title:`Edited ${nt(d.editedAt)}`,children:["Edited",d.editedByName?` by ${d.editedByName}`:""]}),d.orderAdopted&&e.jsx("span",{className:"inline-flex px-2 py-0.5 rounded-full text-[10px] font-semibold bg-teal-100 text-teal-800",title:"This reply's order lines were set as the rehearsal order â verbatim digests show only the rest of the reply.",children:"Set rehearsal order"}),d.excludedAt&&e.jsx("span",{className:"inline-flex px-2 py-0.5 rounded-full text-[10px] font-semibold bg-gray-200 text-gray-600",children:"Excluded from digest"}),d.attachmentCount>0&&e.jsxs("span",{children:[d.attachmentCount," attachment",d.attachmentCount===1?"":"s"]})]}),C===d.id?e.jsxs("div",{className:"mt-2",children:[e.jsx("textarea",{value:w,rows:5,maxLength:8e3,onChange:O=>h(O.target.value),className:"w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-band-500 focus:border-band-500"}),e.jsxs("div",{className:"flex gap-2 mt-2",children:[e.jsx(x,{type:"button",size:"sm",onClick:()=>X(d),isLoading:E,children:"Save"}),e.jsx(x,{type:"button",size:"sm",variant:"ghost",onClick:()=>p(null),children:"Cancel"})]})]}):e.jsx("p",{className:"mt-2 text-sm text-gray-700 whitespace-pre-wrap",children:d.text||e.jsx("span",{className:"text-gray-400 italic",children:"(no text)"})}),C!==d.id&&e.jsxs("div",{className:"flex gap-2 mt-2",children:[e.jsx(x,{type:"button",size:"sm",variant:"ghost",onClick:()=>{p(d.id),h(d.text||"")},children:"Edit"}),e.jsx(x,{type:"button",size:"sm",variant:"ghost",className:d.excludedAt?"":"text-red-600",onClick:()=>T(d),children:d.excludedAt?"Restore":"Exclude"})]})]},d.id)),l.digest&&e.jsxs("div",{className:"rounded-lg border border-dashed border-gray-300 p-3",children:[e.jsx("p",{className:"text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1",children:"Add a note"}),e.jsx("p",{className:"text-xs text-gray-400 mb-2",children:"For the officer who told you in the hallway but never replied â it joins the replies above."}),e.jsx("textarea",{value:j,rows:3,maxLength:8e3,onChange:d=>I(d.target.value),placeholder:"e.g. Dues are $110 â please pay by September 9. Checks payable to HRCB.",className:"w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-band-500 focus:border-band-500"}),e.jsx(x,{type:"button",size:"sm",className:"mt-2",onClick:te,isLoading:E,disabled:!j.trim(),children:"Add to digest inputs"})]})]})]})}const ce=[{value:"0",label:"Sunday"},{value:"1",label:"Monday"},{value:"2",label:"Tuesday"},{value:"3",label:"Wednesday"},{value:"4",label:"Thursday"},{value:"5",label:"Friday"},{value:"6",label:"Saturday"}],as=[{value:"weekly",label:"Every week"},{value:"biweekly",label:"Every 2 weeks"},{value:"monthly",label:"Monthly (1st of month)"}],ns=es.filter(a=>a.value!=="member");function ht(a,r,n){let c=(parseInt(String(r||"09:00").slice(0,2),10)||9)-Math.max(0,Number(n??3)),u=Number(a);return c<0&&(c+=24,u=(u+6)%7),{dayName:ce.find(C=>C.value===String(u))?.label||"",timeLabel:Le(String(Math.max(0,c)).padStart(2,"0")+":00")}}const rs=[{value:"",label:"A specific person"},{value:"president",label:"President"},{value:"vice_president",label:"Vice President"},{value:"music_director",label:"Music Director"}];function is({config:a}){const r=ce.find(u=>u.value===String(a.inputRequestDay))?.label||"Monday",n=ce.find(u=>u.value===String(a.sendDay))?.label||"Wednesday",l=`${n} ${Le(a.effectiveSendTime||"09:00")}
1`,c=[{label:r,desc:"Request input",icon:"1",color:"bg-blue-500"},{label:`${r}â${n}`,desc:"Collect replies",icon:"2",color:"bg-amber-500"}];if(a.approvalRequired){const u=ht(a.sendDay,a.effectiveSendTime,a.composeLeadHours);c.push({label:`${u.dayName} ${u.timeLabel}`,desc:"Approval review",icon:"3",color:"bg-purple-500"}),c.push({label:l,desc:"Send to members",icon:"4",color:"bg-green-500"})}else c.push({label:l,desc:"Send to members",icon:"3",color:"bg-green-500"});return e.jsx("div",{className:"flex flex-col gap-2 py-2 sm:flex-row sm:items-center sm:gap-1 sm:overflow-x-auto",children:c.map((u,v)=>e.jsxs("div",{className:"flex items-center",children:[v>0&&e.jsx("div",{className:"hidden sm:block w-6 h-0.5 bg-gray-300 shrink-0"}),e.jsxs("div",{className:"flex items-center gap-2 px-3 py-2 rounded-lg bg-gray-50 border border-gray-200 shrink-0 w-full sm:w-auto",children:[e.jsx("div",{className:`w-6 h-6 rounded-full ${u.color} text-white text-xs font-bold flex items-center justify-center shrink-0`,children:u.icon}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"text-xs font-semibold text-gray-900",children:u.desc}),e.jsx("p",{className:"text-xs text-gray-500",children:u.label})]})]})]},v))})}function ls({config:a,onSave:r}){const[n,l]=i.useState(a),[c,u]=i.useState(!1),[v,C]=i.useState(!1),[p,w]=i.useState(!1),[h,j]=i.useState(null),[I,E]=i.useState(!1),A=H(s=>s.showSuccess),k=H(s=>s.showError);function g(s,f){l(M=>({...M,[s]:f}))}const[L,X]=i.useState([]),T=n.approverUserId?"":n.approverRole||"";i.useEffect(()=>{if(!n.approvalRequired||T!=="")return;let s=!0;return P.approverCandidates().then(f=>{s&&X(Array.isArray(f)?f:[])}).catch(pt("approver suggestions are a convenience; the field still takes a name")),()=>{s=!1}},[n.approvalRequired,T]);function te(s){l(f=>({...f,approverRole:s||null,approverUserId:s?null:f.approverUserId}))}function d(s){const f=n.inputRecipientRoles||[],M=f.includes(s)?f.filter(V=>V!==s):[...f,s];g("inputRecipientRoles",M)}async function O(){if(v)return;const s=!n.enabled;l(f=>({...f,enabled:s})),C(!0);try{const f=await P.saveConfig(n.ensembleId,{...n,enabled:s});l(f),r(f),A(`${a.ensembleName} digest ${s?"enabled":"disabled"}`)}catch(f){l(M=>({...M,enabled:!s})),k(f.message||"Failed to update digest status")}C(!1)}async function b(){E(!0);try{const s=await P.getPreview(a.ensembleId);j(s)}catch(s){k(s.message||"Preview failed")}E(!1)}async function Z(){u(!0);try{const s=await P.saveConfig(n.ensembleId,n);r(s),A(`${a.ensembleName} digest settings saved`)}catch(s){k(s.message)}u(!1)}return e.jsxs("div",{className:"bg-white rounded-xl border border-gray-200 p-5 mb-4",children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("h3",{className:"font-semibold text-gray-900",children:a.ensembleName}),e.jsx("button",{type:"button",onClick:O,disabled:v,className:`relative inline-flex h-5 w-9 items-center rounded-full transition-colors disabled:opacity-60 ${n.enabled?"bg-green-500":"bg-gray-300"}`,children:e.jsx("span",{className:`inline-block h-3.5 w-3.5 transform rounded-full bg-white transition-transform ${n.enabled?"translate-x-[18px]":"translate-x-[2px]"}`})}),e.jsx("span",{className:`text-xs font-medium ${n.enabled?"text-green-700":"text-gray-400"}`,children:v?"Savingâ¦":n.enabled?"Active":"Disabled"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[n.enabled&&e.jsx(x,{variant:"ghost",size:"sm",onClick:b,isLoading:I,children:"Preview"}),e.jsx("button",{type:"button",onClick:()=>w(!p),className:"text-sm text-band-600 hover:text-band-700 font-medium",children:p?"Collapse":"Configure"})]})]}),n.enabled&&e.jsx(is,{config:n}),n.enabled&&e.jsx(ss,{ensembleId:a.ensembleId}),p&&e.jsxs("div",{className:"mt-4 space-y-4 border-t border-gray-100 pt-4",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide mb-2",children:"Schedule"}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-3",children:[e.jsx(_,{label:"Frequency",options:as,value:n.frequency,onChange:s=>g("frequency",s.target.value)}),e.jsx(_,{label:"Request input on",options:ce,value:String(n.inputRequestDay),onChange:s=>g("inputRequestDay",parseInt(s.target.value))}),e.jsxs("div",{children:[e.jsx(_,{label:"Send digest on",options:ce,value:String(n.sendDay),onChange:s=>g("sendDay",parseInt(s.target.value))}),e.jsxs("p",{className:"text-xs text-gray-400 mt-1",children:["Members receive it about ",Le(a.effectiveSendTime||"09:00")," â set by your delivery window (Delivery settings tab)."]})]})]})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide mb-2",children:"Who provides input?"}),e.jsx("p",{className:"text-xs text-gray-500 mb-2",children:'These roles receive the "what to include?" email and can reply with notes/attachments.'}),e.jsx("div",{className:"flex flex-wrap gap-2",children:ns.map(s=>{const f=(n.inputRecipientRoles||[]).includes(s.value);return e.jsxs("button",{type:"button",onClick:()=>
1d(s.value),className:`px-3 py-1.5 rounded-full text-xs font-medium border transition-colors ${f?"bg-band-50 border-band-300 text-band-700":"bg-white border-gray-200 text-gray-500 hover:border-gray-300"}`,children:[f&&e.jsx("span",{className:"mr-1",children:"â"}),s.label]},s.value)})})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide mb-2",children:"Writing Style"}),e.jsxs("div",{className:"max-w-md",children:[e.jsx(_,{options:[{value:"blend",label:"Blend replies into one voice (recommended)"},{value:"verbatim",label:"Keep leadership's words exactly as written"}],value:n.composeMode||"blend",onChange:s=>g("composeMode",s.target.value)}),e.jsx("p",{className:"text-xs text-gray-500 mt-1",children:(n.composeMode||"blend")==="verbatim"?"Each reply appears word-for-word as its own section. Schedule, music, and upcoming dates are always built from the app.":"Every reply is rewritten into a single cohesive note in your leadershipâs voice. Schedule, music, and upcoming dates are always built from the app."})]})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide mb-2",children:"Also in the email"}),e.jsxs("label",{className:"flex items-center gap-2 text-sm text-gray-700 cursor-pointer mb-2",children:[e.jsx("input",{type:"checkbox",checked:n.playersWantedBlock!==!1,onChange:s=>g("playersWantedBlock",s.target.checked),className:"rounded border-gray-300 text-band-600 focus:ring-band-500"}),"Include the call for sign-up concerts"]}),e.jsx("p",{className:"text-xs text-gray-500 ml-6",children:"When a concert only part of the band plays has sign-ups open, members not yet on the list see a Players wanted box with their own Count me in button."})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide mb-2",children:"Approval"}),e.jsxs("label",{className:"flex items-center gap-2 text-sm text-gray-700 cursor-pointer mb-2",children:[e.jsx("input",{type:"checkbox",checked:n.approvalRequired,onChange:s=>g("approvalRequired",s.target.checked),className:"rounded border-gray-300 text-band-600 focus:ring-band-500"}),"Require approval before sending to members"]}),n.approvalRequired&&e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3 ml-6",children:[e.jsxs("div",{children:[e.jsx(_,{label:"Who approves",options:rs,value:T,onChange:s=>te(s.target.value)}),T==="music_director"&&e.jsx("p",{className:"text-xs text-gray-400 mt-1",children:"Goes to the director of the next performance; falls back to all music directors."}),T===""&&e.jsxs("div",{className:"mt-2",children:[e.jsx(_,{label:"Approver",options:[{value:"",label:"Cho
1ose who approvesâ¦"},...L.map(s=>({value:s.id,label:s.name})),...n.approverUserId&&!L.some(s=>s.id===n.approverUserId)?[{value:n.approverUserId,label:`${n.approverName||"Current approver"} (not in this band's list)`}]:[]],value:n.approverUserId||"",onChange:s=>g("approverUserId",s.target.value||null)}),!n.approverUserId&&e.jsx("p",{className:"text-xs text-amber-700 mt-1",children:"No one picked yet â until then, approval requests go to the org owner."})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:"Send for review (hours before send time)"}),e.jsxs("select",{value:n.composeLeadHours??3,onChange:s=>g("composeLeadHours",parseInt(s.target.value)),className:"w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-band-500 focus:border-band-500",children:[e.jsx("option",{value:"1",children:"1 hour before"}),e.jsx("option",{value:"2",children:"2 hours before"}),e.jsx("option",{value:"3",children:"3 hours before"}),e.jsx("option",{value:"6",children:"6 hours before"}),e.jsx("option",{value:"12",children:"12 hours before"}),e.jsx("option",{value:"15",children:"The evening before"})]}),(()=>{const s=ht(n.sendDay,a.effectiveSendTime,n.composeLeadHours);return e.jsxs("p",{className:"text-xs text-gray-400 mt-1",children:["The approver receives it ",e.jsxs("span",{className:"font-medium text-gray-600",children:[s.dayName," about ",s.timeLabel]}),"."," ","Leadership replies arriving after that won't make this week's digest, and changes made after approval won't appear in the send."]})})()]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:"Grace period after send time"}),e.jsxs("select",{value:n.approvalDeadlineHours,onChange:s=>g("approvalDeadlineHours",parseInt(s.target.value)),className:"w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-band-500 focus:border-band-500",children:[e.jsx("option",{value:"2",children:"2 hours"}),e.jsx("option",{value:"4",children:"4 hours"}),e.jsx("option",{value:"8",children:"8 hours"}),e.jsx("option",{value:"12",children:"12 hours"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:"If still unapproved after that"}),e.jsxs("select",{value:n.approvalTimeoutAction||"hold",onChange:s=>g("approvalTimeoutAction",s.target.value),className:"w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-band-500 focus:border-band-500",children:[e.jsx("option",{value:"hold",children:"Hold the digest and remind the approver"}),e.jsx("option",{value:"send",children:"Send it automatically anyway"})]})]})]})]}),e.jsxs("div",{className:"flex gap-2 pt-2",children:[e.jsx(x,{variant:"primary",size:"sm",onClick:Z,isLoading:c,children:"Save settings"}),e.jsx(x,{variant:"secondary",size:"sm",onClick:()=>w(!1),children:"Cancel"})]})]}),h&&e.jsxs(gt,{isOpen:!0,onClose:()=>j(null),title:h.subject||"Digest preview",size:"lg",children:[h.firstRun&&e.jsx("p",{className:"text-sm bg-amber-50 border border-amber-200 rounded-lg text-amber-900 p-3 mb-2","data-testid":"digest-preview-first-run",children:"Your first digest hasn't started yet, so this shows only the schedule and music for the week. Notes from your leadership team appear here once the first input request goes out and they reply."}),e.jsxs("p",{className:"text-xs text-gray-500 mb-2",children:["Composed just now through the full engine (",h.composeMode==="verbatim"?"verbatim mode":h.aiComposed?"AI blend":"auto-content only",h.panels?", with your personal print/plans panels":"",") â this is what members would receive if it went out right now."]}),e.jsx("iframe",{sandbox:"",srcDoc:h.html,title:"Digest preview",className:"w-full h-[70vh] rounded-lg border border-gray-200 bg-white"})]})]})}function os(){const[a,r]=i.useState(null),[n,l]=i.useState(!0),c=H(p=>p.showError);i.useEffect(()=>{u()},[]);async function u(){try{const p=await P.getConfigs();r({configs:Array.isArray(p?.configs)?p.configs:[],unconfiguredEnsembles:Array.isArray(p?.unconfiguredEnsembles)?p.unconfiguredEnsembles:[]})}catch(p){c(p.message)}l(!1)}function v(p){r(w=>({...w,configs:w.configs.map(h=>h.ensembleId===p.ensembleId?p:h),unconfiguredEnsembles:w.unconfiguredEnsembles.filter(h=>h.id!==p.ensembleId)}))}async function C(p){try{const w=await P.saveConfig(p.id,{enabled:!1});r(h=>({configs:[...h.configs,w],unconfiguredEnsembles:h.unconfiguredEnsembles.filter(j=>j.id!==p.id)}))}catch(w){c(w.message)}}return n?e.jsx("div",{className:"flex items-center justify-center py-8",children:e.jsx("div",{className:"animate-spin motion-reduce:!animate-spin h-6 w-6 border-4 border-band-500 border-t-transparent roun
1ded-full"})}):a?e.jsxs("div",{children:[e.jsx("div",{className:"flex items-center justify-between mb-4",children:e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide",children:"Weekly Digest"}),e.jsx("p",{className:"text-xs text-gray-400 mt-1",children:"Automated weekly email to ensemble members with rehearsal schedules, setlists, and leadership notes."})]})}),a.configs.length===0&&a.unconfiguredEnsembles.length===0&&e.jsx("p",{className:"text-sm text-gray-400 py-4",children:"No ensembles found. Create an ensemble first."}),a.configs.map(p=>e.jsx(ls,{config:p,onSave:v},p.ensembleId)),a.unconfiguredEnsembles.length>0&&e.jsxs("div",{className:"bg-gray-50 rounded-xl border border-dashed border-gray-300 p-4",children:[e.jsx("p",{className:"text-sm text-gray-600 mb-3",children:"Ensembles without digest configured:"}),e.jsx("div",{className:"flex flex-wrap gap-2",children:a.unconfiguredEnsembles.map(p=>e.jsxs("button",{type:"button",onClick:()=>C(p),className:"px-3 py-1.5 rounded-lg border border-gray-200 bg-white text-sm text-gray-700 hover:border-band-300 hover:text-band-700 transition-colors",children:["+ ",p.name]},p.id))})]})]}):null}const ds=/\{\{(\w+)\}\}/g;function cs(a,r){const n=new Set;for(const l of a)for(const c of String(l||"").matchAll(ds))r.has(c[1])||n.add(c[1]);return[...n]}const rt={recipientName:"The reader's first name",orgName:"Band name",ensembleName:"Ensemble name",resourceTitle:"Concert or piece title",performanceTitle:"Concert title",performanceDate:"Concert date",performanceTime:"Concert start time",callTime:"Call time",setupTime:"Setup time",dressAttire:"What to wear",venueName:"Venue",venueAddress:"Venue address",rehearsalDate:"Rehearsal date",startTime:"Start time",endTime:"End time",directorNotes:"Director's notes",rsvpUrl:"Can't-make-it link",performanceRsvpUrl:"Reply link for the concert",smsRsvpAskText:"Text reply instructions",smsConsentUrl:"Text message sign-up link",loginUrl:"Sign-in link",actorName:"Who did it",memberName:"Member name",monthName:"Month",birthdayList:"Birthday list",expectedArrivalDate:"Expected arrival",cost:"Cost",borrowedFrom:"Borrowed from",donatedBy:"Donated by",changeList:"What changed",changeSummary:"What changed (one line)",inviteLink:"Invitation link"};function ms(a){if(rt[a])return rt[a];const r=String(a).replace(/([a-z])([A-Z])/g,"$1 $2").toLowerCase();return r.charAt(0).toUpperCase()+r.slice(1)}const ye=Object.freeze({email_only:{subject:!0,emailBody:!0,smsBody:!1},sms_only:{subject:!1,emailBody:!1,smsBody:!0},both:{subject:!0,emailBody:!0,smsBody:!0},auto:{subject:!0,emailBody:!0,smsBody:!0}}),de=a=>typeof a=="string"&&a.trim().length>0;function us(a){const r=ye[a]||ye.auto;return{name:!0,triggerEvent:!0,subject:r.subject,emailBody:r.emailBody,smsBody:r.smsBody}}function ps(a,r){const n={};de(a.name)?a.name.length>100&&(n.name="Name must be under 100 characters"):n.name="Template name is required";const l=de(a.emailBody),c=de(a.smsBody),u=de(a.subject);switch(r){case"sms_only":c||(n.smsBody="SMS body is required for an SMS-only template");break;case"email_only":u||(n.subject="Subject is required for an email template"),l||(n.emailBody="Email body is required for an email-only template");break;case"both":u||(n.subject="Subject is required when the template sends email"),l||(n.emailBody="Email body is required when the template sends both"),c||(n.smsBody="SMS body is required when the template sends both");break;default:!l&&!c&&(n.emailBody="At least one message body (email or SMS) is required"),l&&!u&&(n.subject="Subject is required when email body is provided")}return n}function it(a,r){const n=ye[r]||ye.auto,l=c=>de(c)?c.trim():null;return{name:(a.name||"").trim(),description:l(a.description),channelMode:r,isActive:!!a.isActive,triggerEvent:a.triggerEvent||null,subject:n.subject?l(a.subject):null,emailBody:n.emailBody?l(a.emailBody):null,smsBody:n.smsBody?l(a.smsBody):null}}const gs=[["triggerEvent",/\btrigger ?event\b/i],["emailBody",/\bemail ?body\b/i],["smsBody",/\bsms ?body\b/i],["subject",/\bsubject\b/i]];function hs(a){const r=String(a||"");let n=null;for(const[l,c]of gs){const u=r.search(c);u>
1=0&&(n===null||u<n.at)&&(n={field:l,at:u})}return n?n.field:null}function xs(a){return(Array.isArray(a)?a:[]).filter(r=>r&&r.key&&r.isActive!==!1).sort((r,n)=>(r.category||"").localeCompare(n.category||"")||(r.label||"").localeCompare(n.label||"")).map(r=>({value:r.key,label:r.category?`${r.category} â ${r.label}`:r.label}))}const bs=[{key:"digest",label:"Weekly digest"},{key:"settings",label:"Delivery settings"},{key:"templates",label:"Templates"}],lt=[{value:"auto",label:"Email, and a text to anyone opted in"},{value:"email_only",label:"Email only"},{value:"sms_only",label:"Text only"},{value:"both",label:"Email and text (both required)"}],ot="Never sent automatically",ys="Your wording replaces the whole built-in message â members will not get the rehearsal order, recordings or the canât-make-it link unless you write them in.",fs="Your text-message wording is kept on screen but not sent â it is removed when you save.",vs="Your email subject and body are kept on screen but not sent â they are removed when you save.",dt=[{label:"Member",items:[{key:"firstName",description:"First name"},{key:"lastName",description:"Last name"},{key:"email",description:"Email address"},{key:"phone",description:"Phone number"},{key:"joinDate",description:"Date joined"}]},{label:"Organization",items:[{key:"organizationName",description:"Org name"},{key:"orgEmail",description:"Org email"},{key:"orgPhone",description:"Org phone"}]},{label:"Performance",items:[{key:"performanceName",description:"Title"},{key:"performanceDate",description:"Date"},{key:"venue",description:"Venue name"}]},{label:"General",items:[{key:"currentDate",description:"Today's date"},{key:"currentYear",description:"Current year"}]}],Be={name:"",description:"",channelMode:"auto",isActive:!0,triggerEvent:"",subject:"",emailBody:"",smsBody:""},ct=a=>Object.fromEntries(Object.entries(a||{}).filter(([,r])=>r!=null).map(([r,n])=>[r,String(n)])),js=new Set(["birthday.digest","payments.item_purchased"]),xe={recipientName:"Jane Doe",displayName:"Jane Doe",firstName:"Jane",lastName:"Doe",email:"[email protected]",phone:"+1 555-123-4567",joinDate:"January 15, 2026",actorName:"Alex Director",role:"Music Director",orgName:"Highlands Ranch Concert Band",organizationName:"Highlands Ranch Concert Band",ensembleName:"Concert Band",orgEmail:"[email protected]",orgPhone:"+1 555-000-0000",memberName:"Bob Wilson",performanceTitle:"Spring Concert 2026",performanceName:"Spring Concert 2026",performanceDate:"April 12, 2026",performanceTime:"7:30 PM",callTime:"6:30 PM",rehearsalDate:"April 5, 2026",startTime:"6:30 PM",endTime:"8:30 PM",venueName:"Main Auditorium",venue:"Main Auditorium",venueAddress:"123 Concert Hall Way, Highlands Ranch, CO 80129",setupTime:"5:45 PM",dressAttire:"Concert black",directorNotes:"Bring a pencil; we start with the Holst.",rsvpUrl:"https://app.backstagebaton.com/app/api/v1/rsvp/sample-token",performanceRsvpUrl:"https://app.backstagebaton.com/app/api/v1/performance-rsvp/sample-token",smsConsentUrl:"https://app.backstagebaton.com/app/api/v1/sms-consent/sample-token",smsRsvpAskText:"
1Can't make it? Reply 2.",loginUrl:"https://app.backstagebaton.com/app/login",cost:"45.00",resourceTitle:"Lincolnshire Posy",musicTitle:"Lincolnshire Posy",borrowedFrom:"Mountain View Community Band",expectedArrivalDate:"May 1, 2026",donatedBy:"Estate of John Smith",monthName:"April",birthdayList:` - Bob Wilson (Trumpet): April 14 2 - Cindy Park (Flute): April 22`,changeSummary:"Venue moved to Backup Hall",changeList:" - Venue: Main Auditorium â Backup Hall",inviteLink:"https://app.backstagebaton.com/app/accept/sample-token",roleName:"Vice President",currentDate:"",currentYear:""},ws=["application/pdf","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document","image/png","image/jpeg"],Ns=["pdf","doc","docx","png","jpg","jpeg"],Ss=10*1024*1024,De=5,ks={email_only:xt,sms_only:Es,auto:ut,both:ut};function mt(a){return a<1024?a+" B":a<1024*1024?(a/1024).toFixed(1)+" KB":(a/(1024*1024)).toFixed(1)+" MB"}function ee(a,r){return a?a.replace(/\{\{(\w+)\}\}/g,(n,l)=>r[l]??n):""}function Cs(a){const r=a?.isActive!==!1,n=!!a?.isCustomized,l=!!a?.systemKey;return a?.notSent?{tone:"default",label:"Not sent",tooltip:"Backstage Baton does not send this message today, so this wording is not used."}:r&&n?{tone:"active",label:"Your wording",tooltip:"Members receive your wording instead of the built-in."}:r?{tone:"active",label:"Active",tooltip:"Members receive this template's wording."}:l?{tone:"default",label:"Off â built-in wording",tooltip:"Members receive the built-in wording. Turn this template on to send yours."}:{tone:"default",label:"Off",tooltip:"Not sending."}}const be=a=>!!(a?.isSystem||a?.systemKey);function Ws(){const a=qt(),{currentOrg:r}=Te(),{showSuccess:n,showError:l}=H(),c=Ht(t=>t.user),{canFully:u}=Vt(),v=u("communications:manage"),C=u("communications:delete"),p=Yt(t=>t.planTier),h=!p||new Set(["complete"]).has(p),[j,I]=i.useState("digest"),[E,A]=i.useState([]),[k,g]=i.useState([]),[L,X]=i.useState(!0),[T,te]=i.useState(""),[d,O]=i.useState(!1),[b,Z]=i.useState(null),[s,f]=i.useState(Be),[M,V]=i.useState({}),[Me,Re]=i.useState(!1),[bt,fe]=i.useState(!1),[yt,ve]=i.useState(!1),[$,W]=i.useState([]),[Ie,Oe]=i.useState(!1),[ft,ze]=i.useState(!1),[Pe,Fe]=i.useState("email"),[Y,vt]=i.useState(null),[jt,_e]=i.useState(!1),[N,Q]=i.useState(null),[se,je]=i.useState(null),[$e,We]=i.useState(!1),[wt,Ue]=i.useState(!1),qe=i.useRef(null),me=i.useRef(null),He=i.useRef(null),Ve=i.useRef(null),we=i.useRef("emailBody"),ue=i.useRef(null),G=h?s.channelMode:"email_only",S=us(G),ae=i.useCallback(async()=>{if(r){X(!0);try{const t=await D.fetchTemplates();A(Array.isArray(t)?t:[])}catch{l(oe("templates"))}finally{X(!1)}}},[r,l]),Ye=i.useCallback(async()=>{if(r)try{const t=await D.fetchTriggerEvents();g(Array.isArray(t)?t:[])}catch{l(oe("trigger events"))}},[r,l]),Ne=i.useCallback(async()=>{if(r){We(!1);try{const t=await D.fetchDeliverySettings(),o={deliveryWindowStart:t?.deliveryWindowStart??"09:00",deliveryWindowEnd:t?.deliveryWindowEnd??"20:00",timezone:t?.timezone??r?.timezone??"America/New_York",isEnabled:t?.isEnabled??!0};Q(o),je(o)}catch{Q(null),je(null),We(!0),l(oe("delivery settings"))}}},[r,l]);i.useEffect(()=>{r&&(ae(),Ye())},[r,ae,Ye]),i.useEffect(()=>{r&&j==="settings"&&Ne()},[r,j,Ne]);const Nt=i.useMemo(()=>xs(k),[k]),U=i.useMemo(()=>new Map(k.map(t=>[t.key,t])),[k]),Se=i.useCallback(t=>t?U.get(t)?.label||t:ot,[U]);function z(t,o){f(m=>({...m,[t]:o})),V(m=>({...m,[t]:void 0}))}function Ge(){V({}),Fe("email"),O(!0),requestAnimationFrame(()=>qe.current?.scrollIntoView({behavior:"smooth",block:"start"}))}function ke(){Z(null);const t={...Be,channelMode:h?Be.channelMode:"email_only"};f(t),me.current={...t},W([]),Ge()}async function St(t){Z(t);const o={name:t.name||"",description:t.description||"",channelMode:h?t.channelMode||"auto":"email_only",isActive:t.isActive!==!1,triggerEvent:t.triggerEvent||"",subject:t.subject||"",emailBody:t.emailBody||"",smsBody:t.smsBody||""};f(o),me.current={...o},W([]),Ge();try{const m=await D.fetchTemplate(t.id);W(Array.isArray(m?.attachments)?m.attachments:[])}catch{l(oe("attachments"))}}function pe(){O(!1),ve(!1),Z(null),V({})}const ne=i.useMemo(()=>JSON.stringify(s)!==JSON.stringify(me.current)||!b&&$.length>0,[b,s,$]);function kt(){ne?ve(!0):pe()}function Ct(t){const o={};for(const[m,y]of Object.entries(t))y&&(S[m]?o[m]=y:l(y));V(o)}function Et(){const t=ps(s,G);return Ct(t),Object.keys(t).length===0}const ge=U.get(s.triggerEvent)?.placeholders||null,At=ge?ge.map(t=>({key:t,description:ms(t)})):dt.flatMap(t=>t.items),Bt=i.useMemo(()=>new Set(ge||[...Object.keys(xe),...dt.flatMap(t=>t.items.map(o=>o.key))]),[ge]),[Je,Ce]=i.useState(null);function Dt(t){if(t.preventDefault(),!Et())return;const o=it(s,G),m=cs([o.subject,o.emailBody,o.smsBody],Bt);if(m.length){Ce(m);return}return Ke()}async function Ke(){Ce(null),Re(!0);try{const t=it(s,G);if(b)await D.updateTemplate(b.id,t),n("Template updated");else{const o=await D.createTemplate(t),m=$.filter(y=>y.isLocal&&y.file);if(o?.id&&m.length)for(const y of m)try{const B=new FormData;B.append("file",y.file),await D.uploadAttachment(o.id,B)}
2catch(B){l(`Couldn't attach ${y.fileName}: ${B?.message||q}`)}if(n("Template created"),o?.id){Z(o),me.current={...s};try{const y=await D.fetchTemplate(o.id);W(Array.isArray(y?.attachments)?y.attachments:[])}catch{l(oe("attachments"))}ae();return}}pe(),ae()}catch(t){if(l(t?.message||q),t?.status===422){const o=hs(t.message);o&&S[o]&&V(m=>({...m,[o]:t.message}))}}finally{Re(!1)}}async function Tt(){if(b)try{await D.deleteTemplate(b.id),n("Template deleted"),fe(!1),pe(),ae()}catch(t){l(t?.message||st)}}function Lt(t){const o=`{{${t}}}`;let m=we.current;S[m]||(m=S.emailBody?"emailBody":"smsBody");const y=m==="smsBody"?Ve.current:He.current,B=s[m]||"";if(y){const J=y.selectionStart,Ee=y.selectionEnd;z(m,B.slice(0,J)+o+B.slice(Ee)),requestAnimationFrame(()=>{y.focus();const Qe=J+o.length;y.setSelectionRange(Qe,Qe)})}else z(m,B+o)}function Mt(t){Array.from(t.target.files||[]).forEach(m=>Xe(m)),ue.current&&(ue.current.value="")}function Rt(t){t.preventDefault(),Array.from(t.dataTransfer.files||[]).forEach(m=>Xe(m))}function It(t){t.preventDefault()}async function Xe(t){if($.length>=De){l(`Maximum ${De} attachments allowed`);return}const o=t.name.split(".").pop()?.toLowerCase();if(!Ns.includes(o)&&!ws.includes(t.type)){l("File type not supported. Use PDF, DOC, DOCX, or images.");return}if(t.size>Ss){l("File exceeds the 10MB size limit");return}if(!b){const m={id:`local-${Date.now()}-${Math.random()}`,fileName:t.name,fileSize:t.size,isLocal:!0,file:t};W(y=>[...y,m]);return}Oe(!0);try{const m=new FormData;m.append("file",t);const y=await D.uploadAttachment(b.id,m);W(B=>[...B,y])}catch(m){l(m?.message||q)}finally{Oe(!1)}}async function Ot(t){if(t.isLocal){W(o=>o.filter(m=>m.id!==t.id));return}try{await D.removeAttachment(b.id,t.id),W(o=>o.filter(m=>m.id!==t.id))}catch(o){l(o?.message||st)}}const R=i.useMemo(()=>({...xe,orgName:r?.name||xe.orgName,organizationName:r?.name||xe.organizationName,currentDate:et(Gt()),currentYear:String(new Date().getFullYear())}),[r?.name]),zt=i.useMemo(()=>ee(s.subject,R),[s.subject,R]),Pt=i.useMemo(()=>ee(s.emailBody,R),[s.emailBody,R]),Ft=i.useMemo(()=>ee(s.smsBody,R),[s.smsBody,R]),re=h&&S.smsBody;i.useEffect(()=>{if(!d||!b||!re||!c?.memberId)return;let t=!1;return Xt.getById(c.memberId).then(o=>{t||vt(o?.phone||null)}).catch(pt("test send: no member phone, SMS test not offered")),()=>{t=!0}},[d,b,re,c?.memberId]);const ie=i.useMemo(()=>{const t=[];return S.emailBody&&c?.email&&t.push({value:"email",label:`Email â ${c.email}`}),re&&Y&&t.push({value:"sms",label:`SMS â ${Y}`}),t},[S.emailBody,re,c?.email,Y]),le=ie.some(t=>t.value===Pe)?Pe:ie[0]?.value;async function _t(){if(!(!b||!le)){_e(!0);try{const t=le==="sms"?{channel:"sms",recipientPhone:Y,sampleData:ct(R)}:{channel:"email",recipientEmail:c.email,sampleData:ct(R)};await D.testSend(b.id,t),n(`Test sent to ${le==="sms"?Y:c.email}`)}catch(t){l(t?.message||q)}finally{_e(!1)}}}const $t=i.useMemo(()=>N&&se?JSON.stringify(N)!==JSON.stringify(se):!1,[N,se]);function Wt(){se&&Q({...se})}async function Ut(){if(N){Ue(!0);try{await D.updateDeliverySettings({deliveryWindowStart:N.deliveryWindowStart,deliveryWindowEnd:N.deliveryWindowEnd,isEnabled:N.isEnabled}),n("Delivery settings saved"),je({...N})}catch(t){l(t?.message||q)}finally{Ue(!1)}}}const Ze=i.useMemo(()=>E.filter(t=>{if(!T.trim())return!0;const o=T.toLowerCase();return(t.name||"").toLowerCase().includes(o)||(t.triggerEvent||"").toLowerCase().includes(o)||Se(t.triggerEvent).toLowerCase().includes(o)}),[E,T,Se]);return e.jsxs("div",{className:"px-4 pt-3 md:px-0 md:pt-0",children:[!a&&e.jsx(Zt,{title:"Communications",breadcrumbs:[{label:"Home",to:"/"},{label:"Settings"},{label:"Communications"}],actions:v&&j==="templates"&&!d?e.jsx(x,{variant:"primary",size:"md",onClick:ke,children:"New template"}):void 0}),e.jsx(ts,{className:"mb-6 -mx-4 px-4 md:mx-0 md:px-0",ariaLabel:"Communications sections",tabs:bs,value:j,onChange:I}),j==="templates"&&e.jsxs(e.Fragment,{children:[!d&&e.jsx("p",{className:"text-sm text-gray-600 mb-4",children:"Write your bandâs own wording for the appâs reminders and notices."}),a&&v&&!d&&e.jsx("div",{className:"mb-3",children:e.jsx(x,{variant:"primary",size:"md",onClick:ke,className:"w-full",children:"New template"})}),E.length>0&&e.jsx("div",{className:"mb-4",children:e.jsx(K,{"aria-label":"Search templates",placeholder:"Search templatesâ¦",value:T,onChange:t=>te(t.target.value),className:"w-full sm:w-64"})}),d&&e.jsxs("div",{ref:qe,className:"bg-white rounded-xl border border-gray-200 p-6 mb-4",children:[e.jsx("h3",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide mb-4",children:b?"Edit template":"New template"}),b&&be(b)&&b.isActive===!1&&e.jsx("div",{className:"mb-5 rounded-lg border border-gray-200 bg-gray-50 px-4 py-3 text-sm text-gray-700",children:s.isActive?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"font-semibold",children:"Currently off"})," â save to send your wording."]}):e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"font-semibold",children:"Off"})," â members receive the built-in wording"]})}),e.jsxs("form",{onSubmit:Dt,className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h4",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide mb-3",children:"Basic info"}),e.jsxs("div",{className:"space-y-3",children:[e.jsx(K,{label:"Template name",required:!0,value:s.name,onChange:t=>z("name",t.target.value),error:M.name,maxLength:100}),e.jsx(K,{label:"Description",hint:"optional",value:s.description,onChange:t=>z("description",t.target.value),maxLength:500}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:[e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(_,{label:"Send by",options:lt.map(t=>{const o=t.value!=="email_only";return!h&&o?{...t,label:`${t.label} (Complete plan)`,disabled:!0}:t}),value:G,disabled:!h,onChange:t=>z("channelMode",h?t.target.value:"email_only")}),!S.smsBody&&s.smsBody?.trim()&&e.jsx("p",{className:"text-xs text-amber-700",children:fs}),!S.emailBody&&(s.subject?.trim()||s.emailBody?.trim())&&e.jsx("p",{className:"text-xs text-amber-700",children:vs})]}),e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("span",{className:"text-sm font-medium text-gray-700",children:"Status"}),e.jsxs("label",{className:"flex items-start gap-2 px-3 py-2",children:[e.jsx("input",{type:"checkbox",className:"mt-0.5 rounded border-gray-300 text-band-600 focus:ring-band-500",checked:s.isActive,onChange:t=>z("isActive",t.target.checked)}),e.jsx("span",{className:"text-sm text-gray-700",children:"Active â members receive this templateâs wording"})]})]})]}),!h&&e.jsx(Qt,{featureName:"SMS Notifications",requiredTier:"complete",currentTier:p,description:"Reach members instantly with text message notifications for rehearsals, cancellations, and reminders.",className:"mt-3"})]})]}),e.jsxs("div",{children:[e.jsx("h4",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide mb-3",children:"When it sends"}),e.jsxs("div",{className:"space-y-3",children:[e.jsx(_,{label:"When it sends",hint:b&&be(b)?"Bu
2ilt-in trigger":void 0,placeholder:ot,options:Nt,value:s.triggerEvent,disabled:!!(b&&be(b)),error:M.triggerEvent,onChange:t=>z("triggerEvent",t.target.value)}),s.triggerEvent&&U.get(s.triggerEvent)?.description&&e.jsx("p",{className:"text-xs text-gray-500 -mt-1",children:U.get(s.triggerEvent).description}),s.triggerEvent&&U.get(s.triggerEvent)?.replacesRichContent&&e.jsx("p",{className:"text-sm text-amber-800 bg-amber-50 border border-amber-200 rounded-lg p-3",children:ys}),js.has(s.triggerEvent)&&e.jsx(Kt,{eventKey:s.triggerEvent,canManage:v,...s.triggerEvent==="payments.item_purchased"?{intro:"When a member pays for an item, everyone you tick gets one email saying who bought what, so it gets handed over."}:{}})]}),s.isActive&&!s.triggerEvent&&e.jsxs("div",{className:"bg-yellow-50 border border-yellow-200 rounded-lg text-sm text-yellow-700 p-3 flex items-center gap-2 mt-3",children:[e.jsx("svg",{className:"h-4 w-4 shrink-0",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,"aria-hidden":"true",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z"})}),e.jsx("span",{children:"This template is never sent automatically â choose when it sends."})]})]}),e.jsxs("div",{children:[e.jsx("h4",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide mb-3",children:"Message content"}),e.jsxs("div",{className:"space-y-3",children:[S.subject&&e.jsx(K,{label:"Email subject",value:s.subject,onChange:t=>z("subject",t.target.value),error:M.subject,placeholder:"e.g. Welcome to {{organizationName}}"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(at,{menuId:"template-placeholders",trigger:e.jsx(x,{type:"button",variant:"ghost",size:"sm",children:"Insert a placeholder"}),children:At.map(t=>e.jsx(at.Item,{onClick:()=>Lt(t.key),children:e.jsxs("span",{className:"flex items-center justify-between gap-3",children:[e.jsx("span",{children:t.description}),e.jsx("code",{className:"font-mono text-xs text-gray-400",children:`{{${t.key}}}`})]})},t.key))}),e.jsx("span",{className:"text-xs text-gray-400",children:"Use placeholders for the memberâs name, the date, the venue."})]}),S.emailBody&&e.jsxs("div",{className:"space-y-1",children:[e.jsx(tt,{ref:He,label:"Email body",className:"min-h-[200px] resize-y",value:s.emailBody,onFocus:()=>{we.current="emailBody"},onChange:t=>z("emailBody",t.target.value),error:M.emailBody,placeholder:"Type your email message here. Use {{variables}} for dynamic content."}),(s.subject||s.emailBody)&&e.jsxs("div",{className:"mt-2 rounded-lg border border-gray-200 bg-gray-50 p-3",children:[e.jsx("div",{className:"text-[11px] font-semibold text-gray-500 uppercase tracking-wide mb-1.5",children:"Preview (sample data)"}),s.subject&&e.jsx("div",{className:"text-sm font-semibold text-gray-900 mb-2",children:ee(s.subject,R)}),s.emailBody&&e.jsx("pre",{className:"whitespace-pre-wrap text-sm text-gray-700 font-sans m-0",children:ee(s.emailBody,R)})]})]}),S.smsBody&&e.jsxs("div",{className:"space-y-1",children:[e.jsx(tt,{ref:Ve,label:"SMS body",className:"min-h-[80px] resize-y",value:s.smsBody,onFocus:()=>{we.current="smsBody"},onChange:t=>z("smsBody",t.target.value),error:M.smsBody,placeholder:"Short SMS message. Use {{variables}} for dynamic content.",maxLength:1600}),(s.smsBody?.length||0)>160&&e.jsx("p",{className:"text-xs text-amber-700",children:"Over 160 characters â sends as more than one text."}),s.smsBody&&e.jsxs("div",{className:"mt-2 rounded-lg border border-gray-200 bg-gray-50 p-3",children:[e.jsx("div",{className:"text-[11px] font-semibold text-gray-500 uppercase tracking-wide mb-1.5",children:"Preview (sample data)"}),e.jsx("pre",{className:"whitespace-pre-wrap text-sm text-gray-700 font-sans m-0",children:ee(s.smsBody,R)})]})]}),(s.emailBody?.trim().length>0||s.smsBody?.trim().length>0)&&e.jsx("div",{className:"flex gap-2",children:e.jsx(x,{type:"button",variant:"ghost",size:"sm",onClick:()=>ze(!0),children:"Preview"})}),b&&e.jsxs("div",{className:"bg-gray-50 rounded-lg p-3 space-y-2",children:[e.jsxs("p",{className:"text-sm text-gray-700",children:["Sends to your own address: ",e.jsx("span",{className:"font-medium",children:c?.email||"â"}),re&&Y&&e.jsxs("span",{className:"text-gray-500",children:[" · phone ",Y]})]}),e.jsxs("div",{className:"flex flex-wrap items-end gap-3",children:[ie.length>1&&e.jsx(_,{label:"Channel",options:ie,value:le,onChange:t=>Fe(t.target.value),className:"sm:w-72"}),e.jsx(x,{type:"button",variant:"secondary",size:"sm",onClick:_t,isLoading:jt,disabled:ne||!le,children:"Send test"})]}),ne&&e.jsx("p",{className:"text-xs text-gray-500",children:"Save first â the test sends the saved wording."}),!ne&&ie.length===0&&e.jsx("p",{className:"text-xs text-gray-500",children:"No address on your account for this templateâs channel."})]})]})]}),S.emailBody&&e.jsxs("div",{children:[e.jsx("h4",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide mb-3",children:"Attachments"}),e.jsxs("div",{className:"border-2 border-dashed border-gray-300 rounded-xl p-6 text-center hover:border-band-400 transition-colors",onDrop:Rt,onDragOver:It,children:[e.jsx("svg",{className:"mx-auto h-8 w-8 text-gray-400",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,"aria-hidden":"true",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 16V4m0 0l-4 4m4-4l4 4M4 18h16"})}),e.jsx("p",{className:"text-sm text-gray-500 mt-2 hidden md:block",children:"Drop files here, or"}),e.jsx(x,{type:"button",variant:"ghost",size:"sm",className:"mt-1",onClick:()=>ue.current?.click(),disabled:Ie,children:"Choose files"}),e.jsxs("p",{className:"text-xs text-gray-400 mt-1",children:["PDF, DOC, DOCX, images. Max 10MB per file, up to ",De,"."]}),e.jsx("input",{ref:ue,type:"file",className:"hidden","aria-label":"Attachment files",accept:".pdf,.doc,.docx,.png,.jpg,.jpeg",multiple:!0,onChange:Mt})]}),Ie&&e.jsx("p",{className:"text-sm text-gray-500 mt-2",children:"Uploadingâ¦"}),$.length>0?e.jsx("ul",{className:"space-y-2 mt-3",children:$.map(t=>e.jsxs("li",{className:"flex items-center gap-3 bg-gray-50 rounded-lg px-3 py-2",children:[e.jsx("svg",{className:"h-5 w-5 text-gray-400 shrink-0",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,"aria-hidden":"true",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M15.172 7l-6.586 6.586a2 2 0 102.828 2.828L18 9.828a4 4 0 00-5.656-5.656L5.757 10.757a6 6 0 008.486 8.48
26L20.5 13"})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"text-sm font-medium text-gray-700 truncate",children:t.fileName}),e.jsxs("p",{className:"text-xs text-gray-400",children:[mt(t.fileSize||0),t.isLocal?" · uploads on create":""]})]}),e.jsx(x,{type:"button",variant:"ghost",size:"sm","aria-label":`Remove ${t.fileName}`,onClick:()=>Ot(t),children:"Remove"})]},t.id))}):e.jsx(he,{size:"compact",title:"No attachments yet."})]}),e.jsxs("div",{className:"flex flex-wrap gap-2 pt-2",children:[e.jsx(x,{type:"submit",size:"sm",isLoading:Me,disabled:!!b&&!ne,children:b?"Save changes":"Create"}),e.jsx(x,{type:"button",variant:"secondary",size:"sm",onClick:kt,children:"Cancel"}),b&&C&&!be(b)&&e.jsx(x,{type:"button",variant:"danger",size:"sm",className:"ml-auto",onClick:()=>fe(!0),children:"Delete"})]})]})]}),L?e.jsx("div",{className:"space-y-2",children:[1,2,3,4].map(t=>e.jsx("div",{className:"bg-white rounded-xl border border-gray-200 p-4 animate-pulse",children:e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("div",{className:"h-5 w-5 bg-gray-200 rounded"}),e.jsxs("div",{className:"flex-1 space-y-2",children:[e.jsx("div",{className:"h-4 w-48 bg-gray-200 rounded"}),e.jsx("div",{className:"h-3 w-32 bg-gray-100 rounded"})]}),e.jsx("div",{className:"h-6 w-16 bg-gray-200 rounded-full"})]})},t))}):E.length===0?e.jsx(he,{card:!0,title:r?.status==="active"?"No templates yet":"Your standard messages arrive when you go live",description:r?.status==="active"?"Write your band's own wording for the app's reminders and notices.":"The app's reminders and notices appear here, ready to edit, the moment your band goes live. You can write your own templates now.",action:v&&e.jsx(x,{onClick:ke,children:"Create first template"})}):Ze.length===0?e.jsx(he,{card:!0,title:"No templates match your search."}):e.jsx("div",{className:"space-y-2",children:Ze.map(t=>{const o=t.channelMode||"auto",m=ks[o]||xt,y=t.triggerEvent||"",B=t.updatedAt?et(t.updatedAt):null,J=Cs(t),Ee=J.tone==="active"?"bg-green-100 text-green-800":J.tone==="draft"?"bg-amber-100 text-amber-800":"bg-gray-100 text-gray-700";return e.jsxs("div",{className:"bg-white rounded-xl border border-gray-200 px-4 py-3 sm:px-5 sm:py-4 flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4",children:[e.jsx(m,{className:"h-5 w-5 text-gray-400 shrink-0 hidden sm:block"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"font-medium text-gray-900",children:t.name}),e.jsxs("div",{className:"text-xs text-gray-500 mt-0.5",children:["Sends: ",Se(y),B&&e.jsxs("span",{className:"ml-3 text-gray-400",children:["Modified ",B]})]}),y&&U.get(y)?.description&&e.jsx("div",{className:"text-[11px] text-gray-400 mt-0.5",children:U.get(y).description})]}),e.jsxs("div",{className:"flex items-center gap-2 sm:gap-3",children:[e.jsx("span",{className:`inline-flex px-2 py-0.5 rounded-full text-xs font-medium whitespace-nowrap ${Ee}`,title:J.tooltip,children:J.label}),v&&e.jsx(x,{variant:"ghost",size:"sm",onClick:()=>St(t),children:"Edit"})]})]},t.id)})})]}),j==="digest"&&e.jsx(os,{}),j==="settings"&&N&&e.jsxs("div",{className:"max-w-2xl space-y-4",children:[e.jsx(As,{}),e.jsxs("div",{className:"bg-white rounded-xl border border-gray-200 p-6",children:[e.jsx("h3",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide mb-4",children:"Delivery window"}),e.jsx("p",{className:"text-sm text-gray-500 mb-4",children:"Notifications go out only during these hours. Anything triggered outside them waits for the next opening."}),e.jsxs("label",{className:"flex items-center gap-3 mb-4",children:[e.jsx("input",{type:"checkbox",className:"rounded border-gray-300 text-band-600 focus:ring-band-500",checked:N.isEnabled,onChange:t=>Q(o=>({...o,isEnabled:t.target.checked}))}),e.jsx("span",{className:"text-sm text-gray-700",children:"Only send during these hours"})]}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4",children:[e.jsx(K,{type:"time",label:"Start Time",value:N.deliveryWindowStart,onChange:t=>Q(o=>({...o,deliveryWindowStart:t.target.value})),disabled:!N.isEnabled}),e.jsx(K,{type:"time",label:"End Time",value:N.deliveryWindowEnd,onChange:t=>Q(o=>({...o,deliveryWindowEnd:t.target.value})),disabled:!N.isEnabled})]}),e.jsxs("p",{className:"text-sm text-gray-600 mt-4",children:["Times are in y
2our organizationâs timezone: ",e.jsx("span",{className:"font-semibold",children:N.timezone}),v&&r?.id&&e.jsxs(e.Fragment,{children:[" â ",e.jsx(Jt,{to:`/settings/organizations/${r.id}?tab=settings`,className:"text-band-600 hover:text-band-700 underline",children:"change it in Organization settings"})]})]}),e.jsxs("div",{className:"flex gap-2 pt-6",children:[e.jsx(x,{onClick:Ut,isLoading:wt,disabled:!$t,size:"sm",children:"Save changes"}),e.jsx(x,{variant:"secondary",size:"sm",onClick:Wt,children:"Cancel"})]})]})]}),j==="settings"&&!N&&$e&&e.jsx(he,{card:!0,title:"Couldn't load delivery settings.",description:"The delivery window is not shown until it loads, so a save cannot overwrite it with defaults.",action:e.jsx(x,{variant:"secondary",onClick:Ne,children:"Try again"})}),j==="settings"&&!N&&!$e&&e.jsx("div",{className:"text-center py-8 text-gray-500",children:"Loading settingsâ¦"}),e.jsx(gt,{isOpen:ft,onClose:()=>ze(!1),title:"Template preview",children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm text-gray-500",children:[e.jsx("span",{className:"font-medium",children:"Channel:"}),e.jsx("span",{className:"inline-flex px-2 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800",children:lt.find(t=>t.value===G)?.label||G})]}),S.subject&&s.subject&&e.jsxs("div",{children:[e.jsx("p",{className:"text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1",children:"Email subject"}),e.jsx("p",{className:"text-sm text-gray-900 bg-gray-50 rounded-lg p-3",children:zt})]}),S.emailBody&&s.emailBody&&e.jsxs("div",{children:[e.jsx("p",{className:"text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1",children:"Email body"}),e.jsx("div",{className:"text-sm text-gray-900 bg-gray-50 rounded-lg p-3 whitespace-pre-wrap",children:Pt})]}),S.smsBody&&s.smsBody&&e.jsxs("div",{children:[e.jsx("p",{className:"text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1",children:"SMS body"}),e.jsx("div",{className:"text-sm text-gray-900 bg-gray-50 rounded-lg p-3 whitespace-pre-wrap",children:Ft})]}),S.emailBody&&$.length>0&&e.jsxs("div",{children:[e.jsx("p",{className:"text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1",children:"Attachments"}),e.jsx("ul",{className:"text-sm text-gray-600 space-y-1",children:$.map(t=>e.jsxs("li",{children:[t.fileName," (",mt(t.fileSize||0),")"]},t.id))})]})]})}),e.jsx(Ae,{isOpen:!!Je,onClose:()=>Ce(null),onConfirm:Ke,isLoading:Me,title:"Some placeholders will not fill in",message:`These are not values the system provides, so they will appear exactly like this in every message sent: ${(Je||[]).map(t=>`[${t}]`).join(", ")}. Save anyway?`,confirmLabel:"Save anyway",confirmVariant:"primary"}),e.jsx(Ae,{isOpen:bt,onClose:()=>fe(!1),onConfirm:Tt,title:"Delete template",message:`Delete "${b?.name}"? This cannot be undone. Members will receive the built-in wording for its trigger.`,confirmLabel:"Delete"}),e.jsx(Ae,{isOpen:yt,onClose:()=>ve(!1),onConfirm:pe,title:"Discard changes?",message:"What you typed in this template will be lost.",confirmLabel:"Discard",cancelLabel:"Keep editing"})]})}function xt({className:a}){return e.jsx("svg",{className:a,fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.75,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"})})}function Es({className:a}){return e.jsx("svg",{className:a,fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.75,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z"})})}function ut({className:a}){return e.jsx("svg",{className:a,fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.75,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"})})}function As(){const a=Te(g=>g.currentOrg),r=Te(g=>g.setNotificationsPause),n=H(g=>g.showSuccess),l=H(g=>g.showError),[c,u]=i.useState(!1),[v,C]=i.useState(""),[p,w]=i.useState(!1),h=a?.notificationsPausedUntil,j=h&&new Date(h).getTime()>Date.now(),I=async g=>{u(!0);try{await r(g),n(g?"Communication blackout active.":"Communication blackout cleared."),w(!1),C("")}catch(L){l(L?.message||"Could not update pause")}finally{u(!1)}},E=g=>{const L=new Date(Date.now()+g*60*60*1e3).toISOString();return I(L)},A=()=>{if(!v)return;const g=new Date(v).toISOString();
2if(new Date(g).getTime()<=Date.now()){l("Pause end must be in the future");return}I(g)},k=h?new Date(h).toLocaleString(void 0,{weekday:"short",month:"short",day:"numeric",hour:"numeric",minute:"2-digit"}):null;return e.jsxs("div",{className:`rounded-xl border p-6 ${j?"bg-amber-50 border-amber-200":"bg-white border-gray-200"}`,children:[e.jsxs("div",{className:"flex items-start justify-between gap-3 mb-1",children:[e.jsx("h3",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide",children:"Communication blackout"}),j&&e.jsxs("span",{className:"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-amber-200 text-amber-900",children:["Active until ",k]})]}),e.jsx("p",{className:"text-sm text-gray-600 mb-4",children:"Temporarily suppress automated member notifications â performance updates, rehearsal updates, setlist changes, reminders, and digests. Useful during iteration bursts or a post-incident comms hold."}),e.jsxs("div",{className:"bg-white/60 rounded-lg border border-gray-200 p-3 mb-4 text-xs text-gray-600 leading-relaxed",children:[e.jsx("strong",{className:"text-gray-700",children:"Always continues to send:"})," password resets, email verifications, new member welcome emails, invitations, and billing alerts. Only queue-driven member notifications are paused."]}),!p&&e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(x,{size:"sm",variant:"secondary",onClick:()=>E(24),disabled:c,children:"24 hours"}),e.jsx(x,{size:"sm",variant:"secondary",onClick:()=>E(48),disabled:c,children:"48 hours"}),e.jsx(x,{size:"sm",variant:"secondary",onClick:()=>E(168),disabled:c,children:"7 days"}),e.jsx(x,{size:"sm",variant:"ghost",onClick:()=>w(!0),disabled:c,children:"Customâ¦"}),j&&e.jsx(x,{size:"sm",variant:"danger",className:"ml-auto",onClick:()=>I(null),disabled:c,children:"Clear blackout"})]}),p&&e.jsxs("div",{className:"space-y-3",children:[e.jsx(K,{label:"Pause until",type:"datetime-local",value:v,onChange:g=>C(g.target.value)}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(x,{size:"sm",onClick:A,disabled:c||!v,children:"Set blackout"}),e.jsx(x,{size:"sm",variant:"ghost",onClick:()=>{w(!1),C("")},disabled:c,children:"Cancel"})]})]})]})}export{Ws as CommunicationsPage};
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.