PageSourceSearch

https://thola.ai/app/assets/CrmTopCustomersPage-hIBnJS_U.js

js thola.ai collected 2026-10-05 14:16:00 UTC 3,306 bytes, 1 lines download raw bytes

1import{h as b,r as p,j as t}from"./app-CL7tOXJE.js";import{c as y,a as v}from"./crmTeam-B5B03pen.js";import{j as h,h as g,C as N,a as k,L as C,E,P as w}from"./crmUi-CjP-Cbii.js";import{f as S}from"./crmFormat-C4ER1Wls.js";import{C as B}from"./crown-DnWNpL2f.js";import"./CrmNav-DmhZTUwR.js";import"./share-2-AHTASOK-.js";import"./award-BBX92-LF.js";import"./dollar-sign-CT_RbFvY.js";import"./circle-alert-5P3kIsA9.js";import"./inbox-5cC3YuYw.js";function G(){const e=b.c(15),[s,f]=p.useState(null),[r,j]=p.useState("");let m;e[0]===Symbol.for("react.memo_cache_sentinel")?(m=async()=>{j(""),f(null);try{f(await y.customerHealth())}catch(_){const x=_;j(x instanceof Error&&!("response"in x)?`We could not show a trustworthy ranking: ${x.message}`:k(x,"Could not load top customers."))}},e[0]=m):m=e[0];const u=m;let c,i;e[1]===Symbol.for("react.memo_cache_sentinel")?(c=()=>{u()},i=[u],e[1]=c,e[2]=i):(c=e[1],i=e[2]),p.useEffect(c,i);let n;e[3]===Symbol.for("react.memo_cache_sentinel")?(n=t.jsx(B,{className:"h-3.5 w-3.5"}),e[3]=n):n=e[3];let a;e[4]!==r||e[5]!==s?(a=!s&&!r&&t.jsx(C,{}),e[4]=r,e[5]=s,e[6]=a):a=e[6];let o;e[7]!==r?(o=r&&t.jsx(E,{message:r,onRetry:()=>void u()}),e[7]=r,e[8]=o):o=e[8];let l;e[9]!==s?(l=s&&t.jsxs("div",{className:"space-y-6",children:[t.jsxs("div",{className:"grid grid-cols-1 gap-4 sm:grid-cols-3",children:[t.jsx(h,{label:"Bought this month",value:s.this_month_spend_count,tone:"green"}),t.jsx(h,{label:"Active",value:s.active_count}),t.jsx(h,{label:"At risk",value:s.at_risk_count,tone:s.at_risk_count?"red":"indigo"})]}),s.summary&&t.jsx("p",{className:"text-sm tx-muted",children:s.summary}),s.top_customers.length===0?t.jsx(g,{title:"No purchases yet",hint:"Customers appear here once they have lifetime value."}):t.jsx(N,{className:"overflow-x-auto",children:t.jsxs("table",{className:"w-full text-left text-sm",children:[t.jsx("thead",{className:"border-b border-[color:var(--tx-card-border)] bg-slate-50/60 dark:bg-neutral-800/40",children:t.jsx("tr",{children:["#","Customer","Segment","Lifetime value","Last purchase"].map(R)})}),t.jsx("tbody",{children:s.top_customers.map(L)})]})})]}),e[9]=s,e[10]=l):l=e[10];let d;return e[11]!==a||e[12]!==o||e[13]!==l?(d=t.jsxs(w,{eyebrow:"Customers",icon:n,title:"Top customers",subtitle:"Ranked by lifetime value.",children:[a,o,l]}),e[11]=a,e[12]=o,e[13]=l,e[14]=d):d=e[14],d}function L(e,s){return t.jsxs("tr",{className:"border-b border-[color:var(--tx-card-border)] last:border-0",children:[t.jsx("td",{className:"px-4 py-3 tx-num tx-muted",children:s+1}),t.jsxs("td",{className:"px-4 py-3",children:[t.jsx("div",{className:"font-medium text-[color:var(--tx-text)]",children:e.name}),e.company&&t.jsx("div",{className:"text-xs tx-muted",children:e.company}),e.last_completed_notes&&t.jsx("div",{className:"mt-0.5 text-xs tx-muted italic",children:e.last_completed_notes})]}),t.jsx("td",{className:"px-4 py-3 capitalize tx-muted",children:e.segment||"—"}),t.jsx("td",{className:"px-4 py-3 tx-num font-semibold text-[color:var(--tx-text)]",children:v(e.lifetime_value)}),t.jsx("td",{className:"px-4 py-3 tx-muted",children:S(e.last_purchase_at)})]},`${e.name}-${s}`)}function R(e){return t.jsx("th",{className:"px-4 py-3 text-[11px] font-bold uppercase tracking-[0.12em] tx-muted",children:e},e)}export{G 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.