PageSourceSearch

https://www.smallbizagent.ai/assets/_id_-wTtMng28.js

js smallbizagent.ai collected 2026-10-05 15:05:21 UTC 46,885 bytes, 6 lines download raw bytes

1import{e as se,r as T,d as O,j as e,u as z}from"./vendor-query-CnAhr2B8.js";import{c as Je,a as ae,u as we,g as Ge,t as Ye,p as v,q as P,r as A,s as b,v as Xe,w as k,x as w,y as S,z as D,I as N,A as I,G as _,B as g,H as $,W as Se,J as re,d as q,K as De,C as B,i as Y,j as X,k as Z,l as ee,N as Te,O as Ze,Q as es,R as ss,T as as,V as ts,m as de,X as ue,Y as le,Z as ns,_ as is,$ as pe,a0 as rs,a1 as ls,a2 as ds,a3 as cs,h as H,a4 as os,a5 as ms,a6 as xs,a7 as hs,a8 as ne,a9 as ce,D as qe,aa as oe,ab as us,F as $e,P as ps,f as je,n as ge,U as js,ac as J,M as G,ad as Me,ae as fe,af as gs,ag as fs,ah as Ns,ai as vs}from"./index-CLUtDhnY.js";import{P as W}from"./PageTitle-BRYll76q.js";import{d as bs,b as ys,c as Ne,s as E,l as R,n as Cs}from"./vendor-forms-UY-il7MQ.js";import{a as ve}from"./api-c_Wfq480.js";import{T as me}from"./textarea-VdIEZsUv.js";import{S as be}from"./switch-wa839A7l.js";import{S as ks}from"./separator-CVR53GEz.js";import{A as Ie,h as Ee,a as Pe,b as Fe,c as Ae,d as Oe,e as Le,f as ze,g as Re}from"./alert-dialog-CVgn4OwE.js";import{P as ws}from"./pencil-XqPqJhqP.js";import{T as Ss}from"./trash-2-B9b4XGw8.js";import{S as Ds}from"./square-pen-6eLYV1-R.js";import{C as Ts}from"./cake-CrQBwcEn.js";import{C as ye}from"./circle-x-CDWbgxd-.js";import{T as Ke}from"./tag-Bc53W9r2.js";import{S as qs}from"./shield-check-BPXHSdeh.js";import{H as $s}from"./heart-BPUPw7pK.js";import{S as Ms}from"./star-W3rPNB9i.js";import"./vendor-ui-CYA7SV0W.js";import"./vendor-charts-CPMWc2oJ.js";/**
2 * @license lucide-react v0.453.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 Is=Je("StickyNote",[["path",{d:"M16 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V8Z",key:"qazsjp"}],["path",{d:"M15 3v4a2 2 0 0 0 2 2h4",key:"40519r"}]]),Es=ys({businessId:Cs(),firstName:E().min(2,"First name must be at least 2 characters"),lastName:E().min(2,"Last name must be at least 2 characters"),email:E().email("Invalid email format").optional().or(R("")),phone:E().min(10,"Phone number must be at least 10 digits"),address:E().optional().or(R("")),city:E().optional().or(R("")),state:E().optional().or(R("")),zip:E().optional().or(R("")),notes:E().optional().or(R("")),birthday:E().optional().or(R("")),smsOptIn:Ne().optional().default(!1),marketingOptIn:Ne().optional().default(!1)});function Ce({customer:s,isEdit:d=!1,onSuccess:n}){const{toast:p}=ae(),f=se(),[,j]=we(),[m,h]=T.useState(!1),{user:r}=Ge(),o=(r==null?void 0:r.businessId)??void 0,l=bs({resolver:Ye(Es),defaultValues:{businessId:o,firstName:(s==null?void 0:s.firstName)||"",lastName:(s==null?void 0:s.lastName)||"",email:(s==null?void 0:s.email)||"",phone:(s==null?void 0:s.phone)||"",address:(s==null?void 0:s.address)||"",city:(s==null?void 0:s.city)||"",state:(s==null?void 0:s.state)||"",zip:(s==null?void 0:s.zip)||"",notes:(s==null?void 0:s.notes)||"",birthday:(s==null?void 0:s.birthday)||"",smsOptIn:(s==null?void 0:s.smsOptIn)??!1,marketingOptIn:(s==null?void 0:s.marketingOptIn)??!1}}),y=O({mutationFn:i=>ve("POST","/api/customers",i),onSuccess:()=>{f.invalidateQueries({queryKey:["/api/customers"]}),p({title:"Success",description:"Customer created successfully"}),j("/customers")},onError:i=>{p({title:"Error",description:"Failed to create customer. Please try again.",variant:"destructive"}),console.error("Error creating customer:",i)}}),a=O({mutationFn:i=>ve("PATCH",`/api/customers/${s.id}`,i),onSuccess:()=>{f.invalidateQueries({queryKey:["/api/customers"]}),f.invalidateQueries({queryKey:[`/api/customers/${s.id}`]}),f.invalidateQueries({queryKey:[`/api/customers/${s.id}/activity`]}),p({title:"Success",description:"Customer updated successfully"}),n?n():j("/customers")},onError:i=>{p({title:"Error",description:"Failed to update customer. Please try again.",variant:"destructive"}),console.error("Error updating customer:",i)}}),M=async i=>{h(!0);try{const u={...i};i.smsOptIn&&!(s!=null&&s.smsOptIn)&&(u.smsOptInDate=new Date().toISOString(),u.smsOptInMethod="manual"),i.marketingOptIn&&!(s!=null&&s.marketingOptIn)&&(u.marketingOptInDate=new Date().toISOString()),d?await a.mutateAsync(u):await y.mutateAsync(u)}finally{h(!1)}};return e.jsxs(v,{children:[e.jsx(P,{children:e.jsx(A,{children:d?"Edit Customer":"Add New Customer"})}),e.jsx(b,{children:e.jsx(Xe,{...l,children:e.jsxs("form",{onSubmit:l.handleSubmit(M),className:"space-y-6",children:[e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:[e.jsx(k,{control:l.control,name:"firstName",render:({field:i})=>e.jsxs(w,{children:[e.jsx(S,{children:"First Name *"}),e.jsx(D,{children:e.jsx(N,{placeholder:"John",...i})}),e.jsx(I,{})]})}),e.jsx(k,{control:l.control,name:"lastName",render:({field:i})=>e.jsxs(w,{children:[e.jsx(S,{children:"Last Name *"}),e.jsx(D,{children:e.jsx(N,{placeholder:"Smith",...i})}),e.jsx(I,{})]})}),e.jsx(k,{control:l.control,name:"phone",render:({field:i})=>e.jsxs(w,{children:[e.jsx(S,{children:"Phone Number *"}),e.jsx(D,{children:e.jsx(N,{placeholder:"555-123-4567",...i})}),e.jsx(I,{})]})}),e.jsx(k,{control:l.control,name:"email",render:({field:i})=>e.jsxs(w,{children:[e.jsx(S,{children:"Email"}),e.jsx(D,{children:e.jsx(N,{type:"email",placeholder:"[email protected]",...i,value:i.value||""})}),e.jsx(I,{})]})}),e.jsx(k,{control:l.control,name:"birthday",render:({field:i})=>e.jsxs(w,{children:[e.jsx(S,{children:"Birthday"}),e.jsx(D,{children:e.jsx(N,{type:"text",placeholder:"MM-DD (e.g., 03-15)",...i,value:i.value||"",maxLength:5,onChange:u=>{let c=u.target.value.replace(/[^0-9-]/g,"");c.length===2&&!c.includes("-")&&(s==null?void 0:s.birthday)!==c&&(c=c+"-"),i.onChange(c)}})}),e.jsx(_,{children:"For birthday specials & discounts"}),e.jsx(I,{})]})}),e.jsx(k,{control:l.control,name:"address",render:({field:i})=>e.jsxs(w,{children:[e.jsx(S,{children:"Address"}),e.jsx(D,{children:e.jsx(N,{placeholder:"123 Main St",...i,value:i.value||""})}),e.jsx(I,{})]})}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-3",children:[e.jsx(k,{control:l.control,name:"city",render:({field:i})=>e.jsxs(w,{children:[e.jsx(S,{children:"City"}),e.jsx(D,{children:e.jsx(N,{placeholder:"Anytown",...i,value:i.value||""})}),e.jsx(I,{})]})}),e.jsx(k,{control:l.control,name:"state",render:({field:i})=>e.jsxs(w,{children:[e.jsx(S,{children:"State"}),e.jsx(D,{children:e.jsx(N,{placeholder:"CA",...i,value:i.value||""})}),e.jsx(I,{})]})}),e.jsx(k,{control:l.control,name:"zip",render:({field:i})=>e.jsxs(w,{children:[e.jsx(S,{children:"ZIP"}),e.jsx(D,{children:e.jsx(N,{placeholder:"12345",...i,value:i.value||""})}),e.jsx(I,{})]})})]})]}),e.jsx(k,{control:l.control,name:"notes",render:({field:i})=>e.jsxs(w,{children:[e.jsx(S,{children:"Notes"}),e.jsx(D,{children:e.jsx(me,{placeholder:"Customer drives a Honda Accord",className:"min-h-[100px]",...i,value:i.value||""})}),e.jsx(_,{children:"Add any additional information about the customer"}),e.jsx(I,{})]})}),e.jsx(ks,{}),e.jsxs("div",{className:"space-y-4",children:[e.jsx("h3",{className:"text-sm font-medium",children:"SMS Preferences"}),e.jsx(k,{control:l.control,name:"smsOptIn",render:({field:i})=>e.jsxs(w,{className:"flex flex-row items-center justify-between rounded-lg border p-4",children:[e.jsxs("div",{className:"space-y-0.5",children:[e.jsx(S,{className:"text-base",children:"SMS Notifications"}),e.jsx(_,{children:"Receive appointment confirmations, reminders, and updates via text message."})]}),e.jsx(D,{children:e.jsx(be,{checked:i.value,onCheckedChange:i.onChange})})]})}),e.jsx(k,{control:l.control,name:"marketingOptIn",render:({field:i})=>e.jsxs(w,{className:"flex flex-row items-center justify-between rounded-lg border p-4",children:[e.jsxs("div",{className:"space-y-0.5",children:[e.jsx(S,{className:"text-base",children:"Marketing Messages"}),e.jsx(_,{children:"Receive promotional offers, discounts, birthday specials, and other marketing messages. Msg & data rates may apply. Reply STOP to opt out."})]}),e.jsx(D,{children:e.jsx(be,{checked:i.value,onCheckedChange:i.onChange})})]})})]}),e.jsxs("div",{className:"flex justify-end space-x-4",children:[e.jsx(g,{type:"button",variant:"outline",onClick:()=>j("/customers"),children:"Cancel"}),e.jsx(g,{type:"submit",disabled:m,children:m?"Saving...":d?"Update Customer":"Create Customer"})]})]})})})]})}const ke=[{value:"furnace",label:"Furnace"},{value:"ac",label:"Air Conditioner"},{value:"heat_pump",label:"Heat Pump"},{value:"mini_split",label:"Mini-Split"},{value:"boiler",label:"Boiler"},{value:"water_heater",label:"Water Heater"},{value:"thermostat",label:"Thermostat"},{value:"vehicle",label:"Vehicle"},{value:"pet",label:"Pet"},{value:"other",label:"Other"}],ie={equipmentType:"furnace",make:"",model:"",serialNumber:"",installDate:"",lastServiceDate:"",warrantyExpiry:"",location:"",notes:"",active:!0};function Ps({customerId:s,label:d}){const{toast:n}=ae(),p=se(),[f,j]=T.useState(!1),[m,h]=T.useState(null),[r,o]=T.useState(ie),l=["/api/customers",s,"equipment"],{data:y=[],isLoading:a}=z({queryKey:l,queryFn:async()=>(await $("GET",`/api/customers/${s}/equipment`)).json()}),M=O({mutationFn:async t=>{const F={...t};for(const V of["make","model","serialNumber","installDate","lastServiceDate","warrantyExpiry","location","notes"])F[V]===""&&(F[V]=null);return m?(await $("PATCH",`/api/customers/${s}/equipment/${m}`,F)).json():(await $("POST",`/api/customers/${s}/equipment`,F)).json()},onSuccess:()=>{p.invalidateQueries({queryKey:l}),n({title:m?"Equipment updated":"Equipment added"}),j(!1),h(null),o(ie)},onError:t=>{n({title:"Save failed",description:(t==null?void 0:t.message)||"Could not save equipment",variant:"destructive"})}}),i=O({mutationFn:async t=>{await $("DELETE",`/api/customers/${s}/equipment/${t}`)},onSuccess:()=>{p.invalidateQueries({queryKey:l}),n({title:"Equipment removed"})},onError:t=>{n({title:"Delete failed",description:(t==null?void 0:t.message)||"Could not delete equipment",variant:"destructive"})}});function u(){h(null),o(ie),j(!0)}function c(t){h(t.id),o({equipmentType:t.equipmentType,make:t.make??"",model:t.model??"",serialNumber:t.serialNumber??"",installDate:t.installDate??"",lastServiceDate:t.lastServiceDate??"",warrantyExpiry:t.warrantyExpiry??"",location:t.location??"",notes:t.notes??"",active:t.active}),j(!0)}function K(){M.mutate(r)}const te=t=>{var F;return((F=ke.find(C=>C.value===t))==null?void 0:F.label)||t};return e.jsxs(v,{"data-testid":"equipment-card",children:[e.jsx(P,{className:"pb-3",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs(A,{className:"text-base flex items-center gap-2",children:[e.jsx(Se,{className:"h-4 w-4 text-muted-foreground"}),d]}),e.jsxs(g,{size:"sm",variant:"outline",onClick:u,"data-testid":"equipment-add",children:[e.jsx(re,{className:"h-3 w-3 mr-1"}),"Add"]})]})}),e.jsx(b,{className:"space-y-3",children:a?e.jsx("p",{className:"text-sm text-muted-foreground",children:"Loading…"}):y.length===0?e.jsxs("p",{className:"text-sm text-muted-foreground",children:["No ",d.toLowerCase()," on file. Click Add to track make, model, install date, and service history."]}):y.map(t=>e.jsx("div",{className:"rounded-lg border p-3 space-y-1","data-testid":`equipment-row-${t.id}`,children:e.jsxs("div",{className:"flex items-start justify-between gap-2",children:[e.jsxs("div",{className:"space-y-1 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx(q,{variant:"secondary",children:te(t.equipmentType)}),t.make||t.model?e.jsx("span",{className:"text-sm font-medium",children:[t.make,t.model].filter(
6Boolean).join(" ")}):null,!t.active&&e.jsx(q,{variant:"outline",className:"text-xs",children:"Retired"})]}),(t.location||t.installDate||t.lastServiceDate)&&e.jsxs("div",{className:"flex items-center gap-3 text-xs text-muted-foreground flex-wrap",children:[t.location&&e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(De,{className:"h-3 w-3"}),t.location]}),t.installDate&&e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(B,{className:"h-3 w-3"}),"Installed ",t.installDate]}),t.lastServiceDate&&e.jsxs("span",{className:"flex items-center gap-1",children:["Last service ",t.lastServiceDate]})]}),t.serialNumber&&e.jsxs("div",{className:"text-xs text-muted-foreground font-mono",children:["S/N: ",t.serialNumber]}),t.notes&&e.jsx("p",{className:"text-xs text-muted-foreground whitespace-pre-wrap",children:t.notes})]}),e.jsxs("div",{className:"flex items-center gap-1 shrink-0",children:[e.jsx(g,{size:"icon",variant:"ghost",onClick:()=>c(t),"data-testid":`equipment-edit-${t.id}`,children:e.jsx(ws,{className:"h-3 w-3"})}),e.jsxs(Ie,{children:[e.jsx(Ee,{asChild:!0,children:e.jsx(g,{size:"icon",variant:"ghost","data-testid":`equipment-delete-${t.id}`,children:e.jsx(Ss,{className:"h-3 w-3 text-destructive"})})}),e.jsxs(Pe,{children:[e.jsxs(Fe,{children:[e.jsxs(Ae,{children:["Remove this ",d.toLowerCase().replace(/s$/,""),"?"]}),e.jsx(Oe,{children:"This permanently deletes the record. To keep history but mark it removed, edit and set it to Retired instead."})]}),e.jsxs(Le,{children:[e.jsx(ze,{children:"Cancel"}),e.jsx(Re,{onClick:()=>i.mutate(t.id),className:"bg-destructive text-destructive-foreground",children:"Delete"})]})]})]})]})]})},t.id))}),e.jsx(Y,{open:f,onOpenChange:j,children:e.jsxs(X,{className:"max-w-md",children:[e.jsxs(Z,{children:[e.jsx(ee,{children:m?`Edit ${d.toLowerCase().replace(/s$/,"")}`:`Add ${d.toLowerCase().replace(/s$/,"")}`}),e.jsx(Te,{children:"Track make, model, install date, and service history so techs walk in prepared."})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{className:"text-sm font-medium",children:"Type"}),e.jsxs(Ze,{value:r.equipmentType,onValueChange:t=>o({...r,equipmentType:t}),children:[e.jsx(es,{"data-testid":"equipment-type-select",children:e.jsx(ss,{})}),e.jsx(as,{children:ke.map(t=>e.jsx(ts,{value:t.value,children:t.label},t.value))})]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{className:"text-sm font-medium",children:"Make"}),e.jsx(N,{value:r.make,onChange:t=>o({...r,make:t.target.value}),placeholder:"e.g. Trane","data-testid":"equipment-make"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{className:"text-sm font-medium",children:"Model"}),e.jsx(N,{value:r.model,onChange:t=>o({...r,model:t.target.value}),placeholder:"e.g. XR16","data-testid":"equipment-model"})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{className:"text-sm font-medium",children:"Serial number"}),e.jsx(N,{value:r.serialNumber,onChange:t=>o({...r,serialNumber:t.target.value}),"data-testid":"equipment-serial"})]}),e.jsxs("div",{className:"grid grid-cols-3 gap-2",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{className:"text-sm font-medium",children:"Installed"}),e.jsx(N,{type:"date",value:r.installDate,onChange:t=>o({...r,installDate:t.target.value}),"data-testid":"equipment-install-date"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{className:"text-sm font-medium",children:"Last service"}),e.jsx(N,{type:"date",value:r.lastServiceDate,onChange:t=>o({...r,lastServiceDate:t.target.value}),"data-testid":"equipment-last-service"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{className:"text-sm font-medium",children:"Warranty"}),e.jsx(N,{type:"date",value:r.warrantyExpiry,onChange:t=>o({...r,warrantyExpiry:t.target.value}),"data-testid":"equipment-warranty"})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{className:"text-sm font-medium",children:"Location"}),e.jsx(N,{value:r.location,onChange:t=>o({...r,location:t.target.value}),placeholder:"e.g. attic, basement, garage","data-testid":"equipment-location"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{className:"text-sm font-medium",children:"Notes"}),e.jsx(me,{value:r.notes,onChange:t=>o({...r,notes:t.target.value}),rows:3,placeholder:"Anything the tech should know — quirks, prior issues, access notes.","data-testid":"equipment-notes"})]}),m&&e.jsxs("div",{className:"flex items-center gap-2 rounded-md border p-2",children:[e.jsx("input",{id:"equipment-active",type:"checkbox",checked:r.active,onChange:t=>o({...r,active:t.target.checked}),"data-testid":"equipment-active"}),e.jsx("label",{htmlFor:"equipment-active",className:"text-sm",children:"Active (uncheck to retire while keeping history)"})]})]}),e.jsxs(de,{children:[e.jsx(g,{variant:"outline",onClick:()=>j(!1),disabled:M.isPending,children:"Cancel"}),e.jsx(g,{onClick:K,disabled:M.isPending,"data-testid":"equipment-save",children:M.isPending?"Saving…":"Save"})]})]})})]})}function Fs({customerId:s}){const{toast:d}=ae(),n=se(),[p,f]=T.useState(!1),[j,m]=T.useState(null),h=["/api/customers",s,"membership"],{data:r,isLoading:o}=z({queryKey:h,queryFn:async()=>(await $("GET",`/api/customers/${s}/membership`)).json()}),{data:l=[],isLoading:y}=z({queryKey:["/api/membership-plans"],queryFn:async()=>(await $("GET","/api/membership-plans?activeOnly=true")).json()}),a=O({mutationFn:async c=>(await $("POST",`/api/customers/${s}/enroll`,{planId:c})).json(),onSuccess:()=>{n.invalidateQueries({queryKey:h}),d({title:"Customer enrolled",description:"Stripe subscription created. Customer needs a payment method on file before billing starts."}),f(!1),m(null)},onError:c=>{d({title:"Enrollment failed",description:(c==null?void 0:c.message)||"Unexpected error",variant:"destructive"})}}),M=O({mutationFn:async c=>(await $("POST",`/api/memberships/${c}/cancel`)).json(),onSuccess:()=>{n.invalidateQueries({queryKey:h}),d({title:"Membership canceled",description:"Customer keeps their benefits until the end of the current billing period."})},onError:c=>{d({title:"Cancel failed",description:(c==null?void 0:c.message)||"Unexpected error",variant:"destructive"})}});if(o)return e.jsxs(v,{children:[e.jsx(P,{className:"pb-3",children:e.jsx(A,{className:"text-base",children:"Membership"})}),e.jsx(b,{children:e.jsx("p",{className:"text-sm text-muted-foreground",children:"Loading…"})})]});const i=r==null?void 0:r.membership,u=r==null?void 0:r.plan;
6return i&&u&&i.status!=="canceled"?e.jsxs(v,{"data-testid":"membership-card",children:[e.jsx(P,{className:"pb-3",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs(A,{className:"text-base flex items-center gap-2",children:[e.jsx(ue,{className:"h-4 w-4 text-amber-500"}),"Membership"]}),e.jsxs(Ie,{children:[e.jsx(Ee,{asChild:!0,children:e.jsxs(g,{size:"sm",variant:"ghost","data-testid":"membership-cancel",children:[e.jsx(le,{className:"h-3 w-3 mr-1"}),"Cancel"]})}),e.jsxs(Pe,{children:[e.jsxs(Fe,{children:[e.jsx(Ae,{children:"Cancel membership?"}),e.jsx(Oe,{children:"The customer keeps their benefits until the end of the current billing period, then the subscription lapses. They can re-enroll any time."})]}),e.jsxs(Le,{children:[e.jsx(ze,{children:"Never mind"}),e.jsx(Re,{onClick:()=>M.mutate(i.id),className:"bg-destructive text-destructive-foreground",children:"Cancel membership"})]})]})]})]})}),e.jsxs(b,{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx(q,{variant:"secondary",className:"text-sm",children:u.name}),e.jsxs("span",{className:"text-sm text-muted-foreground",children:["$",u.priceMonthly,"/",u.billingInterval==="month"?"mo":"yr"]}),i.status==="past_due"&&e.jsx(q,{variant:"destructive",children:"Past due"}),i.status==="paused"&&e.jsx(q,{variant:"outline",children:"Paused"})]}),e.jsxs("div",{className:"space-y-2",children:[u.includedTuneUps>0&&e.jsxs("div",{className:"flex items-center justify-between text-sm",children:[e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx(Se,{className:"h-3 w-3 text-muted-foreground"}),"Tune-ups remaining"]}),e.jsxs("span",{className:"font-medium","data-testid":"membership-tune-ups-remaining",children:[i.tuneUpsRemaining," / ",u.includedTuneUps]})]}),u.includedServiceCalls>0&&e.jsxs("div",{className:"flex items-center justify-between text-sm",children:[e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx(ns,{className:"h-3 w-3 text-muted-foreground"}),"Free service calls remaining"]}),e.jsxs("span",{className:"font-medium","data-testid":"membership-service-calls-remaining",children:[i.serviceCallsRemaining," / ",u.includedServiceCalls]})]}),Number(u.memberDiscountPercent)>0&&e.jsxs("div",{className:"flex items-center justify-between text-sm",children:[e.jsx("span",{className:"text-muted-foreground",children:"Member discount"}),e.jsxs("span",{className:"font-medium",children:[u.memberDiscountPercent,"% off"]})]}),u.priorityDispatch&&e.jsxs("div",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:[e.jsx(is,{className:"h-3 w-3"}),"Priority dispatch — jumps the queue"]}),u.waivesDiagnosticFee&&e.jsxs("div",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:[e.jsx(pe,{className:"h-3 w-3"}),"Diagnostic fee waived"]})]}),i.nextBillingDate&&e.jsxs("div",{className:"flex items-center gap-2 text-xs text-muted-foreground pt-2 border-t",children:[e.jsx(B,{className:"h-3 w-3"}),"Renews"," ",new Date(i.nextBillingDate).toLocaleDateString()]})]})]}):e.jsxs(v,{"data-testid":"membership-card-empty",children:[e.jsx(P,{className:"pb-3",children:e.jsxs(A,{className:"text-base flex items-center gap-2",children:[e.jsx(ue,{className:"h-4 w-4 text-muted-foreground"}),"Membership"]})}),e.jsxs(b,{className:"space-y-3",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Not enrolled. Membership plans turn one-time repair customers into recurring revenue with pre-paid tune-ups, priority dispatch, and auto-applied discounts."}),e.jsxs(g,{size:"sm",onClick:()=>f(!0),disabled:l.length===0,"data-testid":"membership-enroll-open",children:[e.jsx(pe,{className:"h-3 w-3 mr-1"}),"Enroll in plan"]}),l.length===0&&!y&&e.jsx("p",{className:"text-xs text-muted-foreground",children:"No plans configured yet. Go to Settings → Memberships to set up plan tiers."})]}),e.jsx(Y,{open:p,onOpenChange:f,children:e.jsxs(X,{className:"max-w-md",children:[e.jsxs(Z,{children:[e.jsx(ee,{children:"Enroll customer in plan"}),e.jsx(Te,{children:"Pick a tier. Stripe Connect will start the subscription. If the customer doesn't have a payment method on file, they'll need to add one before billing kicks in."})]}),e.jsx("div",{className:"space-y-2 max-h-[50vh] overflow-y-auto",children:l.map(c=>e.jsxs("button",{onClick:()=>m(c.id),className:`w-full text-left rounded-md border p-3 space-y-1 transition-colors hover:bg-accent ${j===c.id?"border-primary bg-accent":""}`,"data-testid":`enroll-plan-${c.id}`,children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"font-medium",children:c.name}),e.jsxs("span",{className:"text-sm text-muted-foreground",children:["$",c.priceMonthly,"/",c.billingInterval==="month"?"mo":"yr"]})]}),c.description&&e.jsx("p",{className:"text-xs text-muted-foreground",children:c.description})]},c.id))}),e.jsxs(de,{children:[e.jsx(g,{variant:"outline",onClick:()=>f(!1),disabled:a.isPending,children:"Cancel"}),e.jsx(g,{onClick:()=>{j&&a.mutate(j)},disabled:!j||a.isPending,"data-testid":"enroll-submit",children:a.isPending?"Enrolling…":"Enroll"})]})]})})]})}function Ve(s){return s?new Date(s).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"}):""}function As(s){return s?new Date(s).toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"}):""}function Os(s){if(!s)return"";const d=Math.floor(s/60),n=s%60;return d===0?`${n}s`:`${d}m ${n}s`}const Ls={job:ce,invoice:$e,appointment:B,quote:gs,call:Me,sms:G},zs={job:"text-amber-500 bg-amber-50 dark:bg-amber-900/20",invoice:"text-green-500 bg-green-50 dark:bg-green-900/20",appointment:"text-purple-500 bg-purple-50 dark:bg-purple-900/20",quote:"text-orange-500 bg-orange-50 dark:bg-orange-900/20",call:"text-blue-500 bg-blue-50 dark:bg-blue-900/20",sms:"text-teal-500 bg-teal-50 dark:bg-teal-900/20"}
6,Rs={job:"/jobs",invoice:"/invoices",appointment:"/appointments",quote:"/quotes"},Ks={completed:"bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400",confirmed:"bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-400",scheduled:"bg-purple-100 text-purple-800 dark:bg-purple-900/30 dark:text-purple-400",pending:"bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400",paid:"bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400",overdue:"bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400",cancelled:"bg-gray-100 text-gray-600 dark:bg-gray-800/30 dark:text-gray-400",no_show:"bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400",answered:"bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400",missed:"bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400",sent:"bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-400"};function Vs({status:s}){if(!s)return null;const d=s.replace(/_/g," ").replace(/\b\w/g,p=>p.toUpperCase()),n=Ks[s]||"bg-gray-100 text-gray-600";return e.jsx(q,{className:`text-[10px] ${n}`,children:d})}function Us({customerId:s,tags:d}){const[n,p]=T.useState(""),[f,j]=T.useState(!1),m=se(),h=O({mutationFn:async l=>(await $("POST",`/api/customers/${s}/tags`,{tags:[l]})).json(),onSuccess:()=>{m.invalidateQueries({queryKey:[`/api/customers/${s}`]}),p(""),j(!1)}}),r=O({mutationFn:async l=>(await $("DELETE",`/api/customers/${s}/tags/${encodeURIComponent(l)}`)).json(),onSuccess:()=>{m.invalidateQueries({queryKey:[`/api/customers/${s}`]})}}),o=()=>{const l=n.trim();l&&!d.includes(l)&&h.mutate(l)};return e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5",children:[d.map(l=>e.jsxs(q,{variant:"secondary",className:"text-xs flex items-center gap-1 pr-1",children:[e.jsx(Ke,{className:"h-3 w-3"}),l,e.jsx("button",{onClick:()=>r.mutate(l),className:"ml-0.5 hover:text-destructive rounded-full",children:e.jsx(le,{className:"h-3 w-3"})})]},l)),f?e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(N,{value:n,onChange:l=>p(l.target.value),onKeyDown:l=>l.key==="Enter"&&o(),placeholder:"Tag name",className:"h-6 w-24 text-xs",autoFocus:!0}),e.jsx(g,{size:"sm",variant:"ghost",className:"h-6 w-6 p-0",onClick:o,children:e.jsx(re,{className:"h-3 w-3"})}),e.jsx(g,{size:"sm",variant:"ghost",className:"h-6 w-6 p-0",onClick:()=>{j(!1),p("")},children:e.jsx(le,{className:"h-3 w-3"})})]}):e.jsxs(g,{size:"sm",variant:"ghost",className:"h-6 text-xs text-muted-foreground",onClick:()=>j(!0),children:[e.jsx(re,{className:"h-3 w-3 mr-1"}),"Add Tag"]})]})}function Bs({trend:s}){return s==="improving"?e.jsx(fs,{className:"h-3.5 w-3.5 text-green-500"}):s==="declining"?e.jsx(Ns,{className:"h-3.5 w-3.5 text-red-500"}):e.jsx(vs,{className:"h-3.5 w-3.5 text-gray-400"})}function Qs({level:s}){return!s||s==="low"?e.jsx(q,{className:"bg-green-100 text-green-800 text-[10px]",children:"Low Risk"}):s==="medium"?e.jsx(q,{className:"bg-yellow-100 text-yellow-800 text-[10px]",children:"Medium Risk"}):e.jsx(q,{className:"bg-red-100 text-red-800 text-[10px]",children:"High Risk"})}function _s({score:s}){const d=Math.round((s??0)*100),n=d>=80?"bg-green-500":d>=50?"bg-yellow-500":"bg-red-500";return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"flex-1 h-2 bg-muted rounded-full overflow-hidden",children:e.jsx("div",{className:`h-full ${n} rounded-full transition-all`,style:{width:`${d}%`}})}),e.jsxs("span",{className:"text-xs font-medium w-8 text-right",children:[d,"%"]})]})}function Hs({insights:s,isError:d}){if(d)return e.jsxs(v,{children:[e.jsx(P,{className:"pb-3",children:e.jsxs(A,{className:"text-base flex items-center gap-2",children:[e.jsx(J,{className:"h-4 w-4"}),"AI Insights"]})}),e.jsx(b,{children:e.jsx("p",{className:"text-sm text-muted-foreground",children:"Unable to load insights. Please try again later."})})]});if(!s||s.message==="No insights calculated yet")return e.jsxs(v,{children:[e.jsx(P,{className:"pb-3",children:e.jsxs(A,{className:"text-base flex items-center gap-2",children:[e.jsx(J,{className:"h-4 w-4"}),"AI Insights"]})}),e.jsx(b,{children:e.jsx("p",{className:"text-sm text-muted-foreground",children:"Insights will appear after more interactions are logged."})})]});const n=s.insights||s,p=Array.isArray(n.preferredServices)?n.preferredServices:[],f=Array.isArray(n.autoTags)?n.autoTags:[],j=Array.isArray(n.riskFactors)?n.riskFactors:[];return e.jsxs(v,{children:[e.jsx(P,{className:"pb-3",children:e.jsxs(A,{className:"text-base flex items-center gap-2",children:[e.jsx(J,{className:"h-4 w-4"}),"AI Insights"]})}),e.jsxs(b,{className:"space-y-4",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"text-xs text-muted-foreground mb-1 flex items-center gap-1",children:[e.jsx(fe,{className:"h-3 w-3"}),"Churn Risk"]}),e.jsx(Qs,{level:n.riskLevel}),n.churnProbability!=null&&e.jsxs("div",{className:"text-[10px] text-muted-foreground mt-0.5",children:[Math.round(n.churnProbability*100),"% probability"]})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"text-xs text-muted-foreground mb-1 flex items-center gap-1",children:[e.jsx(qs,{className:"h-3 w-3"}),"Reliability"]}),e.jsx(_s,{score:n.reliabilityScore})]})]}),n.averageSentiment!=null&&e.jsxs("div",{children:[e.jsxs("div",{className:"text-xs text-muted-foreground mb-1 flex items-center gap-1",children:[e.jsx($s,{className:"h-3 w-3"}),"Sentiment"]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"flex items-center gap-1",children:[1,2,3,4,5].map(m=>e.jsx(Ms,{className:`h-3.5 w-3.5 ${m<=Math.round(n.averageSentiment)?"text-yellow-400 fill-yellow-400":"text-gray-200"}`},m))}),e.jsx(Bs,{trend:n.sentimentTrend}),e.jsx("span",{className:"text-xs text-muted-foreground capitalize",children:n.sentimentTrend||"stable"})]})]}),n.lifetimeValue!=null&&n.lifetimeValue>0&&e.jsxs("div",{children:[e.jsxs("div",{className:"text-xs text-muted-foreground mb-1 flex items-center gap-1",children:[e.jsx(qe,{className:"h-3 w-3"}),"Lifetime Value"]}),e.jsx("div",{className:"text-lg font-semibold",children:oe(n.lifetimeValue)}),e.jsxs("div",{className:"text-[10px] text-muted-foreground",children:[n.totalVisits||0," visits · ",n.totalCalls||0," calls"]})]}),(p.length>0||n.preferredStaff||n.preferredDayOfWeek||n.preferredTimeOfDay)&&e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-muted-foreground mb-1",children:"Preferences"}),e.jsxs("div",{className:"space-y-1",children:[p.length>0&&e.jsxs("div",{className:"text-sm",children:[e.jsx("span",{className:"text-muted-foreground",children:"Services: "}
6),p.join(", ")]}),n.preferredStaff&&e.jsxs("div",{className:"text-sm",children:[e.jsx("span",{className:"text-muted-foreground",children:"Staff: "}),n.preferredStaff]}),(n.preferredDayOfWeek||n.preferredTimeOfDay)&&e.jsxs("div",{className:"text-sm",children:[e.jsx("span",{className:"text-muted-foreground",children:"Prefers: "}),[n.preferredDayOfWeek,n.preferredTimeOfDay].filter(Boolean).join(", ")]})]})]}),n.averageVisitFrequencyDays!=null&&n.averageVisitFrequencyDays>0&&e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-muted-foreground mb-1",children:"Visit Frequency"}),e.jsxs("div",{className:"text-sm",children:["Every ~",Math.round(n.averageVisitFrequencyDays)," days",n.daysSinceLastVisit!=null&&e.jsxs("span",{className:"text-muted-foreground",children:[" · Last visit ",n.daysSinceLastVisit," days ago"]})]})]}),j.length>0&&e.jsxs("div",{children:[e.jsxs("div",{className:"text-xs text-muted-foreground mb-1 flex items-center gap-1",children:[e.jsx(fe,{className:"h-3 w-3"}),"Risk Factors"]}),e.jsx("ul",{className:"text-xs space-y-0.5",children:j.map((m,h)=>e.jsxs("li",{className:"text-red-600 dark:text-red-400",children:["• ",m]},h))})]}),f.length>0&&e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-muted-foreground mb-1",children:"AI Tags"}),e.jsx("div",{className:"flex flex-wrap gap-1",children:f.map((m,h)=>e.jsx(q,{variant:"outline",className:"text-[10px]",children:m},h))})]})]})]})}function Ws({entry:s,navigate:d}){const n=Ls[s.type]||ce,p=zs[s.type]||"",f=Rs[s.type]||"",j=!!f;let m=s.title,h=null;if(s.type==="call"){const r=s.intentDetected||s.intent;if(r&&r!=="ai-call"?m=`Phone Call — ${r.replace(/_/g," ").replace(/\b\w/g,o=>o.toUpperCase())}`:m="Phone Call",s.summary&&(h=s.summary),s.callDuration){const o=Os(s.callDuration);h=h?`${o} — ${h}`:o}}if(s.type==="sms"){const r=s.transcript||s.preview||"";m="SMS Message",r&&r.length>2&&(h=r.length>100?r.substring(0,100)+"...":r)}if(s.type==="appointment"){const r=s.serviceName||s.service,o=s.staffName||s.staff;r?(m=r,o&&(m+=` with ${o}`)):m=(m||"Appointment").replace(/\s*\[.*?\]\s*/g,"").trim()||"Appointment",s.date&&(h=As(s.date))}return e.jsxs("div",{className:`flex items-start gap-3 p-3 rounded-lg transition-colors ${j?"hover:bg-muted/50 cursor-pointer":""}`,onClick:()=>j&&d(`${f}/${s.id}`),children:[e.jsx("div",{className:`w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 ${p}`,children:e.jsx(n,{className:"h-4 w-4"})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"text-sm font-medium truncate",children:m}),e.jsx(Vs,{status:s.status})]}),h&&e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5 line-clamp-2",children:h}),e.jsxs("div",{className:"flex items-center gap-2 mt-0.5 text-xs text-muted-foreground",children:[e.jsx("span",{children:Ve(s.date)}),s.amount!=null&&s.amount>0&&e.jsxs(e.Fragment,{children:[e.jsx("span",{children:"·"}),e.jsx("span",{children:oe(s.amount)})]})]})]})]})}function pa(){var he;const s=rs(),[,d]=we(),n=s.id,p=n==="new",[f,j]=T.useState(!1),[m,h]=T.useState(!1),[r,o]=T.useState(""),{toast:l}=ae(),y=O({mutationFn:async x=>(await $("POST",`/api/customers/${n}/send-sms`,{message:x})).json(),onSuccess:()=>{l({title:"SMS sent",description:"Message delivered successfully."}),h(!1),o("")},onError:()=>{l({title:"Failed to send",description:"Could not send SMS. Please try again.",variant:"destructive"})}}),{data:a,isLoading:M,error:i}=z({queryKey:[`/api/customers/${n}`],enabled:!p&&!!n}),{data:u,isLoading:c}=z({queryKey:[`/api/customers/${n}/activity`],enabled:!p&&!!n}),{data:K,isError:te}=z({queryKey:[`/api/customers/${n}/insights`],enabled:!p&&!!n}),{data:t=[],isLoading:F}=z({queryKey:[`/api/customers/${n}/timeline`],enabled:!p&&!!n}),{data:C}=z({queryKey:["/api/business"]}),V=!!n&&!p&&ls(C==null?void 0:C.industry),Ue=!!n&&!p&&ds(C==null?void 0:C.industry),Be=cs(C==null?void 0:C.industry).equipmentLabel??"Equipment",[Q,xe]=T.useState("activity");if(p)return e.jsxs(H,{title:"New Customer",children:[e.jsx(W,{title:"Add New Customer",breadcrumbs:[{label:"Dashboard",href:"/"},{label:"Customers",href:"/customers"},{label:"New Customer",href:"#"}]}),e.jsx("div",{className:"mt-6",children:e.jsx(Ce,{customer:void 0,isEdit:!1})})]});if(M)return e.jsxs(H,{title:"Customer Details",children:[e.jsx(W,{title:"Loading Customer...",breadcrumbs:[{label:"Dashboard",href:"/"},{label:"Customers",href:"/customers"},{label:"Loading...",href:"#"}]}),e.jsxs("div",{className:"mt-6 space-y-6",children:[e.jsx(os,{}),e.jsx(ms,{})]})]});if(i)return e.jsxs(H,{title:"Customer Details",children:[e.jsx(W,{title:"Customer Not Found",breadcrumbs:[{label:"Dashboard",href:"/"},{label:"Customers",href:"/customers"},{label:"Not Found",href:"#"}]}),e.jsx("div",{className:"bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-md p-4 text-red-800 dark:text-red-300 mt-4",children:"We couldn't find the customer you're looking for."}),e.jsx("div",{className:"mt-4",children:e.jsx(g,{onClick:()=>d("/customers"),children:"Return to Customers"})})]});const U=(u==null?void 0:u.stats)||{};return e.jsxs(H,{title:"Customer Details",children:[e.jsx(W,{title:`${a==null?void 0:a.firstName} ${a==null?void 0:a.lastName}`,breadcrumbs:[{label:"Dashboard",href:"/"},{label:"Customers",href:"/customers"},{label:`${a==null?void 0:a.firstName} ${a==null?void 0:a.lastName}`,href:"#"}],actions:e.jsxs(g,{size:"sm",onClick:()=>j(!0),children:[e.jsx(Ds,{className:"h-4 w-4 mr-1"}),"Edit"]})}),e.jsxs("div",{className:"flex flex-wrap gap-2 mt-4",children:[(a==null?void 0:a.phone)&&e.jsxs(g,{size:"sm",variant:"outline",onClick:()=>h(!0),children:[e.jsx(xs,{className:"h-3.5 w-3.5 mr-1.5"}),"Send SMS"]}),e.jsxs(g,{size:"sm",variant:"outline",onClick:()=>d("/appointments"),children:[e.jsx(B,{className:"h-3.5 w-3.5 mr-1.5"}),"Book Appointment"]}),e.jsxs(g,{size:"sm",variant:"outline",onClick:()=>d("/invoices/create"),children:[e.jsx(hs,{className:"h-3.5 w-3.5 mr-1.5"}),"Create Invoice"]}
6),(a==null?void 0:a.email)&&e.jsxs(g,{size:"sm",variant:"outline",onClick:()=>window.open(`mailto:${a.email}`,"_self"),children:[e.jsx(ne,{className:"h-3.5 w-3.5 mr-1.5"}),"Send Email"]})]}),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-3 mt-4",children:[e.jsx(v,{children:e.jsxs(b,{className:"p-4",children:[e.jsxs("div",{className:"flex items-center gap-2 text-muted-foreground text-xs mb-1",children:[e.jsx(ce,{className:"h-3.5 w-3.5"}),"Total Jobs"]}),e.jsx("p",{className:"text-2xl font-bold",children:U.totalJobs||0})]})}),e.jsx(v,{children:e.jsxs(b,{className:"p-4",children:[e.jsxs("div",{className:"flex items-center gap-2 text-muted-foreground text-xs mb-1",children:[e.jsx(qe,{className:"h-3.5 w-3.5"}),"Total Spent"]}),e.jsx("p",{className:"text-2xl font-bold",children:oe(U.totalSpent||0)})]})}),e.jsx(v,{children:e.jsxs(b,{className:"p-4",children:[e.jsxs("div",{className:"flex items-center gap-2 text-muted-foreground text-xs mb-1",children:[e.jsx(us,{className:"h-3.5 w-3.5"}),"Last Visit"]}),e.jsx("p",{className:"text-lg font-bold truncate",children:U.lastVisit?Ve(U.lastVisit):"—"})]})}),e.jsx(v,{children:e.jsxs(b,{className:"p-4",children:[e.jsxs("div",{className:"flex items-center gap-2 text-muted-foreground text-xs mb-1",children:[e.jsx($e,{className:"h-3.5 w-3.5"}),"Open Invoices"]}),e.jsx("p",{className:"text-2xl font-bold",children:U.activeInvoices||0})]})})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-6 mt-6",children:[e.jsxs("div",{className:"md:col-span-1 space-y-4",children:[e.jsxs(v,{children:[e.jsx(P,{className:"pb-3",children:e.jsx(A,{className:"text-base",children:"Contact Information"})}),e.jsxs(b,{className:"space-y-3",children:[(a==null?void 0:a.phone)&&e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(ps,{className:"h-4 w-4 text-muted-foreground flex-shrink-0"}),e.jsx("span",{className:"text-sm",children:je(a.phone)})]}),(a==null?void 0:a.email)&&e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(ne,{className:"h-4 w-4 text-muted-foreground flex-shrink-0"}),e.jsx("span",{className:"text-sm truncate",children:a.email})]}),((a==null?void 0:a.address)||(a==null?void 0:a.city))&&e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(De,{className:"h-4 w-4 text-muted-foreground flex-shrink-0 mt-0.5"}),e.jsxs("div",{className:"text-sm",children:[a.address&&e.jsx("div",{children:a.address}),a.city&&e.jsxs("div",{className:"text-muted-foreground",children:[a.city,a.state&&`, ${a.state}`," ",a.zipcode||a.zip]})]})]}),(a==null?void 0:a.birthday)&&e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(Ts,{className:"h-4 w-4 text-muted-foreground flex-shrink-0"}),e.jsx("span",{className:"text-sm",children:a.birthday})]}),(a==null?void 0:a.notes)&&e.jsxs("div",{className:"flex items-start gap-3 pt-2 border-t",children:[e.jsx(Is,{className:"h-4 w-4 text-muted-foreground flex-shrink-0 mt-0.5"}),e.jsx("p",{className:"text-sm text-muted-foreground whitespace-pre-line",children:a.notes})]}),e.jsxs("div",{className:"pt-2 border-t space-y-1.5",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-xs text-muted-foreground",children:"SMS Opt-In"}),a!=null&&a.smsOptIn?e.jsxs("span",{className:"flex items-center gap-1 text-xs text-green-600",children:[e.jsx(ge,{className:"h-3 w-3"})," Yes"]}):e.jsxs("span",{className:"flex items-center gap-1 text-xs text-muted-foreground",children:[e.jsx(ye,{className:"h-3 w-3"})," No"]})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-xs text-muted-foreground",children:"Marketing Opt-In"}),a!=null&&a.marketingOptIn?e.jsxs("span",{className:"flex items-center gap-1 text-xs text-green-600",children:[e.jsx(ge,{className:"h-3 w-3"})," Yes"]}):e.jsxs("span",{className:"flex items-center gap-1 text-xs text-muted-foreground",children:[e.jsx(ye,{className:"h-3 w-3"})," No"]})]})]}),(a==null?void 0:a.source)&&e.jsxs("div",{className:"pt-2 border-t",children:[e.jsx("div",{className:"text-xs text-muted-foreground mb-1",children:"Created via"}),e.jsx("span",{className:"text-sm capitalize",children:a.source.replace(/_/g," ")})]}),e.jsxs("div",{className:"pt-3 border-t",children:[e.jsxs("div",{className:"flex items-center gap-2 text-muted-foreground text-xs mb-2",children:[e.jsx(Ke,{className:"h-3.5 w-3.5"}),"Tags"]}),e.jsx(Us,{customerId:parseInt(n),tags:(()=>{try{return a!=null&&a.tags?JSON.parse(a.tags):[]}catch{return[]}})()})]})]})]}),e.jsx(Hs,{insights:K,isError:te}),V&&e.jsx(Ps,{customerId:Number(n),label:Be}),Ue&&e.jsx(Fs,{customerId:Number(n)})]}),e.jsx("div",{className:"md:col-span-2 space-y-0",children:e.jsxs(v,{children:[e.jsx(P,{className:"pb-3",children:e.jsxs("div",{className:"flex items-center gap-1 border-b",children:[e.jsx("button",{onClick:()=>xe("activity"),className:`px-3 py-2 text-sm font-medium border-b-2 transition-colors ${Q==="activity"?"border-primary text-primary":"border-transparent text-muted-foreground hover:text-foreground"}`,children:"Activity"}),e.jsx("button",{onClick:()=>xe("communications"),className:`px-3 py-2 text-sm font-medium border-b-2 transition-colors ${Q==="communications"?"border-primary text-primary":"border-transparent text-muted-foreground hover:text-foreground"}`,children:"Communications"})]})}),e.jsxs(b,{children:[Q==="activity"&&e.jsx(e.Fragment,{children:c?e.jsx("div",{className:"space-y-3",children:Array.from({length:4}).map((x,L)=>e.jsxs("div",{className:"animate-pulse flex items-center gap-3 p-3",children:[e.jsx("div",{className:"w-8 h-8 rounded-full bg-muted"}),e.jsxs("div",{className:"flex-1 space-y-2",children:[e.jsx("div",{className:"h-4 bg-muted rounded w-1/3"}),e.jsx("div",{className:"h-3 bg-muted rounded w-1/4"})]})]},L))}):((he=u==null?void 0:u.timeline)==null?void 0:he.length)>
60?e.jsx("div",{className:"space-y-1",children:u.timeline.map((x,L)=>e.jsx(Ws,{entry:x,navigate:d},`${x.type}-${x.id}-${L}`))}):e.jsxs("div",{className:"text-center py-8 text-muted-foreground",children:[e.jsx(js,{className:"h-8 w-8 mx-auto mb-2 opacity-50"}),e.jsx("p",{className:"text-sm",children:"No activity yet"}),e.jsx("p",{className:"text-xs mt-1",children:"Jobs, invoices, appointments, calls, and messages will appear here"})]})}),Q==="communications"&&e.jsx(e.Fragment,{children:F?e.jsx("div",{className:"space-y-3",children:Array.from({length:4}).map((x,L)=>e.jsxs("div",{className:"animate-pulse flex items-center gap-3 p-3",children:[e.jsx("div",{className:"w-8 h-8 rounded-full bg-muted"}),e.jsxs("div",{className:"flex-1 space-y-2",children:[e.jsx("div",{className:"h-4 bg-muted rounded w-1/3"}),e.jsx("div",{className:"h-3 bg-muted rounded w-1/4"})]})]},L))}):t.length>0?e.jsxs("div",{className:"relative pl-6",children:[e.jsx("div",{className:"absolute left-[11px] top-2 bottom-2 w-0.5 bg-border"}),e.jsx("div",{className:"space-y-0",children:t.map((x,L)=>{const Qe={call:Me,sms:G,email:ne,appointment:B,agent:J},_e={call:"text-blue-500 bg-blue-50 dark:bg-blue-900/20",sms:"text-teal-500 bg-teal-50 dark:bg-teal-900/20",email:"text-purple-500 bg-purple-50 dark:bg-purple-900/20",appointment:"text-indigo-500 bg-indigo-50 dark:bg-indigo-900/20",agent:"text-amber-500 bg-amber-50 dark:bg-amber-900/20"},He=Qe[x.type]||G,We=_e[x.type]||"text-gray-500 bg-gray-50";return e.jsxs("div",{className:"relative flex items-start gap-3 pb-4",children:[e.jsx("div",{className:`relative z-10 -ml-6 w-6 h-6 rounded-full flex items-center justify-center flex-shrink-0 ${We}`,children:e.jsx(He,{className:"h-3 w-3"})}),e.jsxs("div",{className:"flex-1 min-w-0 pt-0.5",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"text-sm font-medium truncate",children:x.title}),x.status&&e.jsx(q,{className:`text-[10px] ${x.status==="sent"||x.status==="delivered"||x.status==="completed"||x.status==="confirmed"?"bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400":x.status==="failed"?"bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400":"bg-gray-100 text-gray-600 dark:bg-gray-800/30 dark:text-gray-400"}`,children:x.status.replace(/_/g," ")})]}),x.details&&e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5 line-clamp-2",children:x.details}),e.jsxs("div",{className:"text-[11px] text-muted-foreground mt-1",children:[x.timestamp?new Date(x.timestamp).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric",hour:"numeric",minute:"2-digit"}):"",x.channel&&e.jsx("span",{className:"ml-2 capitalize",children:x.channel})]})]})]},`${x.type}-${x.id}-${L}`)})})]}):e.jsxs("div",{className:"text-center py-8 text-muted-foreground",children:[e.jsx(G,{className:"h-8 w-8 mx-auto mb-2 opacity-50"}),e.jsx("p",{className:"text-sm",children:"No communications yet"}),e.jsx("p",{className:"text-xs mt-1",children:"SMS, emails, calls, and AI agent interactions will appear here"})]})})]})]})})]}),e.jsx(Y,{open:f,onOpenChange:j,children:e.jsxs(X,{className:"max-w-2xl max-h-[90vh] overflow-y-auto",children:[e.jsx(Z,{children:e.jsx(ee,{children:"Edit Customer"})}),e.jsx(Ce,{customer:a,isEdit:!0,onSuccess:()=>j(!1)})]})}),e.jsx(Y,{open:m,onOpenChange:x=>{h(x),x||o("")},children:e.jsxs(X,{className:"max-w-md",children:[e.jsx(Z,{children:e.jsxs(ee,{children:["Send SMS to ",a==null?void 0:a.firstName]})}),e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"text-sm text-muted-foreground",children:["To: ",a!=null&&a.phone?je(a.phone):""]}),e.jsx(me,{placeholder:"Type your message...",value:r,onChange:x=>o(x.target.value),rows:4,maxLength:1600}),e.jsxs("div",{className:"text-xs text-muted-foreground text-right",children:[r.length,"/1600"]})]}),e.jsxs(de,{children:[e.jsx(g,{variant:"outline",onClick:()=>{h(!1),o("")},children:"Cancel"}),e.jsx(g,{onClick:()=>y.mutate(r),disabled:!r.trim()||y.isPending,children:y.isPending?"Sending...":"Send SMS"})]})]})})]})}export{pa 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.