@powerhousedao/contributor-billing 0.1.36 → 0.1.39

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 (117) hide show
  1. package/dist/document-models/account-transactions/gen/schema/types.d.ts +3 -3
  2. package/dist/document-models/account-transactions/gen/schema/types.d.ts.map +1 -1
  3. package/dist/document-models/accounts/gen/schema/types.d.ts +7 -7
  4. package/dist/document-models/accounts/gen/schema/types.d.ts.map +1 -1
  5. package/dist/document-models/billing-statement/gen/document-schema.d.ts +16 -16
  6. package/dist/document-models/billing-statement/gen/document-schema.d.ts.map +1 -1
  7. package/dist/document-models/billing-statement/gen/schema/types.d.ts +5 -5
  8. package/dist/document-models/billing-statement/gen/schema/types.d.ts.map +1 -1
  9. package/dist/document-models/expense-report/gen/document-model.js +1 -1
  10. package/dist/document-models/expense-report/gen/document-schema.d.ts +16 -16
  11. package/dist/document-models/expense-report/gen/ph-factories.d.ts.map +1 -1
  12. package/dist/document-models/expense-report/gen/ph-factories.js +5 -0
  13. package/dist/document-models/expense-report/gen/schema/types.d.ts +2 -2
  14. package/dist/document-models/expense-report/gen/schema/types.d.ts.map +1 -1
  15. package/dist/document-models/expense-report/gen/schema/zod.d.ts.map +1 -1
  16. package/dist/document-models/expense-report/gen/schema/zod.js +10 -30
  17. package/dist/document-models/expense-report/gen/utils.d.ts.map +1 -1
  18. package/dist/document-models/expense-report/gen/utils.js +5 -0
  19. package/dist/document-models/expense-report/src/reducers/wallet.d.ts.map +1 -1
  20. package/dist/document-models/expense-report/src/reducers/wallet.js +61 -0
  21. package/dist/document-models/invoice/gen/document-schema.d.ts +32 -32
  22. package/dist/document-models/invoice/gen/document-schema.d.ts.map +1 -1
  23. package/dist/document-models/invoice/gen/schema/types.d.ts +10 -10
  24. package/dist/document-models/invoice/gen/schema/types.d.ts.map +1 -1
  25. package/dist/document-models/invoice/gen/schema/zod.d.ts.map +1 -1
  26. package/dist/document-models/service-offering/gen/document-schema.d.ts +16 -16
  27. package/dist/document-models/service-offering/gen/document-schema.d.ts.map +1 -1
  28. package/dist/document-models/service-offering/gen/schema/types.d.ts +11 -11
  29. package/dist/document-models/service-offering/gen/schema/types.d.ts.map +1 -1
  30. package/dist/document-models/service-subscriptions/gen/schema/types.d.ts +6 -6
  31. package/dist/document-models/service-subscriptions/gen/schema/types.d.ts.map +1 -1
  32. package/dist/document-models/snapshot-report/gen/document-schema.d.ts.map +1 -1
  33. package/dist/document-models/snapshot-report/gen/schema/types.d.ts +8 -8
  34. package/dist/document-models/snapshot-report/gen/schema/types.d.ts.map +1 -1
  35. package/dist/document-models/snapshot-report/src/reducers/configuration.d.ts.map +1 -1
  36. package/dist/document-models/snapshot-report/src/reducers/configuration.js +1 -1
  37. package/dist/editors/accounts-editor/components/AccountForm.d.ts.map +1 -1
  38. package/dist/editors/accounts-editor/components/AccountForm.js +3 -1
  39. package/dist/editors/builder-team-admin/components/FolderTree.d.ts.map +1 -1
  40. package/dist/editors/builder-team-admin/components/FolderTree.js +2 -2
  41. package/dist/editors/contributor-billing/components/AddMonthButton.d.ts +5 -0
  42. package/dist/editors/contributor-billing/components/AddMonthButton.d.ts.map +1 -0
  43. package/dist/editors/contributor-billing/components/AddMonthButton.js +56 -0
  44. package/dist/editors/contributor-billing/components/BillingOverview.d.ts +10 -0
  45. package/dist/editors/contributor-billing/components/BillingOverview.d.ts.map +1 -0
  46. package/dist/editors/contributor-billing/components/BillingOverview.js +117 -0
  47. package/dist/editors/contributor-billing/components/DashboardHome.d.ts +11 -0
  48. package/dist/editors/contributor-billing/components/DashboardHome.d.ts.map +1 -0
  49. package/dist/editors/contributor-billing/components/DashboardHome.js +51 -0
  50. package/dist/editors/contributor-billing/components/DriveContents.d.ts +8 -2
  51. package/dist/editors/contributor-billing/components/DriveContents.d.ts.map +1 -1
  52. package/dist/editors/contributor-billing/components/DriveContents.js +24 -10
  53. package/dist/editors/contributor-billing/components/DriveExplorer.d.ts.map +1 -1
  54. package/dist/editors/contributor-billing/components/DriveExplorer.js +18 -3
  55. package/dist/editors/contributor-billing/components/FolderTree.d.ts +19 -9
  56. package/dist/editors/contributor-billing/components/FolderTree.d.ts.map +1 -1
  57. package/dist/editors/contributor-billing/components/FolderTree.js +200 -103
  58. package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.d.ts +8 -1
  59. package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.d.ts.map +1 -1
  60. package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.js +5 -3
  61. package/dist/editors/contributor-billing/components/InvoiceTable/HeaderStats.d.ts +6 -1
  62. package/dist/editors/contributor-billing/components/InvoiceTable/HeaderStats.d.ts.map +1 -1
  63. package/dist/editors/contributor-billing/components/InvoiceTable/HeaderStats.js +14 -6
  64. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.d.ts +6 -2
  65. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.d.ts.map +1 -1
  66. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.js +68 -19
  67. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableContainer.d.ts +10 -1
  68. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableContainer.d.ts.map +1 -1
  69. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableContainer.js +145 -32
  70. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableRow.d.ts.map +1 -1
  71. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableRow.js +6 -1
  72. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableSection.d.ts +1 -1
  73. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableSection.d.ts.map +1 -1
  74. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableSection.js +33 -7
  75. package/dist/editors/contributor-billing/components/MonthOverview.d.ts +12 -0
  76. package/dist/editors/contributor-billing/components/MonthOverview.d.ts.map +1 -0
  77. package/dist/editors/contributor-billing/components/MonthOverview.js +35 -0
  78. package/dist/editors/contributor-billing/components/MonthlyReporting.d.ts +13 -0
  79. package/dist/editors/contributor-billing/components/MonthlyReporting.d.ts.map +1 -0
  80. package/dist/editors/contributor-billing/components/MonthlyReporting.js +90 -0
  81. package/dist/editors/contributor-billing/components/ReportingView.d.ts +10 -0
  82. package/dist/editors/contributor-billing/components/ReportingView.d.ts.map +1 -0
  83. package/dist/editors/contributor-billing/components/ReportingView.js +112 -0
  84. package/dist/editors/contributor-billing/config.js +1 -1
  85. package/dist/editors/contributor-billing/hooks/useBillingFolderStructure.d.ts +54 -0
  86. package/dist/editors/contributor-billing/hooks/useBillingFolderStructure.d.ts.map +1 -0
  87. package/dist/editors/contributor-billing/hooks/useBillingFolderStructure.js +145 -0
  88. package/dist/editors/expense-report/components/AddBillingStatementModal.d.ts +3 -1
  89. package/dist/editors/expense-report/components/AddBillingStatementModal.d.ts.map +1 -1
  90. package/dist/editors/expense-report/components/AddBillingStatementModal.js +23 -7
  91. package/dist/editors/expense-report/components/AggregatedExpensesTable.js +2 -2
  92. package/dist/editors/expense-report/components/ExpenseReportPDF.js +2 -2
  93. package/dist/editors/expense-report/editor.d.ts.map +1 -1
  94. package/dist/editors/expense-report/editor.js +70 -14
  95. package/dist/editors/expense-report/hooks/useSyncWallet.js +9 -9
  96. package/dist/editors/invoice/ingestPDF.js +1 -1
  97. package/dist/editors/invoice/invoiceToGnosis.js +2 -2
  98. package/dist/editors/invoice/requestFinance.js +2 -2
  99. package/dist/editors/invoice/uploadPdfChunked.js +2 -2
  100. package/dist/editors/snapshot-report-editor/editor.d.ts.map +1 -1
  101. package/dist/editors/snapshot-report-editor/editor.js +26 -5
  102. package/dist/scripts/invoice/pdfToClaudeAI.d.ts.map +1 -1
  103. package/dist/scripts/invoice/pdfToClaudeAI.js +3 -1
  104. package/dist/style.css +85 -0
  105. package/dist/subgraphs/budget-statements/index.d.ts +11 -0
  106. package/dist/subgraphs/budget-statements/index.d.ts.map +1 -0
  107. package/dist/subgraphs/budget-statements/index.js +11 -0
  108. package/dist/subgraphs/budget-statements/resolvers.d.ts +3 -0
  109. package/dist/subgraphs/budget-statements/resolvers.d.ts.map +1 -0
  110. package/dist/subgraphs/budget-statements/resolvers.js +335 -0
  111. package/dist/subgraphs/budget-statements/schema.d.ts +3 -0
  112. package/dist/subgraphs/budget-statements/schema.d.ts.map +1 -0
  113. package/dist/subgraphs/budget-statements/schema.js +131 -0
  114. package/dist/subgraphs/index.d.ts +1 -0
  115. package/dist/subgraphs/index.d.ts.map +1 -1
  116. package/dist/subgraphs/index.js +1 -0
  117. package/package.json +1 -1
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ToastContainer } from "@powerhousedao/design-system/connect";
3
+ import { useState } from "react";
3
4
  import { DriveContents } from "./DriveContents.js";
4
5
  import { FolderTree } from "./FolderTree.js";
5
6
  /**
@@ -9,9 +10,23 @@ import { FolderTree } from "./FolderTree.js";
9
10
  export function DriveExplorer({ children }) {
10
11
  // if a document is selected then its editor will be passed as children
11
12
  const showDocumentEditor = !!children;
12
- return (_jsxs("div", { className: "flex h-full w-full overflow-hidden", children: [_jsx(FolderTree, {}), _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 min-w-0 h-full overflow-auto", children: showDocumentEditor ? (
13
+ // Track which folder is selected for content routing
14
+ const [selectedFolder, setSelectedFolder] = useState(null);
15
+ // Track active node in sidebar for visual selection sync
16
+ // Empty string means no selection (home page)
17
+ const [activeNodeId, setActiveNodeId] = useState("");
18
+ const handleFolderSelect = (folderInfo) => {
19
+ setSelectedFolder(folderInfo);
20
+ // Only update sidebar selection when explicitly selecting a folder with a valid ID
21
+ // When folderInfo is null (opening a document), let the sidebar keep its current selection
22
+ // When folderId is empty (e.g., billing folder doesn't exist yet), don't update sidebar
23
+ if (folderInfo && folderInfo.folderId) {
24
+ setActiveNodeId(folderInfo.folderId);
25
+ }
26
+ };
27
+ return (_jsxs("div", { className: "flex h-full w-full overflow-hidden", children: [_jsx(FolderTree, { onFolderSelect: handleFolderSelect, activeNodeId: activeNodeId, onActiveNodeIdChange: setActiveNodeId }), _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 min-w-0 h-full overflow-auto", children: showDocumentEditor ? (
13
28
  /* Document editor view */
14
29
  _jsx("div", { className: "min-h-full", children: children })) : (
15
- /* Operational Hub view */
16
- _jsx(DriveContents, {})) })] }));
30
+ /* Folder content view */
31
+ _jsx(DriveContents, { selectedFolder: selectedFolder, onFolderSelect: handleFolderSelect })) })] }));
17
32
  }
@@ -1,15 +1,25 @@
1
- /** Custom view types that don't correspond to document models */
2
- export type CustomView = "accounts" | "expense-report" | "snapshot-report" | null;
1
+ /** Folder types for content routing */
2
+ export type FolderType = "payments" | "reporting" | "billing" | null;
3
+ /** Selected folder info for content routing */
4
+ export interface SelectedFolderInfo {
5
+ folderId: string;
6
+ folderType: FolderType;
7
+ monthName?: string;
8
+ /** The sibling Reporting folder ID (when in Payments folder context) */
9
+ reportingFolderId?: string;
10
+ /** The sibling Payments folder ID (when in Reporting folder context) */
11
+ paymentsFolderId?: string;
12
+ }
3
13
  type FolderTreeProps = {
4
- onCustomViewChange?: (view: CustomView) => void;
14
+ onFolderSelect?: (folderInfo: SelectedFolderInfo | null) => void;
15
+ activeNodeId?: string;
16
+ onActiveNodeIdChange?: (nodeId: string) => void;
5
17
  };
6
18
  /**
7
- * Sidebar navigation component with hardcoded navigation sections.
8
- * Displays Accounts as the main section.
9
- * If an accounts document exists, clicking shows its editor.
10
- * If it doesn't exist, clicking shows the create document modal.
11
- * Account-transactions documents are shown as children of the Accounts node.
19
+ * Sidebar navigation component with:
20
+ * - Accounts section (with account-transactions children)
21
+ * - Billing folder structure (Month > Payments/Reporting)
12
22
  */
13
- export declare function FolderTree({ onCustomViewChange }: FolderTreeProps): import("react/jsx-runtime").JSX.Element;
23
+ export declare function FolderTree({ onFolderSelect, activeNodeId: controlledActiveNodeId, onActiveNodeIdChange, }: FolderTreeProps): import("react/jsx-runtime").JSX.Element;
14
24
  export {};
15
25
  //# sourceMappingURL=FolderTree.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FolderTree.d.ts","sourceRoot":"","sources":["../../../../editors/contributor-billing/components/FolderTree.tsx"],"names":[],"mappings":"AAeA,iEAAiE;AACjE,MAAM,MAAM,UAAU,GAClB,UAAU,GACV,gBAAgB,GAChB,iBAAiB,GACjB,IAAI,CAAC;AA2CT,KAAK,eAAe,GAAG;IACrB,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;CACjD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,EAAE,kBAAkB,EAAE,EAAE,eAAe,2CAyIjE"}
1
+ {"version":3,"file":"FolderTree.d.ts","sourceRoot":"","sources":["../../../../editors/contributor-billing/components/FolderTree.tsx"],"names":[],"mappings":"AA0BA,uCAAuC;AACvC,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,WAAW,GAAG,SAAS,GAAG,IAAI,CAAC;AAErE,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,KAAK,eAAe,GAAG;IACrB,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,kBAAkB,GAAG,IAAI,KAAK,IAAI,CAAC;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACjD,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,EACzB,cAAc,EACd,YAAY,EAAE,sBAAsB,EACpC,oBAAoB,GACrB,EAAE,eAAe,2CA6SjB"}
@@ -1,57 +1,37 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Sidebar, SidebarProvider, } from "@powerhousedao/document-engineering";
3
- import { setSelectedNode, showCreateDocumentModal, useDocumentsInSelectedDrive, } from "@powerhousedao/reactor-browser";
4
- import { Wallet, FileText, Camera } from "lucide-react";
3
+ import { setSelectedNode, showCreateDocumentModal, useDocumentsInSelectedDrive, useSelectedDrive, isFileNodeKind, } from "@powerhousedao/reactor-browser";
4
+ import { Wallet, FileText, Building2, Calendar, CreditCard, BarChart3, Camera, } from "lucide-react";
5
5
  import { useMemo, useState } from "react";
6
+ import { useBillingFolderStructure } from "../hooks/useBillingFolderStructure.js";
6
7
  const ICON_SIZE = 16;
7
8
  /**
8
- * Maps navigation section IDs to their corresponding document types.
9
- * When a section is clicked, the corresponding document type will be created or navigated to.
9
+ * Sidebar navigation component with:
10
+ * - Accounts section (with account-transactions children)
11
+ * - Billing folder structure (Month > Payments/Reporting)
10
12
  */
11
- const SECTION_TO_DOCUMENT_TYPE = {
12
- accounts: "powerhouse/accounts",
13
- "expense-report": "powerhouse/expense-report",
14
- "snapshot-report": "powerhouse/snapshot-report",
15
- };
16
- /**
17
- * Maps navigation section IDs to custom view identifiers.
18
- */
19
- const SECTION_TO_CUSTOM_VIEW = {
20
- accounts: "accounts",
21
- "expense-report": "expense-report",
22
- "snapshot-report": "snapshot-report",
23
- };
24
- /**
25
- * Base navigation sections for the Contributor Billing drive.
26
- * The accounts section will have dynamic children based on account-transactions documents.
27
- */
28
- const BASE_NAVIGATION_SECTIONS = [
29
- {
30
- id: "accounts",
31
- title: "Accounts",
32
- icon: _jsx(Wallet, { size: ICON_SIZE }),
33
- },
34
- {
35
- id: "expense-report",
36
- title: "Expense Report",
37
- icon: _jsx(FileText, { size: ICON_SIZE }),
38
- },
39
- {
40
- id: "snapshot-report",
41
- title: "Snapshot Report",
42
- icon: _jsx(Camera, { size: ICON_SIZE }),
43
- },
44
- ];
45
- /**
46
- * Sidebar navigation component with hardcoded navigation sections.
47
- * Displays Accounts as the main section.
48
- * If an accounts document exists, clicking shows its editor.
49
- * If it doesn't exist, clicking shows the create document modal.
50
- * Account-transactions documents are shown as children of the Accounts node.
51
- */
52
- export function FolderTree({ onCustomViewChange }) {
53
- const [activeNodeId, setActiveNodeId] = useState(BASE_NAVIGATION_SECTIONS[0].id);
13
+ export function FolderTree({ onFolderSelect, activeNodeId: controlledActiveNodeId, onActiveNodeIdChange, }) {
14
+ // Use controlled state if provided, otherwise use local state
15
+ // Empty string means no selection (home page)
16
+ const [localActiveNodeId, setLocalActiveNodeId] = useState("");
17
+ const activeNodeId = controlledActiveNodeId ?? localActiveNodeId;
18
+ const setActiveNodeId = onActiveNodeIdChange ?? setLocalActiveNodeId;
54
19
  const documentsInDrive = useDocumentsInSelectedDrive();
20
+ const [driveDocument] = useSelectedDrive();
21
+ const { billingFolder, monthFolders, paymentsFolderIds, reportingFolderIds } = useBillingFolderStructure();
22
+ // Build a map of document ID to parent folder ID
23
+ const documentParentMap = useMemo(() => {
24
+ const map = new Map();
25
+ if (!driveDocument)
26
+ return map;
27
+ const nodes = driveDocument.state.global.nodes;
28
+ for (const node of nodes) {
29
+ if (isFileNodeKind(node)) {
30
+ map.set(node.id, node.parentFolder);
31
+ }
32
+ }
33
+ return map;
34
+ }, [driveDocument]);
55
35
  // Find all account-transactions documents in the drive
56
36
  const accountTransactionsDocuments = useMemo(() => {
57
37
  if (!documentsInDrive)
@@ -66,7 +46,47 @@ export function FolderTree({ onCustomViewChange }) {
66
46
  }
67
47
  return nodeIds;
68
48
  }, [accountTransactionsDocuments]);
69
- // Build navigation sections with dynamic account-transactions children
49
+ // Build a set of month folder IDs for quick lookup
50
+ const monthFolderIds = useMemo(() => {
51
+ const ids = new Set();
52
+ for (const [, info] of monthFolders.entries()) {
53
+ ids.add(info.folder.id);
54
+ }
55
+ return ids;
56
+ }, [monthFolders]);
57
+ // Find accounts document
58
+ const accountsDocument = useMemo(() => {
59
+ if (!documentsInDrive)
60
+ return null;
61
+ return documentsInDrive.find((doc) => doc.header.documentType === "powerhouse/accounts");
62
+ }, [documentsInDrive]);
63
+ // Find report documents (expense + snapshot) and build ID set for lookup
64
+ const { reportDocuments, reportDocumentIds } = useMemo(() => {
65
+ if (!documentsInDrive)
66
+ return { reportDocuments: [], reportDocumentIds: new Set() };
67
+ const docs = documentsInDrive.filter((doc) => doc.header.documentType === "powerhouse/expense-report" ||
68
+ doc.header.documentType === "powerhouse/snapshot-report");
69
+ return {
70
+ reportDocuments: docs,
71
+ reportDocumentIds: new Set(docs.map((d) => d.header.id)),
72
+ };
73
+ }, [documentsInDrive]);
74
+ // Generate a stable key based on the node structure to force Sidebar remount when nodes change
75
+ // This works around a bug in the Sidebar component where toggle state isn't updated for new nodes
76
+ const sidebarKey = useMemo(() => {
77
+ const nodeIds = [];
78
+ for (const [, info] of monthFolders.entries()) {
79
+ nodeIds.push(info.folder.id);
80
+ if (info.paymentsFolder)
81
+ nodeIds.push(info.paymentsFolder.id);
82
+ if (info.reportingFolder)
83
+ nodeIds.push(info.reportingFolder.id);
84
+ }
85
+ // Include document count to detect when documents are added/removed
86
+ const docCount = documentsInDrive?.length ?? 0;
87
+ return `${nodeIds.join("-")}-${docCount}`;
88
+ }, [monthFolders, documentsInDrive?.length]);
89
+ // Build navigation sections
70
90
  const navigationSections = useMemo(() => {
71
91
  // Build account-transactions children nodes
72
92
  const accountTransactionsChildren = accountTransactionsDocuments.map((doc) => ({
@@ -74,82 +94,159 @@ export function FolderTree({ onCustomViewChange }) {
74
94
  title: doc.header.name || "Untitled",
75
95
  icon: _jsx(FileText, { size: ICON_SIZE }),
76
96
  }));
77
- // Replace the accounts section with one that has children if any exist
78
- return BASE_NAVIGATION_SECTIONS.map((section) => {
79
- if (section.id === "accounts" && accountTransactionsChildren.length > 0) {
80
- return {
81
- ...section,
82
- children: accountTransactionsChildren,
83
- };
84
- }
85
- return section;
97
+ // Build Billing folder children (month folders)
98
+ const billingChildren = [];
99
+ // Sort months by date (most recent first)
100
+ const sortedMonths = Array.from(monthFolders.entries()).sort(([nameA], [nameB]) => {
101
+ // Parse "January 2025" format
102
+ const dateA = new Date(nameA);
103
+ const dateB = new Date(nameB);
104
+ return dateB.getTime() - dateA.getTime(); // Most recent first
86
105
  });
87
- }, [accountTransactionsDocuments]);
88
- // Create a map of document type to existing document (first one found)
89
- const existingDocumentsByType = useMemo(() => {
90
- const map = {};
91
- if (!documentsInDrive)
92
- return map;
93
- for (const doc of documentsInDrive) {
94
- const docType = doc.header.documentType;
95
- // Only store the first document of each type (singleton pattern)
96
- if (!map[docType]) {
97
- map[docType] = doc.header.id;
106
+ for (const [monthName, info] of sortedMonths) {
107
+ const monthChildren = [];
108
+ if (info.paymentsFolder) {
109
+ monthChildren.push({
110
+ id: info.paymentsFolder.id,
111
+ title: "Payments",
112
+ icon: _jsx(CreditCard, { size: ICON_SIZE }),
113
+ });
114
+ }
115
+ if (info.reportingFolder) {
116
+ // Filter reports that match this specific month by name
117
+ const monthLower = monthName.toLowerCase();
118
+ const folderReports = reportDocuments.filter((doc) => {
119
+ const docName = doc.header.name?.toLowerCase() || "";
120
+ // Only include if report name contains the full month name (e.g., "january 2026")
121
+ return docName.includes(monthLower);
122
+ });
123
+ const reportingChildren = folderReports.map((doc) => ({
124
+ id: doc.header.id,
125
+ title: doc.header.name || "Untitled Report",
126
+ icon: doc.header.documentType === "powerhouse/snapshot-report" ? (_jsx(Camera, { size: ICON_SIZE })) : (_jsx(FileText, { size: ICON_SIZE })),
127
+ }));
128
+ monthChildren.push({
129
+ id: info.reportingFolder.id,
130
+ title: "Reporting",
131
+ icon: _jsx(BarChart3, { size: ICON_SIZE }),
132
+ children: reportingChildren.length > 0 ? reportingChildren : undefined,
133
+ });
98
134
  }
135
+ billingChildren.push({
136
+ id: info.folder.id,
137
+ title: monthName,
138
+ icon: _jsx(Calendar, { size: ICON_SIZE }),
139
+ children: monthChildren.length > 0 ? monthChildren : undefined,
140
+ });
99
141
  }
100
- return map;
101
- }, [documentsInDrive]);
142
+ const sections = [
143
+ // Accounts section
144
+ {
145
+ id: "accounts",
146
+ title: "Accounts",
147
+ icon: _jsx(Wallet, { size: ICON_SIZE }),
148
+ children: accountTransactionsChildren.length > 0
149
+ ? accountTransactionsChildren
150
+ : undefined,
151
+ },
152
+ // Billing folder structure
153
+ {
154
+ id: billingFolder?.id || "billing-placeholder",
155
+ title: "Billing",
156
+ icon: _jsx(Building2, { size: ICON_SIZE }),
157
+ children: billingChildren.length > 0 ? billingChildren : undefined,
158
+ },
159
+ ];
160
+ return sections;
161
+ }, [
162
+ accountTransactionsDocuments,
163
+ billingFolder,
164
+ monthFolders,
165
+ reportDocuments,
166
+ documentParentMap,
167
+ ]);
102
168
  const handleActiveNodeChange = (node) => {
103
169
  setActiveNodeId(node.id);
104
170
  // Check if this is an account-transactions child node
105
171
  if (accountTransactionsNodeIds.has(node.id)) {
106
- // It's an account-transactions document - open the document editor
107
- onCustomViewChange?.(null);
172
+ onFolderSelect?.(null);
108
173
  setSelectedNode(node.id);
109
174
  return;
110
175
  }
111
- // Check if this section has a custom view
112
- const customView = SECTION_TO_CUSTOM_VIEW[node.id];
113
- if (customView) {
114
- // For accounts, check if document exists
115
- const documentType = SECTION_TO_DOCUMENT_TYPE[node.id];
116
- if (documentType) {
117
- const existingDocId = existingDocumentsByType[documentType];
118
- if (existingDocId) {
119
- // Navigate to the existing accounts document
120
- onCustomViewChange?.(null);
121
- setSelectedNode(existingDocId);
122
- }
123
- else {
124
- // Clear selected node to create document at drive root, not in current folder
125
- setSelectedNode("");
126
- showCreateDocumentModal(documentType);
127
- }
128
- }
176
+ // Check if this is an expense or snapshot report document
177
+ if (reportDocumentIds.has(node.id)) {
178
+ onFolderSelect?.(null);
179
+ setSelectedNode(node.id);
129
180
  return;
130
181
  }
131
- // Clear custom view when navigating to a document
132
- onCustomViewChange?.(null);
133
- const documentType = SECTION_TO_DOCUMENT_TYPE[node.id];
134
- if (!documentType)
182
+ // Check if clicking Accounts section
183
+ if (node.id === "accounts") {
184
+ if (accountsDocument) {
185
+ onFolderSelect?.(null);
186
+ setSelectedNode(accountsDocument.header.id);
187
+ }
188
+ else {
189
+ setSelectedNode("");
190
+ showCreateDocumentModal("powerhouse/accounts");
191
+ }
135
192
  return;
136
- const existingDocId = existingDocumentsByType[documentType];
137
- if (existingDocId) {
138
- // Navigate to the existing document
139
- setSelectedNode(existingDocId);
140
193
  }
141
- else {
142
- // Clear selected node to create document at drive root, not in current folder
194
+ // Check if clicking Billing folder
195
+ if (node.id === billingFolder?.id || node.id === "billing-placeholder") {
196
+ onFolderSelect?.({
197
+ folderId: billingFolder?.id || "",
198
+ folderType: "billing",
199
+ });
143
200
  setSelectedNode("");
144
- showCreateDocumentModal(documentType);
201
+ return;
202
+ }
203
+ // Check if clicking a month folder - just let it expand, don't navigate or select
204
+ if (monthFolderIds.has(node.id)) {
205
+ return;
206
+ }
207
+ // Check if clicking a Payments folder
208
+ if (paymentsFolderIds.has(node.id)) {
209
+ // Find the month name for this payments folder
210
+ for (const [monthName, info] of monthFolders.entries()) {
211
+ if (info.paymentsFolder?.id === node.id) {
212
+ onFolderSelect?.({
213
+ folderId: node.id,
214
+ folderType: "payments",
215
+ monthName,
216
+ reportingFolderId: info.reportingFolder?.id,
217
+ });
218
+ setSelectedNode("");
219
+ return;
220
+ }
221
+ }
222
+ }
223
+ // Check if clicking a Reporting folder
224
+ if (reportingFolderIds.has(node.id)) {
225
+ // Find the month name for this reporting folder
226
+ for (const [monthName, info] of monthFolders.entries()) {
227
+ if (info.reportingFolder?.id === node.id) {
228
+ onFolderSelect?.({
229
+ folderId: node.id,
230
+ folderType: "reporting",
231
+ monthName,
232
+ paymentsFolderId: info.paymentsFolder?.id,
233
+ });
234
+ setSelectedNode("");
235
+ return;
236
+ }
237
+ }
145
238
  }
239
+ // Default: clear selection
240
+ onFolderSelect?.(null);
241
+ setSelectedNode("");
146
242
  };
147
243
  return (_jsxs(SidebarProvider, { nodes: navigationSections, children: [_jsx("style", { children: `
148
244
  .folder-tree-sidebar .sidebar__item-caret--no-children {
149
245
  visibility: hidden;
150
246
  }
151
247
  ` }), _jsx(Sidebar, { className: "pt-1 folder-tree-sidebar", nodes: navigationSections, activeNodeId: activeNodeId, onActiveNodeChange: handleActiveNodeChange, sidebarTitle: "Operational Hub Navigation", showSearchBar: false, resizable: true, allowPinning: false, showStatusFilter: false, initialWidth: 256, defaultLevel: 2, handleOnTitleClick: () => {
152
- onCustomViewChange?.(null);
248
+ onFolderSelect?.(null);
153
249
  setSelectedNode("");
154
- } })] }));
250
+ setActiveNodeId("");
251
+ } }, sidebarKey)] }));
155
252
  }
@@ -16,6 +16,13 @@ interface HeaderControlsProps {
16
16
  canExport?: boolean;
17
17
  hasBillingStatements?: boolean;
18
18
  expenseReportDoc?: FileNode;
19
+ /** Existing expense report for the current month (to prevent duplicates) */
20
+ existingExpenseReportForMonth?: {
21
+ header: {
22
+ id: string;
23
+ name?: string;
24
+ };
25
+ } | null;
19
26
  onCreateOrOpenExpenseReport?: () => void;
20
27
  selected?: Record<string, boolean>;
21
28
  handleCreateBillingStatement: (id: string) => Promise<void>;
@@ -34,5 +41,5 @@ interface HeaderControlsProps {
34
41
  }>;
35
42
  canExportSelectedRows: () => boolean;
36
43
  }
37
- export declare const HeaderControls: ({ statusOptions, selectedStatuses, onStatusChange, onSearchChange, onExport, onExpenseReportExport, createIntegrationsDocument, integrationsDoc, hasBillingStatements, expenseReportDoc, onCreateOrOpenExpenseReport, selected, handleCreateBillingStatement, setSelected, invoices, billingStatements, canExportSelectedRows, }: HeaderControlsProps) => import("react/jsx-runtime").JSX.Element;
44
+ export declare const HeaderControls: ({ statusOptions, selectedStatuses, onStatusChange, onSearchChange, onExport, onExpenseReportExport, createIntegrationsDocument, integrationsDoc, hasBillingStatements, expenseReportDoc, existingExpenseReportForMonth, onCreateOrOpenExpenseReport, selected, handleCreateBillingStatement, setSelected, invoices, billingStatements, canExportSelectedRows, }: HeaderControlsProps) => import("react/jsx-runtime").JSX.Element;
38
45
  //# 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":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAW/C,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAGD,YAAY,EAAE,QAAQ,EAAE,CAAC;AAEzB,UAAU,mBAAmB;IAC3B,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,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,0BAA0B,CAAC,EAAE,MAAM,IAAI,CAAC;IACxC,eAAe,CAAC,EAAE,QAAQ,CAAC;IAC3B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,gBAAgB,CAAC,EAAE,QAAQ,CAAC;IAC5B,2BAA2B,CAAC,EAAE,MAAM,IAAI,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,4BAA4B,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACzD,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC;IAC3D,iBAAiB,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC;IACpE,qBAAqB,EAAE,MAAM,OAAO,CAAC;CACtC;AAED,eAAO,MAAM,cAAc,GAAI,kUAkB5B,mBAAmB,4CAuPrB,CAAC"}
1
+ {"version":3,"file":"HeaderControls.d.ts","sourceRoot":"","sources":["../../../../../editors/contributor-billing/components/InvoiceTable/HeaderControls.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAW/C,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAGD,YAAY,EAAE,QAAQ,EAAE,CAAC;AAEzB,UAAU,mBAAmB;IAC3B,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,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,0BAA0B,CAAC,EAAE,MAAM,IAAI,CAAC;IACxC,eAAe,CAAC,EAAE,QAAQ,CAAC;IAC3B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,gBAAgB,CAAC,EAAE,QAAQ,CAAC;IAC5B,4EAA4E;IAC5E,6BAA6B,CAAC,EAAE;QAC9B,MAAM,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KACvC,GAAG,IAAI,CAAC;IACT,2BAA2B,CAAC,EAAE,MAAM,IAAI,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,4BAA4B,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACzD,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC;IAC3D,iBAAiB,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC;IACpE,qBAAqB,EAAE,MAAM,OAAO,CAAC;CACtC;AAED,eAAO,MAAM,cAAc,GAAI,iWAmB5B,mBAAmB,4CA4PrB,CAAC"}
@@ -10,7 +10,7 @@ const currencyOptions = [
10
10
  { label: "GBP", value: "GBP" },
11
11
  { label: "JPY", value: "JPY" },
12
12
  ];
13
- export const HeaderControls = ({ statusOptions = [], selectedStatuses = [], onStatusChange, onSearchChange, onExport, onExpenseReportExport, createIntegrationsDocument, integrationsDoc, hasBillingStatements = false, expenseReportDoc, onCreateOrOpenExpenseReport, selected = {}, handleCreateBillingStatement, setSelected, invoices = [], billingStatements = [], canExportSelectedRows, }) => {
13
+ export const HeaderControls = ({ statusOptions = [], selectedStatuses = [], onStatusChange, onSearchChange, onExport, onExpenseReportExport, createIntegrationsDocument, integrationsDoc, hasBillingStatements = false, expenseReportDoc, existingExpenseReportForMonth, onCreateOrOpenExpenseReport, selected = {}, handleCreateBillingStatement, setSelected, invoices = [], billingStatements = [], canExportSelectedRows, }) => {
14
14
  const batchOptions = [
15
15
  { label: "Generate Bill Statements", value: "generate-bills" },
16
16
  {
@@ -107,9 +107,11 @@ export const HeaderControls = ({ statusOptions = [], selectedStatuses = [], onSt
107
107
  // setSelectedNode(integrationsDoc.id);
108
108
  // }
109
109
  // };
110
- return (_jsxs("div", { className: "contributor-billing-controls flex flex-col gap-4 mb-4", children: [_jsxs("div", { className: "flex justify-between items-center flex-wrap gap-2", children: [_jsxs("div", { className: "flex gap-2 items-center", children: [_jsx("div", { className: "w-[180px]", children: _jsx(Select, { options: statusOptions, onChange: onStatusChange, placeholder: "Status", selectionIcon: "checkmark", multiple: true, value: selectedStatuses }) }), _jsx("input", { type: "text", className: "border border-gray-300 rounded px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent", placeholder: "Search", onChange: (e) => onSearchChange?.(e.target.value) })] }), _jsxs("div", { className: "flex gap-2 items-center", children: [_jsx("button", { type: "button", className: `bg-white border border-gray-300 rounded px-3 py-1.5 text-sm font-medium transition-colors ${hasBillingStatements
110
+ return (_jsxs("div", { className: "contributor-billing-controls flex flex-col gap-4 mb-4", children: [_jsxs("div", { className: "flex justify-between items-center flex-wrap gap-2", children: [_jsxs("div", { className: "flex gap-2 items-center", children: [_jsx("div", { className: "w-[180px]", children: _jsx(Select, { options: statusOptions, onChange: onStatusChange, placeholder: "Status", selectionIcon: "checkmark", multiple: true, value: selectedStatuses }) }), _jsx("input", { type: "text", className: "border border-gray-300 rounded px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent", placeholder: "Search", onChange: (e) => onSearchChange?.(e.target.value) })] }), _jsxs("div", { className: "flex gap-2 items-center", children: [_jsx("button", { type: "button", className: `bg-white border border-gray-300 rounded px-3 py-1.5 text-sm font-medium transition-colors ${hasBillingStatements && !existingExpenseReportForMonth
111
111
  ? "hover:bg-gray-50"
112
- : "opacity-50 cursor-not-allowed"}`, onClick: onCreateOrOpenExpenseReport, disabled: !hasBillingStatements, children: expenseReportDoc ? "Expense Report" : "Create Expense Report" }), _jsx("button", { type: "button", className: `bg-white border border-gray-300 rounded px-3 py-1.5 text-sm font-medium transition-colors ${canExport ? "hover:bg-gray-50" : "opacity-50 cursor-not-allowed"}`, onClick: () => {
112
+ : "opacity-50 cursor-not-allowed"}`, onClick: onCreateOrOpenExpenseReport, disabled: !hasBillingStatements || !!existingExpenseReportForMonth, title: existingExpenseReportForMonth
113
+ ? "Expense report already exists for this month"
114
+ : undefined, children: expenseReportDoc ? "Expense Report" : "Create Expense Report" }), _jsx("button", { type: "button", className: `bg-white border border-gray-300 rounded px-3 py-1.5 text-sm font-medium transition-colors ${canExport ? "hover:bg-gray-50" : "opacity-50 cursor-not-allowed"}`, onClick: () => {
113
115
  setShowCurrencyModal(true);
114
116
  }, disabled: !canExport, children: "Export to CSV" }), _jsx("div", { className: "w-[180px]", children: _jsx(Select, { contentClassName: "w-[240px]", options: batchOptions, value: selectedBatchAction, onChange: (value) => {
115
117
  setSelectedBatchAction(value);
@@ -1,2 +1,7 @@
1
- export declare const HeaderStats: () => import("react/jsx-runtime").JSX.Element;
1
+ interface HeaderStatsProps {
2
+ /** The ID of the payments folder to filter invoices by */
3
+ folderId: string;
4
+ }
5
+ export declare const HeaderStats: ({ folderId }: HeaderStatsProps) => import("react/jsx-runtime").JSX.Element;
6
+ export {};
2
7
  //# sourceMappingURL=HeaderStats.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"HeaderStats.d.ts","sourceRoot":"","sources":["../../../../../editors/contributor-billing/components/InvoiceTable/HeaderStats.tsx"],"names":[],"mappings":"AAuBA,eAAO,MAAM,WAAW,+CAwHvB,CAAC"}
1
+ {"version":3,"file":"HeaderStats.d.ts","sourceRoot":"","sources":["../../../../../editors/contributor-billing/components/InvoiceTable/HeaderStats.tsx"],"names":[],"mappings":"AAwBA,UAAU,gBAAgB;IACxB,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,WAAW,GAAI,cAAc,gBAAgB,4CAgIzD,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Select } from "@powerhousedao/document-engineering/ui";
3
3
  import { useState, useEffect, useMemo } from "react";
4
- import { useFileNodesInSelectedDrive, useGetDocuments, } from "@powerhousedao/reactor-browser";
4
+ import { useGetDocuments, useSelectedDrive, isFileNodeKind, } from "@powerhousedao/reactor-browser";
5
5
  import { getExchangeRate } from "../../utils/exchangeRate.js";
6
6
  import { Tooltip, TooltipProvider } from "@powerhousedao/design-system/ui";
7
7
  const currencyList = [
@@ -16,13 +16,21 @@ const currencyList = [
16
16
  { ticker: "CNY", crypto: false },
17
17
  { ticker: "CHF", crypto: false },
18
18
  ];
19
- export const HeaderStats = () => {
19
+ export const HeaderStats = ({ folderId }) => {
20
20
  const [selectedCurrency, setSelectedCurrency] = useState("USD");
21
21
  const [totalExpenses, setTotalExpenses] = useState(0);
22
- const files = useFileNodesInSelectedDrive();
23
- const invoiceFiles = useMemo(() => files
24
- ?.filter((file) => file.documentType === "powerhouse/invoice")
25
- .map((file) => file.id), [files]);
22
+ const [driveDocument] = useSelectedDrive();
23
+ // Filter invoice files to only those in the specific payments folder
24
+ const invoiceFiles = useMemo(() => {
25
+ if (!driveDocument)
26
+ return [];
27
+ const nodes = driveDocument.state.global.nodes;
28
+ return nodes
29
+ .filter((node) => isFileNodeKind(node) &&
30
+ node.parentFolder === folderId &&
31
+ node.documentType === "powerhouse/invoice")
32
+ .map((node) => node.id);
33
+ }, [driveDocument, folderId]);
26
34
  const invoices = useGetDocuments(invoiceFiles);
27
35
  useEffect(() => {
28
36
  const calculateTotalExpenses = async () => {
@@ -10,13 +10,17 @@ interface InvoiceTableProps {
10
10
  selected: Record<string, boolean>;
11
11
  setSelected: (selected: Record<string, boolean> | ((prev: Record<string, boolean>) => Record<string, boolean>)) => void;
12
12
  filteredDocumentModels: VetraDocumentModelModule[];
13
- onSelectDocumentModel: (model: VetraDocumentModelModule) => void;
13
+ onSelectDocumentModel: (model: VetraDocumentModelModule, name: string) => void;
14
14
  getDocDispatcher: (id: string) => [PHDocument, (action: unknown) => Promise<void>] | null;
15
15
  selectedStatuses: string[];
16
16
  onStatusChange: (value: string | string[]) => void;
17
17
  onRowSelection: (rowId: string, checked: boolean, rowStatus: string) => void;
18
18
  canExportSelectedRows: () => boolean;
19
+ /** The month name (e.g., "January 2026") for checking existing reports */
20
+ monthName?: string;
21
+ /** The sibling Reporting folder ID where expense reports should be created */
22
+ reportingFolderId?: string;
19
23
  }
20
- export declare const InvoiceTable: ({ files, selected, setSelected, filteredDocumentModels, onSelectDocumentModel, getDocDispatcher, selectedStatuses, onStatusChange, onRowSelection, canExportSelectedRows, }: InvoiceTableProps) => import("react/jsx-runtime").JSX.Element;
24
+ export declare const InvoiceTable: ({ files, selected, setSelected, filteredDocumentModels, onSelectDocumentModel, getDocDispatcher, selectedStatuses, onStatusChange, onRowSelection, canExportSelectedRows, monthName, reportingFolderId, }: InvoiceTableProps) => import("react/jsx-runtime").JSX.Element;
21
25
  export {};
22
26
  //# sourceMappingURL=InvoiceTable.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"InvoiceTable.d.ts","sourceRoot":"","sources":["../../../../../editors/contributor-billing/components/InvoiceTable/InvoiceTable.tsx"],"names":[],"mappings":"AACA,OAAO,EAML,KAAK,wBAAwB,EAC9B,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AA6D/C,eAAO,MAAM,aAAa;;;GAUzB,CAAC;AAeF,UAAU,iBAAiB;IACzB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,WAAW,EAAE,CACX,QAAQ,EACJ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KAC7D,IAAI,CAAC;IACV,sBAAsB,EAAE,wBAAwB,EAAE,CAAC;IACnD,qBAAqB,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,IAAI,CAAC;IACjE,gBAAgB,EAAE,CAChB,EAAE,EAAE,MAAM,KACP,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IAC7D,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;AA6BD,eAAO,MAAM,YAAY,GAAI,6KAW1B,iBAAiB,4CAijBnB,CAAC"}
1
+ {"version":3,"file":"InvoiceTable.d.ts","sourceRoot":"","sources":["../../../../../editors/contributor-billing/components/InvoiceTable/InvoiceTable.tsx"],"names":[],"mappings":"AACA,OAAO,EAML,KAAK,wBAAwB,EAC9B,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AA6D/C,eAAO,MAAM,aAAa;;;GAUzB,CAAC;AAeF,UAAU,iBAAiB;IACzB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,WAAW,EAAE,CACX,QAAQ,EACJ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KAC7D,IAAI,CAAC;IACV,sBAAsB,EAAE,wBAAwB,EAAE,CAAC;IACnD,qBAAqB,EAAE,CACrB,KAAK,EAAE,wBAAwB,EAC/B,IAAI,EAAE,MAAM,KACT,IAAI,CAAC;IACV,gBAAgB,EAAE,CAChB,EAAE,EAAE,MAAM,KACP,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IAC7D,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;IACrC,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AA6BD,eAAO,MAAM,YAAY,GAAI,2MAa1B,iBAAiB,4CAmqBnB,CAAC"}