@powerhousedao/contributor-billing 0.1.37 → 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
@@ -0,0 +1,90 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { FileText, Camera, Calendar } from "lucide-react";
3
+ import { useMemo } from "react";
4
+ import { useDocumentsInSelectedDrive, setSelectedNode, } from "@powerhousedao/reactor-browser";
5
+ import { useBillingFolderStructure, formatMonthName, } from "../hooks/useBillingFolderStructure.js";
6
+ /**
7
+ * Get color classes for report status badge
8
+ */
9
+ function getStatusColors(status) {
10
+ const statusLower = status?.toLowerCase() || "draft";
11
+ switch (statusLower) {
12
+ case "final":
13
+ case "approved":
14
+ case "completed":
15
+ return { bg: "bg-green-100", text: "text-green-700" };
16
+ case "submitted":
17
+ case "review":
18
+ case "in_review":
19
+ return { bg: "bg-blue-100", text: "text-blue-700" };
20
+ case "rejected":
21
+ case "cancelled":
22
+ return { bg: "bg-red-100", text: "text-red-700" };
23
+ case "draft":
24
+ default:
25
+ return { bg: "bg-amber-100", text: "text-amber-700" };
26
+ }
27
+ }
28
+ /**
29
+ * Reusable Monthly Reporting component
30
+ * Shows expense and snapshot report status for each month
31
+ */
32
+ export function MonthlyReporting({ onFolderSelect, showAllMonths = false, }) {
33
+ const documentsInDrive = useDocumentsInSelectedDrive();
34
+ const { monthFolders } = useBillingFolderStructure();
35
+ // Get current and prior month names
36
+ const { currentMonth, priorMonth } = useMemo(() => {
37
+ const now = new Date();
38
+ const current = formatMonthName(now);
39
+ const prior = formatMonthName(new Date(now.getFullYear(), now.getMonth() - 1, 1));
40
+ return { currentMonth: current, priorMonth: prior };
41
+ }, []);
42
+ // Get report info for a specific month
43
+ const getReportInfo = (month, type) => {
44
+ const emptyColors = { bg: "bg-gray-100", text: "text-gray-500" };
45
+ const emptyReport = {
46
+ exists: false,
47
+ status: null,
48
+ colors: emptyColors,
49
+ };
50
+ if (!documentsInDrive)
51
+ return emptyReport;
52
+ const doc = documentsInDrive.find((d) => d.header.documentType === type &&
53
+ d.header.name?.toLowerCase().includes(month.toLowerCase()));
54
+ if (!doc)
55
+ return emptyReport;
56
+ const status = doc.state?.global?.status ||
57
+ "Draft";
58
+ return { exists: true, status, colors: getStatusColors(status) };
59
+ };
60
+ // Get months to display
61
+ const monthsToDisplay = useMemo(() => {
62
+ if (showAllMonths) {
63
+ // Show all months sorted by date (most recent first)
64
+ return Array.from(monthFolders.keys()).sort((a, b) => {
65
+ const dateA = new Date(a);
66
+ const dateB = new Date(b);
67
+ return dateB.getTime() - dateA.getTime();
68
+ });
69
+ }
70
+ // Just show current and prior month
71
+ return [currentMonth, priorMonth];
72
+ }, [showAllMonths, monthFolders, currentMonth, priorMonth]);
73
+ const handleOpenMonth = (monthName) => {
74
+ const monthInfo = monthFolders.get(monthName);
75
+ if (monthInfo?.reportingFolder) {
76
+ setSelectedNode(monthInfo.reportingFolder.id);
77
+ onFolderSelect?.({
78
+ folderId: monthInfo.reportingFolder.id,
79
+ folderType: "reporting",
80
+ monthName,
81
+ });
82
+ }
83
+ };
84
+ return (_jsxs("div", { className: "bg-white rounded-xl border border-gray-200 p-6", children: [_jsxs("div", { className: "flex items-center gap-3 mb-5", children: [_jsx("div", { className: "p-2 bg-purple-100 rounded-lg", children: _jsx(Calendar, { className: "w-5 h-5 text-purple-600" }) }), _jsxs("div", { children: [_jsx("h2", { className: "text-lg font-semibold text-gray-900", children: "Monthly Reporting" }), _jsx("p", { className: "text-sm text-gray-600", children: "Track expense and snapshot reports for each period" })] })] }), _jsx("div", { className: "space-y-4", children: monthsToDisplay.map((monthName) => {
85
+ const expenseReport = getReportInfo(monthName, "powerhouse/expense-report");
86
+ const snapshotReport = getReportInfo(monthName, "powerhouse/snapshot-report");
87
+ const monthExists = monthFolders.has(monthName);
88
+ return (_jsxs("div", { className: "border border-gray-100 rounded-lg p-4", children: [_jsxs("div", { className: "flex items-center justify-between mb-3", children: [_jsx("h3", { className: "font-medium text-gray-900", children: monthName }), monthExists ? (_jsx("button", { onClick: () => handleOpenMonth(monthName), className: "text-sm text-blue-600 hover:text-blue-700 font-medium", children: "Open Reporting" })) : (_jsx("span", { className: "text-xs text-gray-400", children: "Month not created" }))] }), _jsxs("div", { className: "grid grid-cols-2 gap-3", children: [_jsxs("div", { className: `flex items-center gap-2 p-2 rounded ${expenseReport.exists ? "bg-blue-50" : "bg-gray-50"}`, children: [_jsx(FileText, { className: `w-4 h-4 ${expenseReport.exists ? "text-blue-600" : "text-gray-400"}` }), _jsx("span", { className: `text-sm ${expenseReport.exists ? "text-blue-700" : "text-gray-500"}`, children: "Expense Report" }), expenseReport.exists && (_jsx("span", { className: `text-xs font-medium px-1.5 py-0.5 rounded ml-auto ${expenseReport.colors.bg} ${expenseReport.colors.text}`, children: expenseReport.status }))] }), _jsxs("div", { className: `flex items-center gap-2 p-2 rounded ${snapshotReport.exists ? "bg-purple-50" : "bg-gray-50"}`, children: [_jsx(Camera, { className: `w-4 h-4 ${snapshotReport.exists ? "text-purple-600" : "text-gray-400"}` }), _jsx("span", { className: `text-sm ${snapshotReport.exists ? "text-purple-700" : "text-gray-500"}`, children: "Snapshot Report" }), snapshotReport.exists && (_jsx("span", { className: `text-xs font-medium px-1.5 py-0.5 rounded ml-auto ${snapshotReport.colors.bg} ${snapshotReport.colors.text}`, children: snapshotReport.status }))] })] }), !expenseReport.exists && !snapshotReport.exists && (_jsx("div", { className: "mt-3 pt-3 border-t border-gray-100", children: _jsxs("span", { className: "text-xs font-medium text-amber-600 bg-amber-50 px-2 py-1 rounded", children: ["Reports pending for ", monthName] }) }))] }, monthName));
89
+ }) })] }));
90
+ }
@@ -0,0 +1,10 @@
1
+ interface ReportingViewProps {
2
+ folderId: string;
3
+ monthName?: string;
4
+ }
5
+ /**
6
+ * View for the Reporting folder showing Expense Reports and Snapshot Reports
7
+ */
8
+ export declare function ReportingView({ folderId, monthName }: ReportingViewProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=ReportingView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReportingView.d.ts","sourceRoot":"","sources":["../../../../editors/contributor-billing/components/ReportingView.tsx"],"names":[],"mappings":"AAcA,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAiBD;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,kBAAkB,2CA0PxE"}
@@ -0,0 +1,112 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { useDocumentsInSelectedDrive, setSelectedNode, addDocument, dispatchActions, useSelectedDrive, } from "@powerhousedao/reactor-browser";
3
+ import { useMemo, useState } from "react";
4
+ import { FileText, Camera, Plus } from "lucide-react";
5
+ import { setName } from "document-model";
6
+ import { moveNode } from "document-drive";
7
+ import { actions as expenseReportActions } from "../../../document-models/expense-report/index.js";
8
+ import { actions as snapshotReportActions } from "../../../document-models/snapshot-report/index.js";
9
+ /**
10
+ * Parse a month name like "January 2026" into start and end dates
11
+ */
12
+ function parseMonthDates(monthName) {
13
+ const date = new Date(monthName + " 1"); // e.g., "January 2026 1"
14
+ if (isNaN(date.getTime()))
15
+ return null;
16
+ const start = new Date(date.getFullYear(), date.getMonth(), 1);
17
+ const end = new Date(date.getFullYear(), date.getMonth() + 1, 0); // Last day of month
18
+ return { start, end };
19
+ }
20
+ /**
21
+ * View for the Reporting folder showing Expense Reports and Snapshot Reports
22
+ */
23
+ export function ReportingView({ folderId, monthName }) {
24
+ const documentsInDrive = useDocumentsInSelectedDrive();
25
+ const [selectedDrive] = useSelectedDrive();
26
+ const [isCreating, setIsCreating] = useState(false);
27
+ // Find expense reports and snapshot reports that match this month
28
+ const { expenseReports, snapshotReports } = useMemo(() => {
29
+ if (!documentsInDrive || !monthName) {
30
+ return { expenseReports: [], snapshotReports: [] };
31
+ }
32
+ const monthLower = monthName.toLowerCase();
33
+ const expense = documentsInDrive.filter((doc) => doc.header.documentType === "powerhouse/expense-report" &&
34
+ doc.header.name?.toLowerCase().includes(monthLower));
35
+ const snapshot = documentsInDrive.filter((doc) => doc.header.documentType === "powerhouse/snapshot-report" &&
36
+ doc.header.name?.toLowerCase().includes(monthLower));
37
+ return { expenseReports: expense, snapshotReports: snapshot };
38
+ }, [documentsInDrive, monthName]);
39
+ const handleOpenDocument = (docId) => {
40
+ setSelectedNode(docId);
41
+ };
42
+ const driveId = selectedDrive?.header.id;
43
+ const handleCreateExpenseReport = async () => {
44
+ if (!driveId || !monthName || isCreating)
45
+ return;
46
+ setIsCreating(true);
47
+ try {
48
+ const reportName = `${monthName} - Expense Report`;
49
+ const createdNode = await addDocument(driveId, reportName, "powerhouse/expense-report", undefined, undefined, undefined, "powerhouse-expense-report-editor");
50
+ if (!createdNode?.id)
51
+ return;
52
+ // Move to reporting folder
53
+ if (folderId) {
54
+ await dispatchActions(moveNode({ srcFolder: createdNode.id, targetParentFolder: folderId }), driveId);
55
+ }
56
+ // Set the document name
57
+ await dispatchActions(setName(reportName), createdNode.id);
58
+ // Set period dates based on month
59
+ const dates = parseMonthDates(monthName);
60
+ if (dates) {
61
+ await dispatchActions([
62
+ expenseReportActions.setPeriodStart({
63
+ periodStart: dates.start.toISOString(),
64
+ }),
65
+ expenseReportActions.setPeriodEnd({
66
+ periodEnd: dates.end.toISOString(),
67
+ }),
68
+ ], createdNode.id);
69
+ }
70
+ // Open the created report
71
+ setSelectedNode(createdNode.id);
72
+ }
73
+ finally {
74
+ setIsCreating(false);
75
+ }
76
+ };
77
+ const handleCreateSnapshotReport = async () => {
78
+ if (!driveId || !monthName || isCreating)
79
+ return;
80
+ setIsCreating(true);
81
+ try {
82
+ const reportName = `${monthName} - Snapshot Report`;
83
+ const createdNode = await addDocument(driveId, reportName, "powerhouse/snapshot-report", undefined, undefined, undefined, "powerhouse-snapshot-report-editor");
84
+ if (!createdNode?.id)
85
+ return;
86
+ // Move to reporting folder
87
+ if (folderId) {
88
+ await dispatchActions(moveNode({ srcFolder: createdNode.id, targetParentFolder: folderId }), driveId);
89
+ }
90
+ // Set the document name
91
+ await dispatchActions(setName(reportName), createdNode.id);
92
+ // Set period dates based on month
93
+ const dates = parseMonthDates(monthName);
94
+ if (dates) {
95
+ await dispatchActions([
96
+ snapshotReportActions.setPeriodStart({
97
+ periodStart: dates.start.toISOString(),
98
+ }),
99
+ snapshotReportActions.setPeriodEnd({
100
+ periodEnd: dates.end.toISOString(),
101
+ }),
102
+ ], createdNode.id);
103
+ }
104
+ // Open the created report
105
+ setSelectedNode(createdNode.id);
106
+ }
107
+ finally {
108
+ setIsCreating(false);
109
+ }
110
+ };
111
+ return (_jsxs("div", { children: [_jsxs("div", { className: "mb-6", children: [_jsxs("h1", { className: "text-2xl font-bold text-gray-900", children: ["Reporting ", monthName ? `- ${monthName}` : ""] }), _jsxs("p", { className: "text-gray-600", children: ["Manage expense reports and snapshot reports", monthName ? ` for ${monthName}` : ""] })] }), _jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-6", children: [_jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [_jsxs("div", { className: "flex items-center justify-between mb-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(FileText, { className: "w-5 h-5 text-blue-600" }), _jsx("h2", { className: "text-lg font-semibold text-gray-900", children: "Expense Reports" })] }), expenseReports.length === 0 && (_jsxs("button", { onClick: () => void handleCreateExpenseReport(), disabled: isCreating, className: "flex items-center gap-1 px-3 py-1.5 text-sm font-medium text-blue-600 hover:bg-blue-50 rounded-md transition-colors disabled:opacity-50 disabled:cursor-not-allowed", children: [_jsx(Plus, { className: "w-4 h-4" }), isCreating ? "Creating..." : "New"] }))] }), expenseReports.length === 0 ? (_jsx("p", { className: "text-gray-500 text-sm", children: "No expense reports yet" })) : (_jsx("div", { className: "space-y-2", children: expenseReports.map((doc) => (_jsxs("button", { onClick: () => handleOpenDocument(doc.header.id), className: "w-full flex items-center gap-3 p-3 text-left hover:bg-gray-50 rounded-md transition-colors border border-gray-100", children: [_jsx(FileText, { className: "w-4 h-4 text-gray-400" }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("p", { className: "text-sm font-medium text-gray-900 truncate", children: doc.header.name || "Untitled" }), _jsxs("p", { className: "text-xs text-gray-500", children: ["Modified:", " ", new Date(doc.header.lastModifiedAtUtcIso || Date.now()).toLocaleDateString()] })] })] }, doc.header.id))) }))] }), _jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [_jsxs("div", { className: "flex items-center justify-between mb-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Camera, { className: "w-5 h-5 text-purple-600" }), _jsx("h2", { className: "text-lg font-semibold text-gray-900", children: "Snapshot Reports" })] }), snapshotReports.length === 0 && (_jsxs("button", { onClick: () => void handleCreateSnapshotReport(), disabled: isCreating, className: "flex items-center gap-1 px-3 py-1.5 text-sm font-medium text-purple-600 hover:bg-purple-50 rounded-md transition-colors disabled:opacity-50 disabled:cursor-not-allowed", children: [_jsx(Plus, { className: "w-4 h-4" }), isCreating ? "Creating..." : "New"] }))] }), snapshotReports.length === 0 ? (_jsx("p", { className: "text-gray-500 text-sm", children: "No snapshot reports yet" })) : (_jsx("div", { className: "space-y-2", children: snapshotReports.map((doc) => (_jsxs("button", { onClick: () => handleOpenDocument(doc.header.id), className: "w-full flex items-center gap-3 p-3 text-left hover:bg-gray-50 rounded-md transition-colors border border-gray-100", children: [_jsx(Camera, { className: "w-4 h-4 text-gray-400" }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("p", { className: "text-sm font-medium text-gray-900 truncate", children: doc.header.name || "Untitled" }), _jsxs("p", { className: "text-xs text-gray-500", children: ["Modified:", " ", new Date(doc.header.lastModifiedAtUtcIso || Date.now()).toLocaleDateString()] })] })] }, doc.header.id))) }))] })] })] }));
112
+ }
@@ -1,6 +1,6 @@
1
1
  /** Editor config for the ContributorBilling */
2
2
  export const editorConfig = {
3
- isDragAndDropEnabled: true,
3
+ isDragAndDropEnabled: false,
4
4
  allowedDocumentTypes: [
5
5
  "powerhouse/invoice",
6
6
  "powerhouse/billing-statement",
@@ -0,0 +1,54 @@
1
+ import type { FolderNode } from "document-drive";
2
+ export interface MonthFolderInfo {
3
+ folder: FolderNode;
4
+ paymentsFolder: FolderNode | null;
5
+ reportingFolder: FolderNode | null;
6
+ }
7
+ export interface UseBillingFolderStructureResult {
8
+ /** The Billing root folder node, or null if it doesn't exist yet */
9
+ billingFolder: FolderNode | null;
10
+ /** Map of month name to folder info (e.g., "January 2025" -> folder info) */
11
+ monthFolders: Map<string, MonthFolderInfo>;
12
+ /** The current month's folder info, or null if not created yet */
13
+ currentMonthFolder: MonthFolderInfo | null;
14
+ /** Create the Billing folder if it doesn't exist */
15
+ createBillingFolder: () => Promise<void>;
16
+ /** Create a new month folder with Payments and Reporting subfolders */
17
+ createMonthFolder: (monthName: string) => Promise<void>;
18
+ /** Check if a folder is a Payments folder */
19
+ isPaymentsFolder: (folderId: string) => boolean;
20
+ /** Check if a folder is a Reporting folder */
21
+ isReportingFolder: (folderId: string) => boolean;
22
+ /** Get all Payments folder IDs */
23
+ paymentsFolderIds: Set<string>;
24
+ /** Get all Reporting folder IDs */
25
+ reportingFolderIds: Set<string>;
26
+ }
27
+ /**
28
+ * Format a date as "January 2025"
29
+ */
30
+ export declare function formatMonthName(date: Date): string;
31
+ /**
32
+ * Get the current month name (e.g., "January 2025")
33
+ */
34
+ export declare function getCurrentMonthName(): string;
35
+ /**
36
+ * Hook that manages the Billing folder structure in the Contributor Billing drive.
37
+ *
38
+ * Structure:
39
+ * Billing/
40
+ * ├── January 2025/
41
+ * │ ├── Payments/
42
+ * │ └── Reporting/
43
+ * ├── February 2025/
44
+ * │ ├── Payments/
45
+ * │ └── Reporting/
46
+ * └── ...
47
+ *
48
+ * This hook:
49
+ * 1. Creates the "Billing" folder if it doesn't exist
50
+ * 2. Auto-creates the current month folder with Payments/Reporting subfolders
51
+ * 3. Provides a function to manually create additional month folders
52
+ */
53
+ export declare function useBillingFolderStructure(): UseBillingFolderStructureResult;
54
+ //# sourceMappingURL=useBillingFolderStructure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useBillingFolderStructure.d.ts","sourceRoot":"","sources":["../../../../editors/contributor-billing/hooks/useBillingFolderStructure.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAQ,MAAM,gBAAgB,CAAC;AAYvD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,UAAU,CAAC;IACnB,cAAc,EAAE,UAAU,GAAG,IAAI,CAAC;IAClC,eAAe,EAAE,UAAU,GAAG,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,+BAA+B;IAC9C,oEAAoE;IACpE,aAAa,EAAE,UAAU,GAAG,IAAI,CAAC;IACjC,6EAA6E;IAC7E,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC3C,kEAAkE;IAClE,kBAAkB,EAAE,eAAe,GAAG,IAAI,CAAC;IAC3C,oDAAoD;IACpD,mBAAmB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,uEAAuE;IACvE,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,6CAA6C;IAC7C,gBAAgB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IAChD,8CAA8C;IAC9C,iBAAiB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IACjD,kCAAkC;IAClC,iBAAiB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC/B,mCAAmC;IACnC,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAElD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,IAAI,+BAA+B,CAsJ3E"}
@@ -0,0 +1,145 @@
1
+ import { useMemo, useCallback } from "react";
2
+ import { isFolderNodeKind, addFolder, useSelectedDrive, } from "@powerhousedao/reactor-browser";
3
+ const BILLING_FOLDER_NAME = "Billing";
4
+ const PAYMENTS_FOLDER_NAME = "Payments";
5
+ const REPORTING_FOLDER_NAME = "Reporting";
6
+ // Module-level tracking to prevent duplicate folder creation across all hook instances
7
+ const globalCreationState = {
8
+ createdBillingFolderForDrives: new Set(),
9
+ creatingMonths: new Set(), // Format: "driveId:monthName"
10
+ };
11
+ /**
12
+ * Format a date as "January 2025"
13
+ */
14
+ export function formatMonthName(date) {
15
+ return date.toLocaleDateString("en-US", { month: "long", year: "numeric" });
16
+ }
17
+ /**
18
+ * Get the current month name (e.g., "January 2025")
19
+ */
20
+ export function getCurrentMonthName() {
21
+ return formatMonthName(new Date());
22
+ }
23
+ /**
24
+ * Hook that manages the Billing folder structure in the Contributor Billing drive.
25
+ *
26
+ * Structure:
27
+ * Billing/
28
+ * ├── January 2025/
29
+ * │ ├── Payments/
30
+ * │ └── Reporting/
31
+ * ├── February 2025/
32
+ * │ ├── Payments/
33
+ * │ └── Reporting/
34
+ * └── ...
35
+ *
36
+ * This hook:
37
+ * 1. Creates the "Billing" folder if it doesn't exist
38
+ * 2. Auto-creates the current month folder with Payments/Reporting subfolders
39
+ * 3. Provides a function to manually create additional month folders
40
+ */
41
+ export function useBillingFolderStructure() {
42
+ const [driveDocument] = useSelectedDrive();
43
+ const driveId = driveDocument?.header.id;
44
+ // Find the "Billing" root folder
45
+ const billingFolder = useMemo(() => {
46
+ if (!driveDocument)
47
+ return null;
48
+ const nodes = driveDocument.state.global.nodes;
49
+ return (nodes.find((node) => isFolderNodeKind(node) && node.name === BILLING_FOLDER_NAME) ?? null);
50
+ }, [driveDocument]);
51
+ // Find all month folders under Billing and their subfolders
52
+ const monthFolders = useMemo(() => {
53
+ const folders = new Map();
54
+ if (!driveDocument || !billingFolder)
55
+ return folders;
56
+ const allNodes = driveDocument.state.global.nodes;
57
+ // Find all folders directly under Billing (these are month folders)
58
+ const monthFolderNodes = allNodes.filter((node) => isFolderNodeKind(node) && node.parentFolder === billingFolder.id);
59
+ for (const monthFolder of monthFolderNodes) {
60
+ // Find Payments and Reporting subfolders
61
+ const paymentsFolder = allNodes.find((node) => isFolderNodeKind(node) &&
62
+ node.parentFolder === monthFolder.id &&
63
+ node.name === PAYMENTS_FOLDER_NAME) ?? null;
64
+ const reportingFolder = allNodes.find((node) => isFolderNodeKind(node) &&
65
+ node.parentFolder === monthFolder.id &&
66
+ node.name === REPORTING_FOLDER_NAME) ?? null;
67
+ folders.set(monthFolder.name, {
68
+ folder: monthFolder,
69
+ paymentsFolder,
70
+ reportingFolder,
71
+ });
72
+ }
73
+ return folders;
74
+ }, [driveDocument, billingFolder]);
75
+ // Get current month folder info
76
+ const currentMonthFolder = useMemo(() => {
77
+ const currentMonth = getCurrentMonthName();
78
+ return monthFolders.get(currentMonth) ?? null;
79
+ }, [monthFolders]);
80
+ // Build sets of Payments and Reporting folder IDs for quick lookup
81
+ const { paymentsFolderIds, reportingFolderIds } = useMemo(() => {
82
+ const paymentsIds = new Set();
83
+ const reportingIds = new Set();
84
+ for (const info of monthFolders.values()) {
85
+ if (info.paymentsFolder) {
86
+ paymentsIds.add(info.paymentsFolder.id);
87
+ }
88
+ if (info.reportingFolder) {
89
+ reportingIds.add(info.reportingFolder.id);
90
+ }
91
+ }
92
+ return { paymentsFolderIds: paymentsIds, reportingFolderIds: reportingIds };
93
+ }, [monthFolders]);
94
+ const isPaymentsFolder = useCallback((folderId) => paymentsFolderIds.has(folderId), [paymentsFolderIds]);
95
+ const isReportingFolder = useCallback((folderId) => reportingFolderIds.has(folderId), [reportingFolderIds]);
96
+ // Create a new month folder with Payments and Reporting subfolders
97
+ const createMonthFolder = useCallback(async (monthName) => {
98
+ if (!driveId || !billingFolder)
99
+ return;
100
+ if (monthFolders.has(monthName))
101
+ return; // Already exists
102
+ const creationKey = `${driveId}:${monthName}`;
103
+ if (globalCreationState.creatingMonths.has(creationKey))
104
+ return; // Already creating
105
+ globalCreationState.creatingMonths.add(creationKey);
106
+ try {
107
+ // Create month folder
108
+ const monthFolder = await addFolder(driveId, monthName, billingFolder.id);
109
+ if (!monthFolder) {
110
+ console.error(`Failed to create month folder: ${monthName}`);
111
+ return;
112
+ }
113
+ // Create Payments subfolder
114
+ await addFolder(driveId, PAYMENTS_FOLDER_NAME, monthFolder.id);
115
+ // Create Reporting subfolder
116
+ await addFolder(driveId, REPORTING_FOLDER_NAME, monthFolder.id);
117
+ }
118
+ catch (error) {
119
+ console.error(`Error creating month folder structure: ${monthName}`, error);
120
+ }
121
+ finally {
122
+ globalCreationState.creatingMonths.delete(creationKey);
123
+ }
124
+ }, [driveId, billingFolder, monthFolders]);
125
+ // Create the Billing folder if it doesn't exist (called manually)
126
+ const createBillingFolder = useCallback(async () => {
127
+ if (!driveId || billingFolder)
128
+ return;
129
+ if (globalCreationState.createdBillingFolderForDrives.has(driveId))
130
+ return;
131
+ globalCreationState.createdBillingFolderForDrives.add(driveId);
132
+ await addFolder(driveId, BILLING_FOLDER_NAME);
133
+ }, [driveId, billingFolder]);
134
+ return {
135
+ billingFolder,
136
+ monthFolders,
137
+ currentMonthFolder,
138
+ createBillingFolder,
139
+ createMonthFolder,
140
+ isPaymentsFolder,
141
+ isReportingFolder,
142
+ paymentsFolderIds,
143
+ reportingFolderIds,
144
+ };
145
+ }
@@ -5,7 +5,9 @@ interface AddBillingStatementModalProps {
5
5
  walletAddress: string;
6
6
  dispatch: any;
7
7
  groups: LineItemGroup[];
8
+ /** The Payments folder ID to filter billing statements by. If not provided, shows all billing statements in the drive. */
9
+ paymentsFolderId?: string | null;
8
10
  }
9
- export declare function AddBillingStatementModal({ isOpen, onClose, walletAddress, dispatch, groups, }: AddBillingStatementModalProps): import("react/jsx-runtime").JSX.Element | null;
11
+ export declare function AddBillingStatementModal({ isOpen, onClose, walletAddress, dispatch, groups, paymentsFolderId, }: AddBillingStatementModalProps): import("react/jsx-runtime").JSX.Element | null;
10
12
  export {};
11
13
  //# sourceMappingURL=AddBillingStatementModal.d.ts.map
@@ -1 +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;AAI1F,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,kDAwU/B"}
1
+ {"version":3,"file":"AddBillingStatementModal.d.ts","sourceRoot":"","sources":["../../../../editors/expense-report/components/AddBillingStatementModal.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sDAAsD,CAAC;AAI1F,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;IACxB,0HAA0H;IAC1H,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AA+BD,wBAAgB,wBAAwB,CAAC,EACvC,MAAM,EACN,OAAO,EACP,aAAa,EACb,QAAQ,EACR,MAAM,EACN,gBAAgB,GACjB,EAAE,6BAA6B,kDA2V/B"}
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState, useMemo } from "react";
3
3
  import { Button } from "@powerhousedao/document-engineering";
4
- import { useDocumentsInSelectedDrive } from "@powerhousedao/reactor-browser";
4
+ import { useDocumentsInSelectedDrive, useSelectedDrive, isFileNodeKind, } from "@powerhousedao/reactor-browser";
5
5
  import { generateId } from "document-model";
6
6
  import { X, FileText, Check } from "lucide-react";
7
7
  import { actions } from "../../../document-models/expense-report/index.js";
@@ -33,8 +33,9 @@ const fusionLabelToValue = {
33
33
  "Non-current Liability": "liabilities/non-current",
34
34
  Equity: "equity/retained",
35
35
  };
36
- export function AddBillingStatementModal({ isOpen, onClose, walletAddress, dispatch, groups, }) {
36
+ export function AddBillingStatementModal({ isOpen, onClose, walletAddress, dispatch, groups, paymentsFolderId, }) {
37
37
  const documents = useDocumentsInSelectedDrive();
38
+ const [driveDocument] = useSelectedDrive();
38
39
  const [selectedStatements, setSelectedStatements] = useState(new Set());
39
40
  const [searchTerm, setSearchTerm] = useState("");
40
41
  // Get already added billing statement IDs for this wallet from documents
@@ -55,18 +56,33 @@ export function AddBillingStatementModal({ isOpen, onClose, walletAddress, dispa
55
56
  });
56
57
  return ids;
57
58
  }, [documents, walletAddress]);
58
- // Get billing statement documents from the drive
59
+ // Get billing statement documents from the drive, filtered by the Payments folder
59
60
  const billingStatements = useMemo(() => {
60
- if (!documents)
61
+ if (!documents || !driveDocument)
61
62
  return [];
63
+ // Get all file nodes from the drive
64
+ const nodes = driveDocument.state.global.nodes;
65
+ // If we have a payments folder ID, filter billing statements to only those in that folder
66
+ // Otherwise, show all billing statements (fallback for editors used outside contributor billing)
62
67
  return documents
63
- .filter((doc) => doc.header.documentType === "powerhouse/billing-statement")
68
+ .filter((doc) => {
69
+ if (doc.header.documentType !== "powerhouse/billing-statement") {
70
+ return false;
71
+ }
72
+ // If we have a payments folder, only include billing statements in that folder
73
+ if (paymentsFolderId) {
74
+ const fileNode = nodes.find((node) => isFileNodeKind(node) && node.id === doc.header.id);
75
+ return fileNode?.parentFolder === paymentsFolderId;
76
+ }
77
+ // Fallback: include all billing statements if no payments folder context
78
+ return true;
79
+ })
64
80
  .map((doc) => ({
65
81
  id: doc.header.id,
66
82
  name: doc.header.name,
67
83
  document: doc, // Full document with state
68
84
  }));
69
- }, [documents]);
85
+ }, [documents, driveDocument, paymentsFolderId]);
70
86
  // Filter billing statements based on search term
71
87
  const filteredStatements = useMemo(() => {
72
88
  if (!searchTerm.trim())
@@ -144,7 +160,7 @@ export function AddBillingStatementModal({ isOpen, onClose, walletAddress, dispa
144
160
  const group = groups.find((g) => g.id === groupId);
145
161
  categoryAggregation.set(categoryKey, {
146
162
  groupId: groupId,
147
- groupLabel: group?.label || "Uncategorised",
163
+ groupLabel: group?.label || "Uncategorized",
148
164
  budget: 0,
149
165
  actuals: billingLineItem.totalPriceCash || 0,
150
166
  forecast: 0,
@@ -191,7 +191,7 @@ export function AggregatedExpensesTable({ wallets, groups, periodStart, periodEn
191
191
  items.push({
192
192
  lineItemId: item.id || "",
193
193
  groupId: item.group || "uncategorized",
194
- groupLabel: item.groupLabel || "Uncategorised",
194
+ groupLabel: item.groupLabel || "Uncategorized",
195
195
  parentGroupId: item.parentGroupId,
196
196
  parentGroupLabel: item.parentGroupLabel,
197
197
  budget: item.budget || 0,
@@ -341,7 +341,7 @@ export function AggregatedExpensesTable({ wallets, groups, periodStart, periodEn
341
341
  return null;
342
342
  const subtotals = calculateSubtotal(items);
343
343
  const parentLabel = parentKey === "uncategorized"
344
- ? "Uncategorised"
344
+ ? "Uncategorized"
345
345
  : items[0]?.parentGroupLabel || "Other";
346
346
  return (_jsxs(React.Fragment, { children: [_jsx("tr", { className: "bg-gray-100 dark:bg-gray-800", children: _jsx("td", { colSpan: 8, className: "px-6 py-3 text-sm font-bold text-gray-900 dark:text-white", children: parentLabel }) }), items.map((item) => {
347
347
  if (!item)
@@ -220,7 +220,7 @@ export function ExpenseReportPDF({ periodStart, periodEnd, wallets, groups, }) {
220
220
  });
221
221
  return entries.map(([key, items]) => ({
222
222
  parentLabel: key === "uncategorized"
223
- ? "Uncategorised"
223
+ ? "Uncategorized"
224
224
  : items[0]?.parentGroupLabel || "Unknown",
225
225
  items,
226
226
  }));
@@ -264,7 +264,7 @@ export function ExpenseReportPDF({ periodStart, periodEnd, wallets, groups, }) {
264
264
  : styles.differenceNormal;
265
265
  return (_jsxs(View, { style: itemIndex % 2 === 0
266
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: [
267
+ : styles.tableRowAlt, children: [_jsx(Text, { style: [styles.cell, styles.categoryCol], children: item.groupLabel || item.label || "Uncategorized" }), _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
268
  styles.cellRight,
269
269
  styles.differenceCol,
270
270
  differenceStyle,
@@ -1 +1 @@
1
- {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../../editors/expense-report/editor.tsx"],"names":[],"mappings":"AAmEA,MAAM,CAAC,OAAO,UAAU,MAAM,4CAoV7B"}
1
+ {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../../editors/expense-report/editor.tsx"],"names":[],"mappings":"AAuEA,MAAM,CAAC,OAAO,UAAU,MAAM,4CAiZ7B"}