PageSourceSearch

https://designpro-beta-production.up.railway.app/assets/sales-hub-CLJ6dLWm.js

js designpro-beta-production.up.railway.app collected 2026-10-03 12:12:44 UTC 36,522 bytes, 1 lines download raw bytes

1import{a as p,j as e}from"./vendor-react-DXumv_YA.js";import{c as De,u as z,v as Ie,b as I,cp as Te,ae as j,B as b,a$ as qe,aD as Pe,ay as X,cu as E,aV as fe,x as Me,I as te,b7 as Ae,d as y,cF as Ee,cq as Le,b1 as ce,q as F,o as Fe,r as Re,c1 as Oe,c2 as ze,aj as Be}from"./index-VMqZ9vdK.js";import{T as ve}from"./textarea-CBnd8QTm.js";import{P as Z,a as U,b as ee}from"./popover-Cyddl-Uv.js";import{C as Ve}from"./checkbox-7nB3q9q7.js";import{A as We}from"./about-customer-banner-DBhbkOCM.js";import{M as Qe}from"./map-pin-CbFysD0m.js";import{U as Ke}from"./undo-2-D0dGPNDc.js";import{M as He}from"./moon-Di4g3oFR.js";import{a as Ge,C as Ye,P as Je}from"./phone-missed-DUQPQ-mY.js";import{B as Xe}from"./ban-1fCdJx0_.js";import{u as Ze}from"./use-reduced-motion-DOB_4Llb.js";import{m as Ue}from"./proxy-mSsNxQYC.js";import{S as et}from"./send-DtXhy9Oq.js";import{C as je}from"./copy-CJM1HLaZ.js";import{F as tt}from"./flag-ssIaALgL.js";import{B as st}from"./book-open-Dwk6G59H.js";import"./vendor-three-BwySL88Q.js";import"./vendor-firebase-6GlpQw54.js";import"./index-2b3YMqIC.js";import"./pencil-0C86jbn0.js";const at=De("Voicemail",[["circle",{cx:"6",cy:"12",r:"4",key:"1ehtga"}],["circle",{cx:"18",cy:"12",r:"4",key:"4vafl8"}],["line",{x1:"6",x2:"18",y1:"16",y2:"16",key:"pmt8us"}]]);function f(t){const n=typeof t=="number"?t:parseFloat(t||"");return!isFinite(n)||n<=0?null:`$${Math.round(n).toLocaleString("en-US")}`}function ue(t){if(!t)return null;const n=t instanceof Date?t:typeof t?.toDate=="function"?t.toDate():new Date(t);return isNaN(n.getTime())?null:n}function nt(t){return ue(t.lastContactedAt)??ue(t.createdAt)}const rt="rounded-[20px] border border-card-border bg-card shadow-[var(--shadow-card)] dark:border-white/[0.10] dark:bg-white/[0.02] dark:bg-[linear-gradient(168deg,rgba(255,255,255,0.075),rgba(255,255,255,0.028)_50%,rgba(255,255,255,0.012))] dark:backdrop-blur-[28px] dark:backdrop-saturate-150 dark:shadow-[inset_0_1px_0_rgba(255,255,255,0.15),inset_0_-1px_0_rgba(0,0,0,0.45),0_2px_4px_rgba(0,0,0,0.45),0_18px_38px_-14px_rgba(0,0,0,0.7),0_44px_80px_-34px_rgba(0,0,0,0.9)]",ae="rounded-2xl border border-card-border bg-card shadow-[var(--shadow-card)] dark:border-white/[0.09] dark:bg-white/[0.02] dark:bg-[linear-gradient(168deg,rgba(255,255,255,0.055),rgba(255,255,255,0.02)_55%,rgba(255,255,255,0.008))] dark:backdrop-blur-[22px] dark:backdrop-saturate-150 dark:shadow-[inset_0_1px_0_rgba(255,255,255,0.10),inset_0_-1px_0_rgba(0,0,0,0.4),0_2px_4px_rgba(0,0,0,0.4),0_14px_30px_-16px_rgba(0,0,0,0.7)]",ot="rounded-[20px] border border-primary/30 bg-gradient-to-b from-primary/[0.07] via-transparent to-transparent shadow-[var(--shadow-card)] dark:border-primary/30 dark:from-primary/[0.13] dark:backdrop-blur-[28px] dark:backdrop-saturate-150 dark:shadow-[inset_0_1px_0_rgba(255,255,255,0.16),inset_0_-1px_0_rgba(0,0,0,0.45),0_2px_4px_rgba(0,0,0,0.45),0_18px_40px_-14px_rgba(0,0,0,0.7),0_46px_84px_-34px_rgba(90,49,244,0.32)]",ne={deposit_no_order:"Deposit",quoted_no_deposit:"Quoted",no_show:"No-show",cold_lead:"Cold"},R={deposit_no_order:"Deposit, no order",quoted_no_deposit:"Quoted, no deposit",no_show:"No-show",cold_lead:"Cold lead"},O={deposit_no_order:{chip:"bg-primary/12 text-primary",bar:"bg-primary",dot:"bg-primary"},quoted_no_deposit:{chip:"bg-sky-500/12 text-sky-600 dark:text-sky-400",bar:"bg-sky-500",dot:"bg-sky-500"},no_show:{chip:"bg-amber-500/12 text-amber-600 dark:text-amber-400",bar:"bg-amber-500",dot:"bg-amber-500"},cold_lead:{chip:"bg-muted text-muted-foreground",bar:"bg-muted-foreground/35",dot:"bg-muted-foreground/35"}},ye=Object.keys(ne),it=[{value:"no_answer",label:"No answer",icon:Ge},{value:"left_voicemail",label:"Voicemail",icon:at}];function me(t){return t.status==="queued"&&(!t.nextActionAt||new Date(t.nextActionAt)<=new Date)}function T(t){return t?new Date(t).toLocaleDateString([],{month:"short",day:"numeric"}):""}function lt(t){return t?new Date(t).toLocaleString([],{month:"short",day:"numeric",hour:"numeric",minute:"2-digit"}):""}function L({label:t,value:n,detail:a,tone:i,testId:d,className:m=""}){return e.jsxs("div",{className:`flex flex-col gap-1.5 p-5 sm:px-6 sm:py-6 ${m}`,children:[e.jsx("span",{className:"text-[10px] font-medium uppercase tracking-[0.16em] text-muted-foreground",children:t}),e.jsx("span",{className:`font-display text-[38px] sm:text-[44px] font-light leading-none tracking-[-0.035em] tabular-nums ${i??""}`,"data-testid":d,children:n}),e.jsx("span",{className:"text-[11.5px] text-muted-foreground",children:a})]})}function we({title:t,count:n,action:a}){return e.jsxs("div",{className:"flex items-baseline gap-3 mt-9 mb-3.5 px-0.5",children:[e.jsx("h2",{className:"text-[19px] font-medium tracking-[-0.02em]",children:t}),n!=null&&n!==""&&e.jsx("span",{className:"font-mono text-[10px] tracking-[0.16em] text-muted-foreground tabular-nums",children:n}),a&&e.jsx("div",{className:"ml-auto self-center",children:a})]})}function se({options:t,value:n,onChange:a,size:i="md",testIdPrefix:d}){const m=i==="sm"?"h-7 px-3 text-[11px]":"h-8 px-3.5 text-xs";return e.jsx("div",{className:"flex gap-0.5 overflow-x-auto scrollbar-hide rounded-full bg-muted/50 dark:bg-white/[0.04] dark:border dark:border-white/[0.07] p-1 w-fit max-w-full",children:t.map(r=>{const o=n===r.key;return e.jsxs("button",{type:"button",onClick:()=>a(r.key),"aria-pressed":o,"data-testid":d?`${d}-${r.key}`:void 0,className:`shrink-0 rounded-full font-medium whitespace-nowrap transition-colors ${m} ${o?"bg-background text-foreground shadow-sm dark:bg-white/[0.09] dar
1k:text-white dark:shadow-[inset_0_1px_0_rgba(255,255,255,0.14)]":"text-muted-foreground hover:text-foreground hover:bg-background/60 dark:hover:bg-white/[0.05]"}`,children:[r.label,r.n?e.jsx("span",{className:`ml-1.5 font-mono text-[10px] tabular-nums ${o?"text-foreground/60":"text-muted-foreground/60"}`,children:r.n}):null]},r.key)})})}function xe({title:t,body:n}){return e.jsxs("div",{className:"rounded-[20px] border border-dashed border-card-border dark:border-white/[0.10] px-6 py-14 text-center",children:[e.jsx("p",{className:"text-[17px] font-medium tracking-[-0.02em]",children:t}),e.jsx("p",{className:"text-sm text-muted-foreground/80 mt-1.5",children:n})]})}function dt({due:t,scheduled:n,stats:a}){const i=p.useMemo(()=>{const r=new Map;for(const c of t){const h=r.get(c.segment)??{n:0,value:0};h.n++,h.value+=parseFloat(c.dollarValue||"0")||0,r.set(c.segment,h)}const o=ye.map(c=>({segment:c,...r.get(c)??{n:0,value:0}})).filter(c=>c.n>0);return{rows:o,total:o.reduce((c,h)=>c+h.value,0)}},[t]),d=i.total>0?i.total:i.rows.reduce((r,o)=>r+o.n,0),m=r=>i.total>0?r.value:r.n;return e.jsxs("div",{className:`${rt} overflow-hidden`,children:[e.jsxs("div",{className:"grid grid-cols-2 lg:grid-cols-4",children:[e.jsx(L,{label:"In the queue",value:t.length,detail:n.length?`${n.length} scheduled ahead`:"nothing scheduled ahead",testId:"stat-queue",className:"border-b border-r border-card-border dark:border-white/[0.08] lg:border-b-0"}),e.jsx(L,{label:"Worked today",value:a?.attemptsToday??0,detail:a?.attemptsToday?"outcomes logged":"nothing logged yet",testId:"stat-worked",className:"border-b border-card-border dark:border-white/[0.08] lg:border-b-0 lg:border-r"}),e.jsx(L,{label:"Won, 30 days",value:a?.revived30??0,detail:a?.revived30?`${f(a.revived30Value)??"$0"} back, ${f(a.revivedAllValue)??"$0"} all time`:"nothing revived this month",tone:a?.revived30?"text-emerald-600 dark:text-emerald-400":void 0,testId:"stat-won",className:"border-r border-card-border dark:border-white/[0.08]"}),e.jsx(L,{label:"Lost, 30 days",value:a?.lost30??0,detail:a?.lost30?`${f(a.lost30Value)??"$0"} written off`:"nothing written off this month",testId:"stat-lost"})]}),e.jsxs("div",{className:"border-t border-card-border dark:border-white/[0.08] p-5 sm:px-6 sm:py-6 flex flex-col gap-3",children:[e.jsx("div",{className:"flex items-baseline gap-3 flex-wrap",children:e.jsx("span",{className:"text-[10px] font-medium uppercase tracking-[0.16em] text-muted-foreground",children:"On the table right now"})}),e.jsxs("div",{className:"flex items-end gap-4 flex-wrap",children:[e.jsx("span",{className:`font-display text-[38px] sm:text-[44px] font-light leading-none tracking-[-0.035em] tabular-nums ${i.total>0?"":"text-muted-foreground/50"}`,"data-testid":"stat-on-the-table",children:f(i.total)??"None"}),e.jsx("span",{className:"text-[11.5px] text-muted-foreground pb-1",children:i.total>0?`across ${t.length} ${t.length===1?"deal":"deals"} due now`:"no quoted value sitting in the queue"})]}),e.jsx("div",{className:"flex gap-0.5 h-1.5 mt-1",role:"img","aria-label":i.rows.length?i.rows.map(r=>`${r.n} ${R[r.segment]}`).join(", "):"Queue is clear",children:i.rows.length===0?e.jsx("span",{className:"flex-1 rounded-full bg-muted"}):i.rows.map(r=>e.jsx("span",{className:`rounded-full min-w-[4px] ${O[r.segment].bar}`,style:{width:`${m(r)/Math.max(1,d)*100}%`}},r.segment))}),e.jsx("div",{className:"flex flex-wrap gap-x-4 gap-y-1.5 text-[11.5px] text-muted-foreground",children:i.rows.length===0?e.jsx("span",{children:"The queue is clear. Refresh to rescan for new dormant deals."}):i.rows.map(r=>e.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[e.jsx("i",{className:`w-[5px] h-[5px] rounded-full ${O[r.segment].dot}`,"aria-hidden":"true"}),R[r.segment]," ",e.jsx("b",{className:"font-medium text-foreground tabular-nums",children:r.n}),f(r.value)?e.jsx("span",{className:"tabular-nums text-muted-foreground/70",children:f(r.value)}):null]},r.segment))})]})]})}function ct(t){return(t||"").split(/\s+/).filter(Boolean).map(n=>n[0]).join("").toUpperCase().slice(0,2)||"?"}function Ne(t){if(!t)return null;if(typeof t=="string"){const n=Date.parse(t);return isNaN(n)?null:n}return typeof t?.toDate=="function"?t.toDate().getTime():typeof t?._seconds=="number"?t._seconds*1e3:t instanceof Date?t.getTime():null}function he(t){const n=Ne(t);if(n==null)return null;const a=Math.floor((Date.now()-n)/864e5);if(a<=0)return"today";if(a===1)return"1 day";if(a<14)return`${a} days`;const i=Math.round(a/7);if(i<9)return`${i} weeks`;const d=Math.round(a/30.44);return d<=1?"1 month":d<24?`${d} months`:`${Math.round(d/12)} years`}function pe(t){const n=Ne(t);return n==null?null:new Date(n).toLocaleDateString([],{month:"short",day:"numeric",year:"numeric"})}function ge({value:t,mono:n}){const{toast:a}=z(),[i,d]=p.useState(!1);return e.jsxs("button",{type:"button",onClick:async()=>{try{await navigator.clipboard.writeText(t),d(!0),setTimeout(()=>d(!1),1400)}catch{a({title:"Could not copy",variant:"destructive"})}},className:"group inline-flex items-center gap-1.5 rounded-md px-1.5 py-0.5 -mx-1.5 text-xs text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground dark:hover:bg-white/[0.06]",title:`Copy ${t}`,children:[e.jsx("span",{className:n?"tabular-nums":"",children:t}),i?e.jsx(Be,{className:"h-3 w-3 text-emerald-500"}):e.jsx(je,{className:"h-3 w-3 opacity-0 transition-opacity group-hover:opacity-60"})]})}function ut({followUp:t,contact:n,onOpenQuote:a}){const i=f(t.dollarValue),d=he(n?nt(n):t.firstAttemptAt),m=(t.attempts??[]).filter(o=>o.outcome!=="note").length,r=[i?{label:"On the table",value:i}:null,d?{label:"Since last touch",value:d}:null,m>0?{label:"Attempts",value:String(m)}
1:null].filter(Boolean);return r.length===0&&!a?null:e.jsxs("div",{className:"mt-4 flex flex-wrap items-stretch gap-px overflow-hidden rounded-xl border border-card-border bg-card-border/60 dark:border-white/[0.08] dark:bg-white/[0.06]",children:[r.map(o=>e.jsxs("div",{className:"flex-1 min-w-[120px] bg-card px-4 py-3 dark:bg-[rgba(14,14,20,0.72)]",children:[e.jsx("div",{className:"text-[9.5px] font-medium uppercase tracking-[0.16em] text-muted-foreground",children:o.label}),e.jsx("div",{className:"mt-1 font-display text-xl font-light tracking-[-0.02em] tabular-nums",children:o.value})]},o.label)),a?e.jsxs("button",{type:"button",onClick:a,"data-testid":"button-open-quote",className:"flex-1 min-w-[120px] bg-card px-4 py-3 text-left transition-colors hover:bg-accent dark:bg-[rgba(14,14,20,0.72)] dark:hover:bg-white/[0.06]",children:[e.jsx("div",{className:"text-[9.5px] font-medium uppercase tracking-[0.16em] text-muted-foreground",children:"The quote"}),e.jsxs("div",{className:"mt-1 inline-flex items-center gap-1.5 text-sm font-medium text-primary",children:["Open ",e.jsx(fe,{className:"h-3.5 w-3.5"})]})]}):null]})}function mt({rows:t}){return t.length===0?null:e.jsx("dl",{className:"mt-4 grid grid-cols-1 gap-x-6 gap-y-2 sm:grid-cols-2",children:t.map(n=>e.jsxs("div",{className:"flex items-baseline gap-3",children:[e.jsx("dt",{className:"w-[86px] shrink-0 text-[9.5px] font-medium uppercase tracking-[0.16em] text-muted-foreground",children:n.k}),e.jsx("dd",{className:"min-w-0 flex-1 text-[13px] leading-snug",children:n.v})]},n.k))})}function be({label:t,body:n,tone:a}){return e.jsxs("div",{className:"mt-4",children:[e.jsx("div",{className:"text-[9.5px] font-medium uppercase tracking-[0.16em] text-muted-foreground",children:t}),e.jsx("p",{className:`mt-1.5 text-[13px] leading-relaxed line-clamp-4 ${a==="quote"?"border-l-2 border-primary/30 pl-3 italic text-foreground/90":"text-muted-foreground"}`,children:n})]})}function xt({followUp:t,contact:n}){const a=n??{},i=Ee(a.projectArea??[]),d=(a.interests??[]).length?Le(a.interests):"",m=(a.doorStyles??[]).join(", "),r=pe(a.quoteSentAt),o=pe(a.createdAt??a.leadReceivedDate),c=[i?{k:"Rooms",v:i}:null,d?{k:"Surfaces",v:d}:null,m?{k:"Doors",v:m}:null,a.desiredCompletion?{k:"Wants by",v:String(a.desiredCompletion)}:null,r?{k:"Quote sent",v:r}:null,o?{k:"Lead since",v:o}:null].filter(Boolean),h=(a.callSummaries??[]).at(-1);return e.jsxs(e.Fragment,{children:[e.jsx(mt,{rows:c}),a.inquiryMessage?e.jsx(be,{label:"In their words",body:String(a.inquiryMessage),tone:"quote"}):null,h?.summary?e.jsx(be,{label:`Last call${h.at?` · ${T(h.at)}`:""}`,body:String(h.summary)}):null,(t.phone||t.email)&&e.jsxs("div",{className:"mt-4 flex flex-wrap items-center gap-x-4 gap-y-1",children:[t.phone?e.jsx(ge,{value:t.phone,mono:!0}):null,t.email?e.jsx(ge,{value:t.email}):null]})]})}function ht({followUp:t,index:n,active:a,onSelect:i,trailing:d}){const m=Ze(),r=f(t.dollarValue),o=t.nextActionAt&&new Date(t.nextActionAt)<new Date,c=O[t.segment];return e.jsxs(Ue.button,{type:"button",onClick:i,"data-testid":`queue-row-${t.contactId}`,initial:m?!1:{opacity:0,y:8},animate:{opacity:1,y:0},transition:{delay:m?0:Math.min(n,10)*.03,duration:.3},className:`text-left w-full p-4 sm:px-5 ${ae} transition-all flex items-center gap-3 ${a?"border-primary/45 dark:border-primary/45 shadow-[var(--shadow-card-hover)]":"hover:shadow-[var(--shadow-card-hover)] hover:-translate-y-0.5 hover:border-primary/30 active:translate-y-0"}`,children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[o?e.jsx("span",{className:"h-1.5 w-1.5 shrink-0 rounded-full bg-red-500","aria-label":"Overdue"}):null,e.jsx("p",{className:"font-medium text-[15px] tracking-[-0.01em] truncate",children:t.contactName||"No name"}),e.jsx("span",{className:`text-[10px] font-semibold uppercase tracking-wide px-1.5 py-0.5 rounded ${c.chip}`,children:ne[t.segment]})]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1 line-clamp-2",children:t.reason}),d]}),r?e.jsx("span",{className:"shrink-0 font-mono text-sm font-semibold tabular-nums",children:r}):null]})}function pt({followUp:t}){const{toast:n}=z(),[a,i]=p.useState("draft"),[d,m]=p.useState("text"),[r,o]=p.useState(""),[c,h]=p.useState(""),[u,N]=p.useState([]),[_,A]=p.useState(null),$=j({mutationFn:async()=>(await y("POST","/api/sales-hub/ai/draft",{contactId:t.contactId,channel:d})).json(),onSuccess:g=>o(g.draft??""),onError:()=>n({title:"Draft failed",variant:"destructive"})}),q=j({mutationFn:async()=>(await y("POST","/api/sales-hub/ai/next-step",{contactId:t.contactId})).json(),onSuccess:g=>A(g),onError:()=>n({title:"Advice failed",variant:"destructive"})}),S=j({mutationFn:async g=>(await y("POST","/api/sales-hub/ai/objection",{contactId:t.contactId,question:g})).json(),onSuccess:(g,w)=>N(C=>[...C,{q:w,a:g.answer??""}]),onError:()=>n({title:"No answer",variant:"destructive"})}),B=async()=>{await navigator.clipboard.writeText(r),n({title:"Copied",description:"Paste it into your text or email and send."})};return e.jsxs("div",{className:"mt-6 rounded-2xl border border-card-border dark:border-white/[0.08] bg-muted/30 dark:bg-white/[0.03] dark:backdrop-blur-[18px] p-4",children:[e.jsxs("div",{className:"mb-3 flex items-center gap-2 flex-wrap",children:[e.jsxs("span",{className:"inline-flex items-center gap-1.5 text-[10px] font-medium uppercase tracking-[0.16em] text-muted-foreground",children:[e.jsx(ce,{className:"h-3.5 w-3.5 text-primary"})," Copilot"]}),e.jsx(se,{size:"sm",value:a,onChange:i,testIdPrefix:"chip-copilot",options:[{key:"draft",label:"Draft"},{key:"next",label:"Next step"},{key:"objections",label:"Objections"}]})]}),a==="draft"&&e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx(se,{size:"sm",value:d,onChange:m,options:[{key:"text",label:"Text"},{key:"email",label:"Email"}]}),e.jsxs(b,{size:"sm",variant:"outline",disabled:$.isPending,onClick:()=>$.mutate(),children:[e.jsx(et,{className:"mr-1.5 h-3.5 w-3.5"}),$.isPending?"Writing":r?"Regenerate":"Generate"]}),r?e.jsxs(b,{size:"sm",onClick:B,children:[e.jsx(je,{className:"mr-1.5 h-3.5 w-3.5"})," Copy"]}):null]}),r?e.jsx(ve,{rows:d==="email"?8:4,value:r,onChange:g=>o(g.target.value)}):e.jsx("p",{className:"text-xs text-muted-foreground",children:"Writes a follow-up in your voice for this segment. Review, edit, copy, and send it yourself."})]}),a==="next"&&e.jsxs("div",{className:"space-y-3",children:[e.jsxs(b,{size:"sm",variant:"outline",disabled:q.isPending,onClick:()=>q.mutate(),children:[e.jsx(ce,{className:"mr-1.5 h-3.5 w-3.5"}),q.isPending?"Thinking":"What should I do with this deal?"]}),_?e.jsxs("div",{className:"space-y-1.5 text-sm",children:[e.jsxs("div",{children:[e.jsx("span",{className:"font-medium",children:"Do:"})," ",_.action]}),e.jsxs("div",{children:[e.jsx("span",{className:"font-medium",children:"When:"})," ",_.timing]}),e.jsx("div",{className:"text-muted-foreground",children:_.reasoning})]}):null]}),a==="objections"&&e.jsxs("div",{className:"space-y-3",children:[e.jsxs("form",{className:"flex gap-2",onSubmit:g=>{g.preventDefault();const w=c.trim();w&&(h(""),S.mutate(w))},children:[e.jsx(te,{placeholder:"They said the quote feels high. What do I say?",value:c,onChange:g=>h(g.target.value)}),e.jsx(b,{type:"submit",size:"sm",variant:"outline",disabled:S.isPending,children:"Ask"})]}),e.jsx("div",{className:"space-y-3",children:u.slice().reverse().map((g,w)=>e.jsxs("div",{className:"rounded-xl border border-card-border dark:border-white/[0.08] bg-background/60 dark:bg-white/[0.02] p-3 text-sm",children:[e.jsx("div",{className:"text-xs font-medium text-muted-foreground",children:g.q}),e.jsx("div",{className:"mt-1 whitespace-pre-wrap",children:g.a})]},w))})]})]})}const gt=[{key:"mattCallDone",label:"Matt called customer"},{key:"quoteReady",label:"Quote ready"},{key:"designReady",label:"Design ready"},{key:"reminderSent",label:"Reminder sent"}],bt={mattCallDone:!1,quoteReady:!1,designReady:!1,reminderSent:!1};function ft(){const{toast:t}=z(),[n,a]=p.useState(null),{data:i=[]}=I({queryKey:["/api/appointments"]}),d=p.useMemo(()=>{const o=u=>`${u.getFullYear()}
1-${String(u.getMonth()+1).padStart(2,"0")}-${String(u.getDate()).padStart(2,"0")}`,c=o(new Date),h=o(new Date(Date.now()+10080*60*1e3));return i.filter(u=>(u.type??"consultation")==="consultation").filter(u=>["scheduled","confirmed"].includes(u.status??"scheduled")).filter(u=>u.scheduledDate>=c&&u.scheduledDate<=h).sort((u,N)=>(u.scheduledDate+(u.scheduledTime??"")).localeCompare(N.scheduledDate+(N.scheduledTime??"")))},[i]),m=j({mutationFn:o=>y("PATCH",`/api/appointments/${o.id}`,{prepChecklist:o.prepChecklist}),onSuccess:()=>F.invalidateQueries({queryKey:["/api/appointments"]}),onError:()=>t({title:"Could not update checklist",variant:"destructive"})}),r=j({mutationFn:async o=>{const c=await y("POST","/api/sales-hub/ai/brief",{appointmentId:o.id});return{appt:o,data:await c.json()}},onSuccess:({appt:o,data:c})=>a({appt:o,text:c.brief??""}),onError:()=>t({title:"Brief failed",variant:"destructive"})});return d.length===0?null:e.jsxs(e.Fragment,{children:[e.jsx(we,{title:"Showroom prep",count:d.length}),e.jsx("div",{className:"flex gap-3 overflow-x-auto scrollbar-hide pb-2",children:d.map(o=>{const c={...bt,...o.prepChecklist??{}},h=!c.mattCallDone;return e.jsxs("div",{className:`w-[300px] shrink-0 p-4 sm:px-5 ${ae} ${h?"border-red-500/40 dark:border-red-500/40":""}`,children:[e.jsxs("div",{className:"flex items-start justify-between gap-2",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[h?e.jsx(tt,{className:"h-3.5 w-3.5 shrink-0 text-red-500"}):null,e.jsx("span",{className:"truncate text-[15px] font-medium tracking-[-0.01em]",children:o.contactName||"No name"})]}),e.jsxs("div",{className:"mt-0.5 text-xs tabular-nums text-muted-foreground",children:[new Date(`${o.scheduledDate}T12:00:00`).toLocaleDateString([],{weekday:"short",month:"short",day:"numeric"}),o.scheduledTime?` at ${o.scheduledTime}`:""]})]}),e.jsxs(b,{size:"sm",variant:"ghost",disabled:r.isPending,onClick:()=>r.mutate(o),children:[e.jsx(st,{className:"mr-1.5 h-3.5 w-3.5"})," Brief"]})]}),e.jsx("div",{className:"mt-3 grid grid-cols-2 gap-x-3 gap-y-1.5",children:gt.map(u=>e.jsxs("label",{className:"flex cursor-pointer items-center gap-1.5 text-xs",children:[e.jsx(Ve,{checked:c[u.key],onCheckedChange:N=>m.mutate({id:o.id,prepChecklist:{...c,[u.key]:N===!0}})}),e.jsx("span",{className:c[u.key]?"text-muted-foreground line-through":"",children:u.label})]},u.key))})]},o.id)})}),e.jsx(Fe,{open:!!n,onOpenChange:o=>{o||a(null)},children:e.jsxs(Re,{className:"w-full overflow-y-auto sm:max-w-lg",children:[e.jsx(Oe,{children:e.jsxs(ze,{className:"font-display",children:["Prep: ",n?.appt.contactName||"Showroom meeting"]})}),e.jsx("div",{className:"mt-4 whitespace-pre-wrap text-sm leading-relaxed",children:n?.text})]})})]})}function Ot(){const{toast:t}=z(),[,n]=Ie(),[a,i]=p.useState("due"),[d,m]=p.useState(null),[r,o]=p.useState(""),[c,h]=p.useState(""),[u,N]=p.useState(""),[_,A]=p.useState(!1),[$,q]=p.useState(!1),{data:S=[],isLoading:B}=I({queryKey:["/api/sales-hub/queue"]}),{data:g}=I({queryKey:["/api/sales-hub/stats"]}),{data:w}=I({queryKey:["/api/sales-hub/closed"]}),{data:C}=I({queryKey:["/api/sales-hub/unmatched-deposits"]}),D=p.useMemo(()=>S.filter(me),[S]),V=p.useMemo(()=>S.filter(s=>!me(s)),[S]),re=w?.lost??[],oe=w?.won??[],ke=p.useMemo(()=>{const s={};for(const x of D)s[x.segment]=(s[x.segment]??0)+1;return s},[D]),k=a==="due"?D:a==="scheduled"?V:a==="lost"?re:a==="won"?oe:D.filter(s=>s.segment===a),W=a==="lost"||a==="won",l=k.find(s=>s.contactId===d)??k[0]??null,{data:P}=I({queryKey:["/api/contacts",l?.contactId],enabled:!!l?.contactId}),ie=p.useMemo(()=>{const s=P??{},x=[s.addressCity,s.addressState].filter(Boolean).join(", "),J=Te(s.projectType||""),$e=typeof s.source=="string"&&s.source&&s.source!=="other"?s.source.replace(/[_-]/g," "):"";
1return[x,J,$e].filter(Boolean).join(" · ")},[P]),M=()=>{F.invalidateQueries({queryKey:["/api/sales-hub/queue"]}),F.invalidateQueries({queryKey:["/api/sales-hub/stats"]}),F.invalidateQueries({queryKey:["/api/sales-hub/closed"]})},Q=s=>{const x=k.filter(J=>J.contactId!==s);m(x[0]?.contactId??null),o(""),h("")},Se=s=>{m(s),o("")},Ce=s=>{i(s),m(null),o("")},K=j({mutationFn:()=>y("POST","/api/sales-hub/scan"),onSuccess:()=>{M(),t({title:"Queue refreshed"})},onError:()=>t({title:"Scan failed",variant:"destructive"})}),H=j({mutationFn:s=>y("POST",`/api/contacts/${s}/dial`),onSuccess:()=>t({title:"Calling",description:"Your phone rings first, then we connect the customer."}),onError:()=>t({title:"Call failed",description:"Check the phone number and try again.",variant:"destructive"})}),v=j({mutationFn:async s=>(await y("POST",`/api/sales-hub/${s.contactId}/outcome`,{outcome:s.outcome,note:r.trim()||void 0,callbackAt:s.callbackAt?new Date(s.callbackAt).toISOString():void 0,lostReason:s.lostReason})).json(),onSuccess:(s,x)=>{M(),x.outcome==="revived"&&t({title:"Deal won",description:"Counted toward revived revenue."}),x.outcome==="lost"&&t({title:"Marked lost",description:`${E[x.lostReason]}. The contact is marked lost too.`}),Q(x.contactId)},onError:()=>t({title:"Could not save outcome",variant:"destructive"})}),G=j({mutationFn:s=>y("POST",`/api/sales-hub/${s}/note`,{note:r.trim()}),onSuccess:()=>{M(),o(""),t({title:"Note saved"})},onError:()=>t({title:"Could not save note",variant:"destructive"})}),le=j({mutationFn:s=>y("POST",`/api/sales-hub/${s.contactId}/snooze`,{until:new Date(s.until).toISOString()}),onSuccess:(s,x)=>{M(),Q(x.contactId),t({title:"Snoozed"})},onError:()=>t({title:"Snooze failed",variant:"destructive"})}),Y=j({mutationFn:s=>y("POST",`/api/sales-hub/${s}/restore`),onSuccess:(s,x)=>{M(),Q(x),t({title:"Back in the queue"})},onError:()=>t({title:"Could not restore",variant:"destructive"})}),_e=[{key:"due",label:"Due now",n:D.length},...ye.map(s=>({key:s,label:ne[s],n:ke[s]??0})),{key:"scheduled",label:"Scheduled",n:V.length},{key:"lost",label:"Lost",n:re.length},{key:"won",label:"Won",n:oe.length}],de={due:{title:"Queue clear.",body:"Nothing is due right now. Refresh to rescan for dormant deals."},scheduled:{title:"Nothing scheduled.",body:"Snoozes and booked callbacks land here."},lost:{title:"Nothing written off.",body:"Deals you mark lost stay here so you can undo one."},won:{title:"Nothing revived yet.",body:"Deals you bring back land here with the money they returned."}};return e.jsxs("div",{className:"px-4 sm:px-6 lg:px-8 py-6 max-w-[1560px] mx-auto w-full",children:[e.jsxs("div",{className:"flex items-center justify-between mb-1 gap-4",children:[e.jsx("h1",{className:"font-display text-2xl sm:text-3xl font-semibold tracking-tight",children:"Sales Hub"}),e.jsxs(b,{variant:"outline",className:"shrink-0",onClick:()=>K.mutate(),disabled:K.isPending,"data-testid":"button-refresh-queue",children:[e.jsx(qe,{className:`mr-1.5 h-4 w-4 ${K.isPending?"animate-spin":""}`}),"Refresh queue"]})]}),e.jsx("p",{className:"text-sm text-muted-foreground mb-6",children:"Dormant money, ranked. Work the queue top to bottom, and close every one out either way."}),e.jsx(dt,{due:D,scheduled:V,stats:g}),e.jsx(we,{title:"Queue",count:k.length||void 0,action:C?.deposits?.length?e.jsxs(b,{variant:"ghost",size:"sm",className:"text-xs gap-1",onClick:()=>q(s=>!s),"data-testid":"button-toggle-deposits",children:[C.deposits.length," unlinked ",C.deposits.length===1?"deposit":"deposits",e.jsx(Pe,{className:`w-3 h-3 transition-transform ${$?"rotate-90":""}`})]}):void 0}),$&&C?.deposits?.length?e.jsxs("div",{className:`mb-3 overflow-hidden ${ae}`,children:[e.jsx("p",{className:"px-4 py-3 text-xs text-muted-foreground border-b border-card-border dark:border-white/[0.08]",children:"These people paid a deposit in QuickBooks, but their name and email do not match a CRM contact, so they are not in the queue. Fix the contact's name or email to pull them in."}),e.jsx("ul",{className:"divide-y divide-card-border dark:divide-white/[0.07]",children:C.deposits.map((s,x)=>e.jsxs("li",{className:"flex items-center justify-between gap-3 px-4 py-2.5",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"truncate text-sm font-medium",children:s.name||"Unnamed customer"}),s.email?e.jsx("div",{className:"truncate text-xs text-muted-foreground",children:s.email}):null]}),e.jsxs("div",{className:"shrink-0 text-right",children:[e.jsx("div",{className:"font-mono text-sm font-semibold tabular-nums",children:f(s.collected)??"$0"}),e.jsx("div",{className:"text-[10px] uppercase tracking-wide text-muted-foreground",children:"deposit paid"})]})]},x))})]}):null,e.jsx("div",{className:"mb-3",children:e.jsx(se,{options:_e,value:a,onChange:Ce,testIdPrefix:"chip-view"})}),e.jsxs("div",{className:"grid gap-4 lg:grid-cols-5 items-start",children:[e.jsx("div",{className:"order-2 lg:order-1 lg:col-span-2 min-w-0 space-y-2",children:B?e.jsxs(e.Fragment,{children:[e.jsx(X,{className:"h-20 w-full rounded-2xl"}),e.jsx(X,{className:"h-20 w-full rounded-2xl"}),e.jsx(X,{className:"h-20 w-full rounded-2xl"})]}):k.length===0?e.jsx(xe,{title:(de[a]??{title:`Nothing in ${R[a]}.`}).title,body:(de[a]??{body:"Try another view, or refresh the queue."}).body}):e.jsxs(e.Fragment,{children:[k.slice(0,40).map((s,x)=>e.jsx(ht,{followUp:s,index:x,active:l?.contactId===s.contactId,onSelect:()=>Se(s.contactId),trailing:a==="scheduled"&&s.nextActionAt?e.jsxs("p",{className:"text-[11px] tabular-nums text-muted-foreground mt-1",children:["Next touch ",lt(s.nextActionAt)]}):a==="lost"?e.jsxs("p",{className:"text-[11px] tabular-nums text-muted-foreground mt-1",children:[s.lostReason?E[s.lostReason]:"No reason recorded",s.lostAt?` · ${T(s.lostAt)}`:""]}):a==="won"?e.jsxs("p",{className:"text-[11px] tabular-nums text-emerald-600 dark:text-emerald-400 mt-1",children:["Won ",T(s.revivedAt),f(s.revivedValue)?` · ${f(s.revivedValue)} back`:""]}):void 0},s.contactId)),k.length>40&&e.jsxs("p",{className:"text-[11px] text-muted-foreground tabular-nums px-1",children:["Showing 40 of ",k.length,". Work these down and the rest move up."]})]})}),e.jsx("div",{className:"order-1 lg:order-2 lg:col-span-3 min-w-0 lg:sticky lg:top-4",children:l?e.jsxs("div",{className:`${ot} p-5 sm:p-6`,"data-testid":"work-pane",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"flex min-w-0 items-start gap-3.5",children:[e.jsx("div",{"aria-hidden":"true",className:"mt-0.5 flex h-11 w-11 shrink-0 items-center justify-center rounded-full border border-primary/25 bg-primary/10 font-display text-sm font-medium tracking-[0.02em] text-primary",children:ct(l.contactName)}),e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{className:`text-[10px] font-semibold uppercase tracking-wide px-1.5 py-0.5 rounded ${O[l.segment].chip}`,children:R[l.segment]}),W&&e.jsx("span",{className:`text-[10px] font-semibold uppercase tracking-wide px-1.5 py-0.5 rounded ${a==="won"?"bg-emerald-500/12 text-emerald-600 dark:text-emerald-400":"bg-muted text-muted-foreground"}`,children:a==="won"?"Won":"Lost"})]}),e.jsx("h2",{className:"mt-1.5 font-display text-2xl sm:text-[26px] font-light tracking-[-0.025em] truncate",children:l.contactName||"No name"}),ie?e.jsxs("p",{className:"mt-1 flex items-center gap-1.5 text-xs text-muted-foreground",children:[P?.addressCity?e.jsx(Qe,{className:"h-3 w-3 shrink-0"}):null,e.jsx("span",{className:"truncate",children:ie})]}):null]})]}),e.jsxs(b,{variant:"ghost",size:"sm",className:"shrink-0",onClick:()=>n(`/leads/${l.contactId}`),"data-testid":"button-full-record","aria-label":"Full record",children:[e.jsx(fe,{className:"h-3.5 w-3.5 sm:mr-1.5"}),e.jsx("span",{className:"hidden sm:inline",children:"Full record"})]})]}),e.jsx(ut,{followUp:l,contact:P,onOpenQuote:l.quoteId?()=>n(`/quotes/${l.quoteId}`):void 0}),e.jsx("div",{className:"mt-4",children:e.jsx(We,{contactId:l.contactId})}),e.jsx(xt,{followUp:l,contact:P}),W?e.jsxs("div",{className:"mt-5 rounded-2xl border border-card-border dark:border-white/[0.08] bg-muted/30 dark:bg-white/[0.03] p-4",children:[e.jsx("p",{className:"text-sm",children:a==="won"?e.jsxs(e.Fragment,{children:["Brought back ",T(l.revivedAt)||"recently",f(l.revivedValue)?`, worth ${f(l.revivedValue)}`:"","."]}):e.jsxs(e.Fragment,{children:["Written off ",T(l.lostAt)||"at some point",l.lostReason?`: ${E[l.lostReason].toLowerCase()}`:" with no reason recorded",f(l.lostValue)?`, ${f(l.lostValue)} on the table at the time`:"","."]})}),e.jsxs(b,{className:"mt-3",size:"sm",variant:"outline",disabled:Y.isPending,onClick:()=>Y.mutate(l.contactId),"data-testid":"button-restore",children:[e.jsx(Ke,{className:"mr-1.5 h-3.5 w-3.5"}),Y.isPending?"Restoring":"Put back in the queue"]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"mt-5 flex flex-wrap items-center gap-2",children:[e.jsxs(b,{size:"lg",disabled:!l.phone||H.isPending,onClick:()=>H.mutate(l.contactId),"data-testid":"button-call",children:[e.jsx(Me,{className:"mr-2 h-4 w-4"}),H.isPending?"Connecting":"Call"]}),e.jsxs(Z,{children:[e.jsx(U,{asChild:!0,children:e.jsxs(b,{variant:"outline",size:"lg",children:[e.jsx(He,{className:"mr-2 h-4 w-4"})," Snooze"]})}),e.jsxs(ee,{className:"w-72 space-y-2",children:[e.jsx("div",{className:"text-sm font-medium",children:"Snooze until"}),e.jsx(te,{type:"datetime-local",value:u,onChange:s=>N(s.target.value)}),e.jsx(b,{className:"w-full",disabled:!u||le.isPending,onClick:()=>le.mutate({contactId:l.contactId,until:u}),children:"Snooze"})]})]})]}),e.jsx("div",{className:"mt-6 text-[10px] font-medium uppercase tracking-[0.16em] text-muted-foreground",children:"Log the outcome"}),e.jsxs("div",{className:"mt-2 flex flex-wrap gap-2",children:[it.map(s=>e.jsxs(b,{variant:"outline",size:"sm",disabled:v.isPending,onClick:()=>v.mutate({contactId:l.contactId,outcome:s.value}),"data-testid":`button-outcome-${s.value}`,children:[e.jsx(s.icon,{className:"mr-1.5 h-3.5 w-3.5"})," ",s.label]},s.value)),e.jsxs(Z,{children:[e.jsx(U,{asChild:!0,children:e.jsxs(b,{variant:"outline",size:"sm",disabled:v.isPending,children:[e.jsx(Ye,{className:"mr-1.5 h-3.5 w-3.5"})," Callback"]})}),e.jsxs(ee,{className:"w-72 space-y-2",children:[e.jsx("div",{className:"text-sm font-medium",children:"Callback t
1ime"}),e.jsx(te,{type:"datetime-local",value:c,onChange:s=>h(s.target.value)}),e.jsx(b,{className:"w-full",disabled:!c||v.isPending,onClick:()=>v.mutate({contactId:l.contactId,outcome:"callback_scheduled",callbackAt:c}),children:"Schedule callback"})]})]}),e.jsxs(b,{variant:"outline",size:"sm",className:"text-emerald-600 hover:bg-emerald-500/10 hover:text-emerald-600 dark:text-emerald-400",disabled:v.isPending,onClick:()=>v.mutate({contactId:l.contactId,outcome:"revived"}),"data-testid":"button-outcome-won",children:[e.jsx(Je,{className:"mr-1.5 h-3.5 w-3.5"})," Won"]}),e.jsxs(Z,{open:_,onOpenChange:A,children:[e.jsx(U,{asChild:!0,children:e.jsxs(b,{variant:"outline",size:"sm",disabled:v.isPending,className:"text-red-600 hover:bg-red-500/10 hover:text-red-600 dark:text-red-400","data-testid":"button-outcome-lost",children:[e.jsx(Xe,{className:"mr-1.5 h-3.5 w-3.5"})," Mark lost"]})}),e.jsxs(ee,{className:"w-72 space-y-2",children:[e.jsx("div",{className:"text-sm font-medium",children:"Why did we lose this deal?"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"This also marks the contact lost, so the Leads board and the lost-reason report agree."}),e.jsx("div",{className:"grid grid-cols-2 gap-2 pt-1",children:Ae.map(s=>e.jsx("button",{type:"button",disabled:v.isPending,"data-testid":`button-lost-reason-${s}`,className:"rounded-xl border border-card-border p-2.5 text-xs font-medium transition-all hover:border-red-500/30 hover:bg-red-500/10 active:scale-[0.97] disabled:opacity-50 dark:border-white/[0.10]",onClick:()=>{A(!1),v.mutate({contactId:l.contactId,outcome:"lost",lostReason:s})},children:E[s]},s))})]})]})]}),e.jsx(ve,{className:"mt-3",rows:2,placeholder:"Add a note, or attach one to an outcome above",value:r,onChange:s=>o(s.target.value),"data-testid":"input-note"}),e.jsx("div",{className:"mt-2 flex justify-end",children:e.jsx(b,{variant:"outline",size:"sm",disabled:!r.trim()||G.isPending||v.isPending,onClick:()=>G.mutate(l.contactId),children:G.isPending?"Saving":"Save note"})})]}),l.attempts?.length?e.jsxs("div",{className:"mt-5",children:[e.jsx("div",{className:"text-[10px] font-medium uppercase tracking-[0.16em] text-muted-foreground",children:"History"}),e.jsx("div",{className:"mt-2 space-y-1",children:l.attempts.slice(-5).reverse().map((s,x)=>e.jsxs("div",{className:"text-xs text-muted-foreground",children:[e.jsx("span",{className:"tabular-nums text-foreground/70",children:T(s.at)})," ",s.outcome.replace(/_/g," "),s.byName?` by ${s.byName}`:"",s.note?`: ${s.note}`:""]},x))})]}):null,!W&&e.jsx(pt,{followUp:l},l.contactId)]}):e.jsx(xe,{title:"Nothing selected.",body:"Pick someone from the list to work them."})})]}),e.jsx(ft,{})]})}export{Ot 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.