1import{r as D,j as e}from"./vendor-react-DKbe1Umz.js";import{u as R,a as S}from"./vendor-data-CjSe2wkl.js";import{u as ye,C as y,s as g,t as N,v as f,A as ge,E as Ne,F as K,G as B,w as L,B as x,D as W,c as Y,d as J,e as X,f as Z,L as c,I as w,T as O,n as ee,S as fe,g as be,h as Ce,i as De,j as I,q as n,o as P,l as m}from"./index-DZ74KeH3.js";import{D as we}from"./date-picker-C8kJjZS9.js";import{C as Se}from"./checkbox-B-BhVsyi.js";import{c0 as b,ay as te,cd as Q,bY as Ie,U as ae,F as $,i as Pe,b8 as se,er as ne,aT as ie}from"./vendor-ui-DMaW9-Ov.js";import{a as F}from"./vendor-dates-5UNeOyFW.js";import"./vendor-charts-DWX9qznF.js";import"./vendor-forms-C2vWC2ab.js";import"./calendar-D1tc6ow-.js";function Le(){const{toast:d}=ye(),[u,H]=D.useState(new Set),[de,T]=D.useState(!1),[le,M]=D.useState(!1),[z,G]=D.useState(null),[r,C]=D.useState({amount:"",paymentDate:new Date().toISOString().split("T")[0],paymentMethod:"CHECK",referenceNumber:"",notes:""}),[i,p]=D.useState({clientName:"",clientAddress:"",clientEmail:"",dueDate:"",taxRate:"0",notes:""}),{data:s,isLoading:re}=R({queryKey:["/api/tm-billing/summary"]}),{data:h,isLoading:ce}=R({queryKey:["/api/tm-billing/pending"]}),{data:o,isLoading:oe}=R({queryKey:["/api/tm-billing/approved"]}),{data:j,isLoading:me}=R({queryKey:["/api/tm-invoices"]}),A=S({mutationFn:async t=>P("POST",`/api/tm-tickets/${t}/approve-for-billing`,{}),onSuccess:()=>{n.invalidateQueries({queryKey:["/api/tm-billing/summary"]}),n.invalidateQueries({queryKey:["/api/tm-billing/pending"]}),n.invalidateQueries({queryKey:["/api/tm-billing/approved"]}),d({title:"Ticket approved for billing"})},onError:()=>{d({title:"Failed to approve ticket",variant:"destructive"})}}),k=S({mutationFn:async t=>P("POST","/api/tm-invoices",t),onSuccess:()=>{n.invalidateQueries({queryKey:["/api/tm-billing/summary"]}),n.invalidateQueries({queryKey:["/api/tm-billing/pending"]}),n.invalidateQueries({queryKey:["/api/tm-billing/approved"]}),n.invalidateQueries({queryKey:["/api/tm-invoices"]}),T(!1),H(new Set),d({title:"Invoice created successfully"})},onError:()=>{d({title:"Failed to create invoice",variant:"destructive"})}}),V=S({mutationFn:async t=>P("POST",`/api/tm-invoices/${t}/mark-paid`,{}),onSuccess:()=>{n.invalidateQueries({queryKey:["/api/tm-invoices"]}),n.invalidateQueries({queryKey:["/api/tm-billing/summary"]}),d({title:"Invoice marked as paid"})},onError:()=>{d({title:"Failed to mark invoice as paid",variant:"destructive"})}}),U=S({mutationFn:async t=>P("POST",`/api/tm-invoices/${t}/send`,{}),onSuccess:()=>{n.invalidateQueries({queryKey:["/api/tm-invoices"]}),n.invalidateQueries({queryKey:["/api/tm-billing/summary"]}),d({title:"Invoice marked as sent"})},onError:()=>{d({title:"Failed to mark invoice as sent",variant:"destructive"})}}),q=S({mutationFn:async t=>P("POST",`/api/tm-invoices/${t.invoiceId}/record-payment`,t),onSuccess:()=>{n.invalidateQueries({queryKey:["/api/tm-invoices"]}),n.invalidateQueries({queryKey:["/api/tm-billing/summary"]}),n.invalidateQueries({queryKey:["/api/payments/ar-summary"]}),M(!1),G(null),C({amount:"",paymentDate:new Date().toISOString().split("T")[0],paymentMethod:"CHECK",referenceNumber:"",notes:""}),d({title:"Payment recorded successfully"})},onError:()=>{d({title:"Failed to record payment",variant:"destructive"})}}),xe=t=>{G(t),M(!0)},ue=()=>{if(!z)return;const t=parseFloat(r.amount);if(isNaN(t)||t<=0){d({title:"Please enter a valid payment amount",variant:"destructive"});return}q.mutate({invoiceId:z,amount:t,paymentDate:r.paymentDate,paymentMethod:r.paymentMethod,referenceNumber:r.referenceNumber||void 0,notes:r.notes||void 0})},pe=(t,a)=>{const l=new Set(u);a?l.add(t):l.delete(t),H(l)},he=()=>{if(u.size===0){d({title:"Please select at least one ticket",variant:"destructive"});return}const t=o==null?void 0:o.find(a=>u.has(a.id));t!=null&&t.project&&p(a=>{var l;return{...a,clientName:((l=t.project)==null?void 0:l.clientName)||""}}),T(!0)},je=()=>{const t=Array.from(u);k.mutate({ticketIds:t,clientName:i.clientName,clientAddress:i.clientAddress||void 0,clientEmail:i.clientEmail||void 0,dueDate:i.dueDate||void 0,taxRate:i.taxRate||void 0,notes:i.notes||void 0})},v=t=>new Intl.NumberFormat("en-US",{style:"currency",currency:"USD"}).format(Number(t)),_=t=>{switch(t){case"PENDING":return e.jsxs(m,{variant:"secondary","data-testid":"badge-status-pending",children:[e.jsx(te,{className:"h-3 w-3 mr-1"}),"Pending"]});case"APPROVED_FOR_BILLING":return e.jsxs(m,{variant:"default","data-testid":"badge-status-approved",children:[e.jsx(Q,{className:"h-3 w-3 mr-1"}),"Ready to Invoice"]});case"INVOICED":return e.jsxs(m,{variant:"outline","data-testid":"badge-status-invoiced",children:[e.jsx($,{className:"h-3 w-3 mr-1"}),"Invoiced"]});case"BILLED":return e.jsxs(m,{className:"bg-green-600","data-testid":"badge-status-billed",children:[e.jsx(ae,{className:"h-3 w-3 mr-1"}),"Billed"]});default:return e.jsx(m,{variant:"secondary",children:t})}},ve=t=>{switch(t){case"DRAFT":return e.jsx(m,{variant:"secondary","data-testid":"badge-invoice-draft",children:"Draft"});case"SENT":return e.jsxs(m,{variant:"default","data-testid":"badge-invoice-sent",children:[e.jsx(se,{className:"h-3 w-3 mr-1"}),"Sent"]});case"PAID":return e.jsxs(m,{className:"bg-green-600","data-testid":"badge-invoice-paid",children:[e.jsx(ie,{className:"h-3 w-3 mr-1"}),"Paid"]});case"CANCELLED":return e.jsx(m,{variant:"destructive","data-testid":"badge-invoice-cancelled",children:"Cancelled"});default:return e.jsx(m,{variant:"secondary",children:t})}};return re?e.jsx("div",{className:"flex items-center justify-center h-64",children:e.jsx(b,{className:"h-8 w-8 animate-spin"})}):e.jsxs("div",{className:"container mx-auto max-w-full p-6 space-y-6",children:[e.jsx("div",{className:"flex items-center justify-between",children:e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold","data-testid":"text-page-title",children:"T&M Billing Management"}),e.jsx("p",{className:"text-muted-foreground",children:"Approve tickets, generate invoices, and track payments"})]})}),e.jsxs("div",{className:"grid gap-4 md:grid-cols-4",children:[e.jsxs(y,{children:[e.jsxs(g,{className:"flex flex-row items-center justify-between gap-2 space-y-0 pb-2",children:[e.jsx(N,{className:"text-sm font-medium",children:"Pending Approval"}),e.jsx(te,{className:"h-4 w-4 text-muted-foreground"})]}),e.jsxs(f,{children:[e.jsx("div",{className:"text-2xl font-bold","data-testid":"text-pending-count",children:(s==null?void 0:s.pendingCount)||0}),e.jsx("p",{className:"text-xs text-muted-foreground",children:v((s==null?void 0:s.pendingTotal)||0)})]})]}),e.jsxs(y,{children:[e.jsxs(g,{className:"flex flex-row items-center justify-between gap-2 space-y-0 pb-2",children:[e.jsx(N,{className:"text-sm font-medium",children:"Ready to Invoice"}),e.jsx(Q,{className:"h-4 w-4 text-muted-foreground"})]}),e.jsxs(f,{children:[e.jsx("div",{className:"text-2xl font-bold","data-testid":"text-approved-count",children:(s==null?void 0:s.approvedForBilling
1Count)||0}),e.jsx("p",{className:"text-xs text-muted-foreground",children:v((s==null?void 0:s.approvedForBillingTotal)||0)})]})]}),e.jsxs(y,{children:[e.jsxs(g,{className:"flex flex-row items-center justify-between gap-2 space-y-0 pb-2",children:[e.jsx(N,{className:"text-sm font-medium",children:"Outstanding Invoices"}),e.jsx(Ie,{className:"h-4 w-4 text-muted-foreground"})]}),e.jsxs(f,{children:[e.jsx("div",{className:"text-2xl font-bold","data-testid":"text-outstanding-count",children:(s==null?void 0:s.sentInvoices)||0}),e.jsx("p",{className:"text-xs text-muted-foreground",children:v((s==null?void 0:s.totalInvoiced)||0)})]})]}),e.jsxs(y,{children:[e.jsxs(g,{className:"flex flex-row items-center justify-between gap-2 space-y-0 pb-2",children:[e.jsx(N,{className:"text-sm font-medium",children:"Total Collected"}),e.jsx(ae,{className:"h-4 w-4 text-muted-foreground"})]}),e.jsxs(f,{children:[e.jsx("div",{className:"text-2xl font-bold","data-testid":"text-collected-total",children:v((s==null?void 0:s.totalPaid)||0)}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[(s==null?void 0:s.paidInvoices)||0," invoices paid"]})]})]})]}),e.jsxs(ge,{defaultValue:"pending",className:"space-y-4",children:[e.jsxs(Ne,{children:[e.jsxs(K,{value:"pending","data-testid":"tab-pending",children:["Pending Approval (",(h==null?void 0:h.length)||0,")"]}),e.jsxs(K,{value:"approved","data-testid":"tab-approved",children:["Ready to Invoice (",(o==null?void 0:o.length)||0,")"]}),e.jsxs(K,{value:"invoices","data-testid":"tab-invoices",children:["Invoices (",(j==null?void 0:j.length)||0,")"]})]}),e.jsx(B,{value:"pending",className:"space-y-4",children:e.jsxs(y,{children:[e.jsxs(g,{children:[e.jsx(N,{children:"Tickets Pending Billing Approval"}),e.jsx(L,{children:"Review and approve completed T&M tickets for billing"})]}),e.jsx(f,{children:ce?e.jsx("div",{className:"flex items-center justify-center h-32",children:e.jsx(b,{className:"h-6 w-6 animate-spin"})}):h!=null&&h.length?e.jsx("div",{className:"space-y-2",children:h.map(t=>{var a,l,E;return e.jsxs("div",{className:"flex items-center justify-between p-4 border rounded-lg","data-testid":`ticket-pending-${t.id}`,children:[e.jsxs("div",{className:"space-y-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-medium",children:t.ticketNumber}),_(t.billingStatus)]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:(a=t.project)==null?void 0:a.name}),e.jsx("p",{className:"text-sm",children:t.scopeDescription}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[F(new Date(t.workDate),"MMM d, yyyy")," ⢠Created by ",(l=t.createdBy)==null?void 0:l.firstName," ",(E=t.createdBy)==null?void 0:E.lastName]})]}),e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("span",{className:"text-lg font-bold",children:v(t.grandTotal)}),e.jsx(x,{onClick:()=>A.mutate(t.id),disabled:A.isPending,"data-testid":`button-approve-${t.id}`,children:A.isPending?e.jsx(b,{className:"h-4 w-4 animate-spin"}):"Approve for Billing"})]})]},t.id)})}):e.jsxs("div",{className:"text-center py-8 text-muted-foreground",children:[e.jsx(Q,{className:"h-12 w-12 mx-auto mb-2 opacity-50"}),e.jsx("p",{children:"No tickets pending approval"})]})})]})}),e.jsx(B,{value:"approved",className:"space-y-4",children:e.jsxs(y,{children:[e.jsx(g,{children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx(N,{children:"Tickets Ready for Invoicing"}),e.jsx(L,{children:"Select tickets to include in an invoice"})]}),u.size>0&&e.jsxs(x,{onClick:he,"data-testid":"button-generate-invoice",children:[e.jsx($,{className:"h-4 w-4 mr-2"}),"Generate Invoice (",u.size," tickets)"]})]})}),e.jsx(f,{children:oe?e.jsx("div",{className:"flex items-center justify-center h-32",children:e.jsx(b,{className:"h-6 w-6 animate-spin"})}):o!=null&&o.length?e.jsx("div",{className:"space-y-2",children:o.map(t=>{var a,l;return e.jsxs("div",{className:"flex items-center gap-4 p-4 border rounded-lg","data-testid":`ticket-approved-${t.id}`,children:[e.jsx(Se,{checked:u.has(t.id),onCheckedChange:E=>pe(t.id,E),"data-testid":`checkbox-ticket-${t.id}`}),e.jsxs("div",{className:"flex-1 space-y-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-medium",children:t.ticketNumber}),_(t.billingStatus)]}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:[(a=t.project)==null?void 0:a.name," ⢠",(l=t.project)==null?void 0:l.clientName]}),e.jsx("p",{className:"text-sm",children:t.scopeDescription}),e.jsx("p",{className:"text-xs text-muted-foreground",children:F(new Date(t.workDate),"MMM d, yyyy")})]}),e.jsx("span",{className:"text-lg font-bold",children:v(t.grandTotal)})]},t.id)})}):e.jsxs("div",{className:"text-center py-8 text-muted-foreground",children:[e.jsx(Pe,{className:"h-12 w-12 mx-auto mb-2 opacity-50"}),e.jsx("p",{children:"No tickets ready for invoicing"})]})})]})}),e.jsx(B,{value:"invoices",className:"space-y-4",children:e.jsxs(y,{children:[e.jsxs(g,{children:[e.jsx(N,{children:"Invoices"}),e.jsx(L,{children:"Track invoice status and payments"})]}),e.jsx(f,{children:me?e.jsx("div",{className:"flex items-center justify-center h-32",children:e.jsx(b,{className:"h-6 w-6 animate-spin"})}):j!=null&&j.length?e.jsx("div",{className:"space-y-2",children:j.map(t=>{var a;return e.jsxs("div",{className:"flex items-center justify-between p-4 border rounded-lg","data-testid":`invoice-${t.id}`,children:[e.jsxs("div",{className:"space-y-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-medium",children:t.invoiceNumber}),ve(t.status)]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:(a=t.project)==null?void 0:a.name}),e.jsxs("p",{className:"text-sm",children:[t.clientName," ⢠",t.ticketCount," tickets"]}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Created"," ",F(new Date(t.invoiceDate),"MMM d, yyyy"),t.dueDate&&` ⢠Due ${F(new Date(t.dueDate),"MMM d, yyyy")}`]})]}),e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("span",{className:"text-lg font-bold",children:v(t.total)}),e.jsxs("div",{className:"flex gap-2",children:[t.status==="DRAFT"&&e.jsxs(x,{variant:"outline",size:"sm",onClick:()=>U.mutate(t.id),disabled:U.isPending,"data-testid":`button-send-${t.id}`,children:[e.jsx(se,{className:"h-4 w-4 mr-1"}),"Mark Sent"]}),(t.status==="DRAFT"||t.status==="SENT")&&e.jsxs(e.Fragment,{children:[e.jsxs(x,{variant:"outline",size:"sm",onClick:()=>xe(t.id),"data-testid":`button-record-payment-${t.id}`,children:[e.jsx(ne,{className:"h-4 w-4 mr-1"}),"Record Payment"]}),e.jsxs(x,{size:"sm",onClick:()=>V.mutate(t.id),disabled:V.isPending,"data-testid":`button-paid-${t.id}`,children:[e.jsx(ie,{className:"h-4 w-4 mr-1"}),"Mark Paid"]})]})]})]})]},t.id)})}):e.jsxs("div",{className:"text-center py-8 text-muted-foreground",children:[e.jsx($,{className:"h-12 w-12 mx-auto mb-2 opacity-50"}),e.jsx("p",{children:"No invoices created yet"})]})})]})})]}),e.jsx(W,{open:de,onOpenChange:T,children:e.jsxs(Y,{children:[e.jsxs(J,{children:[e.jsx(X,{children:"Generate Invoice"}),e.jsxs(Z,{children:["Create an invoice for ",u.size," selected ticket(s)"]})]}),e.jsxs("div",{className:"space-y-4 py-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(c,{htmlFor:"clientName",children:"Client Name *"}),e.jsx(w,{id:"clientName",value:i.clientName,onChange:t=>p(a=>({...a,clientName:t.target.value})),placeholder:"Enter client name","data-testid":"input-client-name"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(c,{htmlFor:"clientEmail",children:"Client Email"}),e.jsx(w,{id:"clientEmail",type:"email",value:i.clientEmail,onChange:t=>p(a=>({...a,clientEmail:t.target.value})),placeholder:"[email protected]","data-testid":"input-client-email"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(c,{htmlFor:"clientAddress",children:"Client Address"}),e.jsx(O,{id:"clientAddress",value:i.clientAddress,onChange:t=>p(a=>({...a,clientAddress:t.target.value})),placeholder:"Enter billing address","data-testid":"input-client-address"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(c,{htmlFor:"dueDate",children:"Due Date"}),e.jsx(we,{value:i.dueDate||void 0,onChange:t=>p(a=>({...a,dueDate:t?F(t,"yyyy-MM-dd"):""})),placeholder:"Select due date","data-testid":"input-due-date"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(c,{htmlFor:"taxRate",children:"Tax Rate (%)"}),e.jsx(w,{id:"taxRate",type:"number",step:"0.01",value:i.taxRate,onChange:t=>p(a=>({...a,taxRate:t.target.value})),placeholder:"0","data-testid":"input-tax-rate"})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(c,{htmlFor:"notes",children:"Notes"}),e.jsx(O,{id:"notes",value:i.notes,onChange:t=>p(a=>({...a,notes:t.target.value})),placeholder:"Additional notes for the invoice","data-testid":"input-notes"})]})]}),e.jsxs(ee,{children:[e.jsx(x,{variant:"outline",onClick:()=>T(!1),"data-testid":"button-cancel-invoice",children:"Cancel"}),e.jsxs(x,{onClick:je,disabled:!i.clientName||k.isPending,"data-testid":"button-create-invoice",children:[k.isPending?e.jsx(b,{className:"h-4 w-4 animate-spin mr-2"}):null,"Create Invoice"]})]})]})}),e.jsx(W,{open:le,onOpenChange:M,children:e.jsxs(Y,{children:[e.jsxs(J,{children:[e.jsx(X,{children:"Record Payment"}),e.jsx(Z,{children:"Record a payment received for this invoice"})]}),e.jsxs("div",{className:"space-y-4 py-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(c,{htmlFor:"paymentAmount",children:"Payment Amount *"}),e.jsx(w,{id:"paymentAmount",type:"number",step:"0.01",value:r.amount,onChange:t=>C(a=>({...a,amount:t.target.value})),placeholder:"0.00","data-testid":"input-payment-amount"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(c,{htmlFor:"paymentDate",children:"Payment Date *"}),e.jsx(w,{id:"paymentDate",type:"date",value:r.paymentDate,onChange:t=>C(a=>({...a,paymentDate:t.target.value})),"data-testid":"input-payment-date"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(c,{htmlFor:"paymentMethod",children:"Payment Method"}),e.jsxs(fe,{value:r.paymentMethod,onValueChange:t=>C(a=>({...a,paymentMethod:t})),children:[e.jsx(be,{"data-testid":"select-payment-method",children:e.jsx(Ce,{placeholder:"Select method"})}),e.jsxs(De,{children:[e.jsx(I,{value:"CHECK",children:"Check"}),e.jsx(I,{value:"ACH",children:"ACH"}),e.jsx(I,{value:"WIRE",children:"Wire Transfer"}),e.jsx(I,{value:"CREDIT_CARD",children:"Credit Card"}),e.jsx(I,{value:"OTHER",children:"Other"})]})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(c,{htmlFor:"referenceNumber",children:"Reference Number"}),e.jsx(w,{id:"referenceNumber",value:r.referenceNumber,onChange:t=>C(a=>({...a,referenceNumber:t.target.value})),placeholder:"Check # or transaction ID","data-testid":"input-reference-number"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(c,{htmlFor:"paymentNotes",children:"Notes"}),e.jsx(O,{id:"paymentNotes",value:r.notes,onChange:t=>C(a=>({...a,notes:t.target.value})),placeholder:"Payment notes","data-testid":"input-payment-notes"})]})]}),e.jsxs(ee,{children:[e.jsx(x,{variant:"outline",onClick:()=>M(!1),"data-testid":"button-cancel-payment",children:"Cancel"}),e.jsxs(x,{onClick:ue,disabled:!r.amount||q.isPending,"data-testid":"button-submit-payment",children:[q.isPending?e.jsx(b,{className:"h-4 w-4 animate-spin mr-2"}):e.jsx(ne,{className:"h-4 w-4 mr-2"}),"Record Payment"]})]})]})})]})}export{Le 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.