1import{r as u,a as w,j as e,L as E}from"./index-MhqSdYbj.js";import{t as M}from"./leadTags-BBQc91ma.js";const O=[{id:"fields",label:"Data fields",lede:"What you capture about a lead, beyond name and number."},{id:"qualification",label:"Qualification",lede:"How a lead gets graded, and how fast you mean to answer."},{id:"tags",label:"Tags",lede:"The labels in use across your leads."}],q=[{v:"string",label:"Text"},{v:"number",label:"Number"},{v:"boolean",label:"Yes / no"},{v:"choice",label:"Pick from a list"}],k=[{v:"is",label:"is",needsValue:!0},{v:"is_any",label:"is any of",needsValue:!0},{v:"is_set",label:"has any value",needsValue:!1},{v:"is_true",label:"is yes",needsValue:!1},{v:"gt",label:"is more than",needsValue:!0},{v:"lt",label:"is less than",needsValue:!0}],R=24,z=24,_=10080,S=c=>c.trim().toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"").slice(0,48);function D(){const[c,h]=u.useState("fields"),[d,o]=u.useState(null),[r,t]=u.useState([]),[s,n]=u.useState(""),[m,g]=u.useState(!1),[x,a]=u.useState(!1),[b,f]=u.useState(null),[y,j]=u.useState("");u.useEffect(()=>{w("/api/limecall/agent",{on401:"throw"}).then(l=>{var A,T;const p=Array.isArray((A=l==null?void 0:l.agent)==null?void 0:A.variables)?l.agent.variables:[],v=(T=l==null?void 0:l.agent)==null?void 0:T.leadRules,C=Array.isArray(v==null?void 0:v.rules)?v.rules:[];o(p),t(C),n(v!=null&&v.slaMinutes?String(v.slaMinutes):""),j(JSON.stringify({vs:p,rs:C,sla:(v==null?void 0:v.slaMinutes)||""}))}).catch(()=>{o([]),g(!0)})},[]);const N=u.useMemo(()=>d!==null&&JSON.stringify({vs:d,rs:r,sla:Number(s)||""})!==y,[d,r,s,y]),i=u.useCallback(async()=>{if(!d)return;a(!0),f(null);const l={variables:d.filter(p=>p.name.trim()),leadRules:{...Number(s)>0?{slaMinutes:Math.min(Number(s),_)}:{},rules:r.filter(p=>p.field)}};try{await w("/api/limecall/agent",{method:"PATCH",on401:"throw",body:JSON.stringify(l)}),j(JSON.stringify({vs:l.variables,rs:l.leadRules.rules,sla:Number(s)||""})),f({ok:!0,text:"Saved."})}catch(p){f({ok:!1,text:(p==null?void 0:p.message)||"Couldnât save that â please try again."})}finally{a(!1)}},[d,r,s]);return d===null?e.jsx("div",{className:"skel",style:{height:280}}):e.jsxs("div",{className:"lm",children:[e.jsx("div",{className:"lm-nav",role:"tablist","aria-label":"Lead settings",children:O.map(l=>e.jsxs("button",{type:"button",role:"tab","aria-selected":c===l.id,className:`lm-navb${c===l.id?" on":""}`,onClick:()=>h(l.id),children:[e.jsx("b",{children:l.label}),e.jsx("small",{children:l.lede})]},l.id))}),e.jsxs("div",{className:"lm-body",children:[m&&e.jsx("p",{className:"lm-warn",children:"Couldnât load your lead settings. These exist on the server â this is a connection or permission problem, not an empty configuration, so nothing has been changed. Reload to try again, and donât save over it from here."}),c==="fields"&&e.jsx(F,{fields:d,setFields:o}),c==="qualification"&&e.jsx(L,{fields:d,rules:r,setRules:t,sla:s,setSla:n}),c==="tags"&&e.jsx(I,{}),c!=="tags"&&e.jsxs("div",{className:"lm-save",children:[e.jsx("button",{className:"btn",disabled:x||!N||m,onClick:i,children:x?"Savingâ¦":"Save changes"}),b&&e.jsx("span",{className:`lm-msg${b.ok?" ok":" bad"}`,children:b.text}),!N&&!b&&e.jsx("span",{className:"lm-msg",children:"No unsaved changes."})]})]}),e.jsx(P,{})]})}function F({fields:c,setFields:h}){const d=(o,r)=>h(c.map((t,s)=>s===o?{...t,...r}:t));return e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"lm-lede",children:"These are the things your AI listens for on a call, and the questions the website widget can ask. They become columns on a lead, and theyâre what the qualification rules read â so a rule can only be written about a field that exists here."}),c.length===0&&e.jsx("p",{className:"lm-empty",children:"No fields yet. Leads carry name, number, and whatever the AI wrote in its summary. Add a field for anything you want to filter or grade on â budget, timeline, company size."}),e.jsx("div",{className:"lm-fields",children:c.map((o,r)=>
1e.jsxs("div",{className:"lm-field",children:[e.jsxs("div",{className:"lm-field-hd",children:[e.jsx("input",{className:"lm-in lm-in-lg",value:o.label||"",placeholder:"Budget","aria-label":"Field label",onChange:t=>{const s=t.target.value;d(r,o.name&&o.name!==S(o.label||"")?{label:s}:{label:s,name:S(s)})}}),e.jsx("select",{className:"lm-in",value:o.type,"aria-label":"Field type",onChange:t=>{const s=t.target.value;d(r,{type:s,...s==="choice"?{options:o.options||[]}:{options:void 0}})},children:q.map(t=>e.jsx("option",{value:t.v,children:t.label},t.v))}),e.jsx("button",{type:"button",className:"lm-x","aria-label":`Remove ${o.label||"field"}`,onClick:()=>h(c.filter((t,s)=>s!==r)),children:"â"})]}),e.jsxs("label",{className:"lm-lab",children:["How should the AI recognise it?",e.jsx("input",{className:"lm-in lm-in-full",value:o.description||"",placeholder:"What they said they can spend, in their own words",onChange:t=>d(r,{description:t.target.value})})]}),o.type==="choice"&&e.jsxs("div",{className:"lm-opts",children:[(o.options||[]).map((t,s)=>e.jsxs("div",{className:"lm-opt",children:[e.jsx("input",{className:"lm-in",value:t.label,placeholder:"Under £1k","aria-label":"Choice label",onChange:n=>{const m=n.target.value,g=(o.options||[]).map((x,a)=>a===s?{...x,label:m,value:x.value||S(m)}:x);d(r,{options:g})}}),e.jsx("button",{type:"button",className:"lm-x","aria-label":"Remove choice",onClick:()=>d(r,{options:(o.options||[]).filter((n,m)=>m!==s)}),children:"â"})]},s)),(o.options||[]).length<12&&e.jsx("button",{type:"button",className:"pill lm-add",onClick:()=>d(r,{options:[...o.options||[],{value:"",label:""}]}),children:"+ Add a choice"})]}),e.jsxs("div",{className:"lm-flags",children:[e.jsxs("label",{children:[e.jsx("input",{type:"checkbox",checked:!!o.askOnWidget,onChange:t=>d(r,{askOnWidget:t.target.checked||void 0})})," Ask on the website widget"]}),e.jsxs("label",{children:[e.jsx("input",{type:"checkbox",checked:o.showOn==="row",onChange:t=>d(r,{showOn:t.target.checked?"row":void 0})})," Show as a column on the Leads list"]})]})]},r))}),c.length<R?e.jsx("button",{type:"button",className:"pill",onClick:()=>h([...c,{name:"",type:"string",description:""}]),children:"+ Add a field"}):e.jsxs("p",{className:"lm-note",children:["Thatâs the maximum of ",R," fields."]})]})}function L({fields:c,rules:h,setRules:d,sla:o,setSla:r}){const t=c.filter(n=>n.name),s=(n,m)=>d(h.map((g,x)=>x===n?{...g,...m}:g));return e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"lm-lede",children:["Rules grade ",e.jsx("b",{children:"every"})," lead â including callback requests, where there was no conversation for the AI to judge. They cost nothing to run and the Leads page shows which rule fired, so a score can be argued with rather than just believed."]}),e.jsxs("div",{className:"lm-sla",children:[e.jsx("span",{children:"Answer a new lead within"}),e.jsx("input",{className:"lm-in lm-in-sm",type:"number",min:1,max:_,value:o,placeholder:"30","aria-label":"Response target in minutes",onChange:n=>r(n.target.value)}),e.jsx("span",{children:"minutes, or flag it as waiting."})]}),t.length===0?e.jsxs("p",{className:"lm-empty",children:["Rules are written about your data fields, and you donât have any yet. Add one under"," ",e.jsx("b",{children:"Data fields"})," first â then a rule like âBudget is more than 500â becomes possible."]}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"lm-rules",children:h.map((n,m)=>{const g=k.find(a=>a.v===n.op)||k[0],x=t.find(a=>a.name===n.field);return e.jsxs("div",{className:"lm-rule",children:[e.jsx("span",{className:"lm-rule-w",children:"When"}),e.jsxs("select",{className:"lm-in",value:n.field,"aria-label":"Field",onChange:a=>s(m,{field:a.target.value}),children:[e.jsx("option",{value:"",children:"Pick a fieldâ¦"}),t.map(a=>e.jsx("option",{value:a.name,children:a.label||a.name},a.name))]}),e.jsx("select",{className:"lm-in",value:n.op,"aria-label":"Condition",onChange:a=>s(m,{op:a.target.value,value:void 0}),children:k.map(a=>e.jsx("option",{value:a.v,children:a.label},a.v))}),g.needsValue&&((x==null?void 0:x.type)==="choice"&&n.op==="is"?e.jsxs("select",{className:"lm-in",value:String(n.value??""),"aria-label":"Value",onCh
1ange:a=>s(m,{value:a.target.value}),children:[e.jsx("option",{value:"",children:"Pickâ¦"}),(x.options||[]).map(a=>e.jsx("option",{value:a.value,children:a.label||a.value},a.value))]}):e.jsx("input",{className:"lm-in","aria-label":"Value",type:n.op==="gt"||n.op==="lt"?"number":"text",value:Array.isArray(n.value)?n.value.join(", "):String(n.value??""),placeholder:n.op==="is_any"?"one, two, three":"",onChange:a=>s(m,{value:n.op==="is_any"?a.target.value.split(",").map(b=>b.trim()).filter(Boolean):n.op==="gt"||n.op==="lt"?Number(a.target.value)||0:a.target.value})})),e.jsx("span",{className:"lm-rule-w",children:"add"}),e.jsx("input",{className:"lm-in lm-in-sm",type:"number",min:-100,max:100,value:String(n.points??0),"aria-label":"Points",onChange:a=>s(m,{points:Math.max(-100,Math.min(100,Number(a.target.value)||0))})}),e.jsx("span",{className:"lm-rule-w",children:"points"}),e.jsxs("label",{className:"lm-rule-q",title:"A lead matching this rule counts as qualified, whatever its score",children:[e.jsx("input",{type:"checkbox",checked:!!n.qualifies,onChange:a=>s(m,{qualifies:a.target.checked||void 0})})," and qualifies it"]}),e.jsx("button",{type:"button",className:"lm-x","aria-label":"Remove rule",onClick:()=>d(h.filter((a,b)=>b!==m)),children:"â"})]},m)})}),h.length===0&&e.jsx("p",{className:"lm-empty",children:"No rules yet, so leads fall back to the AIâs own judgement â which only exists after a real conversation, and can differ between two runs on the same call."}),h.length<z?e.jsx("button",{type:"button",className:"pill",onClick:()=>{var n;return d([...h,{field:((n=t[0])==null?void 0:n.name)||"",op:"is_set",points:10}])},children:"+ Add a rule"}):e.jsxs("p",{className:"lm-note",children:["Thatâs the maximum of ",z," rules."]})]}),e.jsxs("p",{className:"lm-note",style:{marginTop:18},children:["Your AI also judges leads in its own words during a call. That wording lives with the agent, under ",e.jsx(E,{href:"/assistants?tab=leadqual",children:"AI Receptionist"}),"."]})]})}function I(){const[c,h]=u.useState(null),[d,o]=u.useState(!1),[r,t]=u.useState(null),[s,n]=u.useState(null),[m,g]=u.useState(""),[x,a]=u.useState(null),[b,f]=u.useState(null),y=u.useCallback(()=>{w("/api/tags",{on401:"throw"}).then(i=>h((Array.isArray(i)?i:[]).filter(l=>(l==null?void 0:l.name)&&!M(l.name)))).catch(()=>{h([]),o(!0)})},[]);u.useEffect(y,[y]);async function j(i){const l=m.trim();if(!l||l===i){n(null);return}t(i),f(null);try{const p=await w("/api/tags/rename",{method:"POST",on401:"throw",body:JSON.stringify({oldName:i,newName:l})});f(`Renamed on ${(p==null?void 0:p.updated)??0} lead${(p==null?void 0:p.updated)===1?"":"s"}.`),n(null),y()}catch{f("Couldnât rename that tag.")}finally{t(null)}}async function N(i){t(i),f(null);try{const l=await w("/api/tags/delete",{method:"POST",on401:"throw",body:JSON.stringify({tagName:i})});f(`Removed from ${(l==null?void 0:l.updated)??0} lead${(l==null?void 0:l.updated)===1?"":"s"}.`),a(null),y()}catch{f("Couldnât remove that tag.")}finally{t(null)}}return c===null?e.jsx("div",{className:"skel",style:{height:180}}):e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"lm-lede",children:"Every tag in use across your leads. Renaming one here updates it on each lead that carries it; removing it strips it from all of them. Neither can be undone."}),d&&e.jsx("p",{className:"lm-warn",children:"Couldnât load your tags just now. Reload to try again."}),c.length===0?e.jsx("p",{className:"lm-empty",children:"No tags yet. Add one to a lead and itâll show up here."}):e.jsx("div",{className:"lm-tags",children:c.map(i=>e.jsxs("div",{className:"lm-tag",children:[s===i.name?e.jsx("input",{className:"lm-in",autoFocus:!0,value:m,"aria-label":"New tag name",onChange:l=>g(l.target.value),onKeyDown:l=>{l.key==="Enter"&&(l.preventDefault(),j(i.name)),l.key==="Escape"&&n(null)},onBlur:()=>j(i.name)}):e.jsx("b",{children:i.name}),e.jsxs("span",{className:"lm-tag-n",children:[i.contactCount," lead",i.contactCount===1?"":"s"]}),x===i.name?e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",className:"lm-link bad",disabled:r===i.name,onClick:()=>N(i.name),children:r===i.name?"Removingâ¦":`Remove from ${i.contactCount}`}),e.jsx("button",{type:"button",className:"lm-link",onClick:()=>a(null),children:"Cancel"})]}):e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",className:"lm-link",disabled:!!r,onClick:()=>{n(i.name),g(i.name)},children:"Rename"}),e.jsx("button",{type:"button",className:"lm-link",disabled:!!r,onClick:()=>a(i.name),children:"Remove"})]})]},i.name))}),b&&e.jsx("p",{className:"lm-msg",style:{marginTop:12},children:b}),e.jsx("p",{className:"lm-note",style:{marginTop:18},children:"Colour labels applied from the table view are saved in your browser only and arenât shown here â theyâre not shared with your team yet."})]})}function P(){return e.jsx("style",{children:` 2 .lm{display:grid;grid-template-columns:236px 1fr;gap:20px;align-items:start} 3 @media(max-width:860px){.lm{grid-template-columns:1fr}} 4 .lm-nav{display:flex;flex-direction:column;gap:3px;position:sticky;top:64px} 5 @media(max-width:860px){.lm-nav{position:static;flex-direction:row;overflow-x:auto}} 6 .lm-navb{display:flex;flex-direction:column;gap:2px;text-align:left;border:0;background:none; 7 font-family:inherit;padding:10px 12px;border-radius:10px;cursor:pointer;transition:background .12s} 8 .lm-navb:hover{background:var(--line-2)} 9 .lm-navb.on{background:var(--accent-soft)} 10 .lm-navb b{font-size:13.5px;font-weight:620;color:var(--ink)} 11 .lm-navb.on b{color:var(--accent-ink)} 12 .lm-navb small{font-size:12px;line-height:1.45;color:var(--muted)} 13 @media(max-width:860px){.lm-navb small{display:none}} 14 .lm-body{background:var(--panel);border:1px solid var(--line);border-radius:var(--r); 15 box-shadow:var(--sh);padding:20px 22px;min-width:0} 16 .lm-lede{margin:0 0 16px;font-size:13px;line-height:1.6;color:var(--ink-2);max-width:660px} 17 .lm-empty{margin:0 0 14px;font-size:13px;line-height:1.6;color:var(--muted);max-width:620px} 18 .lm-note{margin:14px 0 0;font-size:12.5px;line-height:1.55;color:var(--faint);max-width:620px} 19 .lm-warn{margin:0 0 14px;font-size:12.5px;line-height:1.55;color:var(--warn)} 20 .lm-in{padding:7px 10px;border:1px solid var(--line);border-radius:9px;background:var(--panel); 21 color:var(--ink);font-family:inherit;font-size:13px;min-width:0} 22 .lm-in-sm{width:78px} 23 .lm-in-lg{flex:1;font-weight:600} 24 .lm-in-full{width:100%;margin-top:5px} 25 .lm-lab{display:block;font-size:12.5px;color:var(--muted);margin-top:10px} 26 .lm-x{border:0;background:none;color:var(--faint);font-size:14px;line-height:1;cursor:pointer; 27 padding:6px;border-radius:7px;flex:none} 28 .lm-x:hover{color:var(--crit);background:var(--line-2)} 29 .lm-fields{display:flex;flex-direction:column;gap:12px;margin-bottom:14px} 30 .lm-field{border:1px solid var(--line);border-radius:12px;padding:13px 14px} 31 .lm-field-hd{display:flex;gap:8px;align-items:center} 32 .lm-opts{display:flex;flex-wrap:wrap;gap:7px;margin-top:10px;align-items:center} 33 .lm-opt{display:flex;align-items:center;gap:2px} 34 .lm-add{font-size:12.5px} 35 .lm-flags{display:flex;flex-wrap:wrap;gap:16px;margin-top:11px} 36 .lm-flags label{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--ink-2);cursor:pointer} 37 .lm-sla{display:flex;flex-wrap:wrap;align-items:center;gap:8px;font-size:13px;color:var(--ink-2); 38 margin-bottom:18px;padding-bottom:16px;border-bottom:1px solid var(--line-2)} 39 .lm-rules{display:flex;flex-direction:column;gap:8px;margin-bottom:14px} 40 .lm-rule{display:flex;flex-wrap:wrap;align-items:center;gap:7px;padding:10px 12px; 41 border:1px solid var(--line);border-radius:11px} 42 .lm-rule-w{font-size:12.5px;color:var(--muted);flex:none} 43 .lm-rule-q{display:flex;align-items:center;gap:6px;font-size:12.5px;color:var(--ink-2);cursor:pointer} 44 .lm-tags{display:flex;flex-direction:column} 45 .lm-tag{display:flex;align-items:center;gap:11px;padding:11px 0;border-bottom:1px solid var(--line-2)} 46 .lm-tag:last-child{border-bottom:0} 47 .lm-tag>b{font-size:13.5px;font-weight:600;flex:1;min-width:0;word-break:break-word} 48 .lm-tag>.lm-in{flex:1} 49 .lm-tag-n{font-size:12.5px;color:var(--faint);flex:none;font-variant-numeric:tabular-nums} 50 .lm-link{border:0;background:none;font-family:inherit;font-size:12.5px;font-weight:600; 51 color:var(--accent-ink);cursor:pointer;padding:0;flex:none} 52 .lm-link:hover{text-decoration:underline} 53 .lm-link.bad{color:var(--crit)} 54 .lm-link:disabled{color:var(--faint);cursor:default;text-decoration:none} 55 .lm-save{display:flex;align-items:center;gap:12px;margin-top:22px;padding-top:16px; 56 border-top:1px solid var(--line-2)} 57 .lm-msg{font-size:12.5px;color:var(--muted)} 58 .lm-msg.ok{color:var(--good)} 59 .lm-msg.bad{color:var(--crit)} 60 `})}export{D as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.