1import{p as xe,q as ae,K as te,t as K,O as I,s as N,u as ue,aM as he,r as m,j as e,N as Y,c as pe,B as p,A as ge,C as l,b as c,bH as Z,d as g,e as j,a as f,ac as je,au as fe,at as Ne}from"./index-dLiioUMp.js";import{M as X}from"./MainLayout-DzB2BSdP.js";import{I as D}from"./input-D8NVd1ns.js";import{B as q}from"./badge-SWOxTi8j.js";import{S as ve}from"./slider-CzeEePYc.js";import{T as ye,a as we,b as J,c as ee}from"./tabs-Js_z_oFy.js";import{B as be}from"./bot-CAt6DyxU.js";import{Z as se}from"./zap-B-jqG7uq.js";import{U as Se}from"./user-check-CPi-Ydc4.js";import{U as ke}from"./users-Wz67jG4K.js";import{P as _e}from"./plus-Bbae-nNK.js";import{T as Ce}from"./trash-2-CVvDfz2m.js";import{S as Te}from"./shield-alert-wYW0FcUS.js";import{M as Me}from"./message-square-FKbrk71S.js";import{T as Ae}from"./timer-Cp1-dDIT.js";import"./avatar-DjtkOt3N.js";import"./dropdown-menu-DF5xzmte.js";import"./chevron-right-CmJpZQ5S.js";import"./popover-4Z3N_PWN.js";import"./scroll-area-zDXHKUyb.js";import"./index-BdQq_4o_.js";import"./skeleton-BtqqbLFf.js";import"./gift-CXJTZTjb.js";import"./coins-BamybQzw.js";import"./useDirectMessages-37dSDjuq.js";import"./en-US-DguC7roY.js";import"./endOfMonth-CHlpE8px.js";import"./lightbulb-DE-PSPgs.js";import"./circle-help-BJF2hyou.js";import"./credit-card-BXjFi1Tx.js";import"./ThemeSwitcher-BQ6uKMLy.js";import"./shield-check-Dxm5ChyH.js";import"./wallet-BjFqBuLI.js";import"./message-circle-B0kEVkBX.js";import"./star-8Ded0Bxr.js";import"./trackUpgradeIntent-Bo1LXsPt.js";import"./useProductionAccess-BcCYg5eh.js";import"./useIsProductionInternal-CDhYPjXy.js";import"./graduation-cap-CvtUXBkJ.js";import"./flask-conical-BXQntVI1.js";import"./palette-DmOj5N7P.js";import"./settings-SsJOxsNy.js";import"./chevron-left-D7uQDDlB.js";import"./book-open-BR1QFR4Y.js";/** 2 * @license lucide-react v0.462.0 - ISC 3 * 4 * This source code is licensed under the ISC license. 5 * See the LICENSE file in the root directory of this source tree. 6 */const Ee=xe("Power",[["path",{d:"M12 2v10",key:"mnfbl"}],["path",{d:"M18.4 6.6a9 9 0 1 1-12.77.04",key:"obofu9"}]]);function Le(){const{user:d}=ae(),v=te(),{data:x,isLoading:y}=K({queryKey:["sandra-settings"],queryFn:async()=>{const{data:t,error:n}=await N.from("sandra_ai_settings").select("*").limit(1).maybeSingle();if(n)throw n;return t},enabled:!!d}),w=I({mutationFn:async t=>{if(!(x!=null&&x.id))throw new Error("No settings found");const{error:n}=await N.from("sandra_ai_settings").update({...t,updated_at:new Date().toISOString(),updated_by:d==null?void 0:d.id}).eq("id",x.id);if(n)throw n},onSuccess:()=>{v.invalidateQueries({queryKey:["sandra-settings"]})}});return{settings:x,isLoading:y,updateSettings:w}}function De(){const d=te(),{data:v=[],isLoading:x}=K({queryKey:["team-members"],queryFn:async()=>{const{data:t,error:n}=await N.from("team_members").select("*").order("created_at",{ascending:!0});if(n)throw n;return t||[]}}),y=I({mutationFn:async t=>{const{error:n}=await N.from("team_members").insert(t);if(n)throw n},onSuccess:()=>d.invalidateQueries({queryKey:["team-members"]})}),w=I({mutationFn:async t=>{const{error:n}=await N.from("team_members").delete().eq("id",t);if(n)throw n},onSuccess:()=>d.invalidateQueries({queryKey:["team-members"]})});return{members:v,isLoading:x,addMember:y,removeMember:w}}const qe=["cancel","refund","оÑмена","возвÑаÑ","ÑазоÑаÑован","disappointed","unhappy","lawsuit","lawyer","адвокаÑ","ÑÑд"],ks=()=>{const{user:d}=ae(),v=ue(),{isAdmin:x,isClientManager:y,loading:w}=he(),{settings:t,isLoading:n,updateSettings:T}=Le(),{members:F,isLoading:ne,addMember:R,removeMember:U}=De(),P=x||y,[S,B]=m.useState(""),[O,Q]=m.useState(""),[z,re]=m.useState("editor"),[b,H]=m.useState(!0),[M,A]=m.useState(!1),[u,k]=m.useState([]),[W,$]=m.useState(""),[_,G]=m.useState(30);m.useEffect(()=>{t&&(H(t.is_enabled),A(t.auto_escalate_enabled),k(t.escalation_keywords||[]),G(t.manager_takeover_timeout_minutes??30))},[t]);const{data:o}=K({queryKey:["sandra-analytics"],queryFn:async()=>{const s=new Date(Date.now()-2592e6).toISOString(),{data:i,error:C}=await N.from("sandra_response_log").select("*").gte("created_at",s).order("created_at",{ascending:!1});if(C)throw C;return i||[]},enabled:!!d&&P}),r=m.useMemo(()=>
6{if(!(o!=null&&o.length))return null;const s=o.length,i=o.filter(a=>a.was_hallucination).length,C=o.filter(a=>a.was_fallback).length,de=o.filter(a=>a.had_manager_tag).length,E=o.filter(a=>a.response_time_ms&&!a.was_fallback&&a.ai_response&&!a.ai_response.startsWith("[")).map(a=>a.response_time_ms),oe=E.length>0?Math.round(E.reduce((a,h)=>a+h,0)/E.length/1e3):0,L={};for(const a of o){const h=a.client_name||"Unknown";L[h]=(L[h]||0)+1}const me=Object.entries(L).sort((a,h)=>h[1]-a[1]).slice(0,5);return{total:s,hallucinations:i,fallbacks:C,escalations:de,avgResponseTime:oe,topClients:me}},[o]);if(!d)return e.jsx(Y,{to:"/auth",replace:!0});if(w)return e.jsx(X,{children:e.jsx("div",{className:"flex items-center justify-center py-24",children:e.jsx(pe,{className:"h-8 w-8 animate-spin text-primary"})})});if(!P)return e.jsx(Y,{to:"/production",replace:!0});const ie=async()=>{try{await T.mutateAsync({is_enabled:b,greeting_enabled:!1,auto_escalate_enabled:M,escalation_keywords:u,manager_takeover_timeout_minutes:_}),f.success("Sandra settings saved")}catch{f.error("Failed to save settings")}},V=()=>{const s=W.trim().toLowerCase();s&&!u.includes(s)&&(k([...u,s]),$(""))},le=s=>{k(u.filter(i=>i!==s))},ce=()=>{const s=[...new Set([...u,...qe])];k(s),A(!0),f.success(`Added ${s.length-u.length} default keywords`)};return e.jsx(X,{children:e.jsxs("div",{className:"max-w-2xl mx-auto px-4 py-6",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-6",children:[e.jsx(p,{variant:"ghost",size:"icon",onClick:()=>v("/production/client-health"),children:e.jsx(ge,{className:"w-5 h-5"})}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("h1",{className:"text-2xl font-bold flex items-center gap-2",children:[e.jsx(be,{className:"w-6 h-6 text-primary"}),"Sandra AI â Settings"]}),e.jsx("p",{className:"text-muted-foreground text-sm mt-0.5",children:"Global settings for the AI care manager"})]})]}),n?e.jsx("div",{className:"text-center text-muted-foreground py-12",children:"Loading..."}):e.jsxs(ye,{defaultValue:"settings",className:"space-y-4",children:[e.jsxs(we,{className:"w-full",children:[e.jsx(J,{value:"settings",className:"flex-1",children:"Settings"}),e.jsx(J,{value:"analytics",className:"flex-1",children:"Analytics"})]}),e.jsxs(ee,{value:"settings",className:"space-y-4",children:[e.jsx(l,{children:e.jsx(c,{className:"p-5",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:`p-2 rounded-xl ${b?"bg-green-500/10":"bg-muted"}`,children:e.jsx(Ee,{className:`w-5 h-5 ${b?"text-green-500":"text-muted-foreground"}`})}),e.jsxs("div",{children:[e.jsx("div",{className:"font-semibold",children:"Sandra Active"}),e.jsx("div",{className:"text-sm text-muted-foreground",children:b?"Sandra responds to clients in Slack":"Sandra is disabled â respond manually"})]})]}),e.jsx(Z,{checked:b,onCheckedChange:H})]})})}),e.jsxs(l,{children:[e.jsx(g,{className:"pb-3",children:e.jsxs(j,{className:"text-base flex items-center gap-2",children:[e.jsx(se,{className:"w-4 h-4 text-green-500"}),"Adaptive Response Speed"]})}),e.jsxs(c,{className:"space-y-3",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Sandra automatically adjusts her reply timing based on the message â no manual tuning needed."}),e.jsxs("div",{className:"space-y-2 text-sm bg-muted/50 rounded-xl p-3.5",children:[e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("span",{className:"text-muted-foreground min-w-[7.5rem] shrink-0",children:'"Got it ð"'}),e.jsx("span",{children:"replies in ~3 seconds"})]}),e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("span",{className:"text-muted-foreground min-w-[7.5rem] shrink-0",children:"Quick question"}),e.jsx("span",{children:"5â10 seconds"})]}),e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("span",{className:"text-muted-foreground min-w-[7.5rem] shrink-0",children:"Brief / video Q"}),e.jsx("span",{children:"15â30 seconds"})]}),e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("span",{className:"text-muted-foreground min-w-[7.5rem] shrink-0",children:'"Check
6stats"'}),e.jsx("span",{children:"1â2 minutes (mimics real analysis)"})]})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"She also reacts faster during active conversations and slower outside working hours and on weekends â just like a real person."})]})]}),e.jsxs(l,{children:[e.jsx(g,{className:"pb-3",children:e.jsxs(j,{className:"text-base flex items-center gap-2",children:[e.jsx(Se,{className:"w-4 h-4 text-muted-foreground"}),"Team Takeover"]})}),e.jsxs(c,{className:"space-y-4",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"When a team member writes in the channel, Sandra goes silent for the specified time"}),e.jsxs("div",{children:[e.jsxs("label",{className:"text-sm font-medium",children:["Timeout: ",_," min"]}),e.jsx(ve,{value:[_],onValueChange:([s])=>G(s),min:5,max:120,step:5,className:"mt-2"})]}),e.jsxs("div",{className:"text-xs text-muted-foreground bg-muted/50 rounded-lg p-3",children:["Sandra will resume responding ",_," minutes after the last team member's message"]})]})]}),e.jsxs(l,{children:[e.jsx(g,{className:"pb-3",children:e.jsxs(j,{className:"text-base flex items-center gap-2",children:[e.jsx(ke,{className:"w-4 h-4 text-muted-foreground"}),"Team (Slack)"]})}),e.jsxs(c,{className:"space-y-4",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Team members whose activity silences Sandra. Add the Slack User ID of each team member."}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(D,{value:S,onChange:s=>B(s.target.value),placeholder:"Slack User ID (U...)",className:"flex-1"}),e.jsx(D,{value:O,onChange:s=>Q(s.target.value),placeholder:"Name",className:"w-32"}),e.jsxs("select",{value:z,onChange:s=>re(s.target.value),className:"h-10 rounded-xl border-0 ring-1 ring-black/10 dark:ring-white/10 bg-black/[0.04] dark:bg-white/[0.04] px-2 text-sm",children:[e.jsx("option",{value:"manager",children:"Manager"}),e.jsx("option",{value:"editor",children:"Editor"}),e.jsx("option",{value:"producer",children:"Producer"}),e.jsx("option",{value:"designer",children:"Designer"}),e.jsx("option",{value:"director",children:"Director"}),e.jsx("option",{value:"founder",children:"Founder"}),e.jsx("option",{value:"other",children:"Other"})]}),e.jsx(p,{variant:"outline",size:"icon",disabled:!S.trim()||R.isPending,onClick:async()=>{var s;try{await R.mutateAsync({slack_user_id:S.trim(),display_name:O.trim()||S.trim(),role:z}),B(""),Q(""),f.success("Team member added")}catch(i){f.error((s=i==null?void 0:i.message)!=null&&s.includes("duplicate")?"This Slack ID is already added":"Failed to add")}},children:e.jsx(_e,{className:"w-4 h-4"})})]}),ne?e.jsx("div",{className:"text-sm text-muted-foreground",children:"Loading..."}):F.length===0?e.jsx("div",{className:"text-sm text-muted-foreground bg-muted/50 rounded-lg p-3",children:"No team members added. Sandra will use the channel manager as fallback."}):e.jsx("div",{className:"space-y-2",children:F.map(s=>e.jsxs("div",{className:"flex items-center justify-between p-3 bg-muted/30 rounded-lg",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-8 h-8 rounded-full bg-primary/10 flex items-center justify-center text-xs font-medium text-primary",children:(s.display_name||"?")[0].toUpperCase()}),e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium",children:s.display_name||s.slack_user_id}),e.jsxs("div",{className:"text-xs text-muted-foreground flex items-center gap-2",children:[e.jsx("code",{className:"bg-muted px-1 rounded",children:s.slack_user_id}),s.role&&e.jsx(q,{variant:"outline",className:"text-[10px] px-1.5 py-0",children:s.role==="manager"?"Manager":s.role==="editor"?"Editor":s.role==="producer"?"Producer":s.role==="designer"?"Designer":s.role==="director"?"Director":s.role==="founder"?"Founder":s.role})]})]})]}),e.jsx(p,{variant:"ghost",size:"icon",className:"h-8 w-8 text-destructive/70 hover:text-destructive",disabled:U.isPending,onClick:async()=>{await U.mutateAsync(s.id),f.success("Team member removed")},children:e.jsx(Ce,{className:"w-4 h-4"})})]},s.id))}),e.jsx("div",{className:"text-xs text-muted-foreground bg-muted/50 rounded-lg p-3",children:`ð¡ You can find the Slack User ID in the user's profile â "â®" â "Copy member ID"`})]})]}),e.jsxs(l,{children:[e.jsx(g,{className:"pb-3",children:e.jsxs(j,{className:"text-base flex items-center gap-2",children:[e.jsx(Te,{className:"w-4 h-4 text-muted-foreground"}),"Escalation to Manager"]})}),e.jsxs(c,{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium",children:"Auto Escalation"}),e.jsx("div",{className:"text-xs text-muted-foreground",children:"Sandra will notify the manager when keywords are detected"})]}),e.jsx(Z,{checked:M,onCheckedChange:A})]}),M&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex gap-2",children:[e.jsx(D,{value:W,onChange:s=>$(s.target.value),placeholder:"Keyword...",onKeyDown:s=>s.key==="Enter"&&V(),className:"flex-1"}),e.jsx(p,{variant:"outline",size:"sm",onClick:V,children:"Add"})]}),e.jsxs("div",{className:"flex flex-wrap gap-1.5",children:[u.map(s=>e.jsxs(q,{variant:"secondary",className:"gap-1 pr-1",children:[s,e.jsx("button",{onClick:()=>
6le(s),className:"ml-0.5 rounded-full p-0.5 hover:bg-foreground/10",children:e.jsx(je,{className:"w-3 h-3"})})]},s)),u.length===0&&e.jsx("span",{className:"text-xs text-muted-foreground",children:"No keywords"})]}),u.length===0&&e.jsx(p,{variant:"outline",size:"sm",onClick:ce,className:"text-xs",children:"Load default keywords"})]})]})]}),e.jsx(p,{onClick:ie,disabled:T.isPending,className:"w-full",size:"lg",children:T.isPending?"Saving...":"Save Settings"})]}),e.jsx(ee,{value:"analytics",className:"space-y-4",children:r?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsx(l,{children:e.jsxs(c,{className:"p-4 text-center",children:[e.jsx("div",{className:"text-2xl font-bold",children:r.total}),e.jsxs("div",{className:"text-xs text-muted-foreground flex items-center justify-center gap-1 mt-1",children:[e.jsx(Me,{className:"w-3 h-3"}),"Total Responses"]})]})}),e.jsx(l,{children:e.jsxs(c,{className:"p-4 text-center",children:[e.jsxs("div",{className:"text-2xl font-bold",children:[r.avgResponseTime,"s"]}),e.jsxs("div",{className:"text-xs text-muted-foreground flex items-center justify-center gap-1 mt-1",children:[e.jsx(Ae,{className:"w-3 h-3"}),"Avg Response Time"]})]})}),e.jsx(l,{children:e.jsxs(c,{className:"p-4 text-center",children:[e.jsxs("div",{className:"text-2xl font-bold text-amber-500",children:[r.total>0?Math.round(r.hallucinations/r.total*100):0,"%"]}),e.jsxs("div",{className:"text-xs text-muted-foreground flex items-center justify-center gap-1 mt-1",children:[e.jsx(fe,{className:"w-3 h-3"}),"Hallucination Rate"]})]})}),e.jsx(l,{children:e.jsxs(c,{className:"p-4 text-center",children:[e.jsxs("div",{className:"text-2xl font-bold text-blue-500",children:[r.total>0?Math.round(r.escalations/r.total*100):0,"%"]}),e.jsxs("div",{className:"text-xs text-muted-foreground flex items-center justify-center gap-1 mt-1",children:[e.jsx(se,{className:"w-3 h-3"}),"Escalation Rate"]})]})})]}),e.jsxs(l,{children:[e.jsx(g,{className:"pb-3",children:e.jsxs(j,{className:"text-base flex items-center gap-2",children:[e.jsx(Ne,{className:"w-4 h-4 text-muted-foreground"}),"Breakdown (Last 30 Days)"]})}),e.jsxs(c,{className:"space-y-3",children:[e.jsxs("div",{className:"flex justify-between text-sm",children:[e.jsx("span",{className:"text-muted-foreground",children:"Total responses"}),e.jsx("span",{className:"font-medium",children:r.total})]}),e.jsxs("div",{className:"flex justify-between text-sm",children:[e.jsx("span",{className:"text-muted-foreground",children:"Hallucinations caught"}),e.jsx("span",{className:"font-medium text-amber-500",children:r.hallucinations})]}),e.jsxs("div",{className:"flex justify-between text-sm",children:[e.jsx("span",{className:"text-muted-foreground",children:"Fallback responses"}),e.jsx("span",{className:"font-medium",children:r.fallbacks})]}),e.jsxs("div",{className:"flex justify-between text-sm",children:[e.jsx("span",{className:"text-muted-foreground",children:"Escalations to manager"}),e.jsx("span",{className:"font-medium text-blue-500",children:r.escalations})]})]})]}),r.topClients.length>0&&e.jsxs(l,{children:[e.jsx(g,{className:"pb-3",children:e.jsx(j,{className:"text-base",children:"Most Active Clients"})}),e.jsx(c,{className:"space-y-2",children:r.topClients.map(([s,i])=>e.jsxs("div",{className:"flex justify-between items-center text-sm",children:[e.jsx("span",{children:s}),e.jsxs(q,{variant:"secondary",children:[i," msgs"]})]},s))})]})]}):e.jsx("div",{className:"text-center text-muted-foreground py-12",children:"No data in the last 30 days"})})]})]})})};export{ks 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.