@powerhousedao/contributor-billing 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/dist/document-models/expense-report/gen/actions.d.ts +4 -0
  2. package/dist/document-models/expense-report/gen/actions.d.ts.map +1 -0
  3. package/dist/document-models/expense-report/gen/actions.js +1 -0
  4. package/dist/document-models/expense-report/gen/creators.d.ts +2 -0
  5. package/dist/document-models/expense-report/gen/creators.d.ts.map +1 -0
  6. package/dist/document-models/expense-report/gen/creators.js +1 -0
  7. package/dist/document-models/expense-report/gen/document-model.d.ts +3 -0
  8. package/dist/document-models/expense-report/gen/document-model.d.ts.map +1 -0
  9. package/dist/document-models/expense-report/gen/document-model.js +202 -0
  10. package/dist/document-models/expense-report/gen/expense-report/actions.d.ts +8 -0
  11. package/dist/document-models/expense-report/gen/expense-report/actions.d.ts.map +1 -0
  12. package/dist/document-models/expense-report/gen/expense-report/actions.js +1 -0
  13. package/dist/document-models/expense-report/gen/expense-report/creators.d.ts +4 -0
  14. package/dist/document-models/expense-report/gen/expense-report/creators.d.ts.map +1 -0
  15. package/dist/document-models/expense-report/gen/expense-report/creators.js +3 -0
  16. package/dist/document-models/expense-report/gen/expense-report/error.d.ts +2 -0
  17. package/dist/document-models/expense-report/gen/expense-report/error.d.ts.map +1 -0
  18. package/dist/document-models/expense-report/gen/expense-report/error.js +1 -0
  19. package/dist/document-models/expense-report/gen/expense-report/object.d.ts +7 -0
  20. package/dist/document-models/expense-report/gen/expense-report/object.d.ts.map +1 -0
  21. package/dist/document-models/expense-report/gen/expense-report/object.js +7 -0
  22. package/dist/document-models/expense-report/gen/expense-report/operations.d.ts +7 -0
  23. package/dist/document-models/expense-report/gen/expense-report/operations.d.ts.map +1 -0
  24. package/dist/document-models/expense-report/gen/expense-report/operations.js +1 -0
  25. package/dist/document-models/expense-report/gen/index.d.ts +8 -0
  26. package/dist/document-models/expense-report/gen/index.d.ts.map +1 -0
  27. package/dist/document-models/expense-report/gen/index.js +6 -0
  28. package/dist/document-models/expense-report/gen/object.d.ts +15 -0
  29. package/dist/document-models/expense-report/gen/object.d.ts.map +1 -0
  30. package/dist/document-models/expense-report/gen/object.js +25 -0
  31. package/dist/document-models/expense-report/gen/ph-factories.d.ts +27 -0
  32. package/dist/document-models/expense-report/gen/ph-factories.d.ts.map +1 -0
  33. package/dist/document-models/expense-report/gen/ph-factories.js +189 -0
  34. package/dist/document-models/expense-report/gen/reducer.d.ts +5 -0
  35. package/dist/document-models/expense-report/gen/reducer.d.ts.map +1 -0
  36. package/dist/document-models/expense-report/gen/reducer.js +76 -0
  37. package/dist/document-models/expense-report/gen/schema/index.d.ts +3 -0
  38. package/dist/document-models/expense-report/gen/schema/index.d.ts.map +1 -0
  39. package/dist/document-models/expense-report/gen/schema/index.js +2 -0
  40. package/dist/document-models/expense-report/gen/schema/types.d.ts +254 -0
  41. package/dist/document-models/expense-report/gen/schema/types.d.ts.map +1 -0
  42. package/dist/document-models/expense-report/gen/schema/types.js +1 -0
  43. package/dist/document-models/expense-report/gen/schema/zod.d.ts +32 -0
  44. package/dist/document-models/expense-report/gen/schema/zod.d.ts.map +1 -0
  45. package/dist/document-models/expense-report/gen/schema/zod.js +216 -0
  46. package/dist/document-models/expense-report/gen/types.d.ts +10 -0
  47. package/dist/document-models/expense-report/gen/types.d.ts.map +1 -0
  48. package/dist/document-models/expense-report/gen/types.js +1 -0
  49. package/dist/document-models/expense-report/gen/utils.d.ts +22 -0
  50. package/dist/document-models/expense-report/gen/utils.d.ts.map +1 -0
  51. package/dist/document-models/expense-report/gen/utils.js +181 -0
  52. package/dist/document-models/expense-report/gen/wallet/actions.d.ts +64 -0
  53. package/dist/document-models/expense-report/gen/wallet/actions.d.ts.map +1 -0
  54. package/dist/document-models/expense-report/gen/wallet/actions.js +1 -0
  55. package/dist/document-models/expense-report/gen/wallet/creators.d.ts +18 -0
  56. package/dist/document-models/expense-report/gen/wallet/creators.d.ts.map +1 -0
  57. package/dist/document-models/expense-report/gen/wallet/creators.js +17 -0
  58. package/dist/document-models/expense-report/gen/wallet/error.d.ts +2 -0
  59. package/dist/document-models/expense-report/gen/wallet/error.d.ts.map +1 -0
  60. package/dist/document-models/expense-report/gen/wallet/error.js +1 -0
  61. package/dist/document-models/expense-report/gen/wallet/object.d.ts +21 -0
  62. package/dist/document-models/expense-report/gen/wallet/object.d.ts.map +1 -0
  63. package/dist/document-models/expense-report/gen/wallet/object.js +49 -0
  64. package/dist/document-models/expense-report/gen/wallet/operations.d.ts +21 -0
  65. package/dist/document-models/expense-report/gen/wallet/operations.d.ts.map +1 -0
  66. package/dist/document-models/expense-report/gen/wallet/operations.js +1 -0
  67. package/dist/document-models/expense-report/index.d.ts +39 -0
  68. package/dist/document-models/expense-report/index.d.ts.map +1 -0
  69. package/dist/document-models/expense-report/index.js +21 -0
  70. package/dist/document-models/expense-report/src/reducers/wallet.d.ts +3 -0
  71. package/dist/document-models/expense-report/src/reducers/wallet.d.ts.map +1 -0
  72. package/dist/document-models/expense-report/src/reducers/wallet.js +180 -0
  73. package/dist/document-models/expense-report/src/tests/document-model.test.d.ts +6 -0
  74. package/dist/document-models/expense-report/src/tests/document-model.test.d.ts.map +1 -0
  75. package/dist/document-models/expense-report/src/tests/document-model.test.js +18 -0
  76. package/dist/document-models/expense-report/src/tests/expense-report.test.d.ts +6 -0
  77. package/dist/document-models/expense-report/src/tests/expense-report.test.d.ts.map +1 -0
  78. package/dist/document-models/expense-report/src/tests/expense-report.test.js +24 -0
  79. package/dist/document-models/expense-report/src/tests/wallet.test.d.ts +6 -0
  80. package/dist/document-models/expense-report/src/tests/wallet.test.d.ts.map +1 -0
  81. package/dist/document-models/expense-report/src/tests/wallet.test.js +24 -0
  82. package/dist/document-models/expense-report/src/utils.d.ts +2 -0
  83. package/dist/document-models/expense-report/src/utils.d.ts.map +1 -0
  84. package/dist/document-models/expense-report/src/utils.js +1 -0
  85. package/dist/document-models/index.d.ts +1 -0
  86. package/dist/document-models/index.d.ts.map +1 -1
  87. package/dist/document-models/index.js +1 -0
  88. package/dist/document-models/integrations/gen/ph-factories.d.ts.map +1 -1
  89. package/dist/document-models/integrations/gen/ph-factories.js +2 -14
  90. package/dist/document-models/integrations/gen/utils.d.ts.map +1 -1
  91. package/dist/document-models/integrations/gen/utils.js +2 -14
  92. package/dist/document-models/invoice/gen/ph-factories.d.ts.map +1 -1
  93. package/dist/document-models/invoice/gen/ph-factories.js +2 -5
  94. package/dist/document-models/invoice/gen/schema/types.d.ts +1 -1
  95. package/dist/document-models/invoice/gen/schema/types.d.ts.map +1 -1
  96. package/dist/document-models/invoice/gen/utils.d.ts.map +1 -1
  97. package/dist/document-models/invoice/gen/utils.js +1 -4
  98. package/dist/editors/billing-statement/components/lineItemsTable.d.ts.map +1 -1
  99. package/dist/editors/billing-statement/components/lineItemsTable.js +71 -13
  100. package/dist/editors/billing-statement/editor.js +1 -1
  101. package/dist/editors/contributor-billing/components/DriveExplorer.d.ts.map +1 -1
  102. package/dist/editors/contributor-billing/components/DriveExplorer.js +8 -4
  103. package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.d.ts +4 -1
  104. package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.d.ts.map +1 -1
  105. package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.js +2 -2
  106. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.d.ts.map +1 -1
  107. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.js +24 -1
  108. package/dist/editors/expense-report/components/AddBillingStatementModal.d.ts +11 -0
  109. package/dist/editors/expense-report/components/AddBillingStatementModal.d.ts.map +1 -0
  110. package/dist/editors/expense-report/components/AddBillingStatementModal.js +195 -0
  111. package/dist/editors/expense-report/components/AggregatedExpensesTable.d.ts +11 -0
  112. package/dist/editors/expense-report/components/AggregatedExpensesTable.d.ts.map +1 -0
  113. package/dist/editors/expense-report/components/AggregatedExpensesTable.js +268 -0
  114. package/dist/editors/expense-report/components/ExpenseReportPDF.d.ts +10 -0
  115. package/dist/editors/expense-report/components/ExpenseReportPDF.d.ts.map +1 -0
  116. package/dist/editors/expense-report/components/ExpenseReportPDF.js +287 -0
  117. package/dist/editors/expense-report/components/WalletsTable.d.ts +10 -0
  118. package/dist/editors/expense-report/components/WalletsTable.d.ts.map +1 -0
  119. package/dist/editors/expense-report/components/WalletsTable.js +164 -0
  120. package/dist/editors/expense-report/editor.d.ts +2 -0
  121. package/dist/editors/expense-report/editor.d.ts.map +1 -0
  122. package/dist/editors/expense-report/editor.js +74 -0
  123. package/dist/editors/expense-report/hooks/useSyncWallet.d.ts +5 -0
  124. package/dist/editors/expense-report/hooks/useSyncWallet.d.ts.map +1 -0
  125. package/dist/editors/expense-report/hooks/useSyncWallet.js +75 -0
  126. package/dist/editors/expense-report/hooks/useWalletSync.d.ts +9 -0
  127. package/dist/editors/expense-report/hooks/useWalletSync.d.ts.map +1 -0
  128. package/dist/editors/expense-report/hooks/useWalletSync.js +77 -0
  129. package/dist/editors/expense-report/index.d.ts +3 -0
  130. package/dist/editors/expense-report/index.d.ts.map +1 -0
  131. package/dist/editors/expense-report/index.js +11 -0
  132. package/dist/editors/hooks/useExpenseReportDocument.d.ts +4 -0
  133. package/dist/editors/hooks/useExpenseReportDocument.d.ts.map +1 -0
  134. package/dist/editors/hooks/useExpenseReportDocument.js +8 -0
  135. package/dist/editors/index.d.ts +1 -0
  136. package/dist/editors/index.d.ts.map +1 -1
  137. package/dist/editors/index.js +1 -0
  138. package/dist/editors/invoice/components/statusModalComponents.d.ts.map +1 -1
  139. package/dist/editors/invoice/components/statusModalComponents.js +4 -4
  140. package/dist/editors/invoice/editor.js +1 -1
  141. package/dist/editors/invoice/ingestPDF.d.ts.map +1 -1
  142. package/dist/editors/invoice/ingestPDF.js +3 -3
  143. package/dist/editors/invoice/invoiceToGnosis.js +1 -1
  144. package/dist/editors/invoice/requestFinance.js +1 -1
  145. package/dist/editors/invoice/uploadPdfChunked.js +1 -1
  146. package/dist/index.d.ts +1 -1
  147. package/dist/index.d.ts.map +1 -1
  148. package/dist/powerhouse.manifest.json +13 -2
  149. package/dist/style.css +539 -37
  150. package/dist/subgraphs/expense-report/index.d.ts +11 -0
  151. package/dist/subgraphs/expense-report/index.d.ts.map +1 -0
  152. package/dist/subgraphs/expense-report/index.js +11 -0
  153. package/dist/subgraphs/expense-report/resolvers.d.ts +3 -0
  154. package/dist/subgraphs/expense-report/resolvers.d.ts.map +1 -0
  155. package/dist/subgraphs/expense-report/resolvers.js +252 -0
  156. package/dist/subgraphs/expense-report/schema.d.ts +3 -0
  157. package/dist/subgraphs/expense-report/schema.d.ts.map +1 -0
  158. package/dist/subgraphs/expense-report/schema.js +228 -0
  159. package/dist/subgraphs/index.d.ts +1 -0
  160. package/dist/subgraphs/index.d.ts.map +1 -1
  161. package/dist/subgraphs/index.js +1 -0
  162. package/package.json +13 -13
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Tag } from "lucide-react";
2
+ import { Tag, Plus } from "lucide-react";
3
3
  import { Select } from "@powerhousedao/document-engineering";
4
4
  import { InputField } from "../../invoice/components/inputField.js";
5
5
  import { NumberForm } from "../../invoice/components/numberForm.js";
@@ -7,6 +7,7 @@ import { actions } from "../../../document-models/billing-statement/index.js";
7
7
  import { useState, useRef, useEffect } from "react";
8
8
  import { formatNumber } from "../../invoice/lineItems.js";
9
9
  import { LineItemTagsTable } from "../lineItemTags/lineItemTags.js";
10
+ import { generateId } from "document-model";
10
11
  const initialLineItem = {
11
12
  description: "",
12
13
  unit: "HOUR",
@@ -19,26 +20,34 @@ const LineItemsTable = (props) => {
19
20
  const [editingRow, setEditingRow] = useState(null);
20
21
  const [localLineItem, setLocalLineItem] = useState(initialLineItem);
21
22
  const [showTagTable, setShowTagTable] = useState(false);
23
+ const [isAddingNew, setIsAddingNew] = useState(false);
24
+ const [newLineItem, setNewLineItem] = useState(initialLineItem);
22
25
  const tableRef = useRef(null);
23
26
  useEffect(() => {
24
27
  function handleClickOutside(event) {
25
28
  // Check if the click is on a select menu or its dropdown
26
29
  const target = event.target;
27
30
  const isSelectMenu = target.closest('[role="listbox"]') || target.closest('[role="option"]');
31
+ // Check if clicking on buttons (save/cancel)
32
+ const isButton = target.closest('button');
28
33
  if (tableRef.current &&
29
34
  !tableRef.current.contains(event.target) &&
30
- !isSelectMenu) {
35
+ !isSelectMenu &&
36
+ !isButton) {
31
37
  // Save changes before clearing the editing state
32
38
  if (editingRow !== null) {
33
39
  handleSave();
34
40
  }
41
+ if (isAddingNew) {
42
+ handleCancelAdd();
43
+ }
35
44
  }
36
45
  }
37
46
  document.addEventListener("mousedown", handleClickOutside);
38
47
  return () => {
39
48
  document.removeEventListener("mousedown", handleClickOutside);
40
49
  };
41
- }, [editingRow, localLineItem]);
50
+ }, [editingRow, localLineItem, isAddingNew, newLineItem]);
42
51
  const units = [
43
52
  { label: "Minute", value: "MINUTE" },
44
53
  { label: "Hour", value: "HOUR" },
@@ -97,6 +106,51 @@ const LineItemsTable = (props) => {
97
106
  setLocalLineItem(initialLineItem);
98
107
  }
99
108
  };
109
+ const handleAddLineItem = () => {
110
+ setIsAddingNew(true);
111
+ setNewLineItem(initialLineItem);
112
+ };
113
+ const handleNewLineItemChange = (field, value) => {
114
+ if (field === "unitPriceCash" || field === "unitPricePwt") {
115
+ // Allow negative numbers with optional minus sign at start
116
+ const regex = new RegExp(`^-?\\d*\\.?\\d{0,6}$`);
117
+ const stringValue = String(value);
118
+ if (regex.test(stringValue) || stringValue === "-") {
119
+ setNewLineItem((prev) => ({ ...prev, [field]: value }));
120
+ }
121
+ }
122
+ else {
123
+ setNewLineItem((prev) => ({ ...prev, [field]: value }));
124
+ }
125
+ };
126
+ const handleSaveNewLineItem = () => {
127
+ const { description, unit, quantity, unitPriceCash, unitPricePwt } = newLineItem;
128
+ if (description &&
129
+ unit &&
130
+ quantity !== "" &&
131
+ unitPriceCash !== "" &&
132
+ unitPricePwt !== "") {
133
+ const qty = Number(quantity);
134
+ const fiat = Number(unitPriceCash);
135
+ const powt = Number(unitPricePwt);
136
+ dispatch(actions.addLineItem({
137
+ id: generateId(),
138
+ description,
139
+ unit,
140
+ quantity: qty,
141
+ unitPriceCash: fiat,
142
+ unitPricePwt: powt,
143
+ totalPriceCash: qty * fiat,
144
+ totalPricePwt: qty * powt,
145
+ }));
146
+ setIsAddingNew(false);
147
+ setNewLineItem(initialLineItem);
148
+ }
149
+ };
150
+ const handleCancelAdd = () => {
151
+ setIsAddingNew(false);
152
+ setNewLineItem(initialLineItem);
153
+ };
100
154
  if (showTagTable) {
101
155
  return (_jsx(LineItemTagsTable, { lineItems: state.lineItems, onClose: () => setShowTagTable(false), dispatch: dispatch }));
102
156
  }
@@ -106,15 +160,19 @@ const LineItemsTable = (props) => {
106
160
  height: 28,
107
161
  color: "white",
108
162
  fill: "#475264",
109
- }, onClick: () => setShowTagTable(!showTagTable) }) })] }), _jsx("div", { className: "mt-4 min-w-[900px]", ref: tableRef, children: _jsxs("table", { className: "w-full border border-gray-300 text-sm", children: [_jsx("thead", { className: "h-12", children: _jsxs("tr", { className: "bg-gray-100 h-10", children: [_jsx("th", { className: "border px-2 py-1 w-10", children: "#" }), _jsx("th", { className: "border px-2 py-1 w-72", children: "Desc" }), _jsx("th", { className: "border px-2 py-1 w-40", children: "Unit" }), _jsx("th", { className: "border px-2 py-1 w-16", children: "Qty" }), _jsx("th", { className: "border px-2 py-1 w-16", children: "FIAT/Unit" }), _jsx("th", { className: "border px-2 py-1 w-16", children: "POWT/Unit" }), _jsx("th", { className: "border px-2 py-1 w-16", children: "Total Fiat" }), _jsx("th", { className: "border px-2 py-1 w-16", children: "Total POWT" })] }) }), _jsx("tbody", { children: state.lineItems.map((item, idx) => editingRow === idx ? (_jsxs("tr", { className: "bg-yellow-100", children: [_jsx("td", { className: "border px-2 py-1 text-center w-10", children: idx + 1 }), _jsx("td", { className: "border px-2 py-1 w-72", children: _jsx(InputField, { input: localLineItem.description, value: localLineItem.description, onBlur: () => { }, handleInputChange: (e) => handleInputChange("description", e.target.value), className: "w-full px-1 py-1 border rounded" }) }), _jsx("td", { className: "border px-2 py-1 w-16", children: _jsx(Select, { options: units, value: localLineItem.unit, onChange: (value) => handleInputChange("unit", value), className: "w-32 px-1 py-1 border rounded" }) }), _jsx("td", { className: "border px-2 py-1 w-16", children: _jsx(NumberForm, { number: localLineItem.quantity, handleInputChange: (e) => handleInputChange("quantity", e.target.value), className: "w-32 px-4 py-1 border rounded text-center" }) }), _jsx("td", { className: "border px-2 py-1 w-16", children: _jsx(NumberForm, { number: localLineItem.unitPriceCash, handleInputChange: (e) => handleInputChange("unitPriceCash", String(e.target.value)), className: "w-32 px-4 py-1 border rounded text-center" }) }), _jsx("td", { className: "border px-2 py-1 w-16", children: _jsx(NumberForm, { number: localLineItem.unitPricePwt, handleInputChange: (e) => handleInputChange("unitPricePwt", e.target.value), className: "w-32 px-4 py-1 border rounded text-center" }) }), _jsx("td", { className: "border px-2 py-1 text-center", children: localLineItem.quantity && localLineItem.unitPriceCash
110
- ? Number(localLineItem.quantity) *
111
- Number(localLineItem.unitPriceCash)
112
- : "" }), _jsx("td", { className: "border px-2 py-1 text-center", children: localLineItem.quantity && localLineItem.unitPricePwt
113
- ? Number(localLineItem.quantity) *
114
- Number(localLineItem.unitPricePwt)
115
- : "" })] }, item.id)) : (_jsxs("tr", { className: "hover:bg-gray-50 cursor-pointer", onDoubleClick: () => {
116
- setEditingRow(idx);
117
- setLocalLineItem({ ...item });
118
- }, children: [_jsx("td", { className: "border px-2 py-2 text-center w-10", children: idx + 1 }), _jsx("td", { className: "border px-2 py-2", children: item.description }), _jsx("td", { className: "border px-2 py-2 w-40 text-center", children: item.unit }), _jsx("td", { className: "border px-2 py-2 w-16 text-center", children: item.quantity }), _jsx("td", { className: "border px-2 py-2 w-10 text-center", children: formatNumber(item.unitPriceCash) }), _jsx("td", { className: "border px-2 py-2 w-10 text-center", children: formatNumber(item.unitPricePwt) }), _jsx("td", { className: "border px-2 py-2 text-center", children: formatNumber(item.totalPriceCash) }), _jsx("td", { className: "border px-2 py-2 text-center", children: formatNumber(item.totalPricePwt) })] }, item.id))) })] }) })] }));
163
+ }, onClick: () => setShowTagTable(!showTagTable) }) })] }), _jsxs("div", { className: "mt-4 min-w-[900px]", ref: tableRef, children: [_jsxs("table", { className: "w-full border border-gray-300 text-sm", children: [_jsx("thead", { className: "h-12", children: _jsxs("tr", { className: "bg-gray-100 h-10", children: [_jsx("th", { className: "border px-2 py-1 w-10", children: "#" }), _jsx("th", { className: "border px-2 py-1 w-72", children: "Desc" }), _jsx("th", { className: "border px-2 py-1 w-40", children: "Unit" }), _jsx("th", { className: "border px-2 py-1 w-16", children: "Qty" }), _jsx("th", { className: "border px-2 py-1 w-16", children: "FIAT/Unit" }), _jsx("th", { className: "border px-2 py-1 w-16", children: "POWT/Unit" }), _jsx("th", { className: "border px-2 py-1 w-16", children: "Total Fiat" }), _jsx("th", { className: "border px-2 py-1 w-16", children: "Total POWT" })] }) }), _jsxs("tbody", { children: [state.lineItems.map((item, idx) => editingRow === idx ? (_jsxs("tr", { className: "bg-yellow-100", children: [_jsx("td", { className: "border px-2 py-1 text-center w-10", children: idx + 1 }), _jsx("td", { className: "border px-2 py-1 w-72", children: _jsx(InputField, { input: localLineItem.description, value: localLineItem.description, onBlur: () => { }, handleInputChange: (e) => handleInputChange("description", e.target.value), className: "w-full px-1 py-1 border rounded" }) }), _jsx("td", { className: "border px-2 py-1 w-16", children: _jsx(Select, { options: units, value: localLineItem.unit, onChange: (value) => handleInputChange("unit", value), className: "w-32 px-1 py-1 border rounded" }) }), _jsx("td", { className: "border px-2 py-1 w-16", children: _jsx(NumberForm, { number: localLineItem.quantity, handleInputChange: (e) => handleInputChange("quantity", e.target.value), className: "w-32 px-4 py-1 border rounded text-center" }) }), _jsx("td", { className: "border px-2 py-1 w-16", children: _jsx(NumberForm, { number: localLineItem.unitPriceCash, handleInputChange: (e) => handleInputChange("unitPriceCash", String(e.target.value)), className: "w-32 px-4 py-1 border rounded text-center" }) }), _jsx("td", { className: "border px-2 py-1 w-16", children: _jsx(NumberForm, { number: localLineItem.unitPricePwt, handleInputChange: (e) => handleInputChange("unitPricePwt", e.target.value), className: "w-32 px-4 py-1 border rounded text-center" }) }), _jsx("td", { className: "border px-2 py-1 text-center", children: localLineItem.quantity && localLineItem.unitPriceCash
164
+ ? Number(localLineItem.quantity) *
165
+ Number(localLineItem.unitPriceCash)
166
+ : "" }), _jsx("td", { className: "border px-2 py-1 text-center", children: localLineItem.quantity && localLineItem.unitPricePwt
167
+ ? Number(localLineItem.quantity) *
168
+ Number(localLineItem.unitPricePwt)
169
+ : "" })] }, item.id)) : (_jsxs("tr", { className: "hover:bg-gray-50 cursor-pointer", onDoubleClick: () => {
170
+ setEditingRow(idx);
171
+ setLocalLineItem({ ...item });
172
+ }, children: [_jsx("td", { className: "border px-2 py-2 text-center w-10", children: idx + 1 }), _jsx("td", { className: "border px-2 py-2", children: item.description }), _jsx("td", { className: "border px-2 py-2 w-40 text-center", children: item.unit }), _jsx("td", { className: "border px-2 py-2 w-16 text-center", children: item.quantity }), _jsx("td", { className: "border px-2 py-2 w-10 text-center", children: formatNumber(item.unitPriceCash) }), _jsx("td", { className: "border px-2 py-2 w-10 text-center", children: formatNumber(item.unitPricePwt) }), _jsx("td", { className: "border px-2 py-2 text-center", children: formatNumber(item.totalPriceCash) }), _jsx("td", { className: "border px-2 py-2 text-center", children: formatNumber(item.totalPricePwt) })] }, item.id))), isAddingNew && (_jsxs("tr", { className: "bg-green-50", children: [_jsx("td", { className: "border px-2 py-1 text-center w-10", children: state.lineItems.length + 1 }), _jsx("td", { className: "border px-2 py-1 w-72", children: _jsx(InputField, { input: newLineItem.description, value: newLineItem.description, onBlur: () => { }, handleInputChange: (e) => handleNewLineItemChange("description", e.target.value), className: "w-full px-1 py-1 border rounded" }) }), _jsx("td", { className: "border px-2 py-1 w-16", children: _jsx(Select, { options: units, value: newLineItem.unit, onChange: (value) => handleNewLineItemChange("unit", value), className: "w-32 px-1 py-1 border rounded" }) }), _jsx("td", { className: "border px-2 py-1 w-16", children: _jsx(NumberForm, { number: newLineItem.quantity, handleInputChange: (e) => handleNewLineItemChange("quantity", e.target.value), className: "w-32 px-4 py-1 border rounded text-center" }) }), _jsx("td", { className: "border px-2 py-1 w-16", children: _jsx(NumberForm, { number: newLineItem.unitPriceCash, handleInputChange: (e) => handleNewLineItemChange("unitPriceCash", String(e.target.value)), className: "w-32 px-4 py-1 border rounded text-center" }) }), _jsx("td", { className: "border px-2 py-1 w-16", children: _jsx(NumberForm, { number: newLineItem.unitPricePwt, handleInputChange: (e) => handleNewLineItemChange("unitPricePwt", e.target.value), className: "w-32 px-4 py-1 border rounded text-center" }) }), _jsx("td", { className: "border px-2 py-1 text-center", children: newLineItem.quantity && newLineItem.unitPriceCash
173
+ ? Number(newLineItem.quantity) * Number(newLineItem.unitPriceCash)
174
+ : "" }), _jsx("td", { className: "border px-2 py-1 text-center", children: newLineItem.quantity && newLineItem.unitPricePwt
175
+ ? Number(newLineItem.quantity) * Number(newLineItem.unitPricePwt)
176
+ : "" })] }))] })] }), !isAddingNew && (_jsx("div", { className: "mt-4 flex justify-center", children: _jsxs("button", { onClick: handleAddLineItem, className: "flex items-center gap-1 px-3 py-1.5 text-sm bg-gray-200 text-gray-700 rounded hover:bg-gray-300 transition-colors", children: [_jsx(Plus, { size: 16 }), "Add Line Item"] }) })), isAddingNew && (_jsxs("div", { className: "mt-4 flex justify-center gap-2", children: [_jsx("button", { onClick: handleSaveNewLineItem, className: "px-3 py-1.5 text-sm bg-green-600 text-white rounded hover:bg-green-700 transition-colors", children: "Save Line Item" }), _jsx("button", { onClick: handleCancelAdd, className: "px-3 py-1.5 text-sm bg-gray-500 text-white rounded hover:bg-gray-600 transition-colors", children: "Cancel" })] }))] })] }));
119
177
  };
120
178
  export default LineItemsTable;
@@ -16,7 +16,7 @@ export default function Editor(props) {
16
16
  const [notes, setNotes] = useState(state.notes ?? "");
17
17
  return (_jsxs("div", { className: "editor-container", children: [_jsxs("div", { className: "grid grid-cols-2 gap-2 border border-gray-500 p-2 rounded-md bg-gray-1001", children: [_jsx("div", { className: "col-span-1 flex items-center", children: _jsx("h1", { className: "text-xl md:text-2xl font-bold", children: "Billing Statement" }) }), _jsxs("div", { className: "grid col-span-1 grid-rows-2 gap-2 justify-end ", children: [_jsxs("div", { className: "col-span-1 space-x-2", children: [_jsx("span", { children: "Submitter" }), _jsx("span", { children: state.contributor })] }), _jsxs("div", { className: "col-span-1 space-x-2", children: [_jsx("span", { children: "Status" }), _jsx("span", { children: state.status })] })] })] }), _jsx("div", { className: "mt-6 p-2", children: _jsxs("div", { className: "flex justify-end", children: [_jsx("span", { className: "mr-2 pt-2", children: "Currency: " }), _jsx(CurrencyForm, { currency: state.currency, handleInputChange: (e) => {
18
18
  dispatch(actions.editBillingStatement({ currency: e.target.value }));
19
- } })] }) }), _jsx("div", { className: "", children: _jsx(LineItemsTable, { state: state, dispatch: dispatch }) }), _jsxs("div", { className: "grid sm:grid-cols-2", children: [_jsx("div", { className: "mt-6 p-2 two-column-grid:mt-2", children: _jsx(Textarea, { label: "Notes", placeholder: "Add notes", autoExpand: false, rows: 4, multiline: true, value: notes, onBlur: (e) => {
19
+ } })] }) }), _jsx("div", { className: "", children: _jsx(LineItemsTable, { state: state, dispatch: dispatch }) }), _jsxs("div", { className: "grid sm:grid-cols-2", children: [_jsx("div", { className: "mt-6 p-2 two-column-grid:mt-2", children: _jsx(Textarea, { label: "Notes", placeholder: "Add notes", autoExpand: true, rows: 4, multiline: true, value: notes, onBlur: (e) => {
20
20
  const newValue = e.target.value;
21
21
  if (newValue !== state.notes) {
22
22
  dispatch(actions.editBillingStatement({ notes: newValue }));
@@ -1 +1 @@
1
- {"version":3,"file":"DriveExplorer.d.ts","sourceRoot":"","sources":["../../../../editors/contributor-billing/components/DriveExplorer.tsx"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,gBAAgB,EAOrB,KAAK,OAAO,EACb,MAAM,gCAAgC,CAAC;AAOxC,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,YAAY,CAAC,EAAE;YACb,OAAO,CAAC,EAAE,OAAO,CAAC;SACnB,CAAC;KACH;CACF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,gBAAgB,2CAsSpD"}
1
+ {"version":3,"file":"DriveExplorer.d.ts","sourceRoot":"","sources":["../../../../editors/contributor-billing/components/DriveExplorer.tsx"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,gBAAgB,EAOrB,KAAK,OAAO,EACb,MAAM,gCAAgC,CAAC;AAOxC,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,YAAY,CAAC,EAAE;YACb,OAAO,CAAC,EAAE,OAAO,CAAC;SACnB,CAAC;KACH;CACF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,gBAAgB,2CAwSpD"}
@@ -155,9 +155,13 @@ export function DriveExplorer(props) {
155
155
  const documentModel = selectedDocumentModel.current;
156
156
  if (!documentModel || !selectedDrive?.header.id)
157
157
  return;
158
- const editorType = documentModel.documentModel.id === "powerhouse/invoice"
159
- ? "powerhouse-invoice-editor"
160
- : "integrations-editor";
158
+ let editorType = "integrations-editor";
159
+ if (documentModel.documentModel.id === "powerhouse/invoice") {
160
+ editorType = "powerhouse-invoice-editor";
161
+ }
162
+ else if (documentModel.documentModel.id === "powerhouse/expense-report") {
163
+ editorType = "powerhouse-expense-report-editor";
164
+ }
161
165
  try {
162
166
  const node = await addDocument(selectedDrive.header.id, fileName, documentModel.documentModel.id, selectedFolder?.id, undefined, undefined, editorType);
163
167
  selectedDocumentModel.current = null;
@@ -181,7 +185,7 @@ export function DriveExplorer(props) {
181
185
  // if a document is selected then it's editor will be passed as children
182
186
  const showDocumentEditor = !!children;
183
187
  // === RENDER ===
184
- return (_jsx("div", { className: "flex h-full editor-container", children: _jsxs("div", { className: "h-full", children: [_jsx(ToastContainer, { position: "bottom-right", autoClose: 5000, hideProgressBar: false, newestOnTop: false, closeOnClick: false, rtl: false, pauseOnFocusLoss: true, draggable: true, pauseOnHover: true, theme: "light" }), _jsx("div", { className: "flex-1", children: showDocumentEditor ? (
188
+ return (_jsx("div", { className: `flex h-full ${showDocumentEditor ? "w-full" : "editor-container"}`, children: _jsxs("div", { className: `h-full ${showDocumentEditor ? "w-full" : ""}`, children: [_jsx(ToastContainer, { position: "bottom-right", autoClose: 5000, hideProgressBar: false, newestOnTop: false, closeOnClick: false, rtl: false, pauseOnFocusLoss: true, draggable: true, pauseOnHover: true, theme: "light" }), _jsx("div", { className: "flex-1", children: showDocumentEditor ? (
185
189
  // Document editor view
186
190
  children) : (_jsxs(_Fragment, { children: [_jsx(HeaderStats, {}), _jsx(InvoiceTable, { files: fileChildren, state: allDocuments || [], selected: selected, setSelected: setSelected, filteredDocumentModels: documentModelModules, onSelectDocumentModel: onSelectDocumentModel, getDocDispatcher: getDocDispatcher, selectedStatuses: selectedStatuses, onStatusChange: handleStatusChange, onRowSelection: handleRowSelection, canExportSelectedRows: canExportSelectedRows })] })) }), _jsx(CreateDocumentModal, { onContinue: onCreateDocument, onOpenChange: (open) => setOpenModal(open), open: openModal })] }) }));
187
191
  }
@@ -1,4 +1,4 @@
1
- export declare const HeaderControls: ({ statusOptions, onStatusChange, onSearchChange, onExport, onExpenseReportExport, selectedStatuses, createIntegrationsDocument, integrationsDoc, canExportSelectedRows, }: {
1
+ export declare const HeaderControls: ({ statusOptions, onStatusChange, onSearchChange, onExport, onExpenseReportExport, selectedStatuses, createIntegrationsDocument, integrationsDoc, canExportSelectedRows, hasBillingStatements, expenseReportDoc, onCreateOrOpenExpenseReport, }: {
2
2
  statusOptions?: {
3
3
  label: string;
4
4
  value: string;
@@ -11,5 +11,8 @@ export declare const HeaderControls: ({ statusOptions, onStatusChange, onSearchC
11
11
  createIntegrationsDocument?: () => void;
12
12
  integrationsDoc?: any | null;
13
13
  canExportSelectedRows?: () => boolean;
14
+ hasBillingStatements?: boolean;
15
+ expenseReportDoc?: any | null;
16
+ onCreateOrOpenExpenseReport?: () => void;
14
17
  }) => import("react/jsx-runtime").JSX.Element;
15
18
  //# sourceMappingURL=HeaderControls.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"HeaderControls.d.ts","sourceRoot":"","sources":["../../../../../editors/contributor-billing/components/InvoiceTable/HeaderControls.tsx"],"names":[],"mappings":"AAcA,eAAO,MAAM,cAAc,GAAI,2KAU5B;IACD,aAAa,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACnD,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;IACpD,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,QAAQ,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,qBAAqB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACvD,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,0BAA0B,CAAC,EAAE,MAAM,IAAI,CAAC;IACxC,eAAe,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;IAC7B,qBAAqB,CAAC,EAAE,MAAM,OAAO,CAAC;CACvC,4CA6LA,CAAC"}
1
+ {"version":3,"file":"HeaderControls.d.ts","sourceRoot":"","sources":["../../../../../editors/contributor-billing/components/InvoiceTable/HeaderControls.tsx"],"names":[],"mappings":"AAcA,eAAO,MAAM,cAAc,GAAI,gPAa5B;IACD,aAAa,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACnD,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;IACpD,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,QAAQ,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,qBAAqB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACvD,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,0BAA0B,CAAC,EAAE,MAAM,IAAI,CAAC;IACxC,eAAe,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;IAC7B,qBAAqB,CAAC,EAAE,MAAM,OAAO,CAAC;IACtC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,gBAAgB,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;IAC9B,2BAA2B,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1C,4CAoMA,CAAC"}
@@ -11,7 +11,7 @@ const currencyOptions = [
11
11
  { label: "GBP", value: "GBP" },
12
12
  { label: "JPY", value: "JPY" },
13
13
  ];
14
- export const HeaderControls = ({ statusOptions = [], onStatusChange, onSearchChange, onExport, onExpenseReportExport, selectedStatuses = [], createIntegrationsDocument, integrationsDoc, canExportSelectedRows, }) => {
14
+ export const HeaderControls = ({ statusOptions = [], onStatusChange, onSearchChange, onExport, onExpenseReportExport, selectedStatuses = [], createIntegrationsDocument, integrationsDoc, canExportSelectedRows, hasBillingStatements = false, expenseReportDoc, onCreateOrOpenExpenseReport, }) => {
15
15
  const batchOptions = [
16
16
  { label: "$ Pay Selected", value: "pay" },
17
17
  { label: "Approve Selected", value: "approve" },
@@ -32,7 +32,7 @@ export const HeaderControls = ({ statusOptions = [], onStatusChange, onSearchCha
32
32
  return (_jsxs("div", { className: "flex flex-col gap-4 mb-4", children: [_jsxs("div", { className: "flex justify-between items-center", children: [_jsxs("div", { className: "flex gap-2 items-center", children: [_jsx(Select, { style: {
33
33
  width: "200px",
34
34
  height: "30px",
35
- }, options: statusOptions, onChange: onStatusChange, placeholder: "Status", selectionIcon: "checkmark", multiple: true, value: selectedStatuses }), _jsx("input", { type: "text", className: "border rounded px-2 py-1 text-sm", placeholder: "Search", onChange: (e) => onSearchChange?.(e.target.value) })] }), _jsxs("div", { className: "flex gap-2 items-center", children: [_jsx("button", { className: `bg-white border border-gray-300 rounded px-3 py-1 text-sm hover:bg-gray-100 ${!canExport ? "opacity-50 cursor-not-allowed" : ""}`, onClick: () => setShowCurrencyModal(true), disabled: !canExport, children: "Export to CSV" }), _jsx(Select, { className: "h-[29px]", contentClassName: "w-54", options: batchOptions, onChange: (value) => handleBatchAction(value), placeholder: "Batch Action" }), _jsx("div", { className: "cursor-pointer", children: _jsx(Icon, { name: "Settings", className: "hover:text-blue-300", onClick: () => {
35
+ }, options: statusOptions, onChange: onStatusChange, placeholder: "Status", selectionIcon: "checkmark", multiple: true, value: selectedStatuses }), _jsx("input", { type: "text", className: "border rounded px-2 py-1 text-sm", placeholder: "Search", onChange: (e) => onSearchChange?.(e.target.value) })] }), _jsxs("div", { className: "flex gap-2 items-center", children: [_jsx("button", { className: `bg-white border border-gray-300 rounded px-3 py-1 text-sm hover:bg-gray-100 ${!hasBillingStatements ? "opacity-50 cursor-not-allowed" : ""}`, onClick: onCreateOrOpenExpenseReport, disabled: !hasBillingStatements, children: expenseReportDoc ? "Expense Report" : "Create Expense Report" }), _jsx("button", { className: `bg-white border border-gray-300 rounded px-3 py-1 text-sm hover:bg-gray-100 ${!canExport ? "opacity-50 cursor-not-allowed" : ""}`, onClick: () => setShowCurrencyModal(true), disabled: !canExport, children: "Export to CSV" }), _jsx(Select, { className: "h-[29px]", contentClassName: "w-54", options: batchOptions, onChange: (value) => handleBatchAction(value), placeholder: "Batch Action" }), _jsx("div", { className: "cursor-pointer", children: _jsx(Icon, { name: "Settings", className: "hover:text-blue-300", onClick: () => {
36
36
  console.log("Settings");
37
37
  if (!integrationsDoc) {
38
38
  createIntegrationsDocument?.();
@@ -1 +1 @@
1
- {"version":3,"file":"InvoiceTable.d.ts","sourceRoot":"","sources":["../../../../../editors/contributor-billing/components/InvoiceTable/InvoiceTable.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AA6B1D,KAAK,YAAY,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAExE,UAAU,iBAAiB;IACzB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,KAAK,EAAE,GAAG,EAAE,CAAC;IACb,QAAQ,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACpC,WAAW,EAAE,CACX,QAAQ,EACJ;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,GACzB,CAAC,CAAC,IAAI,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,KAAK;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,KACjE,IAAI,CAAC;IACV,sBAAsB,EAAE,mBAAmB,EAAE,CAAC;IAC9C,qBAAqB,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC5D,gBAAgB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,GAAG,CAAC;IACtC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;IACnD,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7E,qBAAqB,EAAE,MAAM,OAAO,CAAC;CACtC;AAED,eAAO,MAAM,YAAY,GAAI,uKAW1B,iBAAiB,4CA0nBnB,CAAC"}
1
+ {"version":3,"file":"InvoiceTable.d.ts","sourceRoot":"","sources":["../../../../../editors/contributor-billing/components/InvoiceTable/InvoiceTable.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AA6B1D,KAAK,YAAY,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAExE,UAAU,iBAAiB;IACzB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,KAAK,EAAE,GAAG,EAAE,CAAC;IACb,QAAQ,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACpC,WAAW,EAAE,CACX,QAAQ,EACJ;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,GACzB,CAAC,CAAC,IAAI,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,KAAK;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,KACjE,IAAI,CAAC;IACV,sBAAsB,EAAE,mBAAmB,EAAE,CAAC;IAC9C,qBAAqB,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC5D,gBAAgB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,GAAG,CAAC;IACtC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;IACnD,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7E,qBAAqB,EAAE,MAAM,OAAO,CAAC;CACtC;AAED,eAAO,MAAM,YAAY,GAAI,uKAW1B,iBAAiB,4CAoqBnB,CAAC"}
@@ -217,5 +217,28 @@ export const InvoiceTable = ({ files, state, selected, filteredDocumentModels, o
217
217
  setSelectedNode(createdNode.id);
218
218
  }
219
219
  };
220
- return (_jsxs("div", { className: "w-full h-full bg-white rounded-lg p-4 border border-gray-200 shadow-md mt-4 overflow-x-auto", children: [_jsx(HeaderControls, { statusOptions: statusOptions, onStatusChange: onStatusChange, onExport: handleCSVExport, onExpenseReportExport: handleExportCSVExpenseReport, selectedStatuses: selectedStatuses, createIntegrationsDocument: createIntegrationsDocument, integrationsDoc: integrationsDoc, canExportSelectedRows: canExportSelectedRows }), shouldShowSection("DRAFT") && (_jsx(InvoiceTableSection, { title: "Draft", count: draft.length, onSelectDocumentModel: onSelectDocumentModel, filteredDocumentModels: filteredDocumentModels, children: _jsxs("table", { className: "w-full text-sm border-separate border-spacing-0 border border-gray-400", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "px-2 py-2 w-8" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice No." }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issue Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Due Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Currency" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Amount" }), _jsx("th", { className: "px-2 py-2", children: "Exported" })] }) }), _jsx("tbody", { children: draft.map((row) => (_jsx(InvoiceTableRow, { files: files, row: row, isSelected: !!selected[row.id], onSelect: (checked) => onRowSelection(row.id, checked, row.status) }, row.id))) })] }) })), shouldShowSection("ISSUED") && (_jsx(InvoiceTableSection, { title: "Issued", count: issued.length, children: _jsxs("table", { className: "w-full text-sm border-separate border-spacing-0 border border-gray-400", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "px-2 py-2 w-8" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issuer" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice No." }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issue Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Due Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Currency" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Amount" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Billing Statement" }), _jsx("th", { className: "px-2 py-2", children: "Exported" })] }) }), _jsx("tbody", { children: issued.map((row) => (_jsx(InvoiceTableRow, { files: files, row: row, isSelected: !!selected[row.id], onSelect: (checked) => onRowSelection(row.id, checked, row.status), onCreateBillingStatement: handleCreateBillingStatement, billingDocStates: billingDocStates }, row.id))) })] }) })), shouldShowSection("ACCEPTED") && (_jsx(InvoiceTableSection, { title: "Accepted", count: accepted.length, color: "bg-green-100 text-green-600", children: _jsxs("table", { className: "w-full text-sm border-separate border-spacing-0 border border-gray-400", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "px-2 py-2 w-8" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issuer" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice No." }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issue Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Due Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Currency" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Amount" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Billing Statement" }), _jsx("th", { className: "px-2 py-2", children: "Exported" })] }) }), _jsx("tbody", { children: accepted.map((row) => (_jsx(InvoiceTableRow, { files: files, row: row, isSelected: !!selected[row.id], onSelect: (checked) => onRowSelection(row.id, checked, row.status), onCreateBillingStatement: handleCreateBillingStatement, billingDocStates: billingDocStates }, row.id))) })] }) })), shouldShowSection("PAYMENTSCHEDULED") && (_jsx(InvoiceTableSection, { title: "Payment Scheduled", count: paymentScheduled.length, color: "bg-green-100 text-green-600", children: _jsxs("table", { className: "w-full text-sm border-separate border-spacing-0 border border-gray-400", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "px-2 py-2 w-8" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issuer" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice No." }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issue Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Due Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Currency" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Amount" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Billing Statement" }), _jsx("th", { className: "px-2 py-2", children: "Exported" })] }) }), _jsx("tbody", { children: paymentScheduled.map((row) => (_jsx(InvoiceTableRow, { files: files, row: row, isSelected: !!selected[row.id], onSelect: (checked) => onRowSelection(row.id, checked, row.status), onCreateBillingStatement: handleCreateBillingStatement, billingDocStates: billingDocStates }, row.id))) })] }) })), shouldShowSection("PAYMENTSENT") && (_jsx(InvoiceTableSection, { title: "Payment Sent", count: paymentSent.length, color: "bg-green-100 text-green-600", children: _jsxs("table", { className: "w-full text-sm border-separate border-spacing-0 border border-gray-400", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "px-2 py-2 w-8" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issuer" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice No." }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issue Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Due Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Currency" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Amount" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Billing Statement" }), _jsx("th", { className: "px-2 py-2", children: "Exported" })] }) }), _jsx("tbody", { children: paymentSent.map((row) => (_jsx(InvoiceTableRow, { files: files, row: row, isSelected: !!selected[row.id], onSelect: (checked) => onRowSelection(row.id, checked, row.status), onCreateBillingStatement: handleCreateBillingStatement, billingDocStates: billingDocStates }, row.id))) })] }) })), shouldShowSection("PAYMENTISSUE") && (_jsx(InvoiceTableSection, { title: "Payment Issue", count: paymentIssue.length, color: "bg-yellow-100 text-yellow-600", children: _jsxs("table", { className: "w-full text-sm border-separate border-spacing-0 border border-gray-400", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "px-2 py-2 w-8" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issuer" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice No." }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issue Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Due Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Currency" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Amount" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Billing Statement" }), _jsx("th", { className: "px-2 py-2", children: "Exported" })] }) }), _jsx("tbody", { children: paymentIssue.map((row) => (_jsx(InvoiceTableRow, { files: files, row: row, isSelected: !!selected[row.id], onSelect: (checked) => onRowSelection(row.id, checked, row.status), onCreateBillingStatement: handleCreateBillingStatement, billingDocStates: billingDocStates }, row.id))) })] }) })), shouldShowSection("PAYMENTCLOSED") && (_jsx(InvoiceTableSection, { title: "Payment Closed", count: paymentClosed.length, color: "bg-red-500 text-black-600", children: _jsxs("table", { className: "w-full text-sm border-separate border-spacing-0 border border-gray-400", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "px-2 py-2 w-8" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issuer" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice No." }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issue Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Due Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Currency" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Amount" }), _jsx("th", { className: "px-2 py-2", children: "Exported" })] }) }), _jsx("tbody", { children: paymentClosed.map((row) => (_jsx(InvoiceTableRow, { files: files, row: row, isSelected: !!selected[row.id], onSelect: (checked) => onRowSelection(row.id, checked, row.status) }, row.id))) })] }) })), shouldShowSection("REJECTED") && (_jsx(InvoiceTableSection, { title: "Rejected", count: rejected.length, color: "bg-red-500 text-black-600", children: _jsxs("table", { className: "w-full text-sm border-separate border-spacing-0 border border-gray-400", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "px-2 py-2 w-8" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issuer" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice No." }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issue Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Due Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Currency" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Amount" }), _jsx("th", { className: "px-2 py-2", children: "Exported" })] }) }), _jsx("tbody", { children: rejected.map((row) => (_jsx(InvoiceTableRow, { files: files, row: row, isSelected: !!selected[row.id], onSelect: (checked) => onRowSelection(row.id, checked, row.status) }, row.id))) })] }) })), shouldShowSection("OTHER") && (_jsx(InvoiceTableSection, { title: "Other", count: otherInvoices.length, children: _jsxs("table", { className: "w-full text-sm border-separate border-spacing-0 border border-gray-400", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "px-2 py-2 w-8" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issuer" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice No." }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issue Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Due Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Currency" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Amount" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Exported" })] }) }), _jsx("tbody", { children: otherInvoices.map((row) => (_jsx(InvoiceTableRow, { files: files, row: row, isSelected: !!selected[row.id], onSelect: (checked) => onRowSelection(row.id, checked, row.status) }, row.id))) })] }) }))] }, `${state.length}`));
220
+ // check if expense report document exists
221
+ const expenseReportDoc = files.find((file) => file.documentType === "powerhouse/expense-report");
222
+ // check if at least one billing statement exists
223
+ const hasBillingStatements = state.some((doc) => doc.header.documentType === "powerhouse/billing-statement");
224
+ const handleCreateOrOpenExpenseReport = async () => {
225
+ if (expenseReportDoc) {
226
+ // Open existing expense report
227
+ setSelectedNode(expenseReportDoc.id);
228
+ }
229
+ else {
230
+ // Create new expense report
231
+ const expenseReportModel = filteredDocumentModels?.find((model) => model.documentModel.id === "powerhouse/expense-report");
232
+ if (expenseReportModel) {
233
+ const createdNode = await addDocument(selectedDrive?.header.id || "", `expense-report`, "powerhouse/expense-report", undefined, undefined, undefined, "powerhouse-expense-report-editor");
234
+ console.log("created expense report document", createdNode);
235
+ if (!createdNode?.id) {
236
+ console.error("Failed to create expense report document");
237
+ return null;
238
+ }
239
+ setSelectedNode(createdNode.id);
240
+ }
241
+ }
242
+ };
243
+ return (_jsxs("div", { className: "w-full h-full bg-white rounded-lg p-4 border border-gray-200 shadow-md mt-4 overflow-x-auto", children: [_jsx(HeaderControls, { statusOptions: statusOptions, onStatusChange: onStatusChange, onExport: handleCSVExport, onExpenseReportExport: handleExportCSVExpenseReport, selectedStatuses: selectedStatuses, createIntegrationsDocument: createIntegrationsDocument, integrationsDoc: integrationsDoc, canExportSelectedRows: canExportSelectedRows, hasBillingStatements: hasBillingStatements, expenseReportDoc: expenseReportDoc, onCreateOrOpenExpenseReport: handleCreateOrOpenExpenseReport }), shouldShowSection("DRAFT") && (_jsx(InvoiceTableSection, { title: "Draft", count: draft.length, onSelectDocumentModel: onSelectDocumentModel, filteredDocumentModels: filteredDocumentModels, children: _jsxs("table", { className: "w-full text-sm border-separate border-spacing-0 border border-gray-400", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "px-2 py-2 w-8" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice No." }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issue Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Due Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Currency" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Amount" }), _jsx("th", { className: "px-2 py-2", children: "Exported" })] }) }), _jsx("tbody", { children: draft.map((row) => (_jsx(InvoiceTableRow, { files: files, row: row, isSelected: !!selected[row.id], onSelect: (checked) => onRowSelection(row.id, checked, row.status) }, row.id))) })] }) })), shouldShowSection("ISSUED") && (_jsx(InvoiceTableSection, { title: "Issued", count: issued.length, children: _jsxs("table", { className: "w-full text-sm border-separate border-spacing-0 border border-gray-400", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "px-2 py-2 w-8" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issuer" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice No." }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issue Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Due Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Currency" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Amount" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Billing Statement" }), _jsx("th", { className: "px-2 py-2", children: "Exported" })] }) }), _jsx("tbody", { children: issued.map((row) => (_jsx(InvoiceTableRow, { files: files, row: row, isSelected: !!selected[row.id], onSelect: (checked) => onRowSelection(row.id, checked, row.status), onCreateBillingStatement: handleCreateBillingStatement, billingDocStates: billingDocStates }, row.id))) })] }) })), shouldShowSection("ACCEPTED") && (_jsx(InvoiceTableSection, { title: "Accepted", count: accepted.length, color: "bg-green-100 text-green-600", children: _jsxs("table", { className: "w-full text-sm border-separate border-spacing-0 border border-gray-400", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "px-2 py-2 w-8" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issuer" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice No." }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issue Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Due Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Currency" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Amount" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Billing Statement" }), _jsx("th", { className: "px-2 py-2", children: "Exported" })] }) }), _jsx("tbody", { children: accepted.map((row) => (_jsx(InvoiceTableRow, { files: files, row: row, isSelected: !!selected[row.id], onSelect: (checked) => onRowSelection(row.id, checked, row.status), onCreateBillingStatement: handleCreateBillingStatement, billingDocStates: billingDocStates }, row.id))) })] }) })), shouldShowSection("PAYMENTSCHEDULED") && (_jsx(InvoiceTableSection, { title: "Payment Scheduled", count: paymentScheduled.length, color: "bg-green-100 text-green-600", children: _jsxs("table", { className: "w-full text-sm border-separate border-spacing-0 border border-gray-400", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "px-2 py-2 w-8" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issuer" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice No." }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issue Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Due Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Currency" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Amount" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Billing Statement" }), _jsx("th", { className: "px-2 py-2", children: "Exported" })] }) }), _jsx("tbody", { children: paymentScheduled.map((row) => (_jsx(InvoiceTableRow, { files: files, row: row, isSelected: !!selected[row.id], onSelect: (checked) => onRowSelection(row.id, checked, row.status), onCreateBillingStatement: handleCreateBillingStatement, billingDocStates: billingDocStates }, row.id))) })] }) })), shouldShowSection("PAYMENTSENT") && (_jsx(InvoiceTableSection, { title: "Payment Sent", count: paymentSent.length, color: "bg-green-100 text-green-600", children: _jsxs("table", { className: "w-full text-sm border-separate border-spacing-0 border border-gray-400", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "px-2 py-2 w-8" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issuer" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice No." }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issue Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Due Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Currency" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Amount" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Billing Statement" }), _jsx("th", { className: "px-2 py-2", children: "Exported" })] }) }), _jsx("tbody", { children: paymentSent.map((row) => (_jsx(InvoiceTableRow, { files: files, row: row, isSelected: !!selected[row.id], onSelect: (checked) => onRowSelection(row.id, checked, row.status), onCreateBillingStatement: handleCreateBillingStatement, billingDocStates: billingDocStates }, row.id))) })] }) })), shouldShowSection("PAYMENTISSUE") && (_jsx(InvoiceTableSection, { title: "Payment Issue", count: paymentIssue.length, color: "bg-yellow-100 text-yellow-600", children: _jsxs("table", { className: "w-full text-sm border-separate border-spacing-0 border border-gray-400", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "px-2 py-2 w-8" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issuer" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice No." }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issue Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Due Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Currency" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Amount" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Billing Statement" }), _jsx("th", { className: "px-2 py-2", children: "Exported" })] }) }), _jsx("tbody", { children: paymentIssue.map((row) => (_jsx(InvoiceTableRow, { files: files, row: row, isSelected: !!selected[row.id], onSelect: (checked) => onRowSelection(row.id, checked, row.status), onCreateBillingStatement: handleCreateBillingStatement, billingDocStates: billingDocStates }, row.id))) })] }) })), shouldShowSection("PAYMENTCLOSED") && (_jsx(InvoiceTableSection, { title: "Payment Closed", count: paymentClosed.length, color: "bg-red-500 text-black-600", children: _jsxs("table", { className: "w-full text-sm border-separate border-spacing-0 border border-gray-400", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "px-2 py-2 w-8" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issuer" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice No." }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issue Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Due Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Currency" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Amount" }), _jsx("th", { className: "px-2 py-2", children: "Exported" })] }) }), _jsx("tbody", { children: paymentClosed.map((row) => (_jsx(InvoiceTableRow, { files: files, row: row, isSelected: !!selected[row.id], onSelect: (checked) => onRowSelection(row.id, checked, row.status) }, row.id))) })] }) })), shouldShowSection("REJECTED") && (_jsx(InvoiceTableSection, { title: "Rejected", count: rejected.length, color: "bg-red-500 text-black-600", children: _jsxs("table", { className: "w-full text-sm border-separate border-spacing-0 border border-gray-400", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "px-2 py-2 w-8" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issuer" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice No." }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issue Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Due Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Currency" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Amount" }), _jsx("th", { className: "px-2 py-2", children: "Exported" })] }) }), _jsx("tbody", { children: rejected.map((row) => (_jsx(InvoiceTableRow, { files: files, row: row, isSelected: !!selected[row.id], onSelect: (checked) => onRowSelection(row.id, checked, row.status) }, row.id))) })] }) })), shouldShowSection("OTHER") && (_jsx(InvoiceTableSection, { title: "Other", count: otherInvoices.length, children: _jsxs("table", { className: "w-full text-sm border-separate border-spacing-0 border border-gray-400", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "px-2 py-2 w-8" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issuer" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Invoice No." }), _jsx("th", { className: "px-2 py-2 text-center", children: "Issue Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Due Date" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Currency" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Amount" }), _jsx("th", { className: "px-2 py-2 text-center", children: "Exported" })] }) }), _jsx("tbody", { children: otherInvoices.map((row) => (_jsx(InvoiceTableRow, { files: files, row: row, isSelected: !!selected[row.id], onSelect: (checked) => onRowSelection(row.id, checked, row.status) }, row.id))) })] }) }))] }, `${state.length}`));
221
244
  };
@@ -0,0 +1,11 @@
1
+ import type { LineItemGroup } from "../../../document-models/expense-report/gen/types.js";
2
+ interface AddBillingStatementModalProps {
3
+ isOpen: boolean;
4
+ onClose: () => void;
5
+ walletAddress: string;
6
+ dispatch: any;
7
+ groups: LineItemGroup[];
8
+ }
9
+ export declare function AddBillingStatementModal({ isOpen, onClose, walletAddress, dispatch, groups, }: AddBillingStatementModalProps): import("react/jsx-runtime").JSX.Element | null;
10
+ export {};
11
+ //# sourceMappingURL=AddBillingStatementModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AddBillingStatementModal.d.ts","sourceRoot":"","sources":["../../../../editors/expense-report/components/AddBillingStatementModal.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sDAAsD,CAAC;AAO1F,UAAU,6BAA6B;IACrC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,GAAG,CAAC;IACd,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AA+BD,wBAAgB,wBAAwB,CAAC,EACvC,MAAM,EACN,OAAO,EACP,aAAa,EACb,QAAQ,EACR,MAAM,GACP,EAAE,6BAA6B,kDAuU/B"}
@@ -0,0 +1,195 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useMemo } from "react";
3
+ import { Button } from "@powerhousedao/document-engineering";
4
+ import { useSelectedDriveDocuments } from "@powerhousedao/reactor-browser";
5
+ import { generateId } from "document-model";
6
+ import { X, FileText, Check } from "lucide-react";
7
+ import { actions } from "../../../document-models/expense-report/index.js";
8
+ // Mapping of fusion labels to group IDs
9
+ const fusionLabelToValue = {
10
+ Budget: "budget",
11
+ "Current Liability": "liabilities/current",
12
+ "Interest Income": "income/interest",
13
+ "Travel & Entertainment": "expenses/headcount/travel-and-entertainment",
14
+ "Cost of Goods Sold": "expenses/non-headcount/direct-costs",
15
+ "Marketing Expense": "expenses/headcount/marketing",
16
+ "Professional Services": "expenses/headcount/professional-services",
17
+ "Software Development Expense": "expenses/non-headcount/software-development",
18
+ "Compensation & Benefits": "expenses/headcount/compensation-and-benefits",
19
+ "Admin Expense": "expenses/headcount/admin",
20
+ "Other Income Expense (Non-operating)": "income/non-operating",
21
+ "Other Income": "income/other",
22
+ "Income Tax Expense": "expenses/non-headcount/income-tax",
23
+ "Current Asset": "assets/current",
24
+ "Software Expense": "expenses/non-headcount/software",
25
+ "Fixed Asset": "assets/fixed",
26
+ "Non-Current Asset": "assets/non-current",
27
+ "Gas Expense": "expenses/non-headcount/gas",
28
+ "Adjustment A/C": "accounts/adjustment",
29
+ "Temporary Holding Account": "accounts/temporary",
30
+ Other: "accounts/other",
31
+ "Internal Transfers": "accounts/internal-transfers",
32
+ "Owner Equity": "equity/owner",
33
+ "Non-current Liability": "liabilities/non-current",
34
+ Equity: "equity/retained",
35
+ };
36
+ export function AddBillingStatementModal({ isOpen, onClose, walletAddress, dispatch, groups, }) {
37
+ const documents = useSelectedDriveDocuments();
38
+ const [selectedStatements, setSelectedStatements] = useState(new Set());
39
+ const [searchTerm, setSearchTerm] = useState("");
40
+ // Get already added billing statement IDs for this wallet from documents
41
+ const existingBillingStatementIds = useMemo(() => {
42
+ if (!documents)
43
+ return new Set();
44
+ const expenseReports = documents.filter((doc) => doc.header.documentType === "powerhouse/expense-report");
45
+ const ids = new Set();
46
+ expenseReports.forEach((doc) => {
47
+ const wallets = doc.state?.global?.wallets || [];
48
+ const wallet = wallets.find((w) => w.wallet === walletAddress);
49
+ if (wallet?.billingStatements) {
50
+ wallet.billingStatements.forEach((id) => {
51
+ if (id)
52
+ ids.add(id);
53
+ });
54
+ }
55
+ });
56
+ return ids;
57
+ }, [documents, walletAddress]);
58
+ // Get billing statement documents from the drive
59
+ const billingStatements = useMemo(() => {
60
+ if (!documents)
61
+ return [];
62
+ return documents
63
+ .filter((doc) => doc.header.documentType === "powerhouse/billing-statement")
64
+ .map((doc) => ({
65
+ id: doc.header.id,
66
+ name: doc.header.name,
67
+ document: doc, // Full document with state
68
+ }));
69
+ }, [documents]);
70
+ // Filter billing statements based on search term
71
+ const filteredStatements = useMemo(() => {
72
+ if (!searchTerm.trim())
73
+ return billingStatements;
74
+ const search = searchTerm.toLowerCase();
75
+ return billingStatements.filter((stmt) => stmt.name.toLowerCase().includes(search));
76
+ }, [billingStatements, searchTerm]);
77
+ // Toggle statement selection
78
+ const toggleStatement = (id) => {
79
+ // Don't allow selecting already-added statements
80
+ if (existingBillingStatementIds.has(id)) {
81
+ return;
82
+ }
83
+ const newSelected = new Set(selectedStatements);
84
+ if (newSelected.has(id)) {
85
+ newSelected.delete(id);
86
+ }
87
+ else {
88
+ newSelected.add(id);
89
+ }
90
+ setSelectedStatements(newSelected);
91
+ };
92
+ // Format currency with thousand separators
93
+ const formatCurrency = (value) => {
94
+ return new Intl.NumberFormat("en-US", {
95
+ style: "currency",
96
+ currency: "USD",
97
+ minimumFractionDigits: 2,
98
+ maximumFractionDigits: 2,
99
+ }).format(value);
100
+ };
101
+ // Map billing statement line item tag to expense report group
102
+ const mapTagToGroup = (lineItem) => {
103
+ // Find expense-account tag
104
+ const expenseAccountTag = lineItem.lineItemTag?.find((tag) => tag.dimension === "expense-account");
105
+ if (!expenseAccountTag || !expenseAccountTag.label)
106
+ return null;
107
+ // Find matching group by label
108
+ const group = groups.find((g) => g.label === expenseAccountTag.label);
109
+ return group ? group.id : null;
110
+ };
111
+ // Add selected billing statements to wallet
112
+ const handleAddStatements = () => {
113
+ if (selectedStatements.size === 0)
114
+ return;
115
+ // First, add all billing statement references
116
+ selectedStatements.forEach((statementId) => {
117
+ dispatch(actions.addBillingStatement({
118
+ wallet: walletAddress,
119
+ billingStatementId: statementId,
120
+ }));
121
+ });
122
+ // Aggregate line items by category across all selected billing statements
123
+ const categoryAggregation = new Map();
124
+ selectedStatements.forEach((statementId) => {
125
+ const statement = billingStatements.find((s) => s.id === statementId);
126
+ if (!statement || !statement.document)
127
+ return;
128
+ console.log("Statement document:", statement.document);
129
+ // Extract line items from billing statement
130
+ const billingState = statement.document;
131
+ const lineItems = billingState.state?.global?.lineItems || [];
132
+ console.log("Line items found:", lineItems.length, lineItems);
133
+ // Aggregate line items by category
134
+ lineItems.forEach((billingLineItem) => {
135
+ const groupId = mapTagToGroup(billingLineItem);
136
+ const categoryKey = groupId || "uncategorized";
137
+ const existing = categoryAggregation.get(categoryKey);
138
+ if (existing) {
139
+ // Aggregate values for the same category
140
+ existing.actuals += billingLineItem.totalPriceCash || 0;
141
+ }
142
+ else {
143
+ // Create new category entry
144
+ const group = groups.find((g) => g.id === groupId);
145
+ categoryAggregation.set(categoryKey, {
146
+ groupId: groupId,
147
+ groupLabel: group?.label || "Uncategorised",
148
+ budget: 0,
149
+ actuals: billingLineItem.totalPriceCash || 0,
150
+ forecast: 0,
151
+ payments: 0,
152
+ });
153
+ }
154
+ });
155
+ });
156
+ // Now add aggregated line items to wallet
157
+ categoryAggregation.forEach((aggregatedItem) => {
158
+ const expenseLineItem = {
159
+ id: generateId(),
160
+ label: aggregatedItem.groupLabel,
161
+ group: aggregatedItem.groupId,
162
+ budget: aggregatedItem.budget,
163
+ actuals: aggregatedItem.actuals,
164
+ forecast: aggregatedItem.forecast,
165
+ payments: aggregatedItem.payments,
166
+ comments: null,
167
+ };
168
+ dispatch(actions.addLineItem({
169
+ wallet: walletAddress,
170
+ lineItem: expenseLineItem,
171
+ }));
172
+ });
173
+ onClose();
174
+ };
175
+ if (!isOpen)
176
+ return null;
177
+ return (_jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center", children: [_jsx("div", { className: "absolute inset-0 bg-black/30 backdrop-blur-sm", onClick: onClose }), _jsxs("div", { className: "relative w-full max-w-4xl max-h-[80vh] bg-white dark:bg-gray-800 rounded-lg shadow-2xl border border-gray-200 dark:border-gray-700 flex flex-col", children: [_jsxs("div", { className: "flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-gray-700", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-xl font-semibold text-gray-900 dark:text-white", children: "Add Billing Statements" }), _jsxs("p", { className: "text-sm text-gray-500 dark:text-gray-400 mt-1", children: ["Select billing statements to add to wallet", " ", walletAddress.substring(0, 10), "..."] })] }), _jsx("button", { onClick: onClose, className: "text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 transition-colors", children: _jsx(X, { size: 24 }) })] }), _jsx("div", { className: "px-6 py-4 border-b border-gray-200 dark:border-gray-700", children: _jsx("div", { className: "relative", children: _jsx("input", { type: "text", placeholder: "Search billing statements...", value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), className: "w-full px-4 py-2 pl-11 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-transparent" }) }) }), _jsx("div", { className: "flex-1 overflow-auto px-6 py-4", children: filteredStatements.length > 0 ? (_jsx("div", { className: "space-y-2", children: filteredStatements.map((statement) => {
178
+ const isAlreadyAdded = existingBillingStatementIds.has(statement.id);
179
+ const isSelected = selectedStatements.has(statement.id);
180
+ const billingState = statement.document;
181
+ const lineItemCount = billingState.state?.global?.lineItems?.length || 0;
182
+ const totalCash = billingState.state?.global?.totalCash || 0;
183
+ return (_jsxs("div", { onClick: () => toggleStatement(statement.id), className: `flex items-center gap-4 p-4 rounded-lg border-2 transition-all ${isAlreadyAdded
184
+ ? "border-gray-300 dark:border-gray-600 bg-gray-100 dark:bg-gray-800 opacity-60 cursor-not-allowed"
185
+ : isSelected
186
+ ? "border-blue-500 bg-blue-50 dark:bg-blue-900/20 cursor-pointer"
187
+ : "border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600 cursor-pointer"}`, children: [_jsx("div", { className: `flex-shrink-0 w-5 h-5 rounded border-2 flex items-center justify-center ${isAlreadyAdded
188
+ ? "border-gray-400 dark:border-gray-500 bg-gray-200 dark:bg-gray-700"
189
+ : isSelected
190
+ ? "bg-blue-500 border-blue-500"
191
+ : "border-gray-300 dark:border-gray-600"}`, children: (isSelected || isAlreadyAdded) && (_jsx(Check, { className: "text-white", size: 14 })) }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-medium text-gray-900 dark:text-white truncate", children: statement.name }), _jsxs("span", { className: "text-xs text-gray-500 dark:text-gray-400 px-2 py-1 bg-gray-100 dark:bg-gray-700 rounded", children: [lineItemCount, " items"] }), isAlreadyAdded && (_jsx("span", { className: "text-xs text-amber-600 dark:text-amber-400 px-2 py-1 bg-amber-50 dark:bg-amber-900/20 rounded font-medium", children: "Already included" }))] }), _jsxs("div", { className: "flex items-center gap-4 mt-1 text-sm text-gray-600 dark:text-gray-400", children: [_jsxs("span", { children: ["Total: ", formatCurrency(totalCash)] }), _jsxs("span", { className: "text-xs font-mono", children: [statement.id.substring(0, 8), "..."] })] })] })] }, statement.id));
192
+ }) })) : (_jsxs("div", { className: "flex flex-col items-center justify-center py-12 text-gray-500 dark:text-gray-400", children: [_jsx(FileText, { size: 48, className: "mb-4 opacity-50" }), _jsx("p", { className: "text-sm", children: searchTerm
193
+ ? "No billing statements found matching your search"
194
+ : "No billing statements available in this drive" })] })) }), _jsxs("div", { className: "flex items-center justify-between px-6 py-4 border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/50", children: [_jsxs("span", { className: "text-sm text-gray-600 dark:text-gray-400", children: [selectedStatements.size, " statement", selectedStatements.size !== 1 ? "s" : "", " selected"] }), _jsxs("div", { className: "flex gap-3", children: [_jsx(Button, { onClick: onClose, className: "px-4 py-2 text-red-600 dark:text-red-400 bg-red-50 dark:bg-red-900/20 hover:bg-red-100 dark:hover:bg-red-900/30", children: "Cancel" }), _jsxs(Button, { onClick: handleAddStatements, disabled: selectedStatements.size === 0, className: "px-4 py-2", children: ["Add", " ", selectedStatements.size > 0 && `(${selectedStatements.size})`] })] })] })] })] }));
195
+ }
@@ -0,0 +1,11 @@
1
+ import type { Wallet, LineItemGroup } from "../../../document-models/expense-report/gen/types.js";
2
+ interface AggregatedExpensesTableProps {
3
+ wallets: Wallet[];
4
+ groups: LineItemGroup[];
5
+ periodStart?: string | null;
6
+ periodEnd?: string | null;
7
+ dispatch: (action: any) => void;
8
+ }
9
+ export declare function AggregatedExpensesTable({ wallets, groups, periodStart, periodEnd, dispatch, }: AggregatedExpensesTableProps): import("react/jsx-runtime").JSX.Element | null;
10
+ export {};
11
+ //# sourceMappingURL=AggregatedExpensesTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AggregatedExpensesTable.d.ts","sourceRoot":"","sources":["../../../../editors/expense-report/components/AggregatedExpensesTable.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAY,MAAM,sDAAsD,CAAC;AAI5G,UAAU,4BAA4B;IACpC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CACjC;AAQD,wBAAgB,uBAAuB,CAAC,EACtC,OAAO,EACP,MAAM,EACN,WAAW,EACX,SAAS,EACT,QAAQ,GACT,EAAE,4BAA4B,kDAmjB9B"}