PageSourceSearch

https://splashiq.ai/assets/setup-DqZpK3GD.js

js splashiq.ai collected 2026-10-05 12:43:31 UTC 23,068 bytes, 1 lines download raw bytes

1import{g as G,d as ee,r,s as m,a as se,U as te,H as ae,j as e,L as z,B as q,T as re,A as ie,aM as ne,f as oe,I as A,h as J,t as g}from"./index-CzAkNt2W.js";import{R as ce}from"./RequireRole-DhUlFC_T.js";import{L as j}from"./label-BwWVuV93.js";import{C as le}from"./checkbox-G3X53UcF.js";import{T as de}from"./textarea-CMw1Ny2O.js";import{C as me,S as F,a as L,b as B,c as V,d as U}from"./select-CgG1LT6p.js";import{F as ue,C as he}from"./CsvImportDialog-DWnK_gyX.js";import{U as Q}from"./user-plus-oIrmPAoZ.js";import{D as pe}from"./dollar-sign-BZgSS9FC.js";import{C as fe}from"./circle-check-gM2QolJ6.js";import{T as X}from"./trash-2-Bb14b2qT.js";import{P as Y}from"./plus-B3ftHR68.js";import{D as xe}from"./download-C5tX2Uho.js";import"./dialog-DFazxlVc.js";import"./upload-C3gfurJP.js";import"./circle-alert-GZwz9Lsu.js";const ge=[["path",{d:"M10.1 2.182a10 10 0 0 1 3.8 0",key:"5ilxe3"}],["path",{d:"M13.9 21.818a10 10 0 0 1-3.8 0",key:"11zvb9"}],["path",{d:"M17.609 3.721a10 10 0 0 1 2.69 2.7",key:"1iw5b2"}],["path",{d:"M2.182 13.9a10 10 0 0 1 0-3.8",key:"c0bmvh"}],["path",{d:"M20.279 17.609a10 10 0 0 1-2.7 2.69",key:"1ruxm7"}],["path",{d:"M21.818 10.1a10 10 0 0 1 0 3.8",key:"qkgqxc"}],["path",{d:"M3.721 6.391a10 10 0 0 1 2.7-2.69",key:"1mcia2"}],["path",{d:"M6.391 20.279a10 10 0 0 1-2.69-2.7",key:"1fvljs"}]],je=G("circle-dashed",ge);const ve=[["circle",{cx:"6",cy:"19",r:"3",key:"1kj8tv"}],["path",{d:"M9 19h8.5a3.5 3.5 0 0 0 0-7h-11a3.5 3.5 0 0 1 0-7H15",key:"1d8sl"}],["circle",{cx:"18",cy:"5",r:"3",key:"gq8acd"}]],ye=G("route",ve),D=[{key:"company",title:"Company basics",subtitle:"Name, contact info, brand color",icon:se},{key:"office",title:"Add office staff",subtitle:"Invite dispatchers, billing & admin teammates",icon:te},{key:"field",title:"Add field technicians",subtitle:"Invite the crew running your routes",icon:ae},{key:"customers",title:"Add customers & properties",subtitle:"Enter manually or upload a CSV",icon:Q},{key:"routes",title:"Create a route",subtitle:"Schedule recurring weekly visits",icon:ye},{key:"rates",title:"Set your rates",subtitle:"Labor rate & default billing assumptions",icon:pe}],W=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];function be({mode:s="onboarding"}){const c=ee(),[t,_]=r.useState(null),[v,x]=r.useState(!0),[y,u]=r.useState("company"),[d,b]=r.useState(()=>O()),[N,l]=r.useState({office:0,field:0,customers:0,properties:0,schedules:0}),p=r.useCallback(async()=>{x(!0);const a=(await m.auth.getUser()).data.user;if(!a){x(!1);return}const{data:w}=await m.from("profiles").select("company_id, companies:company_id ( id, name, contact_email, contact_phone, brand_color, labor_rate_cents )").eq("id",a.id).maybeSingle(),h=w?.companies??null;if(!h){x(!1);return}_(h);const[{count:f},{count:k},{count:I},{data:E}]=await Promise.all([m.from("customers").select("id",{count:"exact",head:!0}).eq("company_id",h.id),m.from("properties").select("id",{count:"exact",head:!0}).eq("company_id",h.id),m.from("recurring_schedules").select("id",{count:"exact",head:!0}).eq("company_id",h.id),m.from("profiles").select("id").eq("company_id",h.id)]),i=(E??[]).map(C=>C.id);let S=0,T=0;if(i.length){const{data:C}=await m.from("user_roles").select("user_id, role").in("user_id",i),R=new Map;(C??[]).forEach(M=>
1{const H=R.get(M.user_id)??new Set;H.add(M.role),R.set(M.user_id,H)}),R.forEach(M=>{M.has("office")&&S++,M.has("technician")&&T++})}l({office:S,field:T,customers:f??0,properties:k??0,schedules:I??0});const $=Ce(h.id);if(b({company:$.company||!!(h.name&&h.contact_email),office:$.office||S>0,field:$.field||T>0,customers:$.customers||(f??0)>0,routes:$.routes||(I??0)>0,rates:$.rates||h.labor_rate_cents!==12500}),s==="onboarding"){const C=D.find(R=>!$[R.key]);u(C?.key??null)}x(!1)},[s]);r.useEffect(()=>{p()},[p]);function o(a,w=!0){if(t&&(b(h=>{const f={...h,[a]:w};return qe(t.id,f),f}),w)){const h=D.findIndex(k=>k.key===a),f=D.slice(h+1).find(k=>!d[k.key]);u(f?.key??null)}}const P=r.useMemo(()=>D.every(a=>d[a.key]),[d]);if(v)return e.jsx("div",{className:"p-8 text-muted-foreground",children:"Loading setup…"});if(!t)return e.jsxs("div",{className:"p-8 max-w-md mx-auto text-center",children:[e.jsx("p",{className:"text-muted-foreground",children:"No workspace yet."}),e.jsx(z,{to:"/onboarding",children:e.jsx(q,{className:"mt-4",children:"Create workspace"})})]});const n=D.filter(a=>d[a.key]).length;return e.jsxs("div",{className:"mx-auto max-w-3xl p-4 md:p-8",children:[e.jsxs("header",{className:"mb-6",children:[e.jsxs("h1",{className:"font-display text-3xl font-bold flex items-center gap-2",children:[e.jsx(re,{className:"h-7 w-7 text-primary"}),s==="onboarding"?"Finish setting up SplashIQ":"Workspace setup"]}),e.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:s==="onboarding"?"Knock out as much as you can now — skip anything and come back later from Settings → Setup.":"Edit your workspace people, customers, routes, and rates."}),e.jsxs("div",{className:"mt-4 rounded-xl border border-border bg-card p-4",children:[e.jsxs("div",{className:"flex items-center justify-between text-xs mb-2",children:[e.jsxs("span",{className:"font-medium",children:[n," of ",D.length," complete"]}),P&&s==="onboarding"&&e.jsxs(q,{size:"sm",onClick:()=>c({to:"/dashboard"}),className:"gap-1.5",children:["Go to dashboard ",e.jsx(ie,{className:"h-3.5 w-3.5"})]})]}),e.jsx("div",{className:"h-2 rounded-full bg-muted overflow-hidden",children:e.jsx("div",{className:"h-full bg-primary transition-all",style:{width:`${n/D.length*100}%`}})})]})]}),e.jsx("div",{className:"space-y-3",children:D.map(a=>{const w=y===a.key,h=d[a.key],f=a.icon;return e.jsxs("section",{className:`rounded-xl border bg-card overflow-hidden transition ${h?"border-emerald-300 dark:border-emerald-700":"border-border"}`,children:[e.jsxs("button",{type:"button",onClick:()=>u(w?null:a.key),className:"w-full flex items-center gap-3 p-4 text-left hover:bg-muted/30",children:[h?e.jsx(fe,{className:"h-6 w-6 text-emerald-500 shrink-0"}):e.jsx(je,{className:"h-6 w-6 text-muted-foreground shrink-0"}),e.jsx("div",{className:"h-10 w-10 rounded-lg bg-primary/10 grid place-items-center shrink-0",children:e.jsx(f,{className:"h-5 w-5 text-primary"})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"font-semibold",children:a.title}),e.jsx("div",{className:"text-xs text-muted-foreground truncate",children:_e(a.key,a.subtitle,N)})]}),w?e.jsx(me,{className:"h-4 w-4 text-muted-foreground"}):e.jsx(ne,{className:"h-4 w-4 text-muted-foreground"})]}),w&&e.jsxs("div",{className:"border-t border-border p-5",children:[a.key==="company"&&e.jsx(Ne,{company:t,onSaved:()=>{p(),o("company")}}),a.key==="office"&&e.jsx(K,{role:"office",companyId:t.id,onChanged:()=>{p()}}),a.key==="field"&&e.jsx(K,{role:"technician",companyId:t.id,onChanged:()=>{p()}}),a.key==="customers"&&e.jsx(we,{companyId:t.id,onChanged:()=>{p()}}),a.key==="routes"&&e.jsx(ke,{companyId:t.id,onChanged:()=>{p()}}),a.key==="rates"&&e.jsx(Se,{company:t,onSaved:()=>{p(),o("rates")}}),e.jsxs("div",{className:"mt-5 flex flex-wrap items-center justify-between gap-2 border-t border-border pt-4",children:[e.jsx(q,{variant:"ghost",size:"sm",onClick:()=>o(a.key,!1),className:"text-muted-foreground",children:"Reset step"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(q,{variant:"outline",size:"sm",onClick:()=>{u(null),o(a.key,!1)},children:"Skip for now"}),e.jsxs(q,{size:"sm",onClick:()=>o(a.key,!0),className:"gap-1.5",children:[e.jsx(oe,{className:"h-4 w-4"})," Mark complete"]})]})]})]})]},a.key)})}),s==="onboarding"&&e.jsx("div",{className:"mt-8 text-center",children:e.jsx(z,{to:"/dashboard",className:"text-sm text-muted-foreground hover:text-foreground underline-offset-4 hover:underline",children:"Skip everything and go to dashboard →"})})]})}function _e(s,c,t){return s==="office"?t.office?`${t.office} office teammate${t.office===1?"":"s"} on the team`:c:s==="field"?t.field?`${t.field} field tech${t.field===1?"":"s"} on the crew`:c:s==="customers"?t.customers?`${t.customers} customer${t.customers===1?"":"s"} · ${t.properties} propert${t.properties===1?"y":"ies"}`:c:s==="routes"&&t.schedules?`${t.schedules} recurring schedule${t.schedules===1?"":"s"} configured`:c}function Ne({company:s,onSaved:c}){const[t,_]=r.useState(s.name),[v,x]=r.useState(s.contact_email??""),[y,u]=r.useState(s.contact_phone??""),[d,b]=r.useState(s.brand_color??"#0ea5e9"),[N,l]=r.useState(!1);async function p(){l(!0);const{error:o}=await m.from("companies").update({name:t.trim(),contact_email:v.trim()||null,contact_phone:y.trim()||null,brand_color:d}).eq("id",s.id);if(l(!1),o)return g.error(o.message);g.success("Company details saved"),c()}return e.jsxs("div",{className:"grid sm:grid-cols-2 gap-4",children:[e.jsxs("div",{className:"sm:col-span-2 space-y-1.5",children:[e.jsx(j,{children:"Company name"}),e.jsx(A,{value:t,onChange:o=>_(o.target.value)})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(j,{children:"Contact email"}
1),e.jsx(A,{type:"email",value:v,onChange:o=>x(o.target.value),placeholder:"[email protected]"})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(j,{children:"Contact phone"}),e.jsx(A,{value:y,onChange:o=>u(o.target.value),placeholder:"(555) 123-4567"})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(j,{children:"Brand color"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(A,{type:"color",value:d,onChange:o=>b(o.target.value),className:"h-10 w-16 p-1"}),e.jsx(A,{value:d,onChange:o=>b(o.target.value),className:"flex-1"})]})]}),e.jsx("div",{className:"sm:col-span-2",children:e.jsx(q,{onClick:p,disabled:N,children:N?"Saving…":"Save company details"})})]})}function K({role:s,companyId:c,onChanged:t}){const[_,v]=r.useState([]),[x,y]=r.useState([]),[u,d]=r.useState(""),[b,N]=r.useState(!1),l=r.useCallback(async()=>{const{data:n}=await m.from("profiles").select("id, full_name").eq("company_id",c),a=(n??[]).map(f=>f.id);let w=[];if(a.length){const{data:f}=await m.from("user_roles").select("user_id, role").in("user_id",a),k=new Map;(f??[]).forEach(I=>
1{const E=k.get(I.user_id)??[];E.push(I.role),k.set(I.user_id,E)}),w=(n??[]).map(I=>({...I,roles:k.get(I.id)??[]})).filter(I=>I.roles.includes(s))}v(w);const{data:h}=await m.from("company_invites").select("id, email, roles, accepted_at, revoked_at").eq("company_id",c).order("created_at",{ascending:!1});y((h??[]).filter(f=>!f.accepted_at&&!f.revoked_at&&f.roles.includes(s)))},[c,s]);r.useEffect(()=>{l()},[l]);async function p(n){if(n.preventDefault(),!u.trim())return;N(!0);const{error:a}=await m.rpc("create_company_invite",{_email:u.trim(),_roles:[s]});if(N(!1),a)return g.error(a.message);g.success(`Invited ${u}`),d(""),await l(),t()}async function o(n){if(!confirm("Revoke this invite?"))return;const{error:a}=await m.rpc("revoke_company_invite",{_invite_id:n});if(a)return g.error(a.message);g.success("Invite revoked"),await l(),t()}const P=s==="office"?"office teammate":"field technician";return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("form",{onSubmit:p,className:"flex flex-wrap gap-2 items-end",children:[e.jsxs("div",{className:"flex-1 min-w-[220px] space-y-1.5",children:[e.jsxs(j,{children:["Invite ",P," by email"]}),e.jsx(A,{type:"email",placeholder:`new${s==="office"?"office":"tech"}@yourco.com`,value:u,onChange:n=>d(n.target.value)})]}),e.jsxs(q,{type:"submit",disabled:b||!u.trim(),className:"gap-1.5",children:[e.jsx(Q,{className:"h-4 w-4"})," Send invite"]})]}),_.length>0&&e.jsx("div",{className:"rounded-lg border border-border divide-y divide-border",children:_.map(n=>e.jsxs("div",{className:"p-3 flex items-center justify-between text-sm",children:[e.jsx("span",{children:n.full_name??"Unnamed teammate"}),e.jsx(J,{variant:"secondary",className:"capitalize",children:s==="technician"?"Field tech":"Office"})]},n.id))}),x.length>0&&e.jsx("div",{className:"rounded-lg border border-dashed border-border divide-y divide-border",children:x.map(n=>e.jsxs("div",{className:"p-3 flex items-center justify-between text-sm gap-2",children:[e.jsxs("span",{className:"truncate",children:[e.jsx(J,{variant:"outline",className:"mr-2",children:"Pending"}),n.email]}),e.jsx(q,{size:"sm",variant:"ghost",onClick:()=>o(n.id),children:e.jsx(X,{className:"h-3.5 w-3.5"})})]},n.id))}),_.length===0&&x.length===0&&e.jsxs("p",{className:"text-xs text-muted-foreground",children:["No one here yet."," ",s==="office"?"Office staff handle scheduling, billing, marketing.":"Field techs run routes and log visits."]})]})}function we({companyId:s,onChanged:c}){const[t,_]=r.useState(""),[v,x]=r.useState(""),[y,u]=r.useState(""),[d,b]=r.useState(""),[N,l]=r.useState(!1),[p,o]=r.useState(!1);async function P(){if(!t.trim())return g.error("Name required");l(!0);const{data:n,error:a}=await m.from("customers").insert({company_id:s,full_name:t.trim(),email:v.trim()||null,phone:y.trim()||null}).select("id").single();if(a||!n)return l(!1),g.error(a?.message??"Failed");d.trim()&&await m.from("properties").insert({company_id:s,customer_id:n.id,address:d.trim(),service_frequency:"weekly"}),l(!1),_(""),x(""),u(""),b(""),g.success("Customer added"),c()}return e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"text-sm font-semibold mb-1 flex items-center gap-2",children:[e.jsx(Y,{className:"h-4 w-4"})," Add one manually"]}),e.jsxs("div",{className:"grid sm:grid-cols-2 gap-3",children:[e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(j,{children:"Full name *"}),e.jsx(A,{value:t,onChange:n=>_(n.target.value),placeholder:"Jane Smith"})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(j,{children:"Email"}),e.jsx(A,{type:"email",value:v,onChange:n=>x(n.target.value)})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(j,{children:"Phone"}),e.jsx(A,{value:y,onChange:n=>u(n.target.value)})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(j,{children:"Service address (optional)"}),e.jsx(A,{value:d,onChange:n=>b(n.target.value),placeholder:"12 Pool Ln, Austin TX"})]})]}),e.jsx(q,{onClick:P,disabled:N,className:"mt-3",children:"Add customer"})]}),e.jsxs("div",{className:"rounded-lg border border-border bg-muted/20 p-4",children:[e.jsxs("div",{className:"text-sm font-semibold mb-1 flex items-center gap-2",children:[e.jsx(ue,{className:"h-4 w-4"})," Bulk upload via CSV"]}),e.jsxs("p",{className:"text-xs text-muted-foreground mb-3",children:["Already have your book of business? Download the pre-mapped template, fill it in, and upload. The same dialog supports a separate"," ",e.jsx("code",{className:"text-[10px]",children:"properties"})," sheet so you can link service addresses to each customer."]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsxs(q,{variant:"outline",size:"sm",onClick:()=>o(!0),className:"gap-1.5",children:[e.jsx(xe,{className:"h-4 w-4"})," Download template & upload CSV"]}),e.jsx(z,{to:"/customers",children:e.jsx(q,{variant:"ghost",size:"sm",children:"Open full Customers page →"})})]}),e.jsx(he,{open:p,onOpenChange:o,onImported:c}),e.jsxs("details",{className:"mt-4 text-xs text-muted-foreground",children:[e.jsx("summary",{className:"cursor-pointer font-medium text-foreground",children:"How to fill in the CSV"}),e.jsxs("div",{className:"mt-2 space-y-1",children:[e.jsxs("p",{children:[e.jsx("strong",{children:"Customers sheet:"})," required column ",e.jsx("code",{children:"full_name"}),". Optional:"," ",e.jsx("code",{children:"email"}),", ",e.jsx("code",{children:"phone"}),", ",e.jsx("code",{children:"billing_email"}),","," ",e.jsx("code",{children:"billing_address"}),", ",e.jsx("code",{children:"notes"}),"."]}),e.jsxs("p",{children:[e.jsx("strong",{children:"Properties sheet:"})," required ",e.jsx("code",{children:"address"})," + either"," ",e.jsx("code",{children:"customer_email"})," or ",e.jsx("code",{children:"customer_name"})," (must match an existing customer). Optional: ",e.jsx("code",{children:"city"}),", ",e.jsx("code",{children:"state"}),", ",e.jsx("code",{children:"zip"}),","," ",e.jsx("code",{children:"pool_type"}),", ",e.jsx("code",{children:"pool_size_gallons"}),", ",e.jsx("code",{children:"service_frequency"})," ","(weekly | biweekly | monthly | one_time), ",e.jsx("code",{children:"gate_code"}),","," ",e.jsx("code",{children:"key_location"}),", ",e.jsx("code",{children:"billing_rate_cents"})," (in cents, e.g. 12500 = $125)."]}),e.jsxs("p",{children:["Upload ",e.jsx("em",{children:"customers"})," first, then switch the toggle to ",e.jsx("em",{children:"properties"})," and upload that sheet so the linking works."]})]})]})]})]})}function ke({companyId:s,onChanged:c}){const[t,_]=r.useState([]),[v,x]=r.useState([]),[y,u]=r.useState([]),[d,b]=r.useState(""),[N,l]=r.useState("1"),[p,o]=r.useState("09:00"),[P,n]=r.useState("none"),[a,w]=r.useState(!1),[h,f]=r.useState(""),k=r.useCallback(async()=>{const{data:i}=await m.from("properties").select("id, address, customer_id, customers:customer_id ( full_name )").eq("company_id",s).limit(200);_((i??[]).map(C=>({id:C.id,address:C.address,customer_id:C.customer_id,customer_name:C.customers?.full_name})));const{data:S}=await m.from("profiles").select("id, full_name").eq("company_id",s),T=(S??[]).map(C=>C.id);if(T.length){const{data:C}=await m.from("user_roles").select("user_id, role").in("user_id",T),R=new Set((C??[]).filter(M=>M.role==="technician").map(M=>
1M.user_id));x((S??[]).filter(M=>R.has(M.id)))}else x([]);const{data:$}=await m.from("recurring_schedules").select("id, property_id, day_of_week, time_of_day, technician_id").eq("company_id",s).order("day_of_week");u($??[])},[s]);r.useEffect(()=>{k()},[k]);async function I(){if(!d)return g.error("Pick a property first");w(!0);const{error:i}=await m.from("recurring_schedules").insert({company_id:s,property_id:d,day_of_week:Number(N),time_of_day:`${p}:00`,technician_id:P==="none"?null:P,frequency:"weekly",start_date:new Date().toISOString().slice(0,10),active:!0});if(w(!1),i)return g.error(i.message);g.success("Recurring visit scheduled"),b(""),await k(),c()}async function E(i){if(!confirm("Remove this recurring visit?"))return;const{error:S}=await m.from("recurring_schedules").delete().eq("id",i);if(S)return g.error(S.message);await k(),c()}return t.length===0?e.jsx("div",{className:"rounded-lg border border-dashed border-border p-5 text-sm text-muted-foreground",children:"Add at least one customer with a service address first, then come back to build the route."}):e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{className:"grid sm:grid-cols-2 gap-3",children:[e.jsxs("div",{className:"sm:col-span-2 space-y-1.5",children:[e.jsx(j,{children:"Property to visit"}),e.jsxs(F,{value:d,onValueChange:b,children:[e.jsx(L,{children:e.jsx(B,{placeholder:"Choose a property…"})}),e.jsx(V,{children:t.map(i=>e.jsxs(U,{value:i.id,children:[i.address,i.customer_name?` — ${i.customer_name}`:""]},i.id))})]})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(j,{children:"Day of week"}),e.jsxs(F,{value:N,onValueChange:l,children:[e.jsx(L,{children:e.jsx(B,{})}),e.jsx(V,{children:W.map((i,S)=>e.jsx(U,{value:String(S),children:i},S))})]})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(j,{children:"Time"}),e.jsx(A,{type:"time",value:p,onChange:i=>o(i.target.value)})]}),e.jsxs("div",{className:"sm:col-span-2 space-y-1.5",children:[e.jsx(j,{children:"Assign to technician (optional)"}),e.jsxs(F,{value:P,onValueChange:n,children:[e.jsx(L,{children:e.jsx(B,{placeholder:"Unassigned"})}),e.jsxs(V,{children:[e.jsx(U,{value:"none",children:"Unassigned (assign later)"}),v.map(i=>e.jsx(U,{value:i.id,children:i.full_name??"Tech"},i.id))]})]})]}),e.jsxs("div",{className:"sm:col-span-2 space-y-1.5",children:[e.jsx(j,{children:"Internal notes (optional)"}),e.jsx(de,{value:h,onChange:i=>f(i.target.value),placeholder:"Special instructions, parking, etc.",rows:2})]})]}),e.jsxs(q,{onClick:I,disabled:a||!d,className:"gap-1.5",children:[e.jsx(Y,{className:"h-4 w-4"})," Add to route"]}),y.length>0&&e.jsx("div",{className:"rounded-lg border border-border divide-y divide-border",children:y.map(i=>{const S=t.find($=>$.id===i.property_id),T=v.find($=>$.id===i.technician_id);return e.jsxs("div",{className:"p-3 flex items-center justify-between gap-2 text-sm",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"font-medium truncate",children:S?.address??"Property"}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:[W[i.day_of_week]," · ",i.time_of_day.slice(0,5)," ·"," ",T?.full_name??"Unassigned"]})]}),e.jsx(q,{size:"sm",variant:"ghost",onClick:()=>E(i.id),children:e.jsx(X,{className:"h-3.5 w-3.5"})})]},i.id)})}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:["Need to see the full week visually? Open the"," ",e.jsx(z,{to:"/schedule",className:"underline",children:"Schedule"})," ","page after setup."]})]})}function Se({company:s,onSaved:c}){const[t,_]=r.useState((s.labor_rate_cents/100).toFixed(2)),[v,x]=r.useState("125.00"),[y,u]=r.useState(!1),[d,b]=r.useState(!1);async function N(){const l=Math.round(Number(t)*100);if(!Number.isFinite(l)||l<0)return g.error("Invalid labor rate");u(!0);const{error:p}=await m.from("companies").update({labor_rate_cents:l}).eq("id",s.id);if(p)return u(!1),g.error(p.message);if(d){const o=Math.round(Number(v)*100);if(Number.isFinite(o)&&o>0){const{error:P}=await m.from("properties").update({billing_rate_cents:o}).eq("company_id",s.id).is("billing_rate_cents",null);P&&g.error(`Properties update failed: ${P.message}`)}}u(!1),g.success("Rates saved"),c()}return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"grid sm:grid-cols-2 gap-3",children:[e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(j,{children:"Labor rate ($/hour)"}),e.jsx(A,{value:t,onChange:l=>_(l.target.value),placeholder:"125.00"}),e.jsx("p",{className:"text-[11px] text-muted-foreground",children:"Used for estimates and work orders."})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(j,{children:"Default monthly service rate ($)"}
1),e.jsx(A,{value:v,onChange:l=>x(l.target.value),placeholder:"125.00"}),e.jsx("p",{className:"text-[11px] text-muted-foreground",children:"Applied to properties when you tick the box."})]})]}),e.jsxs("label",{className:"flex items-start gap-2 text-sm cursor-pointer",children:[e.jsx(le,{checked:d,onCheckedChange:l=>b(!!l)}),e.jsxs("span",{children:["Apply the default monthly rate to ",e.jsx("strong",{children:"all existing properties"})," that don't already have one."]})]}),e.jsx(q,{onClick:N,disabled:y,children:y?"Saving…":"Save rates"})]})}function O(){return{company:!1,office:!1,field:!1,customers:!1,routes:!1,rates:!1}}function Z(s){return`splashiq-setup-${s}`}function Ce(s){if(typeof window>"u")return O();try{const c=localStorage.getItem(Z(s));return c?{...O(),...JSON.parse(c)}:O()}catch{return O()}}function qe(s,c){if(!(typeof window>"u"))try{localStorage.setItem(Z(s),JSON.stringify(c))}catch{}}const He=()=>e.jsx(ce,{allowed:["owner"],children:e.jsx(be,{mode:"edit"})});export{He as component};

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.