@powerhousedao/contributor-billing 0.1.3 → 0.1.4
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.
- package/dist/document-models/expense-report/gen/actions.d.ts +4 -0
- package/dist/document-models/expense-report/gen/actions.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/actions.js +1 -0
- package/dist/document-models/expense-report/gen/creators.d.ts +2 -0
- package/dist/document-models/expense-report/gen/creators.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/creators.js +1 -0
- package/dist/document-models/expense-report/gen/document-model.d.ts +3 -0
- package/dist/document-models/expense-report/gen/document-model.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/document-model.js +202 -0
- package/dist/document-models/expense-report/gen/expense-report/actions.d.ts +8 -0
- package/dist/document-models/expense-report/gen/expense-report/actions.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/expense-report/actions.js +1 -0
- package/dist/document-models/expense-report/gen/expense-report/creators.d.ts +4 -0
- package/dist/document-models/expense-report/gen/expense-report/creators.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/expense-report/creators.js +3 -0
- package/dist/document-models/expense-report/gen/expense-report/error.d.ts +2 -0
- package/dist/document-models/expense-report/gen/expense-report/error.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/expense-report/error.js +1 -0
- package/dist/document-models/expense-report/gen/expense-report/object.d.ts +7 -0
- package/dist/document-models/expense-report/gen/expense-report/object.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/expense-report/object.js +7 -0
- package/dist/document-models/expense-report/gen/expense-report/operations.d.ts +7 -0
- package/dist/document-models/expense-report/gen/expense-report/operations.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/expense-report/operations.js +1 -0
- package/dist/document-models/expense-report/gen/index.d.ts +8 -0
- package/dist/document-models/expense-report/gen/index.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/index.js +6 -0
- package/dist/document-models/expense-report/gen/object.d.ts +15 -0
- package/dist/document-models/expense-report/gen/object.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/object.js +25 -0
- package/dist/document-models/expense-report/gen/ph-factories.d.ts +27 -0
- package/dist/document-models/expense-report/gen/ph-factories.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/ph-factories.js +189 -0
- package/dist/document-models/expense-report/gen/reducer.d.ts +5 -0
- package/dist/document-models/expense-report/gen/reducer.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/reducer.js +76 -0
- package/dist/document-models/expense-report/gen/schema/index.d.ts +3 -0
- package/dist/document-models/expense-report/gen/schema/index.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/schema/index.js +2 -0
- package/dist/document-models/expense-report/gen/schema/types.d.ts +254 -0
- package/dist/document-models/expense-report/gen/schema/types.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/schema/types.js +1 -0
- package/dist/document-models/expense-report/gen/schema/zod.d.ts +32 -0
- package/dist/document-models/expense-report/gen/schema/zod.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/schema/zod.js +216 -0
- package/dist/document-models/expense-report/gen/types.d.ts +10 -0
- package/dist/document-models/expense-report/gen/types.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/types.js +1 -0
- package/dist/document-models/expense-report/gen/utils.d.ts +22 -0
- package/dist/document-models/expense-report/gen/utils.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/utils.js +181 -0
- package/dist/document-models/expense-report/gen/wallet/actions.d.ts +64 -0
- package/dist/document-models/expense-report/gen/wallet/actions.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/wallet/actions.js +1 -0
- package/dist/document-models/expense-report/gen/wallet/creators.d.ts +18 -0
- package/dist/document-models/expense-report/gen/wallet/creators.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/wallet/creators.js +17 -0
- package/dist/document-models/expense-report/gen/wallet/error.d.ts +2 -0
- package/dist/document-models/expense-report/gen/wallet/error.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/wallet/error.js +1 -0
- package/dist/document-models/expense-report/gen/wallet/object.d.ts +21 -0
- package/dist/document-models/expense-report/gen/wallet/object.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/wallet/object.js +49 -0
- package/dist/document-models/expense-report/gen/wallet/operations.d.ts +21 -0
- package/dist/document-models/expense-report/gen/wallet/operations.d.ts.map +1 -0
- package/dist/document-models/expense-report/gen/wallet/operations.js +1 -0
- package/dist/document-models/expense-report/index.d.ts +39 -0
- package/dist/document-models/expense-report/index.d.ts.map +1 -0
- package/dist/document-models/expense-report/index.js +21 -0
- package/dist/document-models/expense-report/src/reducers/wallet.d.ts +3 -0
- package/dist/document-models/expense-report/src/reducers/wallet.d.ts.map +1 -0
- package/dist/document-models/expense-report/src/reducers/wallet.js +180 -0
- package/dist/document-models/expense-report/src/tests/document-model.test.d.ts +6 -0
- package/dist/document-models/expense-report/src/tests/document-model.test.d.ts.map +1 -0
- package/dist/document-models/expense-report/src/tests/document-model.test.js +18 -0
- package/dist/document-models/expense-report/src/tests/expense-report.test.d.ts +6 -0
- package/dist/document-models/expense-report/src/tests/expense-report.test.d.ts.map +1 -0
- package/dist/document-models/expense-report/src/tests/expense-report.test.js +24 -0
- package/dist/document-models/expense-report/src/tests/wallet.test.d.ts +6 -0
- package/dist/document-models/expense-report/src/tests/wallet.test.d.ts.map +1 -0
- package/dist/document-models/expense-report/src/tests/wallet.test.js +24 -0
- package/dist/document-models/expense-report/src/utils.d.ts +2 -0
- package/dist/document-models/expense-report/src/utils.d.ts.map +1 -0
- package/dist/document-models/expense-report/src/utils.js +1 -0
- package/dist/document-models/index.d.ts +1 -0
- package/dist/document-models/index.d.ts.map +1 -1
- package/dist/document-models/index.js +1 -0
- package/dist/document-models/integrations/gen/ph-factories.d.ts.map +1 -1
- package/dist/document-models/integrations/gen/ph-factories.js +2 -14
- package/dist/document-models/integrations/gen/utils.d.ts.map +1 -1
- package/dist/document-models/integrations/gen/utils.js +2 -14
- package/dist/document-models/invoice/gen/ph-factories.d.ts.map +1 -1
- package/dist/document-models/invoice/gen/ph-factories.js +2 -5
- package/dist/document-models/invoice/gen/schema/types.d.ts +1 -1
- package/dist/document-models/invoice/gen/schema/types.d.ts.map +1 -1
- package/dist/document-models/invoice/gen/utils.d.ts.map +1 -1
- package/dist/document-models/invoice/gen/utils.js +1 -4
- package/dist/editors/billing-statement/components/lineItemsTable.d.ts.map +1 -1
- package/dist/editors/billing-statement/components/lineItemsTable.js +71 -13
- package/dist/editors/billing-statement/editor.js +1 -1
- package/dist/editors/contributor-billing/components/DriveExplorer.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/DriveExplorer.js +8 -4
- package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.d.ts +4 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.js +2 -2
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.js +24 -1
- package/dist/editors/expense-report/components/AddBillingStatementModal.d.ts +11 -0
- package/dist/editors/expense-report/components/AddBillingStatementModal.d.ts.map +1 -0
- package/dist/editors/expense-report/components/AddBillingStatementModal.js +170 -0
- package/dist/editors/expense-report/components/AggregatedExpensesTable.d.ts +11 -0
- package/dist/editors/expense-report/components/AggregatedExpensesTable.d.ts.map +1 -0
- package/dist/editors/expense-report/components/AggregatedExpensesTable.js +232 -0
- package/dist/editors/expense-report/components/WalletsTable.d.ts +10 -0
- package/dist/editors/expense-report/components/WalletsTable.d.ts.map +1 -0
- package/dist/editors/expense-report/components/WalletsTable.js +164 -0
- package/dist/editors/expense-report/editor.d.ts +2 -0
- package/dist/editors/expense-report/editor.d.ts.map +1 -0
- package/dist/editors/expense-report/editor.js +88 -0
- package/dist/editors/expense-report/hooks/useSyncWallet.d.ts +5 -0
- package/dist/editors/expense-report/hooks/useSyncWallet.d.ts.map +1 -0
- package/dist/editors/expense-report/hooks/useSyncWallet.js +55 -0
- package/dist/editors/expense-report/hooks/useWalletSync.d.ts +9 -0
- package/dist/editors/expense-report/hooks/useWalletSync.d.ts.map +1 -0
- package/dist/editors/expense-report/hooks/useWalletSync.js +79 -0
- package/dist/editors/expense-report/index.d.ts +3 -0
- package/dist/editors/expense-report/index.d.ts.map +1 -0
- package/dist/editors/expense-report/index.js +11 -0
- package/dist/editors/hooks/useExpenseReportDocument.d.ts +4 -0
- package/dist/editors/hooks/useExpenseReportDocument.d.ts.map +1 -0
- package/dist/editors/hooks/useExpenseReportDocument.js +8 -0
- package/dist/editors/index.d.ts +1 -0
- package/dist/editors/index.d.ts.map +1 -1
- package/dist/editors/index.js +1 -0
- package/dist/editors/invoice/components/statusModalComponents.d.ts.map +1 -1
- package/dist/editors/invoice/components/statusModalComponents.js +4 -4
- package/dist/editors/invoice/editor.js +1 -1
- package/dist/editors/invoice/ingestPDF.d.ts.map +1 -1
- package/dist/editors/invoice/ingestPDF.js +3 -3
- package/dist/editors/invoice/invoiceToGnosis.js +1 -1
- package/dist/editors/invoice/requestFinance.js +1 -1
- package/dist/editors/invoice/uploadPdfChunked.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/powerhouse.manifest.json +13 -2
- package/dist/style.css +525 -37
- package/dist/subgraphs/expense-report/index.d.ts +11 -0
- package/dist/subgraphs/expense-report/index.d.ts.map +1 -0
- package/dist/subgraphs/expense-report/index.js +11 -0
- package/dist/subgraphs/expense-report/resolvers.d.ts +3 -0
- package/dist/subgraphs/expense-report/resolvers.d.ts.map +1 -0
- package/dist/subgraphs/expense-report/resolvers.js +252 -0
- package/dist/subgraphs/expense-report/schema.d.ts +3 -0
- package/dist/subgraphs/expense-report/schema.d.ts.map +1 -0
- package/dist/subgraphs/expense-report/schema.js +228 -0
- package/dist/subgraphs/index.d.ts +1 -0
- package/dist/subgraphs/index.d.ts.map +1 -1
- package/dist/subgraphs/index.js +1 -0
- 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) }) })] }),
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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:
|
|
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,
|
|
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
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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:
|
|
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,
|
|
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,
|
|
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,kDAqS/B"}
|
|
@@ -0,0 +1,170 @@
|
|
|
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
|
+
selectedStatements.forEach((statementId) => {
|
|
116
|
+
const statement = billingStatements.find((s) => s.id === statementId);
|
|
117
|
+
if (!statement || !statement.document)
|
|
118
|
+
return;
|
|
119
|
+
console.log("Statement document:", statement.document);
|
|
120
|
+
// Add billing statement reference to wallet
|
|
121
|
+
dispatch(actions.addBillingStatement({
|
|
122
|
+
wallet: walletAddress,
|
|
123
|
+
billingStatementId: statementId,
|
|
124
|
+
}));
|
|
125
|
+
// Extract line items from billing statement and add to wallet
|
|
126
|
+
const billingState = statement.document;
|
|
127
|
+
const lineItems = billingState.state?.global?.lineItems || [];
|
|
128
|
+
console.log("Line items found:", lineItems.length, lineItems);
|
|
129
|
+
lineItems.forEach((billingLineItem) => {
|
|
130
|
+
const groupId = mapTagToGroup(billingLineItem);
|
|
131
|
+
// Create expense report line item from billing statement line item
|
|
132
|
+
const expenseLineItem = {
|
|
133
|
+
id: generateId(),
|
|
134
|
+
label: billingLineItem.description,
|
|
135
|
+
group: groupId,
|
|
136
|
+
budget: 0, // Could be mapped if available
|
|
137
|
+
actuals: billingLineItem.totalPriceCash || 0,
|
|
138
|
+
forecast: 0, // Could be mapped if available
|
|
139
|
+
payments: 0, // Could be set based on status
|
|
140
|
+
comments: null,
|
|
141
|
+
};
|
|
142
|
+
dispatch(actions.addLineItem({
|
|
143
|
+
wallet: walletAddress,
|
|
144
|
+
lineItem: expenseLineItem,
|
|
145
|
+
}));
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
onClose();
|
|
149
|
+
};
|
|
150
|
+
if (!isOpen)
|
|
151
|
+
return null;
|
|
152
|
+
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) => {
|
|
153
|
+
const isAlreadyAdded = existingBillingStatementIds.has(statement.id);
|
|
154
|
+
const isSelected = selectedStatements.has(statement.id);
|
|
155
|
+
const billingState = statement.document;
|
|
156
|
+
const lineItemCount = billingState.state?.global?.lineItems?.length || 0;
|
|
157
|
+
const totalCash = billingState.state?.global?.totalCash || 0;
|
|
158
|
+
return (_jsxs("div", { onClick: () => toggleStatement(statement.id), className: `flex items-center gap-4 p-4 rounded-lg border-2 transition-all ${isAlreadyAdded
|
|
159
|
+
? "border-gray-300 dark:border-gray-600 bg-gray-100 dark:bg-gray-800 opacity-60 cursor-not-allowed"
|
|
160
|
+
: isSelected
|
|
161
|
+
? "border-blue-500 bg-blue-50 dark:bg-blue-900/20 cursor-pointer"
|
|
162
|
+
: "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
|
|
163
|
+
? "border-gray-400 dark:border-gray-500 bg-gray-200 dark:bg-gray-700"
|
|
164
|
+
: isSelected
|
|
165
|
+
? "bg-blue-500 border-blue-500"
|
|
166
|
+
: "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));
|
|
167
|
+
}) })) : (_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
|
|
168
|
+
? "No billing statements found matching your search"
|
|
169
|
+
: "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})`] })] })] })] })] }));
|
|
170
|
+
}
|
|
@@ -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,kDAye9B"}
|