PageSourceSearch

https://incommand.ai/assets/Billing-D6AYo7iF.js

js incommand.ai collected 2026-10-05 15:00:58 UTC 25,812 bytes, 16 lines download raw bytes

1import{j as e}from"./vendor-radix-BnNg3BH5.js";import{r}from"./vendor-react-67mgcWXU.js";import{M as L}from"./metric-DK0Tcl4m.js";import{b as ie,s as q,L as ge,w as X,x as Z,y as ee,z as se,A,F as R,U as fe,V as Ne,W as T,Y as I,B as $,k as ce,q as re}from"./index-Epr9psQo.js";import{C as k,d as M,a as U,b as V,c as Y}from"./card-DpKBVi42.js";import{B as ve}from"./badge-Cl7apleB.js";import{D as Se,a as Ae,b as Te,e as oe}from"./dropdown-menu-Duf4NJvQ.js";import{e as ke,a as Me,A as De}from"./ARAgingPanel-D3xi6d2S.js";import{T as le}from"./trending-up-CXZcoU_y.js";import{C as be}from"./clock-BYWbH6MV.js";import{C as Fe}from"./circle-check-Cv8aCTuA.js";import{D as _e}from"./dollar-sign-CC-jyV1q.js";import{A as W}from"./arrow-right-LjC5fuTq.js";import{b as Pe,f as y}from"./format-Bw8okCdv.js";import{s as He}from"./startOfQuarter-fx0aREoi.js";import{s as te}from"./startOfMonth-DSkvSDwv.js";import{s as de}from"./subMonths-Cf3G1AKu.js";import{e as ae}from"./endOfMonth-BJH_LSY0.js";import{C as me}from"./checkbox-CaPhqoy3.js";import{T as Ie,a as Le,b as J,c as D,d as Ee,e as v,f as $e}from"./table-023rHGnC.js";import{P as ue,a as xe,b as pe}from"./popover-C2IiMjDe.js";import{C as he}from"./calendar-Dg9oKd3C.js";import{e as Re,f as qe}from"./exportCsv-BoWPxi9f.js";import{I as we,B as Be}from"./BillingTranscriptDialog-2nvto64J.js";import{C as je}from"./calendar-Ce69BthR.js";import{D as ze}from"./download-CDzT20jl.js";import{u as Oe}from"./useTimePermissions-CU3wg1KY.js";import{P as Ue}from"./PageShell-D4n0-tMZ.js";import{m as Ve}from"./vendor-motion-CSzk-Fqg.js";import{E as Ye}from"./ellipsis-C6BfvtHH.js";import{C as ye}from"./credit-card-rF6FfvWR.js";import{T as Ce}from"./triangle-alert-C6ISfBPd.js";import"./vendor-supabase-CTlrDMdV.js";import"./vendor-charts-Dck3qfzI.js";import"./vendor-query-PMAhJHCS.js";import"./chevron-right-DQtszqux.js";import"./circle-CPv7M1K7.js";import"./en-US-DJiZ5LCQ.js";import"./skeleton-CXDkv5zX.js";import"./addMonths-CAHQ-5pQ.js";import"./isSameDay-YWnicZiN.js";import"./subDays-O0YAIy_S.js";import"./addDays-Cy4sUjNt.js";import"./differenceInCalendarMonths-CBq9QhqA.js";import"./isSameMonth-DowG56g5.js";import"./isAfter-CsIPKNJY.js";import"./endOfWeek-Bk3y437X.js";import"./addYears-BaWD3Fpv.js";import"./addWeeks-QA4EuLDh.js";import"./chevron-left-D3yfuHpM.js";import"./moduleEvents-B5yqdP_9.js";import"./receipt-Fuhr8YYj.js";import"./html2canvas.esm-B4CzG4On.js";import"./PageWidthContext-BSQPZJze.js";function Ge(){const[s,x]=r.useState({pendingHours:0,pendingAmount:0,approvedHours:0,approvedAmount:0,invoicedHours:0,invoicedAmount:0,paidHours:0,paidAmount:0}),[d,j]=r.useState([]),[N,n]=r.useState(!0),[h,p]=r.useState("overview"),[o,a]=r.useState("this_month"),{currentTenant:c}=ie();r.useEffect(()=>{c?.id&&C()},[c,o]);const C=async()=>{n(!0);try{const l=new Date;let m=null,S=null;switch(o){case"this_month":m=te(l),S=ae(l);break;case"last_month":m=te(de(l,1)),S=ae(de(l,1));break;case"this_quarter":m=He(l),S=Me(l);break;case"this_year":m=Pe(l),S=ke(l);break;case"all":break}let E=q.from("time_entries").select(`
2          id,
3          date,
4          hours,
5          rate_override,
6          billing_status,
7          is_billable,
8          projects!inner(name, tenant_id, clients(name)),
9          profiles!time_entries_user_id_fkey(full_name, hourly_rate)
10        `).eq("is_billable",!0).eq("projects.tenant_id",c?.id);m&&S&&(E=E.gte("date",y(m,"yyyy-MM-dd")).lte("date",y(S,"yyyy-MM-dd")));const{data:F}=await E.order("date",{ascending:!1}).limit(500);if(F){const b={pendingHours:0,pendingAmount:0,approvedHours:0,approvedAmount:0,invoicedHours:0,invoicedAmount:0,paidHours:0,paidAmount:0},B=[];F.forEach(_=>{const w=_.hours||0,G=_.rate_override||_.profiles?.hourly_rate||0,P=w*G,z=_.billing_status||"pending";switch(z){case"pending":b.pendingHours+=w,b.pendingAmount+=P;break;case"approved":b.approvedHours+=w,b.approvedAmount+=P;break;case"invoiced":b.invoicedHours+=w,b.invoicedAmount+=P;break;case"paid":b.paidHours+=w,b.paidAmount+=P;break}B.push({id:_.id,date:_.date,hours:w,amount:P,project_name:_.projects?.name||"No Project",client_name:_.projects?.clients?.n
10ame||"No Client",user_name:_.profiles?.full_name||"Unknown",billing_status:z})}),x(b),j(B)}}catch(l){console.error("Error loading billing data:",l)}finally{n(!1)}},g=s.pendingAmount+s.approvedAmount+s.invoicedAmount+s.paidAmount,i=s.pendingHours+s.approvedHours+s.invoicedHours+s.paidHours;return N?e.jsx(k,{children:e.jsx(M,{className:"flex items-center justify-center py-12",children:e.jsx(ge,{className:"h-8 w-8 animate-spin text-muted-foreground"})})}):e.jsxs(k,{children:[e.jsx(U,{children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsxs(V,{className:"flex items-center gap-2",children:[e.jsx(le,{className:"h-5 w-5"}),"Billing Pipeline"]}),e.jsx(Y,{children:"Track hours from time entry to payment"})]}),e.jsxs(X,{value:o,onValueChange:l=>a(l),children:[e.jsx(Z,{className:"w-[140px]",children:e.jsx(ee,{})}),e.jsxs(se,{children:[e.jsx(A,{value:"this_month",children:"This Month"}),e.jsx(A,{value:"last_month",children:"Last Month"}),e.jsx(A,{value:"this_quarter",children:"This Quarter"}),e.jsx(A,{value:"this_year",children:"This Year"}),e.jsx(A,{value:"all",children:"All Time"})]})]})]})}),e.jsxs(M,{className:"space-y-6",children:[e.jsxs("div",{className:"grid grid-cols-4 gap-4",children:[e.jsxs("div",{className:"p-4 rounded-lg border bg-warning/5 border-warning/20",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx(be,{className:"h-4 w-4 text-warning"}),e.jsx("span",{className:"text-sm font-medium text-warning",children:"Pending"})]}),e.jsxs(L,{size:"md",children:[s.pendingHours.toFixed(1),"h"]}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:["$",s.pendingAmount.toLocaleString()]})]}),e.jsxs("div",{className:"p-4 rounded-lg border bg-info/5 border-info/20",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx(Fe,{className:"h-4 w-4 text-info"}),e.jsx("span",{className:"text-sm font-medium text-info",children:"Approved"})]}),e.jsxs(L,{size:"md",children:[s.approvedHours.toFixed(1),"h"]}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:["$",s.approvedAmount.toLocaleString()]})]}),e.jsxs("div",{className:"p-4 rounded-lg border bg-accent-purple/5 border-accent-purple/20",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx(R,{className:"h-4 w-4 text-accent-purple"}),e.jsx("span",{className:"text-sm font-medium text-accent-purple",children:"Invoiced"})]}),e.jsxs(L,{size:"md",children:[s.invoicedHours.toFixed(1),"h"]}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:["$",s.invoicedAmount.toLocaleString()]})]}),e.jsxs("div",{className:"p-4 rounded-lg border bg-success/5 border-success/20",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx(_e,{className:"h-4 w-4 text-success"}),e.jsx("span",{className:"text-sm font-medium text-success",children:"Paid"})]}),e.jsxs(L,{size:"md",children:[s.paidHours.toFixed(1),"h"]}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:["$",s.paidAmount.toLocaleString()]})]})]}),e.jsxs("div",{className:"flex items-center justify-center gap-2 py-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"w-3 h-3 rounded-full bg-warning"}),e.jsx("span",{className:"text-sm",children:"Pending"})]}),e.jsx(W,{className:"h-4 w-4 text-muted-foreground"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"w-3 h-3 rounded-full bg-info"}),e.jsx("span",{className:"text-sm",children:"Approved"})]}),e.jsx(W,{className:"h-4 w-4 text-muted-foreground"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"w-3 h-3 rounded-full bg-accent-purple"}),e.jsx("span",{className:"text-sm",children:"Invoiced"})]}),e.jsx(W,{className:"h-4 w-4 text-muted-foreground"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"w-3 h-3 rounded-full bg-success"}),e.jsx("span",{className:"text-sm",children:"Paid"})]})]}),g>0&&e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex h-4 rounded-full overflow-hidden",children:[e.jsx("div",{className:"bg-warning transition-all",style:{width:`${s.pendingAmount/g*100}%`}}),e.jsx("div",{className:"bg-info transition-all",style:{width:`${s.approvedAmount/g*100}%`}}),e.jsx("div",{className:"bg-accent-purple transition-all",style:{width:`${s.invoicedAmount/g*100}%`}}),e.jsx("div",{className:"bg-success transition-all",style:{width:`${s.paidAmount/g*100}%`}})]}),e.jsxs("div",{className:"flex justify-between text-xs text-muted-foreground",children:[e.jsxs("span",{children:[i.toFixed(1)," total billable hours"]}
10),e.jsxs("span",{children:["$",g.toLocaleString()," total value"]})]})]}),e.jsxs(fe,{value:h,onValueChange:p,children:[e.jsxs(Ne,{className:"grid w-full grid-cols-4",children:[e.jsxs(T,{value:"pending",className:"text-xs",children:["Pending (",d.filter(l=>l.billing_status==="pending").length,")"]}),e.jsxs(T,{value:"approved",className:"text-xs",children:["Approved (",d.filter(l=>l.billing_status==="approved").length,")"]}),e.jsxs(T,{value:"invoiced",className:"text-xs",children:["Invoiced (",d.filter(l=>l.billing_status==="invoiced").length,")"]}),e.jsxs(T,{value:"paid",className:"text-xs",children:["Paid (",d.filter(l=>l.billing_status==="paid").length,")"]})]}),["pending","approved","invoiced","paid"].map(l=>e.jsx(I,{value:l,className:"mt-4",children:e.jsxs("div",{className:"space-y-2 max-h-[300px] overflow-y-auto",children:[d.filter(m=>m.billing_status===l).slice(0,20).map(m=>e.jsxs("div",{className:"flex items-center justify-between p-3 rounded-lg border hover:bg-muted/50",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs("div",{className:"text-center min-w-[50px]",children:[e.jsx("p",{className:"text-xs text-muted-foreground",children:y(new Date(m.date),"MMM")}),e.jsx("p",{className:"font-bold",children:y(new Date(m.date),"d")})]}),e.jsxs("div",{children:[e.jsx("p",{className:"font-medium",children:m.project_name}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:[m.client_name," • ",m.user_name]})]})]}),e.jsxs("div",{className:"text-right",children:[e.jsxs("p",{className:"font-bold",children:["$",m.amount.toFixed(2)]}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[m.hours.toFixed(1),"h"]})]})]},m.id)),d.filter(m=>m.billing_status===l).length===0&&e.jsxs("div",{className:"text-center py-8 text-muted-foreground",children:["No ",l," entries"]})]})},l))]})]})]})}function Qe(s){const{currentTenant:x}=ie(),[d,j]=r.useState([]),[N,n]=r.useState(!0);r.useEffect(()=>{if(!x?.id)return;(async()=>{n(!0);let a=q.from("time_entries").select(`
11          id, date, hours, billable_minutes, description,
12          rate_override, billing_status, project_id, client_id, user_id,
13          profiles:user_id ( full_name, hourly_rate ),
14          projects:project_id ( name, client_id ),
15          clients:client_id ( company_name )
16        `).eq("tenant_id",x.id).eq("is_billable",!0).in("billing_status",["pending","approved"]).gte("date",s.dateFrom).lte("date",s.dateTo).order("date",{ascending:!1});s.clientId&&(a=a.eq("client_id",s.clientId)),s.projectId&&(a=a.eq("project_id",s.projectId));const{data:c,error:C}=await a;if(C)console.error("Error loading unbilled entries:",C),j([]);else{const g=(c||[]).map(i=>({id:i.id,date:i.date,hours:i.hours,billable_minutes:i.billable_minutes,description:i.description,rate_override:i.rate_override,billing_status:i.billing_status,project_id:i.project_id,client_id:i.client_id||i.projects?.client_id||null,user_id:i.user_id,user_name:i.profiles?.full_name||"Unknown",hourly_rate:i.profiles?.hourly_rate||null,project_name:i.projects?.name||"No Project",client_name:i.clients?.company_name||"No Client"}));j(g)}n(!1)})()},[x?.id,s.clientId,s.projectId,s.dateFrom,s.dateTo]);const h=r.useMemo(()=>{const o=new Map;return d.forEach(a=>{const c=a.client_id;c&&!o.has(c)&&o.set(c,a.client_name)}),Array.from(o,([a,c])=>({id:a,name:c}))},[d]),p=r.useMemo(()=>{const o=new Map;return d.forEach(a=>{const c=a.project_id;c&&!o.has(c)&&o.set(c,a.project_name)}),Array.from(o,([a,c])=>({id:a,name:c}))},[d]);return{entries:d,loading:N,clients:h,projects:p}}function O(s){return s.billable_minutes!=null?s.billable_minutes/60:s.hours}function ne(s){return s.rate_override??s.hourly_rate??0}function K(s){return O(s)*ne(s)}function We(){const s=new Date,[x,d]=r.useState(te(s)),[j,N]=r.useState(ae(s)),[n,h]=r.useState(null),[p,o]=r.useState(null),[a,c]=r.useState(new Set),[C,g]=r.useState(!1),{entries:i,loading:l,clients:m,projects:S}=Qe({clientId:n,projectId:p,dateFrom:y(x,"yyyy-MM-dd"),dateTo:y(j,"yyyy-MM-dd")}),E=r.useMemo(()=>{if(!n)return S;const t=i.filter(u=>u.client_id===n),f=new Map;return t.forEach(u=>{u.project_id&&!f.has(u.project_id)&&f.set(u.project_id,u.project_name)}),Array.from(f,([u,H])=>({id:u,name:H}))},[n,i,S]),F=i.length>0&&a.size===i.length,b=a.size>0&&!F,B=r.useCallback(()=>{c(F?new Set:new Set(i.map(t=>
16t.id)))},[F,i]),_=r.useCallback(t=>{c(f=>{const u=new Set(f);return u.has(t)?u.delete(t):u.add(t),u})},[]),w=r.useMemo(()=>{const t=a.size>0?i.filter(H=>a.has(H.id)):i,f=t.reduce((H,Q)=>H+O(Q),0),u=t.reduce((H,Q)=>H+K(Q),0);return{hours:f,amount:u,count:t.length}},[i,a]),G=()=>{const t=a.size>0?i.filter(f=>a.has(f.id)):i;Re(t,[{key:"date",header:"Date",transform:f=>qe(f)},{key:"user_name",header:"Team Member"},{key:"project_name",header:"Project"},{key:"client_name",header:"Client"},{key:"description",header:"Description"},{key:"hours",header:"Hours",transform:(f,u)=>O(u).toFixed(2)},{key:"rate_override",header:"Rate",transform:(f,u)=>ne(u).toFixed(2)},{key:"id",header:"Amount",transform:(f,u)=>K(u).toFixed(2)}],`unbilled-time-${y(new Date,"yyyy-MM-dd")}`)},P=t=>{h(t==="all"?null:t),o(null),c(new Set)},z=t=>{o(t==="all"?null:t),c(new Set)};return e.jsxs("div",{className:"space-y-4",children:[e.jsx(k,{children:e.jsx(M,{className:"pt-6",children:e.jsxs("div",{className:"flex flex-wrap gap-4 items-end",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{className:"text-sm font-medium text-muted-foreground",children:"From"}),e.jsxs(ue,{children:[e.jsx(xe,{asChild:!0,children:e.jsxs($,{variant:"outline",className:ce("w-[160px] justify-start text-left font-normal"),children:[e.jsx(je,{className:"mr-2 h-4 w-4"}),y(x,"MMM d, yyyy")]})}),e.jsx(pe,{className:"w-auto p-0",align:"start",children:e.jsx(he,{mode:"single",selected:x,onSelect:t=>t&&d(t),className:"p-3 pointer-events-auto"})})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{className:"text-sm font-medium text-muted-foreground",children:"To"}),e.jsxs(ue,{children:[e.jsx(xe,{asChild:!0,children:e.jsxs($,{variant:"outline",className:ce("w-[160px] justify-start text-left font-normal"),children:[e.jsx(je,{className:"mr-2 h-4 w-4"}),y(j,"MMM d, yyyy")]})}),e.jsx(pe,{className:"w-auto p-0",align:"start",children:e.jsx(he,{mode:"single",selected:j,onSelect:t=>t&&N(t),className:"p-3 pointer-events-auto"})})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{className:"text-sm font-medium text-muted-foreground",children:"Client"}),e.jsxs(X,{value:n??"all",onValueChange:P,children:[e.jsx(Z,{className:"w-[180px]",children:e.jsx(ee,{placeholder:"All Clients"})}),e.jsxs(se,{children:[e.jsx(A,{value:"all",children:"All Clients"}),m.map(t=>e.jsx(A,{value:t.id,children:t.name},t.id))]})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{className:"text-sm font-medium text-muted-foreground",children:"Project"}),e.jsxs(X,{value:p??"all",onValueChange:z,children:[e.jsx(Z,{className:"w-[180px]",children:e.jsx(ee,{placeholder:"All Projects"})}),e.jsxs(se,{children:[e.jsx(A,{value:"all",children:"All Projects"}),E.map(t=>e.jsx(A,{value:t.id,children:t.name},t.id))]})]})]}),e.jsx("div",{className:"flex-1"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs($,{variant:"outline",size:"sm",onClick:G,disabled:i.length===0,children:[e.jsx(ze,{className:"h-4 w-4 mr-2"}),"Export CSV"]}),e.jsxs($,{size:"sm",onClick:()=>g(!0),disabled:i.length===0,children:[e.jsx(R,{className:"h-4 w-4 mr-2"}),"Create Invoice"]})]})]})})}),e.jsx(k,{children:e.jsx(M,{className:"p-0",children:l?e.jsx("div",{className:"flex items-center justify-center py-12",children:e.jsx(ge,{className:"h-6 w-6 animate-spin text-muted-foreground"})}):i.length===0?e.jsx("div",{className:"text-center py-12 text-muted-foreground",children:"No unbilled time entries found for the selected period."}):e.jsxs(Ie,{children:[e.jsx(Le,{children:e.jsxs(J,{children:[e.jsx(D,{className:"w-[40px]",children:e.jsx(me,{checked:F,onCheckedChange:B,"aria-label":"Select all",...b?{"data-state":"indeterminate"}:{}})}),e.jsx(D,{children:"Date"}),e.jsx(D,{children:"Who"}),e.jsx(D,{children:"Description"}),e.jsx(D,{children:"Status"}),e.jsx(D,{className:"text-right",children:"Hours"}),e.jsx(D,{className:"text-right",children:"Rate"}),e.jsx(D,{className:"text-right",children:"Amount"})]})}),e.jsx(Ee,{children:i.map(t=>e.jsxs(J,{"data-state":a.has(t.id)?"selected":void 0,children:[e.jsx(v,{children:e.jsx(me,{checked:a.has(t.id),onCheckedChange:()=>_(t.id),"aria-label":`Select entry ${t.id}`})}),e.jsx(v,{className:"whitespace-nowrap",children:y(new Date(t.date),"MMM d, yyyy")}),e.jsx(v,{children:t.user_name}),e.jsxs(v,{children:[e.jsxs("div",{children:[e.jsx("span",{className:"font-medium",children:t.project_name}),t.client_name!=="No Client"&&e.jsxs("span",{className:"text-muted-foreground",children:[" · ",t.client_name]})]}),t.description&&e.jsx("p",{className:"text-sm text-muted-foreground truncate max-w-md",children:t.description})]}),e.jsx(v,{children:e.jsx(ve,{variant:t.billing_status==="approved"?"default":"secondary",children:t.billing_status||"pending"})}),e.jsx(v,{className:"text-right tabular-nums",children:O(t).toFixed(2)}),e.jsxs(v,{className:"text-right tabular-nums",children:["$",ne(t).toFixed(0)]}),e.jsxs(v,{className:"text-right tabular-nums font-medium",children:["$",K(t).toFixed(2)]})]},t.id))}),e.jsx($e,{children:e.jsxs(J,{children:[e.jsx(v,{colSpan:5,className:"font-medium",children:a.size>0?`${w.count} of ${i.length} entries selected`:`${i.length} entries total`}),e.jsxs(v,{className:"text-right font-semibold tabular-nums",children:[w.hours.toFixed(2)," hrs"]}),e.jsx(v,{}),e.jsxs(v,{className:"text-right font-semibold tabular-nums",children:["$",w.amount.toFixed(2)]})]})})]})})}),e.jsx(we,{open:C,onOpenChange:g,onSuccess:()=>{g(!1),c(new Set)}})]})}function Je({tenantId:s}
16){const[x,d]=r.useState([]),[j,N]=r.useState(!0);return r.useEffect(()=>{let n=!1;async function h(){try{const{data:p,error:o}=await q.from("invoices").select("id, invoice_number, amount, status, paid_date, clients(company_name)").eq("tenant_id",s).in("status",["paid","partially_paid"]).order("paid_date",{ascending:!1}).limit(20);if(o)throw o;n||d((p||[]).map(a=>({id:a.id,invoice_number:a.invoice_number||"—",client_name:a.clients?.company_name||"Unknown",amount:a.amount||0,paid_date:a.paid_date,status:a.status})))}catch(p){n||re.error("Failed to load payments: "+(p.message||"Unknown error"))}finally{n||N(!1)}}return h(),()=>{n=!0}},[s]),j?e.jsx(k,{children:e.jsx(M,{className:"py-8 text-center text-muted-foreground",children:"Loading payments..."})}):e.jsxs(k,{children:[e.jsxs(U,{children:[e.jsxs(V,{className:"flex items-center gap-2",children:[e.jsx(ye,{className:"h-5 w-5"}),"Recent Payments"]}),e.jsx(Y,{children:"Payments received in the last 90 days"})]}),e.jsx(M,{children:x.length===0?e.jsx("p",{className:"text-sm text-muted-foreground text-center py-6",children:"No recent payments recorded"}):e.jsx("div",{className:"space-y-3",children:x.map(n=>e.jsxs("div",{className:"flex items-center justify-between p-3 rounded-lg border",children:[e.jsxs("div",{children:[e.jsx("p",{className:"font-medium text-sm",children:n.client_name}),e.jsx("p",{className:"text-xs text-muted-foreground",children:n.invoice_number})]}),e.jsxs("div",{className:"text-right",children:[e.jsxs("p",{className:"font-semibold text-sm",children:["$",n.amount.toLocaleString()]}),n.paid_date&&e.jsx("p",{className:"text-xs text-muted-foreground",children:new Date(n.paid_date).toLocaleDateString()})]})]},n.id))})})]})}function Ke({tenantId:s}){const[x,d]=r.useState([]),[j,N]=r.useState(!0);return r.useEffect(()=>{let n=!1;async function h(){try{const{data:p,error:o}=await q.from("invoices").select("id, invoice_number, amount, status, dispute_reason, created_at, clients(company_name)").eq("tenant_id",s).eq("status","disputed").order("created_at",{ascending:!1}).limit(20);if(o)throw o;n||d((p||[]).map(a=>({id:a.id,invoice_number:a.invoice_number||"—",client_name:a.clients?.company_name||"Unknown",amount:a.amount||0,reason:a.dispute_reason||"No reason provided",status:a.status,created_at:a.created_at})))}catch(p){n||re.error("Failed to load disputes: "+(p.message||"Unknown error"))}finally{n||N(!1)}}return h(),()=>{n=!0}},[s]),j?e.jsx(k,{children:e.jsx(M,{className:"py-8 text-center text-muted-foreground",children:"Loading disputes..."})}):e.jsxs(k,{children:[e.jsxs(U,{children:[e.jsxs(V,{className:"flex items-center gap-2",children:[e.jsx(Ce,{className:"h-5 w-5 text-warning"}),"Active Disputes"]}),e.jsx(Y,{children:"Invoices currently under dispute"})]}),e.jsx(M,{children:x.length===0?e.jsx("p",{className:"text-sm text-muted-foreground text-center py-6",children:"No active disputes"}):e.jsx("div",{className:"space-y-3",children:x.map(n=>e.jsxs("div",{className:"p-3 rounded-lg border border-warning/30 bg-warning/5",children:[e.jsxs("div",{className:"flex items-center justify-between mb-1",children:[e.jsx("p",{className:"font-medium text-sm",children:n.client_name}),e.jsxs(ve,{variant:"outline",className:"text-warning border-warning",children:["$",n.amount.toLocaleString()]})]}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[n.invoice_number," — ",n.reason]})]},n.id))})})]})}function Xe({tenantId:s}){const[x,d]=r.useState(0),[j,N]=r.useState(0),[n,h]=r.useState(!0);return r.useEffect(()=>{let p=!1;async function o(){try{const{data:a,error:c}=await q.from("project_billing_policies").select("id, retainer_amount, monthly_retainer_amount, billing_model, projects!inner(id, tenant_id, status)").eq("projects.tenant_id",s).eq("projects.status","active").eq("billing_model","retainer");if(c)throw c;if(!p){const C=a||[];d(C.length),N(C.reduce((g,i)=>g+(i.monthly_retainer_amount||i.retainer_amount||0),0))}}catch(a){p||re.error("Failed to load recurring billing: "+(a.message||"Unknown error"))}finally{p||h(!1)}}return o(),()=>{p=!0}},[s]),e.jsxs(k,{children:[e.jsxs(U,{children:[e.jsxs(V,{className:"flex items-center gap-2",children:[e.jsx(le,{className:"h-5 w-5"}),"Recurring Revenue"]}),e.jsx(Y,{children:"Active retainer and recurring billing overview"})]}),e.jsx(M,{children:n?e.jsx("p",{className:"text-sm text-muted-foreground text-center py-6",children:"Loading..."}):e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"text-center p-4 rounded-lg bg-muted/50",children:[e.jsx(L,{size:"md",children:x}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Active Retainers"})]}),e.jsxs("div",{className:"text-center p-4 rounded-lg bg-muted/50",children:[e.jsxs(L,{size:"md",children:["$",j.toLocaleStr
16ing()]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Total Budget"})]})]})})]})}function Zs(){const[s,x]=r.useState(!1),[d,j]=r.useState(!1),{canGenerateTranscripts:N,isAdminOrOwner:n}=Oe(),{currentTenant:h}=ie();return e.jsx(Ue,{width:"full",children:e.jsxs(Ve.div,{initial:{opacity:0},animate:{opacity:1},className:"space-y-6",children:[e.jsxs("div",{className:"flex flex-col sm:flex-row sm:items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-3xl font-bold tracking-tight",children:"Billing"}),e.jsx("p",{className:"text-muted-foreground",children:"Track billing status, review unbilled time, and generate invoices"})]}),e.jsx("div",{className:"flex gap-2 flex-wrap items-center",children:e.jsxs(Se,{children:[e.jsx(Ae,{asChild:!0,children:e.jsxs($,{children:[e.jsx(R,{className:"h-4 w-4 mr-2"}),"Actions",e.jsx(Ye,{className:"h-4 w-4 ml-1"})]})}),e.jsxs(Te,{align:"end",children:[e.jsxs(oe,{onClick:()=>x(!0),children:[e.jsx(R,{className:"h-4 w-4 mr-2"}),"Generate Invoice"]}),N&&e.jsxs(oe,{onClick:()=>j(!0),children:[e.jsx(R,{className:"h-4 w-4 mr-2"}),"Billing Statement"]})]})]})})]}),e.jsxs(fe,{defaultValue:"pipeline",className:"w-full",children:[e.jsxs(Ne,{children:[e.jsxs(T,{value:"pipeline",className:"gap-1",children:[e.jsx(_e,{className:"h-3.5 w-3.5"}),"Pipeline"]}),e.jsxs(T,{value:"aging",className:"gap-1",children:[e.jsx(be,{className:"h-3.5 w-3.5"}),"AR Aging"]}),e.jsxs(T,{value:"payments",className:"gap-1",children:[e.jsx(ye,{className:"h-3.5 w-3.5"}),"Payments"]}),e.jsxs(T,{value:"disputes",className:"gap-1",children:[e.jsx(Ce,{className:"h-3.5 w-3.5"}),"Disputes"]}),e.jsxs(T,{value:"recurring",className:"gap-1",children:[e.jsx(le,{className:"h-3.5 w-3.5"}),"Recurring"]})]}),e.jsxs(I,{value:"pipeline",className:"space-y-6 mt-4",children:[e.jsx(Ge,{}),n&&e.jsx(We,{})]}),e.jsx(I,{value:"aging",className:"mt-4",children:e.jsx(De,{})}),e.jsx(I,{value:"payments",className:"mt-4",children:h?.id?e.jsx(Je,{tenantId:h.id}):null}),e.jsx(I,{value:"disputes",className:"mt-4",children:h?.id?e.jsx(Ke,{tenantId:h.id}):null}),e.jsx(I,{value:"recurring",className:"mt-4",children:h?.id?e.jsx(Xe,{tenantId:h.id}):null})]}),e.jsx(we,{open:s,onOpenChange:x,onSuccess:()=>{}}),e.jsx(Be,{open:d,onOpenChange:j})]})})}export{Zs 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.