PageSourceSearch

https://app.pippify.ai/assets/SequencesPage-D9z-NuEk.js

js pippify.ai collected 2026-10-05 14:08:15 UTC 17,699 bytes, 1 lines download raw bytes

1import{a as w,j as e,L as $}from"./vendor-react-DQmRrvQV.js";import{m as R,l as _,o as S,k as O}from"./vendor-state-3t2mugU9.js";import{u as Q,e as U,s as B,g as V,h as K,j as F,k as W,m as H,f as G,n as Y}from"./sequences-D6lZ7Qbm.js";import{u as Z}from"./aiStudio-DgRQcXzd.js";import{v as I,c as X,aP as J,Z as ee,aQ as te,z as se}from"./index-Cn9rYaym.js";import{m as ae,P as y,T as ne}from"./vendor-mui-BxA0N6WT.js";import{E as ie}from"./EmptyState-AUoemN3z.js";import{u as le,A as oe}from"./useToast-BRuWnAEv.js";import{r as re}from"./readErrorMessage-DmAQ1luZ.js";import"./sse-B8JMfTht.js";const de={hours:1,days:24};function ce(n){return n%24===0&&n>=24?{value:n/24,unit:"days"}:{value:n,unit:"hours"}}function L(){return{channel:"email",delayValue:2,delayUnit:"days",instruction:""}}function ue(n){return{name:n.name.trim(),exhaustAction:n.exhaustAction,steps:n.steps.map(a=>{var f;return{channel:a.channel,delayHours:Math.max(1,Math.min(720,Math.round(Number(a.delayValue)*de[a.delayUnit]))),...(f=a.instruction)!=null&&f.trim()?{instruction:a.instruction.trim()}:{}}})}}
1function P(n){return n?{name:n.name??"",exhaustAction:n.exhaustAction??"mark_lost",steps:(n.steps??[]).map(a=>{const{value:f,unit:i}=ce(a.delayHours??24);return{channel:a.channel,delayValue:f,delayUnit:i,instruction:a.instruction??""}})}:{name:"",exhaustAction:"mark_lost",steps:[L()]}}const D=12,T=({open:n,sequence:a,onClose:f,onSave:i,isSaving:x,importContext:o=null,onImportContextChange:g,onCopyMission:m})=>{const{t:v}=I(),[d,p]=w.useState(()=>P(a));w.useEffect(()=>{n&&p(P(a))},[n,a]);const r=(l,s)=>{p(c=>({...c,steps:c.steps.map((b,j)=>j===l?{...b,...s}:b)}))},h=()=>{p(l=>l.steps.length>=D?l:{...l,steps:[...l.steps,L()]})},N=l=>{p(s=>s.steps.length<=1?s:{...s,steps:s.steps.filter((c,b)=>b!==l)})},k=(l,s)=>{p(c=>{const b=l+s;if(b<0||b>=c.steps.length)return c;const j=[...c.steps];return[j[l],j[b]]=[j[b],j[l]],{...c,steps:j}})},C=d.name.trim().length>0&&d.steps.length>=1&&d.steps.every(l=>Number(l.delayValue)>0);return e.jsx(ae,{anchor:"right",open:n,onClose:f,PaperProps:{sx:{width:520,maxWidth:"100vw"}},children:e.jsxs("div",{className:"seq-edit-drawer",children:[e.jsxs("div",{className:"seq-edit-drawer__header",children:[e.jsxs("div",{children:[e.jsx("h5",{className:"mb-0",children:a?"Edit sequence":"New sequence"}),e.jsx("span",{className:"text-muted",style:{fontSize:12},children:"Each step waits its delay after the previous touch, then the AI writes it from the live conversation."})]}),e.jsx("button",{type:"button",className:"btn btn-sm btn-link text-muted p-0",onClick:f,"aria-label":"Close",children:e.jsx("i",{className:"mdi mdi-close",style:{fontSize:18}})})]}),e.jsxs("div",{className:"seq-edit-drawer__body",children:[e.jsxs("div",{className:"mb-3",children:[e.jsx("label",{className:"form-label",style:{fontSize:13},htmlFor:"seq-name",children:"Name"}),e.jsx("input",{id:"seq-name",className:"form-control form-control-sm",value:d.name,maxLength:120,placeholder:"e.g. 7 Attempts to Qualify",onChange:l=>p(s=>({...s,name:l.target.value}))})]}),e.jsxs("div",{className:"mb-3",children:[e.jsx("label",{className:"form-label",style:{fontSize:13},htmlFor:"seq-exhaust",children:"After the final step"}),e.jsxs("select",{id:"seq-exhaust",className:"form-select form-select-sm",value:d.exhaustAction,onChange:l=>p(s=>({...s,exhaustAction:l.target.value})),children:[e.jsx("option",{value:"mark_lost",children:"Mark the lead as lost"}),e.jsx("option",{value:"none",children:"End quietly"})]})]}),e.jsx("label",{className:"form-label",style:{fontSize:13},children:"Steps"}),d.steps.map((l,s)=>e.jsxs("div",{className:"sequence-step-row","data-testid":`step-row-${s}`,children:[e.jsxs("div",{className:"sequence-step-row__day",children:[e.jsx("div",{className:"sequence-step-row__day-label",children:"Step"}),e.jsx("div",{className:"sequence-step-row__day-num",children:s+1})]}),e.jsxs("div",{className:"sequence-step-row__card",children:[e.jsxs("div",{className:"sequence-step-row__card-header",children:[e.jsxs("select",{className:"form-select form-select-sm",style:{width:110},"aria-label":`Step ${s+1} channel`,value:l.channel,onChange:c=>r(s,{channel:c.target.value}),children:[e.jsx("option",{value:"email",children:"Email"}),e.jsx("option",{value:"sms",children:"SMS"})]}),e.jsx("span",{className:"text-muted",style:{fontSize:12},children:"after"}),e.jsx("input",{type:"number",min:1,className:"form-control form-control-sm",style:{width:76},"aria-label":`Step ${s+1} delay`,value:l.delayValue,onChange:c=>r(s,{delayValue:c.target.value})}),e.jsxs("select",{className:"form-select form-select-sm",style:{width:92},"aria-label":`Step ${s+1} delay unit`,value:l.delayUnit,onChange:c=>r(s,{delayUnit:c.target.value}),children:[e.jsx("option",{value:"hours",children:"hours"}),e.jsx("option",{value:"days",children:"days"})]}),e.jsxs("div",{className:"ms-auto d-flex gap-1",children:[e.jsx("button",{type:"button",className:"btn btn-sm btn-link p-0 text-muted","aria-label":`Move step ${s+1} up`,disabled:s===0,onClick:()=>k(s,-1),children:e.jsx("i",{className:"mdi mdi-arrow-up"})}),e.jsx("button",{type:"button",className:"btn btn-sm btn-link p-0 text-muted","aria-label":`Move step ${s+1} down`,disabled:s===d.steps.length-1,onClick:()=>k(s,1),children:e.jsx("i",{className:"mdi mdi-arrow-down"})}),e.jsx("button",{type:"button",className:"btn btn-sm btn-link p-0 text-danger","aria-label":`Remove step ${s+1}`,disabled:d.steps.length<=1,onClick:()=>N(s),children:e.jsx("i",{className:"mdi mdi-trash-can-outline"})})]})]}),e.jsx("input",{className:"form-control form-control-sm mt-1",placeholder:"Optional instruction for this touch, e.g. “mention the promo ends Friday”","aria-label":`Step ${s+1} instruction`,maxLength:500,value:l.instruction,onChange:c=>r(s,{instruction:c.target.value})})]})]},s)),e.jsx("button",{type:"button",className:"btn btn-sm btn-outline-secondary mt-1",onClick:h,disabled:d.steps.length>=D,children:v("sequences.addStep")}),o&&e.jsxs("div",{className:"seq-edit-drawer__meta mt-3","data-testid":"import-extras",children:[e.jsxs("div",{className:"form-check",style:{fontSize:12.5},children:[e.jsx("input",{id:"seq-disable-original",className:"form-check-input",type:"checkbox",checked:!!o.disableOriginal,onCh
1ange:l=>g==null?void 0:g({...o,disableOriginal:l.target.checked})}),e.jsx("label",{className:"form-check-label",htmlFor:"seq-disable-original",children:"Disable the original guidance rule after saving (recommended — the schedule prose confuses the reply prompt)"})]}),o.missionCandidate&&e.jsxs("div",{className:"mt-2",style:{fontSize:12.5},children:[e.jsx("div",{className:"text-muted mb-1",children:"This rule also contains a job description for the AI:"}),e.jsxs("div",{style:{fontStyle:"italic",marginBottom:6},children:["“",o.missionCandidate,"”"]}),e.jsx("button",{type:"button",className:"btn btn-sm btn-outline-primary",onClick:()=>m==null?void 0:m(o.missionCandidate),children:"Copy it to the Mission field"})]})]})]}),e.jsxs("div",{className:"seq-edit-drawer__footer",children:[e.jsx("button",{type:"button",className:"btn btn-sm btn-outline-secondary",onClick:f,disabled:x,children:"Cancel"}),e.jsx("button",{type:"button",className:"btn btn-sm btn-primary",disabled:!C||x,onClick:()=>i(ue(d)),children:x?"Saving…":"Save sequence"})]})]})})};T.propTypes={open:y.bool.isRequired,sequence:y.object,onClose:y.func.isRequired,onSave:y.func.isRequired,isSaving:y.bool,importContext:y.shape({guidanceId:y.string,missionCandidate:y.string,disableOriginal:y.bool}),onImportContextChange:y.func,onCopyMission:y.func};const me=(n,a)=>!!(n&&a&&n>a);function he(n){let a;try{a=Intl.supportedValuesOf("timeZone")}catch{a=["Asia/Manila","Asia/Singapore","Asia/Hong_Kong","Asia/Tokyo","Australia/Sydney","Europe/London","America/New_York","America/Los_Angeles","UTC"]}return n&&!a.includes(n)?[n,...a]:a}const pe=({canEdit:n,onToast:a})=>{const f=R(),[i,x]=w.useState(null),{data:o,isLoading:g}=_({queryKey:["sequences","quiet-hours"],queryFn:U,select:r=>{var h;return((h=r.data)==null?void 0:h.data)??null}});w.useEffect(()=>{o&&x(o)},[o]);const m=S({mutationFn:r=>Q(r),onSuccess:r=>{var N;const h=(N=r.data)==null?void 0:N.data;h&&(x(h),f.setQueryData(["sequences","quiet-hours"],r)),a==null||a("success","Sending window updated.")},onError:()=>a==null?void 0:a("error","Could not update the sending window.")});if(g||!i)return null;const v=r=>h=>x({...i,[r]:h.target.value}),d=i.start!==(o==null?void 0:o.start)||i.end!==(o==null?void 0:o.end)||i.timezone!==(o==null?void 0:o.timezone),p=!!i.start&&i.start===i.end;return e.jsx("div",{className:"card mb-3","data-testid":"quiet-hours-card",children:e.jsxs("div",{className:"card-body py-3",children:[e.jsxs("div",{className:"fw-semibold mb-1",style:{fontSize:13.5},children:[e.jsx("i",{className:"mdi mdi-clock-outline me-1"}),"Follow-up sending window"]}),e.jsx("div",{className:"text-muted mb-3",style:{fontSize:12.5},children:"Scheduled follow-ups only go out between these times — a touch that comes due outside the window waits for the next opening. Replies to a live question are never held back."}),e.jsxs("div",{className:"d-flex align-items-end gap-3 flex-wrap",children:[e.jsxs("div",{children:[e.jsx("label",{className:"form-label mb-1",htmlFor:"quiet-hours-start",style:{fontSize:12},children:"From"}),e.jsx("input",{id:"quiet-hours-start",type:"time",className:"form-control form-control-sm",style:{width:120},value:i.start??"",disabled:!n||m.isPending,onChange:v("start")})]}),e.jsxs("div",{children:[e.jsx("label",{className:"form-label mb-1",htmlFor:"quiet-hours-end",style:{fontSize:12},children:"To"}),e.jsx("input",{id:"quiet-hours-end",type:"time",className:"form-control form-control-sm",style:{width:120},value:i.end??"",disabled:!n||m.isPending,onChange:v("end")})]}),e.jsxs("div",{children:[e.jsx("label",{className:"form-label mb-1",htmlFor:"quiet-hours-tz",style:{fontSize:12},children:"Timezone"}),e.jsx("select",{id:"quiet-hours-tz",className:"form-select form-select-sm",style:{width:220},value:i.timezone??"",disabled:!n||m.isPending,onChange:v("timezone"),children:he(o==null?void 0:o.timezone).map(r=>e.jsx("option",{value:r,children:r},r))})]}),n&&e.jsx("button",{type:"button",className:"btn btn-sm btn-primary ms-auto",disabled:!d||p||m.isPending,onClick:()=>m.mutate(i),children:m.isPending?"Saving…":"Save window"})]}),p&&e.jsx("div",{className:"text-danger mt-2",style:{fontSize:12},children:"Start and end can't be the same time — that would leave no window to send in."}),!p&&me(i.start,i.end)&&e.jsxs("div",{className:"text-muted mt-2",style:{fontSize:12},children:["This window runs overnight: follow-ups send from ",i.start," through to"," ",i.end," the next morning."]}),!n&&e.jsx("div",{className:"text-muted mt-2",style:{fontSize:12},children:"Only client admins can change the sending window."})]})})},qe=()=>{const{t:n}=I(),a=R(),f=O(X),i=ee(f,se.CLIENT_ADMIN),[x,o]=w.useState({open:!1,sequence:null}),[g,m]=w.useState(null),{toast:v,showToast:d,hideToast:p}=le(),[r,h]=w.useState(null),{data:N=[],isLoading:k}=_({queryKey:["sequences"],queryFn:G,select:t=>{var u;return((u=t.data)==null?void 0:u.data)??[]},staleTime:30*1e3}),{data:C=[]}=_({queryKey:["sequences","import-candidates"],queryFn:Y,select:t=>{var u;return((u=t.data)==null?void 0:u.data)??[]},enabled:i}),l=()=>a.invalidateQueries({queryKey:["sequences"]}),s=(t,u)=>
1d("error",re(t,u)),c=S({mutationFn:async t=>{var u;return(u=x.sequence)!=null&&u._id?F(x.sequence._id,t):H(t)},onSuccess:async()=>{let t=null;if(r!=null&&r.disableOriginal&&(r!=null&&r.guidanceId))try{await Z({id:r.guidanceId,enabled:!1}),a.invalidateQueries({queryKey:["sequences","import-candidates"]})}catch{t="Sequence saved, but the original guidance rule could not be disabled — disable it in AI Studio."}o({open:!1,sequence:null}),h(null),t?d("warning",t):d("success","Sequence saved."),l()},onError:t=>s(t,"Could not save the sequence.")}),b=S({mutationFn:t=>V(t),onSuccess:(t,u)=>{var E;const q=(E=t.data)==null?void 0:E.data;q&&(h({guidanceId:u,missionCandidate:q.missionCandidate??null,disableOriginal:!0}),o({open:!0,sequence:{name:q.name,exhaustAction:q.exhaustAction,steps:q.steps}}))},onError:t=>s(t,"Could not read a schedule out of that rule.")}),j=S({mutationFn:t=>te({mission:t}),onSuccess:()=>d("success","Copied to the Mission field in AI Studio → Basics."),onError:t=>s(t,"Could not update the Mission field.")}),z=S({mutationFn:({id:t,enabled:u})=>F(t,{enabled:u}),onSuccess:l,onError:t=>s(t,"Could not update the sequence.")}),A=S({mutationFn:t=>K(t),onSuccess:l,onError:t=>s(t,"Could not change the default sequence.")}),M=S({mutationFn:t=>W(t),onSuccess:()=>{m(null),d("success","Sequence deleted."),l()},onError:t=>s(t,"Could not delete the sequence.")});return e.jsxs("div",{className:"container-fluid py-3 sequences-page",style:{maxWidth:900},children:[e.jsxs("div",{className:"d-flex align-items-center mb-1",children:[e.jsx("h4",{className:"mb-0",children:n("sequences.title")}),i&&e.jsxs("button",{type:"button",className:"btn btn-sm btn-primary ms-auto",onClick:()=>o({open:!0,sequence:null}),children:[e.jsx("i",{className:"mdi mdi-plus me-1"}),"New sequence"]})]}),e.jsx("p",{className:"text-muted mb-3",style:{fontSize:12.5},children:"When a lead goes quiet after your last message, the default sequence enrolls them automatically and the AI writes each touch from the live conversation. A reply, a booked meeting, or an opt-out stops it immediately."}),e.jsx(pe,{canEdit:i,onToast:d}),i&&C.length>0&&e.jsx("div",{className:"card mb-3","data-testid":"import-banner",style:{background:"#fff8e6",borderColor:"#f3e2bf"},children:e.jsxs("div",{className:"card-body py-3",children:[e.jsxs("div",{className:"fw-semibold mb-1",style:{fontSize:13.5},children:[e.jsx("i",{className:"mdi mdi-lightbulb-on-outline me-1"}),"We found a follow-up schedule in your guidance rules"]}),e.jsx("div",{className:"text-muted mb-2",style:{fontSize:12.5},children:"Guidance rules can't send messages on a timer — import the schedule here so it actually runs. You'll review it before anything is saved."}),C.map(t=>e.jsxs("div",{className:"d-flex align-items-center gap-2 py-1",style:{fontSize:13},children:[e.jsx("span",{className:"fw-semibold",children:t.title}),e.jsx("span",{className:"text-muted text-truncate",style:{fontSize:12,maxWidth:380},children:t.snippet}),e.jsx("button",{type:"button",className:"btn btn-sm btn-primary ms-auto",disabled:b.isPending,onClick:()=>b.mutate(t.guidanceId),children:b.isPending?"Reading…":"Import"})]},t.guidanceId))]})}),k?e.jsxs("div",{className:"text-center text-muted py-5",children:[e.jsx("div",{className:"spinner-border spinner-border-sm me-2",role:"status"}),"Loading…"]}):N.length===0?e.jsx(ie,{icon:"mdi-timeline-clock-outline",title:"No sequences yet",description:"Build a follow-up schedule and silent leads will be nudged automatically.",actionLabel:i?"Create your first sequence":void 0,onAction:i?()=>o({open:!0,sequence:null}):void 0}):N.map(t=>e.jsx("div",{className:"card mb-2","data-testid":`sequence-${t._id}`,children:e.jsxs("div",{className:"card-body py-3 d-flex align-items-center gap-2 flex-wrap",children:[e.jsx(ne,{title:t.isDefault?"Default sequence — auto-enrollment uses this one":"Make default",arrow:!0,children:e.jsx("span",{children:e.jsx("button",{type:"button",className:"btn btn-sm btn-link p-0","aria-label":t.isDefault?"Default sequence":`Make ${t.name} the default`,disabled:!i||t.isDefault||A.isPending,onClick:()=>A.mutate(t._id),children:e.jsx("i",{className:`mdi ${t.isDefault?"mdi-star text-warning":"mdi-star-outline text-muted"}`,style:{fontSize:18}})})})}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"fw-semibold",children:t.name}),e.jsxs("div",{className:"text-muted",style:{fontSize:12},children:[B(t.steps),t.exhaustAction==="mark_lost"?" · exhausts to lost":""]})]}),e.jsxs("div",{className:"ms-auto d-flex align-items-center gap-2",children:[e.jsxs($,{to:J(t._id),className:"btn btn-sm btn-outline-primary",children:["View leads",t.liveRunCount>0?` (${t.liveRunCount})`:""]}),e.jsx("div",{className:"form-check form-switch mb-0",children:e.jsx("input",{className:"form-check-input",type:"checkbox",role:"switch","aria-label":`${t.name} enabled`,checked:!!t.enabled,disabled:!i||z.isPending,onChange:u=>z.mutate({id:t._id,enabled:u.target.checked})})}),i&&e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",className:"btn btn-sm btn-outline-secondary",onClick:()=>o({open:!0,sequence:t}),children:"Edit"}),e.jsx("button",{type:"button",className:"btn btn-sm btn-outline-danger","aria-label":`Delete ${t.name}`,onClick:()=>m(t),children:e.jsx("i",{className:"mdi mdi-trash-can-outline"})})]})]})]})},t._id)),g&&e.jsx("div",{className:"card border-danger mt-3",role:"alertdialog","aria-label":"Confirm delete",children:e.jsxs("div",{className:"card-body py-3 d-flex align-items-center gap-2 flex-wrap",children:[e.jsxs("span",{style:{fontSize:13.5},children:["Delete “",g.name,"”? Active follow-ups using it stop immediately. This cannot be undone."]}),e.jsxs("div",{className:"ms-auto d-flex gap-2",children:[e.jsx("button",{type:"button",className:"btn btn-sm btn-outline-secondary",onClick:()=>m(null),children:"Cancel"}),e.jsx("button",{type:"button",className:"btn btn-sm btn-danger",disabled:M.isPending,onClick:()=>M.mutate(g._id),children:"Delete sequence"})]})]})}),e.jsx(T,{open:x.open,sequence:x.sequence,onClose:()=>{o({open:!1,sequence:null}),h(null)},onSave:t=>c.mutate(t),isSaving:c.isPending,importContext:r,onImportContextChange:h,onCopyMission:t=>j.mutate(t)}),e.jsx(oe,{toast:v,onClose:p})]})};export{qe as default,B as stepSummary};

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.