1import{g as B,Y,Z as U,r as c,s as C,j as e,B as _,t as D,cr as Q,D as P,k as K,aL as q,ab as O,F as I,cs as Z,I as G,aw as X,M as J}from"./index-CzAkNt2W.js";import{L as T}from"./label-BwWVuV93.js";import{T as z}from"./textarea-CMw1Ny2O.js";import{D as R,b as F,c as M,d as H,f as V}from"./dialog-DFazxlVc.js";import{M as ee}from"./message-square-z9UYXooj.js";import{S as W}from"./send-CH5TfEm8.js";import{F as te}from"./flask-conical-kc3-ZtHR.js";import{R as se,L as re,C as ae,X as oe,Y as ne,T as de,b as E}from"./LineChart-DrdcZWj2.js";import{C as ie}from"./circle-check-gM2QolJ6.js";import{P as le}from"./printer-C3BfX3tt.js";import"./index-BeFjuTjb.js";const ce=[["path",{d:"M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z",key:"m61m77"}],["path",{d:"M17 14V2",key:"8ymqnk"}]],L=B("thumbs-down",ce);const me=[["path",{d:"M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z",key:"emmmcr"}],["path",{d:"M7 10v12",key:"1qc93n"}]],A=B("thumbs-up",me),xe=Y({method:"POST"}).handler(U("6c2b8a9c79feee201f7e0aa567bbabc7e96cb43858c868d668d577abbc018303"));function ue({token:x,visitId:l,brand:j}){const[f,N]=c.useState([]),[o,r]=c.useState(""),[n,b]=c.useState(""),[w,v]=c.useState(!1),a=c.useCallback(async()=>{const{data:m,error:S}=await C.rpc("portal_get_visit_messages",{_token:x,_visit_id:l});S||N((m??[]).map(h=>({id:h.id,sender_role:h.sender_role,sender_name:h.sender_name,body:h.body,created_at:h.created_at})))},[x,l]);c.useEffect(()=>{a()},[a]);async function u(m){m.preventDefault();const S=o.trim();if(!S)return;v(!0);const{error:h}=await C.rpc("portal_send_visit_message",{_token:x,_visit_id:l,_body:S,_sender_name:n||void 0});if(v(!1),h)return D.error(h.message);r(""),D.success("Sent to your pool tech"),await a()}return e.jsxs("div",{className:"mt-3 rounded-lg border border-border bg-background/60 p-3",children:[e.jsxs("div",{className:"text-xs font-semibold flex items-center gap-1.5",style:{color:j},children:[e.jsx(ee,{className:"h-3.5 w-3.5"})," Notes for your technician"]}),e.jsx("p",{className:"text-[11px] text-muted-foreground mt-0.5",children:`e.g. "Gate code 1234 â please make sure it's closed for the dogs."`}),e.jsx("div",{className:"mt-2 space-y-1.5 max-h-40 overflow-y-auto",children:f.map(m=>e.jsxs("div",{className:`rounded p-2 text-xs ${m.sender_role==="homeowner"?"bg-muted/50":"border border-border"}`,children:[e.jsxs("div",{className:"text-[10px] uppercase tracking-wide text-muted-foreground",children:[m.sender_role==="homeowner"?"You":m.sender_name??"Your tech"," ·"," ",new Date(m.created_at).toLocaleString([],{month:"short",day:"numeric",hour:"numeric",minute:"2-digit"})]}),e.jsx("div",{className:"mt-0.5 whitespace-pre-wrap",children:m.body})]},m.id))}),e.jsxs("form",{onSubmit:u,className:"mt-2 space-y-2",children:[!n&&e.jsx("input",{className:"w-full rounded-md border border-input bg-transparent px-2 py-1 text-xs",placeholder:"Your name (optional)",value:n,onChange:m=>b(m.target.value)}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("textarea",{rows:2,className:"flex-1 rounded-md border border-input bg-transparent px-2 py-1 text-xs",placeholder:"Leave a note for your pool techâ¦",value:o,onChange:m=>r(m.target.value)}),e.jsx(_,{type:"submit",size:"sm",disabled:w||!o.trim(),className:"gap-1.5 self-end",children:e.jsx(W,{className:"h-3 w-3"})})]})]})]})}const p=x=>`$${(x/100).toLocaleString(void 0,{minimumFractionDigits:2,maximumFractionDigits:2})}`;function $e(){const{token:x}=Q.useParams(),[l,j]=c.useState(void 0),[f,N]=c.useState({}),o=s=>s?/^https?:/i.test(s)?s:f[s]??null:null,r=()=>C.rpc("get_portal_data",{_token:x}).then(async({data:s})=>{j(s??null);const i=new Set;for(const t of s?.visits??[]){t.before_photo_url&&i.add(t.before_photo_url),t.after_photo_url&&i.add(t.after_photo_url);for(const y of t.photos??[])y.url&&i.add(y.url)}if(i.size!==0)try{const t=await xe({data:{token:x,refs:Array.from(i).slice(0,64)}});N(y=>({...y,...t.urls}))}catch{}});if(c.useEffect(()=>{r();const s=()=>{document.visibilityState==="visible"&&r()},i=window.setInterval(s,15e3);
1return document.addEventListener("visibilitychange",s),()=>{window.clearInterval(i),document.removeEventListener("visibilitychange",s)}},[x]),c.useEffect(()=>{if(l==null)return;const s=()=>{const t=window.location.hash.replace("#","");if(!t)return;const y=document.getElementById(t);y&&y.scrollIntoView({behavior:"smooth",block:"start"})},i=setTimeout(s,50);return window.addEventListener("hashchange",s),()=>{clearTimeout(i),window.removeEventListener("hashchange",s)}},[l]),c.useEffect(()=>{if(!l?.property.company_name)return;const s=document.title;return document.title=`${l.property.company_name} â Homeowner Portal`,()=>{document.title=s}},[l?.property.company_name]),l===void 0)return e.jsx("div",{className:"min-h-screen grid place-items-center text-muted-foreground",children:"Loading your pool reportâ¦"});if(l===null)return e.jsx("div",{className:"min-h-screen grid place-items-center p-6 text-center",children:e.jsxs("div",{children:[e.jsx("h1",{className:"font-display text-2xl font-bold",children:"Link not found"}),e.jsx("p",{className:"text-sm text-muted-foreground mt-2",children:"This homeowner link is invalid or has been revoked. Please contact your service provider."})]})});const{property:n,visits:b,readings:w,invoices:v,chat:a}=l,u=(v??[]).filter(s=>s.status!=="paid"),m=(v??[]).filter(s=>s.status==="paid"),S=u.filter(s=>s.status!=="draft").reduce((s,i)=>s+i.total_cents,0),h=b.filter(s=>s.status!=="completed"&&new Date(s.scheduled_for)>=new Date).sort((s,i)=>+new Date(s.scheduled_for)-+new Date(i.scheduled_for)),d=b.filter(s=>s.status==="completed"),k=[...w].reverse().map(s=>({t:new Date(s.recorded_at).toLocaleDateString(void 0,{month:"short",day:"numeric"}),pH:s.ph,Chlorine:s.chlorine})),g=n.brand_color||"#0ea5e9",$=n.chat_route_to==="office"?"the office":"your technician";return e.jsxs("div",{className:"min-h-screen bg-sky",children:[e.jsx("header",{className:"border-b border-border bg-card",children:e.jsx("div",{className:"max-w-4xl mx-auto px-6 py-5 flex items-center justify-between gap-4",children:e.jsxs("div",{className:"flex items-center gap-3",children:[n.logo_url?e.jsx("img",{src:n.logo_url,alt:n.company_name,className:"h-9 w-9 rounded-lg object-cover"}):e.jsx("div",{className:"h-9 w-9 rounded-lg grid place-items-center",style:{background:g},children:e.jsx(P,{className:"h-4 w-4 text-white"})}),e.jsxs("div",{children:[e.jsx("div",{className:"font-display font-bold text-lg",children:n.company_name}),e.jsx("div",{className:"text-xs text-muted-foreground",children:"Homeowner portal"})]})]})})}),e.jsxs("main",{className:"max-w-4xl mx-auto px-6 py-8",children:[e.jsxs("div",{className:"mb-4 rounded-xl border border-primary/30 bg-primary/5 p-4 flex items-start justify-between gap-3 flex-wrap",children:[e.jsxs("div",{className:"text-sm",children:[e.jsx("div",{className:"font-medium",children:"Create a free account to keep your pool's history."}),e.jsx("div",{className:"text-muted-foreground text-xs mt-0.5",children:"Your records follow you â even if you switch contractors. Review visits, quotes, and invoices in one place."})]}),e.jsx("a",{href:"/auth",className:"text-sm font-medium underline text-primary whitespace-nowrap",children:"Create account â"})]}),e.jsxs("div",{id:"overview",className:"rounded-2xl border border-border bg-card p-6 scroll-mt-24",children:[e.jsxs("div",{className:"text-xs uppercase tracking-wide text-muted-foreground",children:["Welcome, ",n.customer_name.split(" ")[0]]}),e.jsxs("h1",{className:"font-display text-3xl font-bold mt-1 flex items-center gap-2",children:[e.jsx(K,{className:"h-6 w-6",style:{color:g}})," ",n.address]}),e.jsxs("div",{className:"mt-1 text-sm text-muted-foreground",children:[[n.city,n.state].filter(Boolean).join(", ")," · ",n.pool_type??"pool"," · ",n.pool_size_gallons?`${n.pool_size_gallons.toLocaleString()} gal`:"â"," · ",n.service_frequency," service"]})]}),e.jsx("div",{id:"chat",children:e.jsx(he,{token:x,chat:a,brand:g,chatTo:$,onPosted:r})}),e.jsxs("section",{id:"visits",className:"mt-6 rounded-2xl border border-border bg-card p-6 scroll-mt-24",children:[e.jsxs("h2",{className:"font-display text-xl font-bold flex items-center gap-2",children:[e.jsx(q,{className:"h-5 w-5",style:{color:g}})," Upcoming visits"]}),h.length===0?e.jsx("p",{className:"mt-3 text-sm text-muted-foreground",children:"No upcoming visits scheduled."}):e.jsxs("div",{className:"mt-4 space-y-2",children:[h.slice(0,5).map(s=>e.jsxs("div",{className:"rounded-lg border border-border p-3 flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-sm",children:new Date(s.scheduled_for).toLocaleDateString(void 0,{weekday:"long",month:"long",day:"numeric"})}),e.jsx("div",{className:"text-xs text-muted-foreground",children:new Date(s.scheduled_for).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"})})]}),e.jsx("span",{className:"text-xs px-2 py-1 rounded-full bg-sky text-primary font-medium",children:"scheduled"})]},s.id)),h[0]&&e.jsx(ue,{token:x,visitId:h[0].id,brand:g})]})]}),k.length>1&&e.jsxs("section",{id:"water",className:"mt-6 rounded-2xl border border-border bg-card p-6 scroll-mt-24",children:[e.jsxs("h2",{className:"font-display text-xl font-bold flex items-center gap-2",children:[e.jsx(te,{className:"h-5 w-5",style:{color:g}})," Water trends"]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5",children:"pH and chlorine readings over time."}),e.jsx("div",{className:"mt-4 h-56",children:e.jsx(se,{width:"100%",height:"100%",children:e.jsxs(re,{data:k,children:[e.jsx(ae,{strokeDasharray:"3 3",opacity:.3}),e.jsx(oe,{dataKey:"t",fontSize:11}),e.jsx(ne,{fontSize:11}),e.jsx(de,{}),e.jsx(E,{type:"monotone",dataKey:"pH",stroke:g,strokeWidth:2,dot:{r:3}}),e.jsx(E,{type:"monotone",dataKey:"Chlorine",stroke:"#84cc16",strokeWidth:2,dot:{r:3}})]})})})]}),e.jsxs("section",{className:"mt-6 rounded-2xl border border-border bg-card p-6",children:[e.jsxs("h2",{className:"font-display text-xl font-bold flex items-center gap-2",children:[e.jsx(ie,{className:"h-5 w-5",style:{color:g}})," Service history"]}),d.length===0?e.jsx("p",{className:"mt-3 text-sm text-muted-foreground",children:"No completed visits yet."}):e.jsx("div",{className:"mt-4 space-y-4",children:d.slice(0,10).map(s=>e.jsxs("div",{className:"rounded-xl border border-border p-4",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx(O,{className:"h-3.5 w-3.5 text-muted-foreground"}),e.jsx("span",{className:"font-medium",children:new Date(s.completed_at??s.scheduled_for).toLocaleDateString(void 0,{weekday:"long",month:"long",day:"numeric",year:"numeric"})})]}),s.notes&&e.jsx("p",{className:"mt-2 text-sm text-muted-foreground",children:s.notes}),(s.before_photo_url||s.after_photo_url)&&e.jsx("div",{className:"mt-3 grid grid-cols-2 gap-3",children:["before","after"].map(i=>{const t=o(i==="before"?s.before_photo_url:s.after_photo_url);return t?e.jsxs("div",{children:[e.jsx("div",{className:"text-[10px] uppercase tracking-wide text-muted-foreground mb-1",children:i}),e.jsx("img",{src:t,alt:`${i} pool`,className:"w-full aspect-square object-cover rounded-lg border border-border",loading:"lazy"})]},i):e.jsx("div",{},i)})}),s.photos&&s.photos.length>0&&e.jsxs("div",{className:"mt-3",children:[e.jsx("div",{className:"text-[10px] uppercase tracking-wide text-muted-foreground mb-2",children:"Photos from this visit"}),e.jsx("div",{className:"grid grid-cols-2 sm:grid-cols-4 gap-2",children:s.photos.map((i,t)=>e.jsxs("a",{href:o(i.url)??"#",target:"_blank",rel:"noreferrer",className:"block group",children:[e.jsx("img",{src:o(i.url)??void 0,alt:i.caption??"Visit p
1hoto",className:"w-full aspect-square object-cover rounded-lg border border-border group-hover:opacity-90",loading:"lazy"}),i.caption&&e.jsx("div",{className:"text-[10px] text-muted-foreground mt-1 truncate",children:i.caption})]},t))})]}),s.service_reports&&s.service_reports.length>0&&e.jsx("div",{className:"mt-4 space-y-3",children:s.service_reports.map((i,t)=>e.jsxs("details",{className:"rounded-lg border border-border bg-muted/30 p-3",children:[e.jsxs("summary",{className:"cursor-pointer text-sm font-medium flex items-center gap-2",children:[e.jsx(I,{className:"h-4 w-4",style:{color:g}}),i.subject,i.sent_at&&e.jsxs("span",{className:"text-xs font-normal text-muted-foreground",children:["· sent ",new Date(i.sent_at).toLocaleDateString()]})]}),e.jsx("div",{className:"mt-3 whitespace-pre-wrap text-sm text-foreground/90",children:i.body_text})]},t))})]},s.id))})]}),e.jsx(fe,{token:x,brand:g,onChange:r}),e.jsx(ge,{token:x,brand:g,onChange:r}),e.jsx(pe,{token:x,invoices:[...u,...m],openCount:u.length,outstandingCents:S,brand:g,property:n}),e.jsxs("section",{id:"account",className:"mt-6 rounded-2xl border border-border bg-card p-6 scroll-mt-24",children:[e.jsxs("h2",{className:"font-display text-xl font-bold flex items-center gap-2",children:[e.jsx(P,{className:"h-5 w-5",style:{color:g}})," Account"]}),e.jsxs("div",{className:"mt-4 grid sm:grid-cols-2 gap-4 text-sm",children:[e.jsxs("div",{className:"rounded-lg border border-border p-4",children:[e.jsx("div",{className:"text-xs uppercase tracking-wide text-muted-foreground",children:"Name on file"}),e.jsx("div",{className:"mt-1 font-semibold",children:n.customer_name})]}),e.jsxs("div",{className:"rounded-lg border border-border p-4",children:[e.jsx("div",{className:"text-xs uppercase tracking-wide text-muted-foreground",children:"Service address"}),e.jsx("div",{className:"mt-1 font-semibold",children:n.address}),e.jsx("div",{className:"text-xs text-muted-foreground",children:[n.city,n.state].filter(Boolean).join(", ")})]}),e.jsxs("div",{className:"rounded-lg border border-border p-4 sm:col-span-2",children:[e.jsx("div",{className:"text-xs uppercase tracking-wide text-muted-foreground",children:"Notifications & saved payment methods"}),e.jsxs("div",{className:"mt-1 text-sm text-muted-foreground",children:["Email and SMS preferences plus saved cards on file land here next. For now, billing changes go through ",n.company_name,"."]})]})]})]}),e.jsx("footer",{className:"mt-8 text-center text-xs text-muted-foreground py-4",children:"Powered by SplashIQ"})]})]})}function pe({token:x,invoices:l,openCount:j,outstandingCents:f,brand:N,property:o}){const[r,n]=c.useState(null),[b,w]=c.useState(null),[v,a]=c.useState({}),u=c.useRef(null),m=!1;c.useEffect(()=>{},[x,m]);function S(){if(!u.current)return;const d=window.open("","_blank","width=800,height=900");if(!d){D.error("Pop-up blocked. Allow pop-ups to print.");return}d.document.write(`<!doctype html><html><head><title>Invoice ${r?.number??""}</title> 2 <style> 3 body{font-family:ui-sans-serif,system-ui,-apple-system,sans-serif;color:#0f172a;padding:32px;max-width:720px;margin:0 auto;} 4 h1{font-size:24px;margin:0 0 4px;} 5 .muted{color:#64748b;font-size:13px;} 6 .row{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;margin-bottom:24px;} 7 .total{font-size:28px;font-weight:700;text-align:right;} 8 table{width:100%;border-collapse:collapse;margin-top:16px;} 9 td,th{padding:10px 8px;text-align:left;border-bottom:1px solid #e2e8f0;font-size:14px;} 10 th{font-size:11px;text-transform:uppercase;letter-spacing:0.05em;color:#64748b;} 11 .right{text-align:right;} 12 .status{display:inline-block;padding:2px 10px;border-radius:9999px;font-size:11px;text-transform:uppercase;letter-spacing:0.05em;font-weight:600;background:#e2e8f0;} 13 .status.paid{background:#dcfce7;color:#166534;} 14 .notes{margin-top:24px;padding:12px;background:#f8fafc;border-radius:8px;font-size:13px;white-space:pre-wrap;} 15 </style></head><body>${u.current.innerHTML}</body></html>`),d.document.close(),d.focus(),setTimeout(()=>{d.print()},250)}function h(){if(!r)return;const d=`Invoice ${r.number} from ${o.company_name}`,k=[`Invoice #${r.number}`,`From: ${o.company_name}`,`Property: ${o.address}`,"",r.issued_on?`Issued: ${new Date(r.issued_on).toLocaleDateString()}`:"",r.due_on?`Due: ${new Date(r.due_on).toLocaleDateString()}`:"",r.paid_at?`Paid: ${new Date(r.paid_at).toLocaleDateString()}`:"","",`Subtotal: ${p(r.subtotal_cents)}`,`Tax: ${p(r.tax_cents)}`,`Total: ${p(r.total_cents)}`,`Status: ${r.status}`,r.notes?` 16Notes: 17${r.notes}
17`:""].filter(Boolean).join(` 18`);window.location.href=`mailto:?subject=${encodeURIComponent(d)}&body=${encodeURIComponent(k)}`}return e.jsxs("section",{id:"invoices",className:"mt-6 rounded-2xl border border-border bg-card p-6 scroll-mt-24",children:[e.jsx("div",{className:"flex items-start justify-between gap-3 flex-wrap",children:e.jsxs("div",{children:[e.jsxs("h2",{className:"font-display text-xl font-bold flex items-center gap-2",children:[e.jsx(X,{className:"h-5 w-5",style:{color:N}})," Invoices"]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5",children:l.length===0?e.jsx(e.Fragment,{children:"No invoices yet â you'll see them here once a work order is completed."}):f>0?e.jsxs(e.Fragment,{children:["You have ",e.jsx("span",{className:"font-semibold text-foreground",children:p(f)})," outstanding across ",j," invoice",j===1?"":"s","."]}):e.jsx(e.Fragment,{children:"All paid up â thanks!"})})]})}),e.jsx("div",{className:"mt-4 space-y-2",children:l.length===0?e.jsx("div",{className:"rounded-lg border border-dashed border-border p-6 text-center text-xs text-muted-foreground",children:"Invoices generated from your completed work orders will appear here."}):l.slice(0,20).map(d=>{const k=d.due_on&&d.status!=="paid"&&new Date(d.due_on)<new Date;return e.jsxs("button",{type:"button",onClick:()=>n(d),className:`w-full text-left rounded-lg border p-3 flex flex-wrap items-center justify-between gap-3 transition-colors hover:bg-muted/50 ${k?"border-destructive/40 bg-destructive/5":"border-border"}`,children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"font-medium text-sm",children:["Invoice #",d.number]}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:[d.issued_on?`Issued ${new Date(d.issued_on).toLocaleDateString()}`:"â",d.due_on?` · Due ${new Date(d.due_on).toLocaleDateString()}`:"",d.paid_at?` · Paid ${new Date(d.paid_at).toLocaleDateString()}`:""]})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"font-display font-bold tabular-nums",children:p(d.total_cents)}),e.jsx("span",{className:`text-[10px] uppercase tracking-wide px-2 py-0.5 rounded-full font-medium ${d.status==="paid"?"bg-secondary text-secondary-foreground":k?"bg-destructive text-destructive-foreground":"text-primary-foreground"}`,style:d.status!=="paid"&&!k?{background:N}:void 0,children:k?"overdue":d.status})]})]},d.id)})}),e.jsx(R,{open:!!r,onOpenChange:d=>!d&&n(null),children:e.jsxs(F,{className:"max-w-2xl max-h-[90vh] overflow-y-auto",children:[e.jsx(M,{children:e.jsxs(H,{children:["Invoice #",r?.number]})}),r&&e.jsxs("div",{children:[e.jsxs("div",{ref:u,children:[e.jsxs("div",{className:"row",style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:16,marginBottom:16},children:[e.jsxs("div",{children:[e.jsx("h1",{style:{fontSize:22,fontWeight:700,margin:0},children:o.company_name}),e.jsxs("div",{className:"muted text-sm text-muted-foreground",children:["Invoice for ",o.customer_name]}),e.jsxs("div",{className:"muted text-sm text-muted-foreground",children:[o.address,o.city?`, ${o.city}`:"",o.state?`, ${o.state}`:""]})]}),e.jsxs("div",{style:{textAlign:"right"},children:[e.jsx("div",{className:"text-xs uppercase tracking-wide text-muted-foreground",children:"Invoice #"}),e.jsx("div",{className:"font-semibold",children:r.number}),e.jsx("span",{className:`status ${r.status==="paid"?"paid":""} inline-block mt-2 px-2 py-0.5 rounded-full text-[10px] uppercase tracking-wide font-semibold`,style:{background:r.status==="paid"?"#dcfce7":"#e2e8f0",color:r.status==="paid"?"#166534":"#0f172a"},children:r.status})]})]}),e.jsxs("table",{style:{width:"100%",borderCollapse:"collapse"},children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{style:{textAlign:"left",padding:"8px",borderBottom:"1px solid #e2e8f0",fontSize:11,textTransform:"uppercase",letterSpacing:"0.05em",color:"#64748b"},children:"Detail"}),e.jsx("th",{style:{textAlign:"right",padding:"8px",borderBottom:"1px solid #e2e8f0",fontSize:11,textTransform:"uppercase",letterSpacing:"0.05em",color:"#64748b"},children:"Amount"})]})}),e.jsxs("tbody",{children:[e.jsxs("tr",{children:[e.jsx("td",{style:{padding:8,borderBottom:"1px solid #e2e8f0"},children:"Issued"}),e.jsx("td",{className:"right",style:{padding:8,borderBottom:"1px solid #e2e8f0",textAlign:"right"},children:r.issued_on?new Date(r.issued_on).toLocaleDateString():"â"})]}),e.jsxs("tr",{children:[e.jsx("td",{style:{padding:8,borderBottom:"1px solid #e2e8f0"},children:"Due"}),e.jsx("td",{className:"right",style:{padding:8,borderBottom:"1px solid #e2e8f0",textAlign:"right"},children:r.due_on?new Date(r.due_on).toLocaleDateString():"â"})]}),r.paid_at&&e.jsxs("tr",{children:[e.jsx("td",{style:{padding:8,borderBottom:"1px solid #e2e8f0"},children:"Paid"}),e.jsx("td",{className:"right",style:{padding:8,borderBottom:"1px solid #e2e8f0",textAlign:"right"},children:new Date(r.paid_at).toLocaleDateString()})]}),e.jsxs("tr",{children:[e.jsx("td",{style:{padding:8,borderBottom:"1px solid #e2e8f0"},children:"Subtotal"}),e.jsx("td",{className:"right tabular-nums",style:{padding:8,borderBottom:"1px solid #e2e8f0",textAlign:"right"},children:p(r.subtotal_cents)})]}),e.jsxs("tr",{children:[e.jsx("td",{style:{padding:8,borderBottom:"1px solid #e2e8f0"},children:"Tax"}),e.jsx("td",{className:"right tabular-nums",style:{padding:8,borderBottom:"1px solid #e2e8f0",textAlign:"right"},children:p(r.tax_cents)})]}),e.jsxs("tr",{children:[e.jsx("td",{style:{padding:8,fontWeight:700},children:"Total"}),e.jsx("td",{className:"right tabular-nums total",style:{padding:8,textAlign:"right",fontSize:22,fontWeight:700},children:p(r.total_cents)})]})]})]}),r.notes&&e.jsx("div",{className:"notes mt-4 p-3 bg-muted rounded-md text-sm whitespace-pre-wrap",children:r.notes})]}),m]}),e.jsxs(V,{className:"gap-2 sm:gap-2 print:hidden",children:[e.jsxs(_,{variant:"outline",onClick:h,className:"gap-1.5",children:[e.jsx(J,{className:"h-4 w-4"})," Email"]}),e.jsxs(_,{onClick:S,className:"gap-1.5",style:{background:N},children:[e.jsx(le,{className:"h-4 w-4"})," Print"]})]})]})})]})}function he({token:x,chat:l,brand:j,chatTo:f,onPosted:N}){const[o,r]=c.useState(""),[n,b]=c.useState(!1),w=c.useRef(null);c.useEffect(()=>{w.current?.scrollIntoView({behavior:"smooth"})},[l.length]);async function v(){const a=o.trim();if(!a)return;b(!0);const{error:u}=await C.rpc("post_portal_message",{_token:x,_body:a});if(b(!1),u){D.error(u.message);return}r(""),N()}return e.jsxs("section",{className:"mt-6 rounded-2xl border border-border bg-card p-6",children:[e.jsxs("h2",{className:"font-display text-xl font-bold flex items-center gap-2",children:[e.jsx(Z,{className:"h-5 w-5",style:{color:j}})," Chat with your pool team"]}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-0.5",children:["Messages go directly to ",f,". Replies refresh here automatically."]}),e.jsxs("div",{className:"mt-4 max-h-80 overflow-y-auto rounded-xl border border-border bg-background p-3 space-y-2",children:[l.length===0?e.jsx("p",{className:"text-sm text-muted-foreground text-center py-6",children:"No messages yet. Say hi ð"}):l.map(a=>e.jsx("div",{className:`flex ${a.sender_role==="homeowner"?"justify-end":"justify-start"}`,children:e.jsxs("div",{className:`max-w-[80%] rounded-2xl px-3 py-2 text-sm whitespace-pre-wrap ${a.sender_role==="homeowner"?"text-white":"bg-muted text-foreground"}`,style:a.sender_role==="homeowner"?{background:j}:void 0,children:[a.body,e.jsx("div",{className:"text-[10px] mt-1 opacity-70",children:new Date(a.created_at).toLocaleStr
18ing([],{hour:"numeric",minute:"2-digit",month:"short",day:"numeric"})})]})},a.id)),e.jsx("div",{ref:w})]}),e.jsxs("div",{className:"mt-3 flex gap-2",children:[e.jsx(z,{value:o,onChange:a=>r(a.target.value),placeholder:"Ask a question or request a serviceâ¦",className:"min-h-[44px] max-h-32",onKeyDown:a=>{a.key==="Enter"&&!a.shiftKey&&(a.preventDefault(),v())}}),e.jsx(_,{onClick:v,disabled:n||!o.trim(),className:"h-auto",style:{background:j},children:e.jsx(W,{className:"h-4 w-4"})})]})]})}function ge({token:x,brand:l,onChange:j}){const[f,N]=c.useState([]),[o,r]=c.useState(null);async function n(){const{data:a}=await C.rpc("get_portal_quotes",{_token:x});N(a??[])}c.useEffect(()=>{n()},[x]);async function b(a,u){r(a);const{error:m}=await C.rpc("decide_quote",{_token:x,_work_order_id:a,_decision:u});if(r(null),m){D.error(m.message);return}D.success(u==="approved"?"Approved â we'll be in touch to schedule.":"Quote declined"),n(),j()}if(f.length===0)return null;const w=f.filter(a=>a.customer_decision==="pending"),v=f.filter(a=>a.customer_decision!=="pending");return e.jsxs("section",{id:"quotes",className:"mt-6 rounded-2xl border border-border bg-card p-6",children:[e.jsxs("h2",{className:"font-display text-xl font-bold flex items-center gap-2",children:[e.jsx(I,{className:"h-5 w-5",style:{color:l}})," Quotes for your pool"]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5",children:"Review and approve work proposed by your service team."}),e.jsxs("div",{className:"mt-4 space-y-3",children:[w.map(a=>e.jsxs("div",{className:"rounded-xl border-2 p-4",style:{borderColor:l},children:[e.jsxs("div",{className:"flex items-start justify-between gap-3 flex-wrap",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-semibold",children:a.title}),a.description&&e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5 whitespace-pre-line",children:a.description})]}),e.jsx("div",{className:"font-display text-2xl font-bold tabular-nums",children:p(a.quote_amount_cents??0)})]}),a.line_items.length>0&&e.jsx("ul",{className:"mt-3 text-sm space-y-1",children:a.line_items.map((u,m)=>e.jsxs("li",{className:"flex justify-between gap-3 text-muted-foreground",children:[e.jsxs("span",{children:[u.qty,"à ",u.description]}),e.jsx("span",{className:"tabular-nums",children:p(u.qty*u.amount_cents)})]},m))}),a.quote_notes&&e.jsx("p",{className:"mt-3 text-sm bg-muted rounded-md p-2",children:a.quote_notes}),e.jsxs("div",{className:"mt-4 flex flex-wrap gap-2",children:[e.jsxs(_,{onClick:()=>b(a.id,"approved"),disabled:o===a.id,className:"gap-1.5",style:{background:l},children:[e.jsx(A,{className:"h-4 w-4"})," Approve"]}),e.jsxs(_,{onClick:()=>b(a.id,"declined"),disabled:o===a.id,variant:"outline",className:"gap-1.5",children:[e.jsx(L,{className:"h-4 w-4"})," Decline"]})]})]},a.id)),v.map(a=>e.jsxs("div",{className:"rounded-lg border border-border p-3 flex flex-wrap items-center justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"font-medium text-sm",children:a.title}),e.jsx("div",{className:"text-xs text-muted-foreground",children:p(a.quote_amount_cents??0)})]}),e.jsx("div",{className:"flex items-center gap-2",children:e.jsx("span",{className:`text-[10px] uppercase tracking-wide px-2 py-0.5 rounded-full font-medium ${a.customer_decision==="approved"?"bg-emerald-100 text-emerald-700":"bg-destructive/10 text-destructive"}`,children:a.customer_decision})})]},a.id))]})]})}function fe({token:x,brand:l,onChange:j}){const[f,N]=c.useState([]),[o,r]=c.useState(null),[n,b]=c.useState("view"),[w,v]=c.useState(""),[a,u]=c.useState(!1),[m,S]=c.useState(""),[h,d]=c.useState(!1);async function k(){const{data:t}=await C.rpc("get_portal_estimates",{_token:x});N(t??[])}c.useEffect(()=>{k()},[x]);function g(t,y="view"){r(t),b(y),v(""),u(!1),S("")}async function $(){if(!o)return;if(n==="approve"&&(!w.trim()||!a)){D.error("Please type your name and confirm acceptance.");return}d(!0);const t={_token:x,_estimate_id:o.id,_decision:n==="approve"?"approved":"declined"};n==="approve"&&(t._signature_name=w.trim()),n==="decline"&&m&&(t._decline_reason=m);const{error:y}=await C.rpc("decide_estimate",t);if(d(!1),y){D.error(y.message);return}D.success(n==="approve"?"Approved â we'll be in touch to schedule.":"Estimate declined"),r(null),k(),j()}const s=f.filter(t=>t.status==="sent"||t.status==="draft"),i=f.filter(t=>t.status==="approved"||t.status==="declined");return e.jsxs("section",{className:"mt-6 rounded-2xl border border-border bg-card p-6",children:[e.jsxs("h2",{className:"font-display text-xl font-bold flex items-center gap-2",children:[e.jsx(I,{className:"h-5 w-5",style:{color:l}})," Estimates"]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5",children:"Review and approve proposed work. Approved estimates are scheduled as work orders."}),e.jsxs("div",{className:"mt-4 space-y-3",children:[f.length===0&&e.jsx("div",{className:"rounded-lg border border-dashed border-border p-6 text-center text-sm text-muted-foreground",children:"No estimates yet. When your service team sends one, it'll show up here for you to review and approve."}),s.map(t=>e.jsxs("div",{className:"rounded-xl border-2 p-4",style:{borderColor:l},children:[e.jsxs("div",{className:"flex items-start justify-between gap-3 flex-wrap",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"font-semibold flex items-center gap-2",children:["Estimate #",t.number,e.jsx("span",{className:"text-[10px] uppercase tracking-wide px-2 py-0.5 rounded-full font-medium bg-amber-100 text-amber-700",children:"Pending"})]}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:[t.sent_at?`Sent ${new Date(t.sent_at).toLocaleDateString()}`:`Prepared ${new Date(t.created_at).toLocaleDateString()}`,t.valid_until?` · Valid until ${new Date(t.valid_until).toLocaleDateString()}`:""]})]}),e.jsx("div",{className:"font-display text-2xl font-bold tabular-nums",children:p(t.total_cents)})]}),e.jsxs("div",{className:"mt-4 flex flex-wrap gap-2",children:[e.jsx(_,{onClick:()=>g(t,"view"),variant:"outline",size:"sm",children:"View details"}),e.jsxs(_,{onClick:()=>g(t,"approve"),size:"sm",className:"gap-1.5",style:{background:l},children:[e.jsx(A,{className:"h-4 w-4"})," Approve & sign"]}),e.jsxs(_,{onClick:()=>g(t,"decline"),variant:"outline",size:"sm",className:"gap-1.5",children:[e.jsx(L,{className:"h-4 w-4"})," Decline"]})]})]},t.id)),i.map(t=>e.jsxs("button",{onClick:()=>g(t,"view"),className:"w-full text-left rounded-lg border border-border p-3 flex flex-wrap items-center justify-between gap-3 hover:bg-muted/50",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"font-medium text-sm",children:["Estimate #",t.number]}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:[p(t.total_cents),t.signature_name?` · Signed by ${t.signature_name}`:""]})]}),e.jsx("span",{className:`text-[10px] uppercase tracking-wide px-2 py-0.5 rounded-full font-medium ${t.status==="approved"?"bg-emerald-100 text-emerald-700":"bg-destructive/10 text-destructive"}`,children:t.status})]},t.id))]}),e.jsx(R,{open:!!o,onOpenChange:t=>!t&&r(null),children:e.jsxs(F,{className:"max-w-2xl max-h-[90vh] overflow-y-auto",children:[e.jsx(M,{children:e.jsxs(H,{
18children:["Estimate #",o?.number]})}),o&&e.jsxs("div",{className:"space-y-4",children:[e.jsx("div",{className:"rounded-lg border border-border",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{className:"bg-muted/50",children:e.jsxs("tr",{className:"text-xs uppercase tracking-wide text-muted-foreground",children:[e.jsx("th",{className:"text-left p-2",children:"Item"}),e.jsx("th",{className:"text-right p-2",children:"Qty"}),e.jsx("th",{className:"text-right p-2",children:"Amount"})]})}),e.jsx("tbody",{children:o.lines.map((t,y)=>e.jsxs("tr",{className:"border-t border-border",children:[e.jsxs("td",{className:"p-2",children:[e.jsx("div",{children:t.description}),t.labor_hours>0&&e.jsxs("div",{className:"text-xs text-muted-foreground",children:[t.labor_hours," hr labor @ ",p(t.labor_rate_cents),"/hr",t.part_cents>0?` + part ${p(t.part_cents)}`:""]})]}),e.jsx("td",{className:"text-right p-2 tabular-nums",children:t.qty}),e.jsx("td",{className:"text-right p-2 tabular-nums",children:p(t.line_total_cents)})]},y))})]})}),e.jsxs("div",{className:"text-sm space-y-1 max-w-xs ml-auto",children:[e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"Subtotal"}),e.jsx("span",{className:"tabular-nums",children:p(o.subtotal_cents)})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"Tax"}),e.jsx("span",{className:"tabular-nums",children:p(o.tax_cents)})]}),e.jsxs("div",{className:"flex justify-between font-semibold text-base pt-1 border-t border-border",children:[e.jsx("span",{children:"Total"}),e.jsx("span",{className:"tabular-nums",children:p(o.total_cents)})]})]}),o.notes&&e.jsx("div",{className:"text-sm bg-muted rounded-md p-3 whitespace-pre-line",children:o.notes}),n==="approve"&&o.status==="sent"&&e.jsxs("div",{className:"space-y-3 border-t border-border pt-4",children:[e.jsxs("div",{children:[e.jsx(T,{htmlFor:"sig-name",children:"Type your full name to sign"}),e.jsx(G,{id:"sig-name",value:w,onChange:t=>v(t.target.value),placeholder:"Jane Homeowner"})]}),e.jsxs("label",{className:"flex items-start gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:a,onChange:t=>u(t.target.checked),className:"mt-1"}),e.jsxs("span",{className:"text-muted-foreground",children:["I authorize the work described above for the amount of ",e.jsx("strong",{className:"text-foreground",children:p(o.total_cents)}),". My typed name constitutes an electronic signature."]})]})]}),n==="decline"&&o.status==="sent"&&e.jsxs("div",{className:"space-y-2 border-t border-border pt-4",children:[e.jsx(T,{htmlFor:"decline-reason",children:"Reason (optional)"}),e.jsx(z,{id:"decline-reason",rows:3,value:m,onChange:t=>S(t.target.value),placeholder:"Anything you'd like us to know"})]}),o.signature_name&&e.jsxs("div",{className:"text-xs text-muted-foreground border-t border-border pt-3",children:["Signed by ",e.jsx("strong",{className:"text-foreground",children:o.signature_name}),o.signed_at?` on ${new Date(o.signed_at).toLocaleString()}`:""]})]}),e.jsxs(V,{children:[o?.status==="sent"&&n==="view"&&e.jsxs(e.Fragment,{children:[e.jsxs(_,{variant:"outline",onClick:()=>b("decline"),className:"gap-1.5",children:[e.jsx(L,{className:"h-4 w-4"})," Decline"]}),e.jsxs(_,{onClick:()=>b("approve"),className:"gap-1.5",style:{background:l},children:[e.jsx(A,{className:"h-4 w-4"})," Approve & sign"]})]}),o?.status==="sent"&&n!=="view"&&e.jsxs(e.Fragment,{children:[e.jsx(_,{variant:"ghost",onClick:()=>b("view"),children:"Back"}),e.jsx(_,{onClick:$,disabled:h,style:n==="approve"?{background:l}:void 0,variant:n==="decline"?"destructive":"default",children:h?"Submittingâ¦":n==="approve"?"Confirm approval":"Submit decline"})]})]})]})})]})}export{$e 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.