@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
@@ -0,0 +1,268 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMemo, useState } from "react";
3
+ import React from "react";
4
+ import { actions } from "../../../document-models/expense-report/index.js";
5
+ import { Textarea } from "@powerhousedao/document-engineering";
6
+ export function AggregatedExpensesTable({ wallets, groups, periodStart, periodEnd, dispatch, }) {
7
+ // State for active tab (selected wallet)
8
+ const [activeWalletIndex, setActiveWalletIndex] = useState(0);
9
+ // State for editing comments
10
+ const [editingGroupId, setEditingGroupId] = useState(null);
11
+ const [editingComment, setEditingComment] = useState("");
12
+ const [originalComment, setOriginalComment] = useState("");
13
+ // State for editing numeric fields
14
+ const [editingField, setEditingField] = useState(null);
15
+ const [editingValue, setEditingValue] = useState("");
16
+ // Format period for title
17
+ const periodTitle = useMemo(() => {
18
+ if (!periodStart)
19
+ return "Breakdown";
20
+ const date = new Date(periodStart);
21
+ const month = date.toLocaleDateString("en-US", { month: "short" });
22
+ const year = date.getFullYear();
23
+ return `${month} ${year} Breakdown`;
24
+ }, [periodStart]);
25
+ // Create a map of groups with their parent info
26
+ const groupsMap = useMemo(() => {
27
+ const map = new Map();
28
+ groups.forEach((group) => {
29
+ map.set(group.id, { group });
30
+ });
31
+ // Add parent references
32
+ groups.forEach((group) => {
33
+ if (group.parentId) {
34
+ const entry = map.get(group.id);
35
+ const parentEntry = map.get(group.parentId);
36
+ if (entry && parentEntry) {
37
+ entry.parent = parentEntry.group;
38
+ }
39
+ }
40
+ });
41
+ return map;
42
+ }, [groups]);
43
+ // Get line items for the active wallet with group information
44
+ // Line items are now already aggregated by category
45
+ const walletLineItems = useMemo(() => {
46
+ if (!wallets[activeWalletIndex])
47
+ return [];
48
+ const wallet = wallets[activeWalletIndex];
49
+ const lineItems = wallet.lineItems || [];
50
+ return lineItems
51
+ .filter((item) => item !== null && item !== undefined)
52
+ .map((item) => {
53
+ const groupInfo = item.group ? groupsMap.get(item.group) : undefined;
54
+ return {
55
+ ...item,
56
+ groupLabel: groupInfo?.group.label || item.label || undefined,
57
+ parentGroupId: groupInfo?.parent?.id || null,
58
+ parentGroupLabel: groupInfo?.parent?.label || undefined,
59
+ };
60
+ });
61
+ }, [wallets, activeWalletIndex, groupsMap]);
62
+ // Group line items by parent category
63
+ // Line items are already aggregated by category, so we just need to group them by parent
64
+ const groupedAndAggregatedItems = useMemo(() => {
65
+ const grouped = new Map();
66
+ walletLineItems.forEach((item) => {
67
+ if (!item)
68
+ return;
69
+ const parentKey = item.parentGroupId || "uncategorized";
70
+ const items = grouped.get(parentKey) || [];
71
+ items.push({
72
+ lineItemId: item.id || "",
73
+ groupId: item.group || "uncategorized",
74
+ groupLabel: item.groupLabel || "Uncategorised",
75
+ parentGroupId: item.parentGroupId,
76
+ parentGroupLabel: item.parentGroupLabel,
77
+ budget: item.budget || 0,
78
+ forecast: item.forecast || 0,
79
+ actuals: item.actuals || 0,
80
+ payments: item.payments || 0,
81
+ comment: item.comments || "",
82
+ });
83
+ grouped.set(parentKey, items);
84
+ });
85
+ return grouped;
86
+ }, [walletLineItems]);
87
+ // Calculate subtotals for each parent group
88
+ const calculateSubtotal = (items) => {
89
+ return items.reduce((acc, item) => ({
90
+ budget: acc.budget + item.budget,
91
+ forecast: acc.forecast + item.forecast,
92
+ actuals: acc.actuals + item.actuals,
93
+ difference: acc.difference + (item.forecast - item.actuals),
94
+ payments: acc.payments + item.payments,
95
+ }), { budget: 0, forecast: 0, actuals: 0, difference: 0, payments: 0 });
96
+ };
97
+ // Calculate grand totals
98
+ const grandTotals = useMemo(() => {
99
+ return walletLineItems.reduce((acc, item) => ({
100
+ budget: acc.budget + (item?.budget || 0),
101
+ forecast: acc.forecast + (item?.forecast || 0),
102
+ actuals: acc.actuals + (item?.actuals || 0),
103
+ difference: acc.difference + ((item?.forecast || 0) - (item?.actuals || 0)),
104
+ payments: acc.payments + (item?.payments || 0),
105
+ }), { budget: 0, forecast: 0, actuals: 0, difference: 0, payments: 0 });
106
+ }, [walletLineItems]);
107
+ const formatNumber = (value) => {
108
+ return new Intl.NumberFormat("en-US", {
109
+ minimumFractionDigits: 2,
110
+ maximumFractionDigits: 2,
111
+ }).format(value);
112
+ };
113
+ const formatWalletAddress = (address) => {
114
+ if (!address || address.length < 13)
115
+ return address;
116
+ return `${address.substring(0, 6)}...${address.substring(address.length - 6)}`;
117
+ };
118
+ // Handle starting comment edit
119
+ const handleStartEdit = (lineItemId, currentComment) => {
120
+ setEditingGroupId(lineItemId);
121
+ setEditingComment(currentComment);
122
+ setOriginalComment(currentComment);
123
+ };
124
+ // Handle saving comment for a single line item
125
+ const handleSaveComment = () => {
126
+ const wallet = wallets[activeWalletIndex];
127
+ if (!wallet || !wallet.wallet || !editingGroupId)
128
+ return;
129
+ // Only dispatch if the comment has actually changed
130
+ if (editingComment !== originalComment) {
131
+ dispatch(actions.updateLineItem({
132
+ wallet: wallet.wallet,
133
+ lineItemId: editingGroupId,
134
+ comments: editingComment,
135
+ }));
136
+ }
137
+ // Reset editing state
138
+ setEditingGroupId(null);
139
+ setEditingComment("");
140
+ setOriginalComment("");
141
+ };
142
+ // Handle canceling comment edit
143
+ const handleCancelEdit = () => {
144
+ setEditingGroupId(null);
145
+ setEditingComment("");
146
+ setOriginalComment("");
147
+ };
148
+ // Handle starting numeric field edit
149
+ const handleStartFieldEdit = (lineItemId, field, currentValue) => {
150
+ setEditingField({ lineItemId, field, originalValue: currentValue });
151
+ setEditingValue(currentValue.toString());
152
+ };
153
+ // Handle saving numeric field
154
+ const handleSaveField = () => {
155
+ const wallet = wallets[activeWalletIndex];
156
+ if (!wallet || !wallet.wallet || !editingField)
157
+ return;
158
+ const numericValue = parseFloat(editingValue);
159
+ if (isNaN(numericValue)) {
160
+ // Invalid number, cancel edit
161
+ handleCancelFieldEdit();
162
+ return;
163
+ }
164
+ // Only dispatch if the value has actually changed
165
+ if (numericValue !== editingField.originalValue) {
166
+ dispatch(actions.updateLineItem({
167
+ wallet: wallet.wallet,
168
+ lineItemId: editingField.lineItemId,
169
+ [editingField.field]: numericValue,
170
+ }));
171
+ }
172
+ // Reset editing state
173
+ setEditingField(null);
174
+ setEditingValue("");
175
+ };
176
+ // Handle canceling numeric field edit
177
+ const handleCancelFieldEdit = () => {
178
+ setEditingField(null);
179
+ setEditingValue("");
180
+ };
181
+ // Sort parent groups: Headcount first, then Non-Headcount, then others, then uncategorized
182
+ const sortedParentKeys = useMemo(() => {
183
+ const keys = Array.from(groupedAndAggregatedItems.keys());
184
+ // Find Headcount and Non-Headcount group IDs
185
+ const headcountGroup = groups.find(g => g.label === "Headcount Expenses");
186
+ const nonHeadcountGroup = groups.find(g => g.label === "Non-Headcount Expenses");
187
+ return keys.sort((a, b) => {
188
+ // Uncategorized always goes last
189
+ if (a === "uncategorized")
190
+ return 1;
191
+ if (b === "uncategorized")
192
+ return -1;
193
+ // Headcount Expenses always first
194
+ if (a === headcountGroup?.id)
195
+ return -1;
196
+ if (b === headcountGroup?.id)
197
+ return 1;
198
+ // Non-Headcount Expenses always second
199
+ if (a === nonHeadcountGroup?.id)
200
+ return -1;
201
+ if (b === nonHeadcountGroup?.id)
202
+ return 1;
203
+ // For other groups, maintain their original order
204
+ return 0;
205
+ });
206
+ }, [groupedAndAggregatedItems, groups]);
207
+ if (wallets.length === 0) {
208
+ return null;
209
+ }
210
+ return (_jsxs("div", { className: "space-y-4", children: [_jsx("div", { className: "border-b border-gray-200 dark:border-gray-700", children: _jsx("nav", { className: "-mb-px flex space-x-8", "aria-label": "Tabs", children: wallets.map((wallet, index) => {
211
+ const isActive = index === activeWalletIndex;
212
+ return (_jsx("button", { onClick: () => setActiveWalletIndex(index), className: `
213
+ whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm transition-colors
214
+ ${isActive
215
+ ? "border-green-500 text-green-600 dark:text-green-400"
216
+ : "border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-600"}
217
+ `, children: wallet.name || formatWalletAddress(wallet.wallet || "") }, wallet.wallet || index));
218
+ }) }) }), _jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "min-w-full divide-y divide-gray-200 dark:divide-gray-700", children: [_jsx("thead", { className: "bg-gray-50 dark:bg-gray-800", children: _jsxs("tr", { children: [_jsx("th", { className: "px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Expense Category" }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Mthly Budget" }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Forecast" }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Actuals" }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Difference" }), _jsx("th", { className: "px-3 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider w-96", children: "Comments" }), _jsx("th", { className: "px-3 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider w-32", children: "Payments" })] }) }), _jsxs("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-700", children: [sortedParentKeys.map((parentKey) => {
219
+ const items = groupedAndAggregatedItems.get(parentKey) || [];
220
+ if (items.length === 0)
221
+ return null;
222
+ const subtotals = calculateSubtotal(items);
223
+ const parentLabel = parentKey === "uncategorized"
224
+ ? "Uncategorised"
225
+ : items[0]?.parentGroupLabel || "Other";
226
+ return (_jsxs(React.Fragment, { children: [_jsx("tr", { className: "bg-gray-100 dark:bg-gray-800", children: _jsx("td", { colSpan: 7, className: "px-6 py-3 text-sm font-bold text-gray-900 dark:text-white", children: parentLabel }) }), items.map((item) => {
227
+ if (!item)
228
+ return null;
229
+ const difference = item.forecast - item.actuals;
230
+ const isEditingComment = editingGroupId === item.lineItemId;
231
+ // Helper function to render editable numeric cell
232
+ const renderEditableCell = (field, value) => {
233
+ const isEditingThis = editingField?.lineItemId === item.lineItemId &&
234
+ editingField?.field === field;
235
+ if (isEditingThis) {
236
+ return (_jsx("div", { className: "flex items-center gap-1", children: _jsx("input", { type: "number", step: "0.01", value: editingValue, onChange: (e) => setEditingValue(e.target.value), onKeyDown: (e) => {
237
+ if (e.key === "Enter") {
238
+ handleSaveField();
239
+ }
240
+ else if (e.key === "Escape") {
241
+ handleCancelFieldEdit();
242
+ }
243
+ }, onBlur: handleSaveField, autoFocus: true, className: "w-full px-2 py-1 text-right text-sm border border-blue-500 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-800 text-gray-900 dark:text-white" }) }));
244
+ }
245
+ return (_jsx("div", { className: "group cursor-pointer text-right", onClick: () => handleStartFieldEdit(item.lineItemId, field, value), children: _jsx("span", { className: "group-hover:bg-blue-50 dark:group-hover:bg-blue-900/20 inline-block px-1 py-0.5 rounded transition-colors min-w-[4rem]", children: formatNumber(value) }) }));
246
+ };
247
+ return (_jsxs("tr", { className: "bg-white dark:bg-gray-900 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors align-top", children: [_jsx("td", { className: "px-6 py-3 whitespace-nowrap text-sm text-gray-900 dark:text-white", children: item.groupLabel }), _jsx("td", { className: "px-6 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: renderEditableCell("budget", item.budget) }), _jsx("td", { className: "px-6 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: renderEditableCell("forecast", item.forecast) }), _jsx("td", { className: "px-6 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: renderEditableCell("actuals", item.actuals) }), _jsx("td", { className: `px-6 py-3 whitespace-nowrap text-right text-sm font-medium ${difference < 0
248
+ ? "text-red-600 dark:text-red-400"
249
+ : "text-gray-900 dark:text-white"}`, children: formatNumber(difference) }), _jsx("td", { className: "px-3 py-3 text-sm w-96", children: isEditingComment ? (_jsx(Textarea, { value: editingComment, onChange: (e) => setEditingComment(e.target.value), placeholder: "Add comment...", autoExpand: true, multiline: true, onKeyDown: (e) => {
250
+ if (e.key === "Enter" && !e.shiftKey) {
251
+ e.preventDefault();
252
+ handleSaveComment();
253
+ }
254
+ else if (e.key === "Escape") {
255
+ handleCancelEdit();
256
+ }
257
+ else if (e.key === "Tab") {
258
+ e.preventDefault();
259
+ handleSaveComment();
260
+ }
261
+ }, onBlur: handleSaveComment, autoFocus: true, className: "w-full px-2 py-1 text-sm border border-blue-500 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-800 text-gray-900 dark:text-white max-h-32 overflow-y-auto" })) : (_jsx("div", { className: "group cursor-pointer w-full max-h-20 overflow-hidden", onClick: () => handleStartEdit(item.lineItemId, item.comment), title: item.comment || "No comments", children: _jsx("span", { className: "group-hover:bg-blue-50 dark:group-hover:bg-blue-900/20 px-1 py-0.5 rounded transition-colors block text-gray-600 dark:text-gray-400 break-words", children: item.comment || "No comments" }) })) }), _jsx("td", { className: "px-3 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white w-32", children: renderEditableCell("payments", item.payments) })] }, item.lineItemId));
262
+ }), _jsxs("tr", { className: "bg-gray-50 dark:bg-gray-800/50 font-semibold align-top", children: [_jsx("td", { className: "px-6 py-3 whitespace-nowrap text-sm text-gray-900 dark:text-white", children: "Subtotal" }), _jsx("td", { className: "px-6 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(subtotals.budget) }) }) }), _jsx("td", { className: "px-6 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(subtotals.forecast) }) }) }), _jsx("td", { className: "px-6 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(subtotals.actuals) }) }) }), _jsx("td", { className: `px-6 py-3 whitespace-nowrap text-right text-sm font-bold ${subtotals.difference < 0
263
+ ? "text-red-600 dark:text-red-400"
264
+ : "text-gray-900 dark:text-white"}`, children: formatNumber(subtotals.difference) }), _jsx("td", { className: "px-3 py-3" }), _jsx("td", { className: "px-3 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white w-32", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(subtotals.payments) }) }) })] })] }, parentKey));
265
+ }), _jsxs("tr", { className: "bg-gray-100 dark:bg-gray-800 font-bold align-top", children: [_jsx("td", { className: "px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white", children: "Total" }), _jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(grandTotals.budget) }) }) }), _jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(grandTotals.forecast) }) }) }), _jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(grandTotals.actuals) }) }) }), _jsx("td", { className: `px-6 py-4 whitespace-nowrap text-right text-sm ${grandTotals.difference < 0
266
+ ? "text-red-600 dark:text-red-400"
267
+ : "text-gray-900 dark:text-white"}`, children: formatNumber(grandTotals.difference) }), _jsx("td", { className: "px-3 py-4" }), _jsx("td", { className: "px-3 py-4 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white w-32", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(grandTotals.payments) }) }) })] })] })] }) })] }));
268
+ }
@@ -0,0 +1,10 @@
1
+ import type { Wallet, LineItemGroup } from "../../../document-models/expense-report/gen/types.js";
2
+ interface ExpenseReportPDFProps {
3
+ periodStart?: string | null;
4
+ periodEnd?: string | null;
5
+ wallets: Wallet[];
6
+ groups: LineItemGroup[];
7
+ }
8
+ export declare function ExpenseReportPDF({ periodStart, periodEnd, wallets, groups, }: ExpenseReportPDFProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=ExpenseReportPDF.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpenseReportPDF.d.ts","sourceRoot":"","sources":["../../../../editors/expense-report/components/ExpenseReportPDF.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,MAAM,EACN,aAAa,EAEd,MAAM,sDAAsD,CAAC;AAE9D,UAAU,qBAAqB;IAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAmKD,wBAAgB,gBAAgB,CAAC,EAC/B,WAAW,EACX,SAAS,EACT,OAAO,EACP,MAAM,GACP,EAAE,qBAAqB,2CAiVvB"}
@@ -0,0 +1,287 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Document, Page, Text, View, StyleSheet } from "@react-pdf/renderer";
3
+ // Tailwind-inspired styles for PDF
4
+ const styles = StyleSheet.create({
5
+ page: {
6
+ padding: 32,
7
+ fontSize: 8,
8
+ fontFamily: "Helvetica",
9
+ backgroundColor: "#ffffff",
10
+ },
11
+ header: {
12
+ marginBottom: 20,
13
+ borderBottom: "1pt solid #e5e7eb",
14
+ paddingBottom: 12,
15
+ },
16
+ title: {
17
+ fontSize: 18,
18
+ fontWeight: "bold",
19
+ marginBottom: 6,
20
+ color: "#111827",
21
+ textAlign: "center",
22
+ },
23
+ period: {
24
+ fontSize: 9,
25
+ color: "#6b7280",
26
+ textAlign: "center",
27
+ marginTop: 2,
28
+ },
29
+ sectionTitle: {
30
+ fontSize: 12,
31
+ fontWeight: "bold",
32
+ marginTop: 16,
33
+ marginBottom: 8,
34
+ color: "#111827",
35
+ },
36
+ walletInfo: {
37
+ fontSize: 8,
38
+ color: "#6b7280",
39
+ marginBottom: 8,
40
+ },
41
+ table: {
42
+ marginBottom: 16,
43
+ },
44
+ tableHeader: {
45
+ flexDirection: "row",
46
+ borderBottom: "1pt solid #e5e7eb",
47
+ paddingBottom: 6,
48
+ marginBottom: 6,
49
+ backgroundColor: "#f9fafb",
50
+ paddingTop: 6,
51
+ paddingHorizontal: 6,
52
+ },
53
+ tableRow: {
54
+ flexDirection: "row",
55
+ paddingVertical: 4,
56
+ paddingHorizontal: 6,
57
+ borderBottom: "0.5pt solid #f3f4f6",
58
+ minHeight: 20,
59
+ },
60
+ tableRowAlt: {
61
+ flexDirection: "row",
62
+ paddingVertical: 4,
63
+ paddingHorizontal: 6,
64
+ backgroundColor: "#f9fafb",
65
+ borderBottom: "0.5pt solid #f3f4f6",
66
+ minHeight: 20,
67
+ },
68
+ subtotalRow: {
69
+ flexDirection: "row",
70
+ paddingVertical: 6,
71
+ paddingHorizontal: 6,
72
+ borderTop: "1pt solid #d1d5db",
73
+ marginTop: 3,
74
+ fontWeight: "bold",
75
+ backgroundColor: "#fafafa",
76
+ },
77
+ totalRow: {
78
+ flexDirection: "row",
79
+ paddingVertical: 6,
80
+ paddingHorizontal: 6,
81
+ borderTop: "2pt solid #111827",
82
+ marginTop: 3,
83
+ fontWeight: "bold",
84
+ backgroundColor: "#f3f4f6",
85
+ },
86
+ headerCell: {
87
+ fontSize: 7,
88
+ fontWeight: "bold",
89
+ color: "#374151",
90
+ textTransform: "uppercase",
91
+ letterSpacing: 0.3,
92
+ },
93
+ cell: {
94
+ fontSize: 8,
95
+ color: "#111827",
96
+ },
97
+ cellRight: {
98
+ fontSize: 8,
99
+ color: "#111827",
100
+ textAlign: "right",
101
+ },
102
+ cellBold: {
103
+ fontSize: 8,
104
+ color: "#111827",
105
+ fontWeight: "bold",
106
+ },
107
+ // Breakdown table columns - adjusted to match AggregatedExpensesTable
108
+ categoryCol: { width: "20%" },
109
+ budgetCol: { width: "11%", textAlign: "right" },
110
+ forecastCol: { width: "11%", textAlign: "right" },
111
+ actualsCol: { width: "11%", textAlign: "right" },
112
+ differenceCol: { width: "11%", textAlign: "right" },
113
+ commentsCol: { width: "25%", paddingLeft: 4 },
114
+ paymentsCol: { width: "11%", textAlign: "right" },
115
+ commentsText: {
116
+ fontSize: 7,
117
+ color: "#6b7280",
118
+ lineHeight: 1.4,
119
+ },
120
+ // Color styles for difference column
121
+ differenceNegative: {
122
+ color: "#dc2626", // red-600 for negative values
123
+ },
124
+ differenceNormal: {
125
+ color: "#111827", // gray-900 for positive or zero
126
+ },
127
+ pageNumber: {
128
+ position: "absolute",
129
+ bottom: 20,
130
+ left: 0,
131
+ right: 0,
132
+ textAlign: "center",
133
+ fontSize: 7,
134
+ color: "#6b7280",
135
+ },
136
+ });
137
+ // Format number as currency
138
+ const formatNumber = (value) => {
139
+ if (value === null || value === undefined)
140
+ return "0.00";
141
+ return value.toLocaleString("en-US", {
142
+ minimumFractionDigits: 2,
143
+ maximumFractionDigits: 2,
144
+ });
145
+ };
146
+ // Format date
147
+ const formatDate = (dateString) => {
148
+ if (!dateString)
149
+ return "";
150
+ const date = new Date(dateString);
151
+ return date.toLocaleDateString("en-US", {
152
+ month: "short",
153
+ day: "numeric",
154
+ year: "numeric",
155
+ });
156
+ };
157
+ export function ExpenseReportPDF({ periodStart, periodEnd, wallets, groups, }) {
158
+ // Create a map of groups with their parent info
159
+ const groupsMap = new Map();
160
+ groups.forEach((group) => {
161
+ groupsMap.set(group.id, { group });
162
+ });
163
+ groups.forEach((group) => {
164
+ if (group.parentId) {
165
+ const entry = groupsMap.get(group.id);
166
+ const parentEntry = groupsMap.get(group.parentId);
167
+ if (entry && parentEntry) {
168
+ entry.parent = parentEntry.group;
169
+ }
170
+ }
171
+ });
172
+ // Get line items for a wallet with group information
173
+ const getWalletLineItems = (wallet) => {
174
+ const lineItems = wallet.lineItems || [];
175
+ return lineItems
176
+ .filter((item) => item !== null && item !== undefined)
177
+ .map((item) => {
178
+ const groupInfo = item.group ? groupsMap.get(item.group) : undefined;
179
+ return {
180
+ ...item,
181
+ groupLabel: groupInfo?.group.label || item.label || undefined,
182
+ parentGroupId: groupInfo?.parent?.id || null,
183
+ parentGroupLabel: groupInfo?.parent?.label || undefined,
184
+ };
185
+ });
186
+ };
187
+ // Group line items by parent category
188
+ const groupLineItemsByParent = (lineItems) => {
189
+ const grouped = new Map();
190
+ lineItems.forEach((item) => {
191
+ const key = item.parentGroupId || "uncategorized";
192
+ if (!grouped.has(key)) {
193
+ grouped.set(key, []);
194
+ }
195
+ grouped.get(key).push(item);
196
+ });
197
+ // Convert to array and sort by hierarchy: Headcount, Non-Headcount, others, then uncategorized
198
+ const entries = Array.from(grouped.entries());
199
+ // Find Headcount and Non-Headcount group IDs
200
+ const headcountGroup = groups.find((g) => g.label === "Headcount Expenses");
201
+ const nonHeadcountGroup = groups.find((g) => g.label === "Non-Headcount Expenses");
202
+ entries.sort(([keyA], [keyB]) => {
203
+ // Uncategorized always goes last
204
+ if (keyA === "uncategorized")
205
+ return 1;
206
+ if (keyB === "uncategorized")
207
+ return -1;
208
+ // Headcount Expenses always first
209
+ if (keyA === headcountGroup?.id)
210
+ return -1;
211
+ if (keyB === headcountGroup?.id)
212
+ return 1;
213
+ // Non-Headcount Expenses always second
214
+ if (keyA === nonHeadcountGroup?.id)
215
+ return -1;
216
+ if (keyB === nonHeadcountGroup?.id)
217
+ return 1;
218
+ // For other groups, maintain their original order
219
+ return 0;
220
+ });
221
+ return entries.map(([key, items]) => ({
222
+ parentLabel: key === "uncategorized"
223
+ ? "Uncategorised"
224
+ : items[0]?.parentGroupLabel || "Unknown",
225
+ items,
226
+ }));
227
+ };
228
+ return (_jsx(Document, { children: _jsxs(Page, { size: "A4", style: styles.page, children: [_jsxs(View, { style: styles.header, children: [_jsx(Text, { style: styles.title, children: "Expense Report" }), periodStart && (_jsxs(Text, { style: styles.period, children: ["Period: ", formatDate(periodStart), " to ", formatDate(periodEnd)] }))] }), wallets.map((wallet, walletIndex) => {
229
+ const lineItems = getWalletLineItems(wallet);
230
+ const groupedItems = groupLineItemsByParent(lineItems);
231
+ // Calculate grand totals
232
+ const grandTotals = lineItems.reduce((acc, item) => ({
233
+ budget: acc.budget + (item.budget || 0),
234
+ forecast: acc.forecast + (item.forecast || 0),
235
+ actuals: acc.actuals + (item.actuals || 0),
236
+ payments: acc.payments + (item.payments || 0),
237
+ }), { budget: 0, forecast: 0, actuals: 0, payments: 0 });
238
+ return (_jsxs(View, { wrap: false, break: walletIndex > 0, children: [_jsxs(Text, { style: styles.sectionTitle, children: [periodStart &&
239
+ new Date(periodStart).toLocaleDateString("en-US", {
240
+ month: "short",
241
+ year: "numeric",
242
+ }), " ", "Breakdown"] }), _jsxs(Text, { style: styles.walletInfo, children: [wallet.name && `${wallet.name} • `, wallet.wallet || "Unknown Wallet"] }), _jsxs(View, { style: styles.table, children: [_jsxs(View, { style: styles.tableHeader, children: [_jsx(Text, { style: [styles.headerCell, styles.categoryCol], children: "Category" }), _jsx(Text, { style: [styles.headerCell, styles.budgetCol], children: "Budget" }), _jsx(Text, { style: [styles.headerCell, styles.forecastCol], children: "Forecast" }), _jsx(Text, { style: [styles.headerCell, styles.actualsCol], children: "Actuals" }), _jsx(Text, { style: [styles.headerCell, styles.differenceCol], children: "Difference" }), _jsx(Text, { style: [styles.headerCell, styles.commentsCol], children: "Comments" }), _jsx(Text, { style: [styles.headerCell, styles.paymentsCol], children: "Payments" })] }), groupedItems.map((group, groupIndex) => {
243
+ const subtotals = group.items.reduce((acc, item) => ({
244
+ budget: acc.budget + (item.budget || 0),
245
+ forecast: acc.forecast + (item.forecast || 0),
246
+ actuals: acc.actuals + (item.actuals || 0),
247
+ payments: acc.payments + (item.payments || 0),
248
+ }), { budget: 0, forecast: 0, actuals: 0, payments: 0 });
249
+ const subtotalDifference = subtotals.forecast - subtotals.actuals;
250
+ return (_jsxs(View, { children: [_jsx(View, { style: {
251
+ paddingVertical: 6,
252
+ paddingHorizontal: 6,
253
+ backgroundColor: "#f9fafb",
254
+ borderBottom: "1pt solid #e5e7eb",
255
+ marginTop: groupIndex > 0 ? 8 : 0,
256
+ }, children: _jsx(Text, { style: {
257
+ fontSize: 9,
258
+ fontWeight: "bold",
259
+ color: "#111827",
260
+ }, children: group.parentLabel }) }), group.items.map((item, itemIndex) => {
261
+ const difference = (item.forecast || 0) - (item.actuals || 0);
262
+ const differenceStyle = difference < 0
263
+ ? styles.differenceNegative
264
+ : styles.differenceNormal;
265
+ return (_jsxs(View, { style: itemIndex % 2 === 0
266
+ ? styles.tableRow
267
+ : styles.tableRowAlt, children: [_jsx(Text, { style: [styles.cell, styles.categoryCol], children: item.groupLabel || item.label || "Uncategorised" }), _jsx(Text, { style: [styles.cellRight, styles.budgetCol], children: formatNumber(item.budget) }), _jsx(Text, { style: [styles.cellRight, styles.forecastCol], children: formatNumber(item.forecast) }), _jsx(Text, { style: [styles.cellRight, styles.actualsCol], children: formatNumber(item.actuals) }), _jsx(Text, { style: [
268
+ styles.cellRight,
269
+ styles.differenceCol,
270
+ differenceStyle,
271
+ ], children: formatNumber(difference) }), _jsx(View, { style: styles.commentsCol, children: item.comments && (_jsx(Text, { style: styles.commentsText, children: item.comments })) }), _jsx(Text, { style: [styles.cellRight, styles.paymentsCol], children: formatNumber(item.payments) })] }, item.id));
272
+ }), _jsxs(View, { style: styles.subtotalRow, children: [_jsx(Text, { style: [styles.cellBold, styles.categoryCol], children: "Subtotal" }), _jsx(Text, { style: [styles.cellRight, styles.budgetCol], children: formatNumber(subtotals.budget) }), _jsx(Text, { style: [styles.cellRight, styles.forecastCol], children: formatNumber(subtotals.forecast) }), _jsx(Text, { style: [styles.cellRight, styles.actualsCol], children: formatNumber(subtotals.actuals) }), _jsx(Text, { style: [
273
+ styles.cellRight,
274
+ styles.differenceCol,
275
+ subtotalDifference < 0
276
+ ? styles.differenceNegative
277
+ : styles.differenceNormal,
278
+ ], children: formatNumber(subtotalDifference) }), _jsx(View, { style: styles.commentsCol }), _jsx(Text, { style: [styles.cellRight, styles.paymentsCol], children: formatNumber(subtotals.payments) })] })] }, group.parentLabel));
279
+ }), _jsxs(View, { style: styles.totalRow, children: [_jsx(Text, { style: [styles.cellBold, styles.categoryCol], children: "Total" }), _jsx(Text, { style: [styles.cellRight, styles.budgetCol], children: formatNumber(grandTotals.budget) }), _jsx(Text, { style: [styles.cellRight, styles.forecastCol], children: formatNumber(grandTotals.forecast) }), _jsx(Text, { style: [styles.cellRight, styles.actualsCol], children: formatNumber(grandTotals.actuals) }), _jsx(Text, { style: [
280
+ styles.cellRight,
281
+ styles.differenceCol,
282
+ grandTotals.forecast - grandTotals.actuals < 0
283
+ ? styles.differenceNegative
284
+ : styles.differenceNormal,
285
+ ], children: formatNumber(grandTotals.forecast - grandTotals.actuals) }), _jsx(View, { style: styles.commentsCol }), _jsx(Text, { style: [styles.cellRight, styles.paymentsCol], children: formatNumber(grandTotals.payments) })] })] })] }, wallet.wallet || walletIndex));
286
+ }), _jsx(Text, { style: styles.pageNumber, render: ({ pageNumber, totalPages }) => `Page ${pageNumber} of ${totalPages}`, fixed: true })] }) }));
287
+ }
@@ -0,0 +1,10 @@
1
+ import type { Wallet, LineItemGroup } from "../../../document-models/expense-report/gen/types.js";
2
+ interface WalletsTableProps {
3
+ wallets: Wallet[];
4
+ groups: LineItemGroup[];
5
+ onAddBillingStatement: (walletAddress: string) => void;
6
+ dispatch: any;
7
+ }
8
+ export declare function WalletsTable({ wallets, groups, onAddBillingStatement, dispatch, }: WalletsTableProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=WalletsTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WalletsTable.d.ts","sourceRoot":"","sources":["../../../../editors/expense-report/components/WalletsTable.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,sDAAsD,CAAC;AAKlG,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,qBAAqB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IACvD,QAAQ,EAAE,GAAG,CAAC;CACf;AAED,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,MAAM,EACN,qBAAqB,EACrB,QAAQ,GACT,EAAE,iBAAiB,2CA+XnB"}