1const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/onboarding-flags-izowS2nh.js","assets/index-CbvCveKN.js","assets/index-DK9kCj9D.css"])))=>i.map(i=>d[i]); 2import{r,o as F,j as e,T as ye,U as ve,V as we,W as Ne,Y as ke,a7 as Ce,ai as le,B as G,Q as Se,_ as _e,K as Q,a9 as Fe,k as Ee,m as Ae,z as V,I as H}from"./index-CbvCveKN.js";import{i as ce}from"./initials-a0OX-QAT.js";import{D as De,P as Oe,U as Pe,f as de}from"./PageContainer-Bx7SVsdy.js";import{P as Ie}from"./PageHeader-ohyr15TW.js";import{F as $e}from"./FilterChips-CYAfenlT.js";import{E as me}from"./EmptyState-CvKdOS6b.js";import{S as Le}from"./SearchInput-CwtZ1bZ_.js";import{T as ze}from"./textarea-BGGCYgxW.js";import{S as pe}from"./skeleton-CQrTucTw.js";import{e as Ue}from"./pipeline-57THQ7iX.js";import{S as Be,a as Te,b as Me,c as Ve,d as Re}from"./select-C3XbO4_1.js";import{a as te,f as Je,p as He,n as qe}from"./csv-BqE4KxYN.js";import{F as We}from"./file-up-B8H2Y9hJ.js";import{D as Ze}from"./download-q_CUCbMH.js";import{T as Ge}from"./triangle-alert-BJBV5PBt.js";import{U as Qe}from"./upload-BDKwK5D_.js";import{U as xe}from"./users-BkZzL3s4.js";import{F as Ke}from"./file-text-DDhZ7a0t.js";import{C as Ye}from"./calendar-clock-CsLtIGEm.js";import{P as ue}from"./phone-C9i08TZ5.js";import{S as Xe}from"./search-fqqyqjqf.js";import{d as fe}from"./differenceInDays-DKaeRypT.js";import{p as Z}from"./parseISO-B0WEjCD3.js";import{s as et}from"./differenceInCalendarDays-BmAYwV3_.js";import{i as tt}from"./isAfter-BG9KlOmt.js";import"./check-Bjw6cCk6.js";import"./index-Jf4OHjGl.js";import"./chevron-right-f4vsMuAf.js";import"./en-US-wdCzBwgh.js";import"./plus-kYCBPFxU.js";import"./layout-dashboard-rEexJXnQ.js";import"./ek-mark-light-Y4_w-cFG.js";import"./plug-BAhKXAxN.js";import"./chevron-down-yKD6BMcU.js";import"./GrainGradient-kJbOtAvv.js";import"./index-CKxf6gP2.js";import"./index-DlFerWUd.js";const he={name:"Full name",first_name:"First name",last_name:"Last name",company:"Company",email:"Email",phone:"Phone",phone2:"Second phone",address:"Street address",address2:"Address line 2",city:"City",state:"State / Province",zip:"ZIP / Postal",notes:"Notes",skip:"Don't import"},ge={name:["name","full name","customer","customer name","client","client name","contact","contact name","display name","primary contact"],first_name:["first name","first","given name","contact first name"],last_name:["last name","last","surname","family name","contact last name"],company:["company","company name","business","business name","organization"],email:["email","e mail","email address","primary email","e mail 1 value","customer email"],phone:["phone","phone number","primary phone","mobile","mobile phone","cell","cell phone","phone 1 value","main phone","customer phone","telephone"],phone2:["phone 2","secondary phone","home phone","work phone","other phone","phone 2 value","alt phone"],address:["address","street","street address","address 1","address line 1","service address","billing address","address street","street 1","address 1 street","address 1 formatted"],address2:["address 2","address line 2","unit","apt","suite","street 2"],city:["city","town","address city","service city","billing city","address 1 city"],state:["state","province","state province","region","address state","service state","address 1 region"],zip:["zip","zip code","postal","postal code","zipcode","address zip","service zip","postcode","address 1 postal code"],notes:["notes","note","comments","description","customer notes","memo"]},je=m=>{const g=qe(m);for(const[N,L]of Object.entries(ge))if(L.includes(g))return N;const j=["zip","city","state","address2","email","phone2","phone","first_name","last_name","company","notes","name","address"];for(const N of j)if(ge[N].some(L=>g.includes(L)))return N;return"skip"},st=`Name,Company,Email,Phone,Address,City,State,ZIP,Notes 3Jane Smith,,[email protected],(555) 010-2020,100 Main St,Phoenix,AZ,85001,Gate code 1234 4`,at=({open:m,onOpenChange:g,onImported:j})=>{const[N,L]=r.useState([]),[ae,q]=r.useState(""),[z,E]=r.useState([]),[U,R]=r.useState(!0),[P,ne]=r.useState("skip"),[A,oe]=r.useState([]),[B,b]=r.useState(!1),[K,W]=r.useState(0),[k,T]=r.useState(null),J=r.useRef(null);r.useEffect(()=>{m&&(T(null),F.from("accounts").select("id, client_name, email, phone, zip").then(({data:s})=>oe(s||[])))},[m]);const re=async s=>{const n=He(await s.text());q(s.name),L(n);
4const x=n[0]||[],u=x.some(_=>je(_)!=="skip");R(u),E(u?x.map(je):x.map(()=>"skip")),T(null)},f=r.useMemo(()=>U?N.slice(1):N,[N,U]),h=r.useMemo(()=>{const s=i=>z.indexOf(i),n=new Map(A.filter(i=>i.email).map(i=>[i.email.toLowerCase(),i])),x=new Map(A.filter(i=>i.phone).map(i=>[te(i.phone),i])),u=new Map(A.map(i=>[`${i.client_name.trim().toLowerCase()}|${(i.zip||"").trim()}`,i])),_=new Set;return f.map((i,l)=>{const d=o=>{const M=s(o);return M>=0?(i[M]||"").trim():""},I=d("name")||[d("first_name"),d("last_name")].filter(Boolean).join(" "),c=d("company"),C=I||c,w=d("email").toLowerCase()||null,D=d("phone")||d("phone2"),S=D?Je(D):null,Y=[d("address"),d("address2")].filter(Boolean).join(", ")||null,X=[d("notes"),I&&c&&c!==I?`Company: ${c}`:""].filter(Boolean),$={client_name:C,email:w,phone:S,address:Y,city:d("city")||null,state:d("state")||null,zip:d("zip")||null,notes:X.join(` 5`)||null,rowIndex:l+(U?2:1)};C||($.problem="No name");const ee=`${C.toLowerCase()}|${w||""}|${te(S)}`;!$.problem&&_.has(ee)&&($.problem="Duplicate row in file"),_.add(ee);const O=w&&n.get(w)||S&&te(S).length>=7&&x.get(te(S))||u.get(`${C.toLowerCase()}|${$.zip||""}`);return O&&($.duplicateOf=O.id),$})},[f,z,A,U]),v=r.useMemo(()=>({total:h.length,ready:h.filter(s=>!s.problem&&!s.duplicateOf).length,dupes:h.filter(s=>!s.problem&&s.duplicateOf).length,problems:h.filter(s=>s.problem).length}),[h]),y=z.includes("name")||z.includes("first_name")||z.includes("company"),t=async()=>{b(!0),W(0);const s={added:0,updated:0,skipped:0,failed:0};try{const{data:{user:n}}=await F.auth.getUser();if(!n)throw new Error("Not signed in");const x=h.filter(l=>!l.problem&&!l.duplicateOf),u=P==="update"?h.filter(l=>!l.problem&&l.duplicateOf):[];s.skipped=h.filter(l=>l.problem||l.duplicateOf&&P==="skip").length;const _=x.length+u.length;let i=0;for(let l=0;l<x.length;l+=100){const d=x.slice(l,l+100).map(({rowIndex:c,problem:C,duplicateOf:w,...D})=>({...D,user_id:n.id})),{error:I}=await F.from("accounts").insert(d);I?s.failed+=d.length:s.added+=d.length,i+=d.length,W(Math.round(i/_*100))}for(const l of u){const d={};for(const c of["email","phone","address","city","state","zip","notes"])l[c]&&(d[c]=l[c]);const{error:I}=await F.from("accounts").update(d).eq("id",l.duplicateOf);I?s.failed++:s.updated++,i++,W(Math.round(i/_*100))}if(T(s),s.added>0){const{markOnboardingFlag:l}=await _e(async()=>{const{markOnboardingFlag:d}=await import("./onboarding-flags-izowS2nh.js");return{markOnboardingFlag:d}},__vite__mapDeps([0,1,2]));await l("has_created_customer"),await l("has_imported_data")}j()}catch(n){Q({title:"Import failed",description:n instanceof Error?n.message:"Try again",variant:"destructive"})}finally{b(!1)}},p=()=>{L([]),q(""),E([]),T(null)},a=()=>{const s=new Blob([st],{type:"text/csv"}),n=URL.createObjectURL(s),x=document.createElement("a");x.href=n,x.download="estimatekit-customers-template.csv",x.click(),URL.revokeObjectURL(n)};return e.jsx(ye,{open:m,onOpenChange:s=>{g(s),s||p()},children:e.jsxs(ve,{className:"max-h-[90vh] overflow-y-auto sm:max-w-2xl",children:[e.jsxs(we,{children:[e.jsx(Ne,{children:"Import customers"}),e.jsx(ke,{children:"Upload a CSV from Jobber, Housecall Pro, ServiceTitan, QuickBooks, Google Contacts, or any spreadsheet. We'll match the columns; you can adjust before importing."})]}),k?e.jsxs("div",{className:"space-y-4 py-2",children:[e.jsxs("div",{className:"flex items-center gap-3 rounded-xl border border-ink/[0.06] bg-card p-5",children:[e.jsx(Ce,{className:"h-6 w-6 shrink-0 text-ok",strokeWidth:1.8}),e.jsxs("div",{children:[e.jsx("p",{className:"font-semibold text-foreground",children:"Import finished"}),e.jsxs("p",{className:"text-[14px] text-foreground-secondary",children:[k.added," added",k.updated?`, ${k.updated} updated`:"",k.skipped?`, ${k.skipped} skipped`:"",k.failed?`, ${k.failed} failed`:"","."]})]})]}),e.jsx(le,{children:e.jsx(G,{variant:"orange",onClick:()=>{g(!1),p()},children:"Done"})})]}):N.length===0?e.jsxs("div",{className:"space-y-3",children:[e.jsx("input",{ref:J,type:"file",accept:".csv,text/csv",className:"hidden",onChange:s=>{var n;return((n=s.target.files)==null?void 0:n[0])&&re(s.target.files[0])}}),e.jsxs("button",{type:"button",onClick:()=>{var s;return(s=J.current)==null?void 0:s.click()},className:"flex w-full flex-col items-center gap-2 rounded-xl border border-dashed border-ink/[0.12] bg-card px-4 py-10 text-center transition-colors hover:bg-ink/[0.04]",children:[e.jsx(We,{className:"h-7 w-7 text-foreground-tertiary",strokeWidth:1.8}),e.jsx("span",{className:"text-[14px] font-semibold text-foreground",children:"Choose a CSV file"}),e.jsx("span",{className:"text-[12.5px] text-foreground-secondary",children:"Name, email, phone, address in any order. Duplicates are detected by email, phone, or name + ZIP."})]}),e.jsxs("button",{type:"button",onClick:a,className:"inline-flex items-center gap-1.5 text-[12.5px] font-medium text-info underline-offset-2 hover:underline",children:[e.jsx(Ze,{className:"h-4 w-4",strokeWidth:1.8})," Download a blank template"]})]}):e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2 text-sm",children:[e.jsxs("span",{className:"truncate text-foreground-secondary",children:[ae," · ",f.length," row",f.length===1?"":"s"]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("label",{className:"flex items-center gap-1.5 text-[12.5px] text-foreground-secondary",children:[e.jsx("input",{type:"checkbox",checked:U,onChange:s=>
5R(s.target.checked),className:"h-4 w-4 rounded"})," First row is a header"]}),e.jsx("button",{type:"button",className:"text-[12.5px] font-medium text-info underline-offset-2 hover:underline",onClick:p,children:"Choose another file"})]})]}),e.jsxs("div",{className:"overflow-hidden rounded-xl border border-ink/[0.06]",children:[e.jsxs("div",{className:"grid grid-cols-[1fr_1fr_1fr] gap-2 border-b border-ink/[0.06] bg-card px-4 py-2.5 font-mono text-[11.5px] uppercase tracking-[0.08em] text-foreground-tertiary",children:[e.jsx("span",{children:"Column in your file"}),e.jsx("span",{children:"Example"}),e.jsx("span",{children:"Imports as"})]}),e.jsx("div",{className:"max-h-56 divide-y divide-ink/[0.06] overflow-y-auto bg-card",children:(N[0]||[]).map((s,n)=>{var x;return e.jsxs("div",{className:"grid grid-cols-[1fr_1fr_1fr] items-center gap-2 px-4 py-2 text-[14px]",children:[e.jsx("span",{className:"truncate font-medium text-foreground",children:U?s||`Column ${n+1}`:`Column ${n+1}`}),e.jsx("span",{className:"truncate text-foreground-secondary",children:((x=f[0])==null?void 0:x[n])||"â"}),e.jsxs(Be,{value:z[n]||"skip",onValueChange:u=>E(_=>_.map((i,l)=>l===n?u:i)),children:[e.jsx(Te,{className:"h-9 text-sm",children:e.jsx(Me,{})}),e.jsx(Ve,{className:"z-[110]",children:Object.keys(he).map(u=>e.jsx(Re,{value:u,children:he[u]},u))})]})]},n)})})]}),!y&&e.jsxs("p",{className:"flex items-center gap-2 text-[13px] text-warn",children:[e.jsx(Ge,{className:"h-4 w-4 shrink-0",strokeWidth:1.8})," Pick which column is the customer's name (or company) to continue."]}),y&&e.jsxs("div",{className:"grid gap-px overflow-hidden rounded-xl border border-ink/[0.06] bg-ink/[0.06] sm:grid-cols-3",children:[e.jsxs("div",{className:"flex flex-col gap-1.5 bg-card px-[18px] py-4",children:[e.jsx("p",{className:"text-[12.5px] text-foreground-secondary",children:"Ready to add"}),e.jsx("p",{className:"font-mono text-[18px] font-medium tracking-[-0.02em] text-foreground",children:v.ready})]}),e.jsxs("div",{className:"flex flex-col gap-1.5 bg-card px-[18px] py-4",children:[e.jsx("p",{className:"text-[12.5px] text-foreground-secondary",children:"Already in your list"}),e.jsx("p",{className:"font-mono text-[18px] font-medium tracking-[-0.02em] text-foreground",children:v.dupes})]}),e.jsxs("div",{className:"flex flex-col gap-1.5 bg-card px-[18px] py-4",children:[e.jsx("p",{className:"text-[12.5px] text-foreground-secondary",children:"Missing a name"}),e.jsx("p",{className:`font-mono text-[18px] font-medium tracking-[-0.02em] ${v.problems?"text-warn":"text-foreground"}`,children:v.problems})]})]}),y&&v.dupes>0&&e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2 rounded-xl border border-ink/[0.06] bg-card px-4 py-3 text-[14px]",children:[e.jsx("span",{className:"text-foreground-secondary",children:"For customers already in your list:"}),e.jsx("div",{role:"tablist",className:"flex rounded-xl border border-ink/[0.06] bg-card p-[3px]",children:[["skip","Skip them"],["update","Fill in missing details"]].map(([s,n])=>e.jsx("button",{role:"tab","aria-selected":P===s,onClick:()=>ne(s),className:`h-8 min-h-0 rounded-md px-3 text-[12.5px] font-semibold transition-colors ${P===s?"bg-ink/[0.08] text-foreground":"text-foreground-secondary hover:text-foreground"}`,children:n},s))})]}),y&&e.jsxs("div",{className:"overflow-hidden rounded-xl border border-ink/[0.06]",children:[e.jsx("div",{className:"border-b border-ink/[0.06] bg-card px-4 py-2.5 font-mono text-[11.5px] uppercase tracking-[0.08em] text-foreground-tertiary",children:"Preview"}),e.jsxs("div",{className:"max-h-48 divide-y divide-ink/[0.06] overflow-y-auto bg-card",children:[h.slice(0,10).map(s=>e.jsxs("div",{className:"flex items-center gap-3 px-4 py-2.5 text-[14px]",children:[e.jsxs("span",{className:"min-w-0 flex-1",children:[e.jsx("span",{className:"block truncate font-semibold text-foreground",children:s.client_name||e.jsx("span",{className:"text-warn",children:"(no name)"})}),e.jsx("span",{className:"block truncate text-[12px] text-foreground-secondary",children:[s.phone,s.email,[s.city,s.state].filter(
5Boolean).join(", ")].filter(Boolean).join(" · ")||"no contact details"})]}),e.jsx("span",{className:"shrink-0 text-xs font-semibold",children:s.problem?e.jsx("span",{className:"whitespace-nowrap rounded-full bg-amber-500/15 px-2.5 py-[3px] text-warn",children:s.problem}):s.duplicateOf?e.jsx("span",{className:"whitespace-nowrap rounded-full bg-ink/10 px-2.5 py-[3px] text-muted-foreground",children:P==="update"?"Update":"Skip · exists"}):e.jsx("span",{className:"whitespace-nowrap rounded-full bg-emerald-500/15 px-2.5 py-[3px] text-ok",children:"Add"})})]},s.rowIndex)),h.length>10&&e.jsxs("div",{className:"px-4 py-2.5 text-[12px] text-foreground-tertiary",children:["â¦and ",h.length-10," more"]})]})]}),B&&e.jsx("div",{className:"h-1.5 overflow-hidden rounded-full bg-ink/[0.08]",children:e.jsx("div",{className:"h-full bg-cta-orange transition-all",style:{width:`${K}%`}})}),e.jsxs(le,{className:"gap-2",children:[e.jsx(G,{variant:"outline",onClick:()=>g(!1),disabled:B,children:"Cancel"}),e.jsxs(G,{variant:"orange",onClick:t,disabled:B||!y||v.ready===0&&!(P==="update"&&v.dupes>0),children:[B?e.jsx(Se,{className:"h-4 w-4 animate-spin"}):null,P==="update"&&v.dupes>0?`Import ${v.ready} · update ${v.dupes}`:`Import ${v.ready}`]})]})]})]})})},se=m=>`$${m.toLocaleString("en-US",{maximumFractionDigits:0})}`,ie=(m,g)=>m?g?tt(Z(m),Z(g))?m:g:m:g,be={client_name:"",email:"",phone:"",address:"",city:"",state:"",zip:"",notes:""},Mt=()=>{const m=Fe(),g=Ee(),[j,N]=r.useState([]),[L,ae]=r.useState(!0),[q,z]=r.useState(""),[E,U]=r.useState("all"),[R,P]=r.useState("recent"),[ne,A]=r.useState(!1),[oe,B]=r.useState(!1),[b,K]=r.useState(be),[W,k]=r.useState(!1),T=async()=>{try{const t=et(new Date).toISOString().slice(0,10),[p,a,s,n,x]=await Promise.all([F.from("accounts").select("*").order("client_name"),F.from("estimates").select("id, account_id, status, created_at, approved_at, approved_tier_id, estimate_settings(total), estimate_tiers!estimate_tiers_estimate_id_fkey(id, total, is_recommended)"),F.from("jobs").select("customer_id, scheduled_date, status, created_at"),F.from("customer_contacts").select("customer_id, contact_date, follow_up_date, follow_up_completed"),F.from("invoices").select("customer_id, total, status, paid_at")]);if(p.error)throw p.error;const u=(c,C)=>{const w=new Map;for(const D of c||[]){const S=C(D);S&&w.set(S,[...w.get(S)||[],D])}return w},_=u(a.data,c=>c.account_id),i=u(s.data,c=>c.customer_id),l=u(n.data,c=>c.customer_id),d=u(x.data,c=>c.customer_id),I=(p.data||[]).map(c=>{const C=_.get(c.id)||[],w=i.get(c.id)||[],D=l.get(c.id)||[],S=d.get(c.id)||[],Y=C.filter(o=>["sent","viewed"].includes(o.status)),X=o=>Ue(o).value,$=S.filter(o=>o.status==="paid").reduce((o,M)=>o+Number(M.total||0),0),ee=C.filter(o=>o.status==="approved"||o.status==="completed").reduce((o,M)=>o+X(M),0);let O=c.created_at;for(const o of C)O=ie(O,o.created_at);for(const o of w)O=ie(O,o.created_at);for(const o of D)O=ie(O,o.contact_date);return{...c,lastActivity:O,openEstimates:Y.length,openValue:Y.reduce((o,M)=>o+X(M),0),upcomingJobs:w.filter(o=>o.scheduled_date>=t&&!["completed","cancelled"].includes(o.status)).length,totalJobs:w.length,lifetimeValue:$>0?$:ee,followUpDue:D.some(o=>o.follow_up_date&&!o.follow_up_completed&&o.follow_up_date<=t)}});N(I)}catch(t){Q({title:"Couldn't load customers",description:t instanceof Error?t.message:"",variant:"destructive"})}finally{ae(!1)}};r.useEffect(()=>{T()},[]);const[J,re]=Ae();r.useEffect(()=>{J.get("new")==="1"&&(A(!0),J.delete("new"),re(J,{replace:!0}))},[J]);const f=r.useMemo(()=>({all:j.length,followup:j.filter(t=>t.followUpDue).length,open:j.filter(t=>t.openEstimates>0).length,jobs:j.filter(t=>t.upcomingJobs>0).length,quiet:j.filter(t=>!t.lastActivity||fe(new Date,Z(t.lastActivity))>90).length,openValue:j.reduce((t,p)=>t+p.openValue,0)}),[j]),h=r.useMemo(()=>{const t=q.trim().toLowerCase();return j.filter(a=>E==="followup"&&!a.followUpDue||E==="open"&&a.openEstimates===0||E==="jobs"&&a.upcomingJobs===0||E==="quiet"&&a.lastActivity&&fe(new Date,Z(a.lastActivity))<=90?!1:t?[a.client_name,a.phone,a.email,a.address,a.city,a.zip].some(s=>s==null?void 0:s.toLowerCase().includes(t)):!0).sort((a,s)=>R==="name"?a.client_name.localeCompare(s.client_name):(s.lastActivity||"").localeCompare(a.lastActivity||""))},[j,q,E,R]),v=async()=>
5{if(!b.client_name.trim()){Q({title:"Customer name is required",variant:"destructive"});return}k(!0);try{const{data:{user:t}}=await F.auth.getUser();if(!t)throw new Error("Not signed in");const p=Object.fromEntries(Object.entries(b).map(([x,u])=>[x,u.trim()||null])),{data:a,error:s}=await F.from("accounts").insert({...p,client_name:b.client_name.trim(),user_id:t.id}).select("id").single();if(s)throw s;const{markOnboardingFlag:n}=await _e(async()=>{const{markOnboardingFlag:x}=await import("./onboarding-flags-izowS2nh.js");return{markOnboardingFlag:x}},__vite__mapDeps([0,1,2]));await n("has_created_customer"),Q({title:"Customer added"}),A(!1),K(be),a!=null&&a.id?g(`/customers/${a.id}`):T()}catch(t){Q({title:"Couldn't add customer",description:t instanceof Error?t.message:"",variant:"destructive"})}finally{k(!1)}},y=(t,p)=>K(a=>({...a,[t]:p}));return e.jsxs("div",{className:"min-h-screen bg-background",children:[e.jsx(De,{}),e.jsxs(Oe,{width:"wide",children:[e.jsx(Ie,{title:"Customers",description:"Everyone you've quoted or worked with, sorted by who needs you next.",actions:m.office?e.jsxs(G,{variant:"outline",className:"gap-2",onClick:()=>B(!0),children:[e.jsx(Qe,{className:"h-4 w-4"})," Import"]}):void 0}),e.jsxs("div",{className:"space-y-6 md:space-y-8",children:[e.jsx("div",{className:"grid grid-cols-2 gap-px overflow-hidden rounded-xl border border-ink/[0.06] bg-ink/[0.06] md:grid-cols-[repeat(auto-fit,minmax(160px,1fr))]",children:[{label:"Customers",value:String(f.all),icon:xe},...m.office?[{label:"Open estimates",value:f.openValue>0?se(f.openValue):String(f.open),icon:Ke}]:[],{label:"Upcoming jobs",value:String(f.jobs),icon:Ye},{label:"Follow-ups due",value:String(f.followup),icon:ue,warn:f.followup>0}].map(t=>e.jsxs("div",{className:"flex min-w-0 flex-col gap-1.5 bg-card px-4 py-4 md:gap-2 md:px-5 md:py-5",children:[e.jsx("p",{className:"text-[12.5px] text-foreground-secondary md:text-[13px]",children:t.label}),e.jsx("p",{className:`truncate font-mono text-[17px] font-medium tracking-[-0.02em] md:text-[18px] ${"warn"in t&&t.warn?"text-warn":"text-foreground"}`,children:t.value})]},t.label))}),e.jsxs("div",{className:"flex flex-col gap-3.5",children:[e.jsx(Le,{value:q,onChange:z,placeholder:"Search customers"}),e.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",children:[e.jsx($e,{value:E,onChange:U,options:[{value:"all",label:"All",count:f.all},{value:"followup",label:"Follow-up due",count:f.followup},{value:"open",label:"Open estimates",count:f.open},{value:"jobs",label:"Upcoming jobs",count:f.jobs},{value:"quiet",label:"Quiet 90+ days",count:f.quiet}]}),e.jsx("div",{role:"tablist",className:"flex shrink-0 self-start rounded-xl border border-ink/[0.06] bg-card p-[3px]",children:[["recent","Recent"],["name","AâZ"]].map(([t,p])=>e.jsx("button",{role:"tab","aria-selected":R===t,onClick:()=>P(t),className:`h-8 min-h-0 rounded-md px-3.5 text-[13px] font-semibold transition-colors ${R===t?"bg-ink/[0.08] text-foreground":"text-foreground-secondary hover:text-foreground"}`,children:p},t))})]})]}),L?e.jsx("div",{className:"flex flex-col gap-px overflow-hidden rounded-xl border border-ink/[0.06] bg-ink/[0.05]",children:[1,2,3,4].map(t=>e.jsxs("div",{className:"flex items-center gap-3.5 bg-card py-3.5 pl-4 pr-5",children:[e.jsx(pe,{className:"h-10 w-10 shrink-0 rounded-full"}),e.jsx(pe,{className:"h-10 flex-1 rounded-xl"})]},t))}):h.length===0?j.length===0?e.jsx(me,{icon:xe,title:"No customers yet",description:"Add your first customer, or create an estimate and save the client as a customer.",action:{label:"Add customer",onClick:()=>A(!0),icon:Pe},secondaryAction:{label:"Import from a spreadsheet",onClick:()=>B(!0)}}):e.jsx(me,{icon:Xe,title:"No customers match",description:"Try another search or filter."}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"hidden overflow-hidden rounded-[14px] border border-ink/[0.07] bg-white shadow-[0_1px_2px_rgba(24,24,27,0.04)] md:block",children:[e.jsxs("div",{role:"row",className:"grid h-9 grid-cols-[minmax(0,2fr)_minmax(0,1.2fr)_minmax(0,1.3fr)_120px_130px_130px] items-center border-b border-ink/[0.07] bg-[#FAFAF9] px-4 text-[12px] text-foreground-tertiary",children:[e.jsx("span",{children:"Customer"}),e.jsx("span",{children:"Location"}),e.jsx("span",{children:m.canSeeContact?"Contact":""}),e.jsx("span",{children:"Open"}),e.jsx("span",{children:"Last activity"}),e.jsx("span",{className:"text-right",children:m.office?"Lifetime":""})]}),h.map(t=>
5{const p=[t.city,t.state].filter(Boolean).join(", "),a=t.lastActivity?de(Z(t.lastActivity),{addSuffix:!0}):"No activity";return e.jsxs("button",{role:"row",type:"button",onClick:()=>g(`/customers/${t.id}`),className:"grid w-full grid-cols-[minmax(0,2fr)_minmax(0,1.2fr)_minmax(0,1.3fr)_120px_130px_130px] items-center border-b border-ink/[0.05] px-4 py-2.5 text-left text-[13px] transition-colors last:border-b-0 hover:bg-[#FAFAF9]",children:[e.jsxs("span",{className:"flex min-w-0 items-center gap-2.5 pr-3",children:[e.jsx("span",{className:"flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-[#EC4899]/10 text-[11px] font-medium text-[#BE185D]",children:ce(t.client_name)}),e.jsx("span",{className:"truncate text-foreground",children:t.client_name}),t.followUpDue&&e.jsx("span",{className:"shrink-0 rounded-md bg-warn/10 px-1.5 py-0.5 text-[11px] font-medium text-warn",children:"Follow up"})]}),e.jsx("span",{className:"truncate pr-3 text-foreground-secondary",children:p||"â"}),e.jsx("span",{className:"truncate pr-3 text-foreground-secondary",children:m.canSeeContact?t.phone||t.email||"â":""}),e.jsxs("span",{className:"flex gap-1.5",children:[t.openEstimates>0&&e.jsxs("span",{className:"rounded-md bg-info/10 px-1.5 py-0.5 text-[11px] font-medium text-info",children:[t.openEstimates," open"]}),t.upcomingJobs>0&&e.jsxs("span",{className:"rounded-md bg-ok/10 px-1.5 py-0.5 text-[11px] font-medium text-ok",children:[t.upcomingJobs," job",t.upcomingJobs===1?"":"s"]}),!t.openEstimates&&!t.upcomingJobs&&e.jsx("span",{className:"text-foreground-tertiary",children:"â"})]}),e.jsx("span",{className:"truncate text-foreground-secondary",children:a}),e.jsx("span",{className:"ek-num text-right text-foreground",children:m.office&&t.lifetimeValue>0?se(t.lifetimeValue):""})]},t.id)}),e.jsxs("div",{className:"grid h-10 grid-cols-[minmax(0,2fr)_minmax(0,1.2fr)_minmax(0,1.3fr)_120px_130px_130px] items-center border-t border-ink/[0.07] bg-[#FAFAF9] px-4 text-[12.5px] text-foreground-secondary",children:[e.jsxs("span",{className:"ek-num",children:[h.length," ",h.length===1?"customer":"customers"]}),e.jsx("span",{}),e.jsx("span",{}),e.jsx("span",{}),e.jsx("span",{}),e.jsx("span",{className:"ek-num text-right text-foreground",children:m.office?se(h.reduce((t,p)=>t+(p.lifetimeValue||0),0)):""})]})]}),e.jsx("div",{className:"ek-zebra flex flex-col gap-px overflow-hidden rounded-xl border border-ink/[0.06] bg-ink/[0.05] md:hidden",children:h.map(t=>{const p=[t.city,t.state].filter(Boolean).join(", "),a=t.lastActivity?de(Z(t.lastActivity),{addSuffix:!0}):"no activity";return e.jsxs("div",{className:"flex items-center gap-3 bg-card py-3.5 pl-4 pr-4 transition-colors hover:bg-ink/[0.04] md:pr-5",children:[e.jsxs("button",{type:"button",onClick:()=>g(`/customers/${t.id}`),className:"flex min-w-0 flex-1 cursor-pointer items-center gap-3.5 text-left",children:[e.jsx("span",{className:"flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-[#EC4899]/10 text-[13px] font-medium text-[#BE185D]",children:ce(t.client_name)}),e.jsxs("span",{className:"flex min-w-0 flex-1 flex-col gap-[3px]",children:[e.jsxs("span",{className:"flex min-w-0 items-center gap-2",children:[e.jsx("span",{className:"truncate text-[14px] font-semibold text-foreground",children:t.client_name}),t.followUpDue&&e.jsx("span",{className:"shrink-0 rounded-[5px] bg-amber-500/15 px-1.5 py-px text-[11px] font-medium text-warn",children:"Follow up"})]}),e.jsx("span",{className:"block truncate text-[13px] text-foreground-secondary",children:m.canSeeContact?[p,t.phone].filter(Boolean).join(" · ")||t.email||"No contact info":p||""})]}),e.jsxs("span",{className:"flex shrink-0 flex-col items-end gap-[3px] text-right",children:[m.office&&t.lifetimeValue>0&&e.jsx("span",{className:"font-mono text-[14px] text-foreground",children:se(t.lifetimeValue)}),e.jsx("span",{className:"text-[12px] text-foreground-tertiary",children:a}),(t.openEstimates>0||t.upcomingJobs>0)&&e.jsxs("span",{className:"hidden gap-1.5 sm:flex",children:[t.openEstimates>0&&e.jsxs("span",{className:"rounded-[5px] bg-sky-500/15 px-1.5 py-px text-[11px] font-medium text-info",children:[t.openEstimates," open"]}),t.upcomingJobs>0&&e.jsxs("span",{className:"rounded-[5px] bg-emerald-500/15 px-1.5 py-px text-[11px] font-medium text-ok",children:[t.upcomingJobs," job",t.upcomingJobs===1?"":"s"]})]})]})]}),t.phone&&m.canSeeContact&&e.jsx("a",{href:`tel:${t.phone}`,"aria-label":`Call ${t.client_name}`,className:"flex h-11 md:h-9 w-11 md:w-9 shrink-0 items-center justify-center rounded-full border border-ink/[0.12] text-ink/80 hover:border-ink/25 hover:text-foreground md:hidden",children:e.jsx(ue,{className:"h-4 w-4",strokeWidth:1.8})})]},t.id)})})]})]})]}),e.jsx(at,{open:oe,onOpenChange:B,onImported:T}),e.jsx(ye,{open:ne,onOpenChange:A,children:e.jsxs(ve,{className:"sm:max-w-md",children:[e.jsxs(we,{children:[e.jsx(Ne,{children:"Add customer"}),e.jsx(ke,{children:"You can fill in the rest later from their page."})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{children:[e.jsx(V,{htmlFor:"c-name",children:"Name"}),e.jsx(H,{id:"c-name",value:b.client_name,onChange:t=>y("client_name",t.target.value),className:"mt-1.5",placeholder:"Jane Smith or Smith Re
5sidence",autoFocus:!0})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx(V,{htmlFor:"c-phone",children:"Phone"}),e.jsx(H,{id:"c-phone",type:"tel",value:b.phone,onChange:t=>y("phone",t.target.value),className:"mt-1.5"})]}),e.jsxs("div",{children:[e.jsx(V,{htmlFor:"c-email",children:"Email"}),e.jsx(H,{id:"c-email",type:"email",value:b.email,onChange:t=>y("email",t.target.value),className:"mt-1.5"})]})]}),e.jsxs("div",{children:[e.jsx(V,{htmlFor:"c-address",children:"Address"}),e.jsx(H,{id:"c-address",value:b.address,onChange:t=>y("address",t.target.value),className:"mt-1.5"})]}),e.jsxs("div",{className:"grid grid-cols-[1fr_5rem_6rem] gap-3",children:[e.jsxs("div",{children:[e.jsx(V,{htmlFor:"c-city",children:"City"}),e.jsx(H,{id:"c-city",value:b.city,onChange:t=>y("city",t.target.value),className:"mt-1.5"})]}),e.jsxs("div",{children:[e.jsx(V,{htmlFor:"c-state",children:"State"}),e.jsx(H,{id:"c-state",value:b.state,onChange:t=>y("state",t.target.value),className:"mt-1.5"})]}),e.jsxs("div",{children:[e.jsx(V,{htmlFor:"c-zip",children:"ZIP"}),e.jsx(H,{id:"c-zip",value:b.zip,onChange:t=>y("zip",t.target.value),className:"mt-1.5"})]})]}),e.jsxs("div",{children:[e.jsx(V,{htmlFor:"c-notes",children:"Notes"}),e.jsx(ze,{id:"c-notes",value:b.notes,onChange:t=>y("notes",t.target.value),className:"mt-1.5 min-h-[70px]",placeholder:"Gate code, dog in yard, preferred contact timeâ¦"})]})]}),e.jsxs(le,{className:"gap-2",children:[e.jsx(G,{variant:"outline",onClick:()=>A(!1),children:"Cancel"}),e.jsx(G,{variant:"orange",onClick:v,disabled:W,children:W?"Savingâ¦":"Add customer"})]})]})})]})};export{Mt 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.