@powerhousedao/contributor-billing 0.1.53 → 1.0.0-dev.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/document-models/account-transactions/gen/schema/zod.d.ts.map +1 -1
- package/dist/document-models/account-transactions/gen/schema/zod.js +3 -3
- package/dist/document-models/account-transactions/module.d.ts +1 -1
- package/dist/document-models/account-transactions/module.d.ts.map +1 -1
- package/dist/document-models/account-transactions/module.js +1 -1
- package/dist/document-models/accounts/gen/schema/zod.d.ts.map +1 -1
- package/dist/document-models/accounts/module.d.ts +1 -1
- package/dist/document-models/accounts/module.d.ts.map +1 -1
- package/dist/document-models/accounts/module.js +1 -1
- package/dist/document-models/billing-statement/gen/schema/zod.d.ts.map +1 -1
- package/dist/document-models/billing-statement/gen/schema/zod.js +4 -4
- package/dist/document-models/billing-statement/module.d.ts +1 -1
- package/dist/document-models/billing-statement/module.d.ts.map +1 -1
- package/dist/document-models/billing-statement/module.js +1 -1
- package/dist/document-models/expense-report/gen/schema/zod.d.ts.map +1 -1
- package/dist/document-models/expense-report/gen/schema/zod.js +38 -18
- package/dist/document-models/expense-report/module.d.ts +1 -1
- package/dist/document-models/expense-report/module.d.ts.map +1 -1
- package/dist/document-models/expense-report/module.js +1 -1
- package/dist/document-models/invoice/gen/document-model.d.ts.map +1 -1
- package/dist/document-models/invoice/gen/document-model.js +150 -150
- package/dist/document-models/invoice/gen/schema/types.d.ts +3 -6
- package/dist/document-models/invoice/gen/schema/types.d.ts.map +1 -1
- package/dist/document-models/invoice/gen/schema/zod.d.ts +2 -8
- package/dist/document-models/invoice/gen/schema/zod.d.ts.map +1 -1
- package/dist/document-models/invoice/gen/schema/zod.js +14 -25
- package/dist/document-models/invoice/module.d.ts +1 -1
- package/dist/document-models/invoice/module.d.ts.map +1 -1
- package/dist/document-models/invoice/module.js +1 -1
- package/dist/document-models/invoice/src/reducers/general.d.ts.map +1 -1
- package/dist/document-models/invoice/src/reducers/general.js +8 -0
- package/dist/document-models/invoice/src/reducers/items.d.ts.map +1 -1
- package/dist/document-models/invoice/src/reducers/items.js +2 -1
- package/dist/document-models/invoice/src/reducers/parties.d.ts.map +1 -1
- package/dist/document-models/invoice/src/reducers/parties.js +6 -2
- package/dist/document-models/invoice/src/reducers/transitions.d.ts +0 -5
- package/dist/document-models/invoice/src/reducers/transitions.d.ts.map +1 -1
- package/dist/document-models/invoice/src/reducers/transitions.js +19 -6
- package/dist/document-models/invoice/tests/general.test.js +11 -2
- package/dist/document-models/invoice/tests/items.test.js +1 -1
- package/dist/document-models/invoice/tests/parties.test.js +1 -1
- package/dist/document-models/invoice/tests/transitions.test.js +7 -2
- package/dist/document-models/operational-hub-profile/module.d.ts +1 -1
- package/dist/document-models/operational-hub-profile/module.d.ts.map +1 -1
- package/dist/document-models/operational-hub-profile/module.js +1 -1
- package/dist/document-models/snapshot-report/gen/schema/zod.d.ts.map +1 -1
- package/dist/document-models/snapshot-report/gen/schema/zod.js +12 -12
- package/dist/document-models/snapshot-report/module.d.ts +1 -1
- package/dist/document-models/snapshot-report/module.d.ts.map +1 -1
- package/dist/document-models/snapshot-report/module.js +1 -1
- package/dist/editors/accounts-editor/editor.d.ts.map +1 -1
- package/dist/editors/accounts-editor/editor.js +2 -2
- package/dist/editors/builder-team-admin/components/DriveExplorer.d.ts.map +1 -1
- package/dist/editors/builder-team-admin/components/DriveExplorer.js +64 -4
- package/dist/editors/builder-team-admin/module.js +1 -1
- package/dist/editors/contributor-billing/components/DashboardHome.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/DashboardHome.js +2 -8
- package/dist/editors/contributor-billing/components/DocumentDropZone.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/DocumentDropZone.js +37 -8
- package/dist/editors/contributor-billing/components/DriveContents.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/DriveContents.js +4 -1
- package/dist/editors/contributor-billing/components/DriveExplorer.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/DriveExplorer.js +54 -3
- package/dist/editors/contributor-billing/components/FolderTree.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/FolderTree.js +6 -15
- package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.d.ts +2 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.js +41 -6
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.d.ts +1 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.js +16 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableContainer.d.ts +3 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableContainer.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableContainer.js +13 -11
- package/dist/editors/contributor-billing/components/MonthReportCard.d.ts +11 -4
- package/dist/editors/contributor-billing/components/MonthReportCard.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/MonthReportCard.js +55 -6
- package/dist/editors/contributor-billing/components/MonthlyReportsOverview.d.ts +1 -1
- package/dist/editors/contributor-billing/components/MonthlyReportsOverview.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/MonthlyReportsOverview.js +104 -7
- package/dist/editors/contributor-billing/components/ReportingView.d.ts +0 -3
- package/dist/editors/contributor-billing/components/ReportingView.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/ReportingView.js +65 -8
- package/dist/editors/contributor-billing/components/ToastRenderer.d.ts +2 -0
- package/dist/editors/contributor-billing/components/ToastRenderer.d.ts.map +1 -0
- package/dist/editors/contributor-billing/components/ToastRenderer.js +14 -0
- package/dist/editors/contributor-billing/components/cbToast.d.ts +16 -0
- package/dist/editors/contributor-billing/components/cbToast.d.ts.map +1 -0
- package/dist/editors/contributor-billing/components/cbToast.js +29 -0
- package/dist/editors/contributor-billing/hooks/useDocumentAutoPlacement.d.ts.map +1 -1
- package/dist/editors/contributor-billing/hooks/useDocumentAutoPlacement.js +42 -2
- package/dist/editors/contributor-billing/hooks/useMonthlyReports.d.ts +4 -0
- package/dist/editors/contributor-billing/hooks/useMonthlyReports.d.ts.map +1 -1
- package/dist/editors/contributor-billing/hooks/useMonthlyReports.js +4 -0
- package/dist/editors/contributor-billing/module.js +1 -1
- package/dist/editors/invoice/InvoicePDF.d.ts.map +1 -1
- package/dist/editors/invoice/InvoicePDF.js +12 -9
- package/dist/editors/invoice/editor.d.ts.map +1 -1
- package/dist/editors/invoice/editor.js +6 -10
- package/dist/editors/invoice/exportUBL.d.ts.map +1 -1
- package/dist/editors/invoice/exportUBL.js +1 -2
- package/dist/editors/invoice/ingestPDF.js +1 -1
- package/dist/editors/invoice/invoiceToGnosis.d.ts.map +1 -1
- package/dist/editors/invoice/invoiceToGnosis.js +25 -22
- package/dist/editors/invoice/invoiceToast.d.ts +4 -0
- package/dist/editors/invoice/invoiceToast.d.ts.map +1 -0
- package/dist/editors/invoice/invoiceToast.js +6 -0
- package/dist/editors/invoice/legalEntity/legalEntity.d.ts +2 -1
- package/dist/editors/invoice/legalEntity/legalEntity.d.ts.map +1 -1
- package/dist/editors/invoice/legalEntity/legalEntity.js +3 -14
- package/dist/editors/invoice/legalEntity/walletSection.d.ts +1 -0
- package/dist/editors/invoice/legalEntity/walletSection.d.ts.map +1 -1
- package/dist/editors/invoice/legalEntity/walletSection.js +2 -2
- package/dist/editors/invoice/lineItems.js +1 -1
- package/dist/editors/invoice/requestFinance.d.ts +3 -2
- package/dist/editors/invoice/requestFinance.d.ts.map +1 -1
- package/dist/editors/invoice/requestFinance.js +38 -42
- package/dist/editors/invoice/validation/validationHandler.d.ts +1 -1
- package/dist/editors/invoice/validation/validationHandler.d.ts.map +1 -1
- package/dist/editors/invoice/validation/validationHandler.js +15 -2
- package/dist/editors/invoice/validation/validationManager.d.ts +1 -1
- package/dist/editors/invoice/validation/validationManager.d.ts.map +1 -1
- package/dist/editors/invoice/validation/validationManager.js +2 -1
- package/dist/editors/invoice/validation/validationRules.d.ts +1 -0
- package/dist/editors/invoice/validation/validationRules.d.ts.map +1 -1
- package/dist/editors/invoice/validation/validationRules.js +26 -1
- package/dist/editors/snapshot-report-editor/components/DateRangePicker.d.ts +19 -0
- package/dist/editors/snapshot-report-editor/components/DateRangePicker.d.ts.map +1 -0
- package/dist/editors/snapshot-report-editor/components/DateRangePicker.js +66 -0
- package/dist/editors/snapshot-report-editor/editor.d.ts.map +1 -1
- package/dist/editors/snapshot-report-editor/editor.js +72 -48
- package/dist/scripts/download-all-drive-documents/download-drive-documents.d.ts +33 -0
- package/dist/scripts/download-all-drive-documents/download-drive-documents.d.ts.map +1 -0
- package/dist/scripts/download-all-drive-documents/download-drive-documents.js +583 -0
- package/dist/scripts/invoice/requestFinance.d.ts +18 -1
- package/dist/scripts/invoice/requestFinance.d.ts.map +1 -1
- package/dist/scripts/invoice/requestFinance.js +17 -5
- package/dist/scripts/upload-phd-documents/upload-phd-documents.d.ts +20 -0
- package/dist/scripts/upload-phd-documents/upload-phd-documents.d.ts.map +1 -0
- package/dist/scripts/upload-phd-documents/upload-phd-documents.js +313 -0
- package/dist/style.css +201 -106
- package/dist/subgraphs/budget-statements/resolvers.d.ts +38 -0
- package/dist/subgraphs/budget-statements/resolvers.d.ts.map +1 -1
- package/dist/subgraphs/budget-statements/resolvers.js +192 -62
- package/dist/subgraphs/budget-statements/resolvers.test.d.ts +2 -0
- package/dist/subgraphs/budget-statements/resolvers.test.d.ts.map +1 -0
- package/dist/subgraphs/budget-statements/resolvers.test.js +339 -0
- package/dist/subgraphs/budget-statements/schema.d.ts.map +1 -1
- package/dist/subgraphs/budget-statements/schema.js +8 -0
- package/dist/subgraphs/index.d.ts +0 -1
- package/dist/subgraphs/index.d.ts.map +1 -1
- package/dist/subgraphs/index.js +0 -1
- package/dist/subgraphs/invoice-addon/customResolvers.d.ts +70 -11
- package/dist/subgraphs/invoice-addon/customResolvers.d.ts.map +1 -1
- package/dist/subgraphs/invoice-addon/customResolvers.js +12 -27
- package/package.json +35 -28
- package/dist/document-models/invoice/src/tests/document-model.test.d.ts +0 -10
- package/dist/document-models/invoice/src/tests/document-model.test.d.ts.map +0 -1
- package/dist/document-models/invoice/src/tests/document-model.test.js +0 -104
- package/dist/document-models/invoice/src/tests/general.test.d.ts +0 -6
- package/dist/document-models/invoice/src/tests/general.test.d.ts.map +0 -1
- package/dist/document-models/invoice/src/tests/general.test.js +0 -49
- package/dist/document-models/invoice/src/tests/items.test.d.ts +0 -6
- package/dist/document-models/invoice/src/tests/items.test.d.ts.map +0 -1
- package/dist/document-models/invoice/src/tests/items.test.js +0 -59
- package/dist/document-models/invoice/src/tests/parties.test.d.ts +0 -6
- package/dist/document-models/invoice/src/tests/parties.test.d.ts.map +0 -1
- package/dist/document-models/invoice/src/tests/parties.test.js +0 -69
- package/dist/document-models/invoice/src/tests/transitions.test.d.ts +0 -6
- package/dist/document-models/invoice/src/tests/transitions.test.d.ts.map +0 -1
- package/dist/document-models/invoice/src/tests/transitions.test.js +0 -59
- package/dist/document-models/invoice/utils/statusTransitions.d.ts +0 -13
- package/dist/document-models/invoice/utils/statusTransitions.d.ts.map +0 -1
- package/dist/document-models/invoice/utils/statusTransitions.js +0 -13
- package/dist/editors/builder-team-admin/components/overview/SubscriptionsStats.d.ts +0 -15
- package/dist/editors/builder-team-admin/components/overview/SubscriptionsStats.d.ts.map +0 -1
- package/dist/editors/builder-team-admin/components/overview/SubscriptionsStats.js +0 -61
- package/dist/editors/contributor-billing/components/CreateHubProfileModal.d.ts +0 -12
- package/dist/editors/contributor-billing/components/CreateHubProfileModal.d.ts.map +0 -1
- package/dist/editors/contributor-billing/components/CreateHubProfileModal.js +0 -74
- package/dist/subgraphs/resources-services/index.d.ts +0 -11
- package/dist/subgraphs/resources-services/index.d.ts.map +0 -1
- package/dist/subgraphs/resources-services/index.js +0 -11
- package/dist/subgraphs/resources-services/resolvers.d.ts +0 -3
- package/dist/subgraphs/resources-services/resolvers.d.ts.map +0 -1
- package/dist/subgraphs/resources-services/resolvers.js +0 -462
- package/dist/subgraphs/resources-services/schema.d.ts +0 -3
- package/dist/subgraphs/resources-services/schema.d.ts.map +0 -1
- package/dist/subgraphs/resources-services/schema.js +0 -284
|
@@ -1,13 +1,32 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { setName } from "document-model";
|
|
2
3
|
import { FolderTree } from "./FolderTree.js";
|
|
3
4
|
import { DriveContents } from "./DriveContents.js";
|
|
4
5
|
import { ContributorsSection } from "./team-members.js";
|
|
5
|
-
import { useDocumentsInSelectedDrive,
|
|
6
|
-
import { useMemo, useState } from "react";
|
|
6
|
+
import { useDocumentsInSelectedDrive, useSelectedDrive, addDocument, dispatchActions, setSelectedNode, } from "@powerhousedao/reactor-browser";
|
|
7
|
+
import { useCallback, useMemo, useState } from "react";
|
|
8
|
+
import { isValidName } from "document-drive";
|
|
7
9
|
import { ExpenseReports } from "./expense-reports.js";
|
|
8
10
|
import { SnapshotReports } from "./snapshot-reports.js";
|
|
9
11
|
import { ResourcesServices } from "./ResourcesServices.js";
|
|
10
12
|
import { ServiceSubscriptions } from "./service-subscriptions.js";
|
|
13
|
+
import { actions as builderProfileActions } from "@powerhousedao/builder-profile/document-models/builder-profile";
|
|
14
|
+
function generateCode(name) {
|
|
15
|
+
const words = name.trim().split(/\s+/).filter(Boolean);
|
|
16
|
+
if (words.length >= 2) {
|
|
17
|
+
// Acronym from first letter of each word, capped at 5
|
|
18
|
+
let code = words.map((w) => w[0]).join("");
|
|
19
|
+
// If only 2 words, pad with second letter of the first word
|
|
20
|
+
if (code.length < 3 && words[0].length > 1) {
|
|
21
|
+
code = words[0][0] + words[0][1] + words[1][0];
|
|
22
|
+
}
|
|
23
|
+
return code.slice(0, 5).toUpperCase();
|
|
24
|
+
}
|
|
25
|
+
// Single word: first, middle, last letter
|
|
26
|
+
const word = words[0];
|
|
27
|
+
const mid = Math.floor(word.length / 2);
|
|
28
|
+
return (word[0] + word[mid] + word[word.length - 1]).toUpperCase();
|
|
29
|
+
}
|
|
11
30
|
/**
|
|
12
31
|
* Main drive explorer component with sidebar navigation and content area.
|
|
13
32
|
* Layout: Left sidebar (folder tree) + Right content area (files/folders + document editor)
|
|
@@ -17,15 +36,56 @@ export function DriveExplorer({ children }) {
|
|
|
17
36
|
const showDocumentEditor = !!children;
|
|
18
37
|
const documentsInSelectedDrive = useDocumentsInSelectedDrive();
|
|
19
38
|
const [customView, setCustomView] = useState(null);
|
|
39
|
+
const [profileName, setProfileName] = useState("");
|
|
40
|
+
const [isCreating, setIsCreating] = useState(false);
|
|
41
|
+
const [selectedDrive] = useSelectedDrive();
|
|
20
42
|
// Check if builder profile document exists
|
|
21
43
|
const hasBuilderProfile = useMemo(() => {
|
|
22
44
|
if (!documentsInSelectedDrive)
|
|
23
45
|
return false;
|
|
24
46
|
return documentsInSelectedDrive.some((doc) => doc.header.documentType === "powerhouse/builder-profile");
|
|
25
47
|
}, [documentsInSelectedDrive]);
|
|
26
|
-
|
|
48
|
+
const handleCreateProfile = useCallback(async () => {
|
|
49
|
+
const trimmedName = profileName.trim();
|
|
50
|
+
const driveId = selectedDrive?.header.id;
|
|
51
|
+
if (!trimmedName || !driveId || isCreating)
|
|
52
|
+
return;
|
|
53
|
+
setIsCreating(true);
|
|
54
|
+
try {
|
|
55
|
+
const createdNode = await addDocument(driveId, trimmedName, "powerhouse/builder-profile");
|
|
56
|
+
if (!createdNode?.id) {
|
|
57
|
+
console.error("Failed to create builder profile document");
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
// Set the profile name, slug, and code in the document state
|
|
61
|
+
const slug = trimmedName
|
|
62
|
+
.toLowerCase()
|
|
63
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
64
|
+
.replace(/^-|-$/g, "");
|
|
65
|
+
const code = generateCode(trimmedName);
|
|
66
|
+
await dispatchActions(builderProfileActions.updateProfile({ name: trimmedName, slug, code }), createdNode.id);
|
|
67
|
+
// Set the document name to match
|
|
68
|
+
await dispatchActions(setName(trimmedName), createdNode.id);
|
|
69
|
+
// Deselect so the main drive view renders instead of the document editor
|
|
70
|
+
setSelectedNode("");
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
console.error("Error creating builder profile:", error);
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
setIsCreating(false);
|
|
77
|
+
}
|
|
78
|
+
}, [profileName, selectedDrive?.header.id, isCreating]);
|
|
79
|
+
const handleSubmit = useCallback((e) => {
|
|
80
|
+
e.preventDefault();
|
|
81
|
+
if (isValidName(profileName) && !isCreating) {
|
|
82
|
+
void handleCreateProfile();
|
|
83
|
+
}
|
|
84
|
+
}, [profileName, isCreating, handleCreateProfile]);
|
|
85
|
+
// If no builder profile exists, show the creation form
|
|
27
86
|
if (!hasBuilderProfile) {
|
|
28
|
-
|
|
87
|
+
const isValid = isValidName(profileName);
|
|
88
|
+
return (_jsx("div", { className: "flex h-full items-center justify-center px-4 py-12", children: _jsxs("div", { className: "relative w-full max-w-2xl overflow-hidden rounded-2xl border border-slate-200/50 bg-gradient-to-br from-slate-50 via-blue-50/30 to-indigo-50/40 p-12 shadow-xl shadow-slate-200/50 backdrop-blur-sm", children: [_jsx("div", { className: "absolute -right-20 -top-20 h-64 w-64 rounded-full bg-gradient-to-br from-blue-400/20 to-indigo-400/20 blur-3xl" }), _jsx("div", { className: "absolute -bottom-16 -left-16 h-48 w-48 rounded-full bg-gradient-to-br from-indigo-300/20 to-purple-300/20 blur-2xl" }), _jsxs("div", { className: "relative z-10 text-center", children: [_jsx("div", { className: "mb-6 inline-flex items-center justify-center rounded-full bg-gradient-to-r from-blue-500 to-indigo-600 p-3 shadow-lg shadow-blue-500/30", children: _jsx("svg", { className: "h-8 w-8 text-white", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" }) }) }), _jsx("h2", { className: "mb-4 text-3xl font-bold tracking-tight text-slate-900", children: "Create your Builder Team Profile" }), _jsx("p", { className: "mb-8 text-lg leading-relaxed text-slate-600", children: "Get started by creating your builder profile to manage your team, services, and build your presence in the Achra ecosystem." }), _jsxs("form", { onSubmit: handleSubmit, className: "mx-auto max-w-md", children: [!isValid && profileName && (_jsx("div", { className: "mb-2 text-sm text-red-500", children: "Document name must be valid URL characters." })), _jsx("input", { type: "text", value: profileName, onChange: (e) => setProfileName(e.target.value), placeholder: "Builder Profile name", maxLength: 100, disabled: isCreating, className: "mb-6 w-full rounded-xl border border-slate-200 bg-white px-4 py-3 text-base text-slate-900 placeholder-slate-400 shadow-sm outline-none transition-all focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 disabled:opacity-50" }), _jsxs("button", { type: "submit", disabled: !isValid || isCreating, className: "group relative w-full overflow-hidden rounded-xl bg-gradient-to-r from-blue-600 to-indigo-600 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-blue-500/40 transition-all duration-300 hover:scale-105 hover:shadow-xl hover:shadow-blue-500/50 active:scale-100 disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:scale-100 disabled:hover:shadow-lg", children: [_jsxs("span", { className: "relative z-10 flex items-center justify-center gap-2", children: [_jsx("span", { children: isCreating ? "Creating..." : "Create Builder Profile" }), !isCreating && (_jsx("svg", { className: "h-5 w-5 transition-transform duration-300 group-hover:translate-x-1", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M13 7l5 5m0 0l-5 5m5-5H6" }) }))] }), _jsx("div", { className: "absolute inset-0 bg-gradient-to-r from-blue-700 to-indigo-700 opacity-0 transition-opacity duration-300 group-hover:opacity-100" })] })] })] })] }) }));
|
|
29
89
|
}
|
|
30
90
|
// Render the appropriate content based on state
|
|
31
91
|
const renderContent = () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardHome.d.ts","sourceRoot":"","sources":["../../../../editors/contributor-billing/components/DashboardHome.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"DashboardHome.d.ts","sourceRoot":"","sources":["../../../../editors/contributor-billing/components/DashboardHome.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAI1D,UAAU,kBAAkB;IAC1B,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,kBAAkB,GAAG,IAAI,KAAK,IAAI,CAAC;CAClE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,cAAc,EAAE,EAAE,kBAAkB,2CAoWnE"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Wallet, CheckCircle2, ArrowRight, Building2, User, } from "lucide-react";
|
|
3
|
-
import { useCallback, useMemo
|
|
3
|
+
import { useCallback, useMemo } from "react";
|
|
4
4
|
import { addDocument, useDocumentsInSelectedDrive, useSelectedDrive, setSelectedNode, isFileNodeKind, } from "@powerhousedao/reactor-browser";
|
|
5
5
|
import { useBillingFolderStructure } from "../hooks/useBillingFolderStructure.js";
|
|
6
|
-
import { CreateHubProfileModal } from "./CreateHubProfileModal.js";
|
|
7
6
|
/**
|
|
8
7
|
* Dashboard home page for the Operational Hub
|
|
9
8
|
* Shows setup status and guides users through important actions
|
|
@@ -97,8 +96,6 @@ export function DashboardHome({ onFolderSelect }) {
|
|
|
97
96
|
parts.push(statusParts.join(", "));
|
|
98
97
|
return parts.join(" · ");
|
|
99
98
|
}, [selectedDrive, documentsInDrive, monthFolders.size, paymentsFolderIds]);
|
|
100
|
-
// State for custom create hub profile modal
|
|
101
|
-
const [showCreateHubModal, setShowCreateHubModal] = useState(false);
|
|
102
99
|
const handleOpenAccounts = useCallback(async () => {
|
|
103
100
|
if (accountsDocument) {
|
|
104
101
|
setSelectedNode(accountsDocument.header.id);
|
|
@@ -124,9 +121,6 @@ export function DashboardHome({ onFolderSelect }) {
|
|
|
124
121
|
if (operationalHubProfileDocument) {
|
|
125
122
|
setSelectedNode(operationalHubProfileDocument.header.id);
|
|
126
123
|
}
|
|
127
|
-
else {
|
|
128
|
-
setShowCreateHubModal(true);
|
|
129
|
-
}
|
|
130
124
|
}, [operationalHubProfileDocument]);
|
|
131
125
|
// Calculate setup progress with clickable steps
|
|
132
126
|
const setupSteps = useMemo(() => {
|
|
@@ -165,5 +159,5 @@ export function DashboardHome({ onFolderSelect }) {
|
|
|
165
159
|
? profileStats || "View and update your hub profile"
|
|
166
160
|
: "Set up your hub profile" })] })] }), _jsx(ArrowRight, { className: "w-5 h-5 text-gray-400 group-hover:text-blue-500 transition-colors" })] }), !operationalHubProfileDocument && (_jsx("div", { className: "mt-3 pt-3 border-t border-gray-100", children: _jsx("span", { className: "text-xs font-medium text-amber-600 bg-amber-50 px-2 py-1 rounded", children: "Action Required" }) }))] }), _jsxs("button", { onClick: () => void handleOpenAccounts(), className: "bg-white rounded-xl border border-gray-200 p-5 text-left hover:shadow-md hover:border-blue-200 transition-all group", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: `p-3 rounded-lg ${accountsDocument ? "bg-green-100" : "bg-amber-100"}`, children: _jsx(Wallet, { className: `w-5 h-5 ${accountsDocument ? "text-green-600" : "text-amber-600"}` }) }), _jsxs("div", { children: [_jsx("h3", { className: "font-semibold text-gray-900", children: "Accounts" }), _jsx("p", { className: "text-sm text-gray-500", children: accountsDocument
|
|
167
161
|
? accountStats || "View and manage accounts"
|
|
168
|
-
: "Set up your accounts first" })] })] }), _jsx(ArrowRight, { className: "w-5 h-5 text-gray-400 group-hover:text-blue-500 transition-colors" })] }), !accountsDocument && (_jsx("div", { className: "mt-3 pt-3 border-t border-gray-100", children: _jsx("span", { className: "text-xs font-medium text-amber-600 bg-amber-50 px-2 py-1 rounded", children: "Action Required" }) }))] }), _jsx("button", { onClick: handleOpenBilling, className: "bg-white rounded-xl border border-gray-200 p-5 text-left hover:shadow-md hover:border-blue-200 transition-all group", children: _jsxs("div", { className: "flex items-start justify-between", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "p-3 bg-blue-100 rounded-lg", children: _jsx(Building2, { className: "w-5 h-5 text-blue-600" }) }), _jsxs("div", { children: [_jsx("h3", { className: "font-semibold text-gray-900", children: "Billing" }), _jsx("p", { className: "text-sm text-gray-500", children: billingStats || "Manage monthly billing cycles" })] })] }), _jsx(ArrowRight, { className: "w-5 h-5 text-gray-400 group-hover:text-blue-500 transition-colors" })] }) })] })
|
|
162
|
+
: "Set up your accounts first" })] })] }), _jsx(ArrowRight, { className: "w-5 h-5 text-gray-400 group-hover:text-blue-500 transition-colors" })] }), !accountsDocument && (_jsx("div", { className: "mt-3 pt-3 border-t border-gray-100", children: _jsx("span", { className: "text-xs font-medium text-amber-600 bg-amber-50 px-2 py-1 rounded", children: "Action Required" }) }))] }), _jsx("button", { onClick: handleOpenBilling, className: "bg-white rounded-xl border border-gray-200 p-5 text-left hover:shadow-md hover:border-blue-200 transition-all group", children: _jsxs("div", { className: "flex items-start justify-between", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "p-3 bg-blue-100 rounded-lg", children: _jsx(Building2, { className: "w-5 h-5 text-blue-600" }) }), _jsxs("div", { children: [_jsx("h3", { className: "font-semibold text-gray-900", children: "Billing" }), _jsx("p", { className: "text-sm text-gray-500", children: billingStats || "Manage monthly billing cycles" })] })] }), _jsx(ArrowRight, { className: "w-5 h-5 text-gray-400 group-hover:text-blue-500 transition-colors" })] }) })] })] }));
|
|
169
163
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocumentDropZone.d.ts","sourceRoot":"","sources":["../../../../editors/contributor-billing/components/DocumentDropZone.tsx"],"names":[],"mappings":"AAUA,UAAU,qBAAqB;IAC7B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,SAAc,GACf,EAAE,qBAAqB,
|
|
1
|
+
{"version":3,"file":"DocumentDropZone.d.ts","sourceRoot":"","sources":["../../../../editors/contributor-billing/components/DocumentDropZone.tsx"],"names":[],"mappings":"AAUA,UAAU,qBAAqB;IAC7B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,SAAc,GACf,EAAE,qBAAqB,2CAgLvB"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useRef, useState } from "react";
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
3
|
import { useOnDropFile, useSelectedDrive, useDocumentsInSelectedDrive, } from "@powerhousedao/reactor-browser";
|
|
4
|
-
import { toast } from "@powerhousedao/design-system/connect";
|
|
5
4
|
import { useDocumentAutoPlacement } from "../hooks/useDocumentAutoPlacement.js";
|
|
5
|
+
import { cbToast } from "./cbToast.js";
|
|
6
6
|
/**
|
|
7
7
|
* Drop zone component that handles document uploads for the Contributor Billing drive.
|
|
8
8
|
* Supports:
|
|
@@ -17,6 +17,35 @@ export function DocumentDropZone({ children, className = "", }) {
|
|
|
17
17
|
const dragCounterRef = useRef(0);
|
|
18
18
|
// Activate auto-placement hook
|
|
19
19
|
useDocumentAutoPlacement();
|
|
20
|
+
// Safety net: reset drag state when the drag operation ends globally.
|
|
21
|
+
// This catches cases the component-level handlers miss:
|
|
22
|
+
// - Drop intercepted by child elements (stopPropagation)
|
|
23
|
+
// - Drag cancelled by leaving the browser window
|
|
24
|
+
// - Counter getting out of sync from DOM changes during drag
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const resetDragState = () => {
|
|
27
|
+
setIsDragging(false);
|
|
28
|
+
dragCounterRef.current = 0;
|
|
29
|
+
};
|
|
30
|
+
const handleDocumentDrop = () => {
|
|
31
|
+
resetDragState();
|
|
32
|
+
};
|
|
33
|
+
const handleDocumentDragLeave = (e) => {
|
|
34
|
+
// relatedTarget is null when the cursor leaves the browser window
|
|
35
|
+
if (!e.relatedTarget) {
|
|
36
|
+
resetDragState();
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
// Use capture phase for drop so it fires BEFORE any React handler
|
|
40
|
+
// can call stopPropagation (e.g., InvoiceTableContainer stops the
|
|
41
|
+
// event from reaching DocumentDropZone's React handler)
|
|
42
|
+
document.addEventListener("drop", handleDocumentDrop, true);
|
|
43
|
+
document.addEventListener("dragleave", handleDocumentDragLeave);
|
|
44
|
+
return () => {
|
|
45
|
+
document.removeEventListener("drop", handleDocumentDrop, true);
|
|
46
|
+
document.removeEventListener("dragleave", handleDocumentDragLeave);
|
|
47
|
+
};
|
|
48
|
+
}, []);
|
|
20
49
|
const driveId = selectedDrive?.header.id;
|
|
21
50
|
const handleDragEnter = useCallback((e) => {
|
|
22
51
|
e.preventDefault();
|
|
@@ -53,7 +82,7 @@ export function DocumentDropZone({ children, className = "", }) {
|
|
|
53
82
|
// Show error for rejected files
|
|
54
83
|
if (rejectedFiles.length > 0) {
|
|
55
84
|
const rejectedNames = rejectedFiles.map((f) => f.name).join(", ");
|
|
56
|
-
|
|
85
|
+
cbToast(`Only .phd files (Powerhouse documents) can be dropped here. Rejected: ${rejectedNames}`, { type: "error" });
|
|
57
86
|
}
|
|
58
87
|
if (phdFiles.length === 0)
|
|
59
88
|
return;
|
|
@@ -62,12 +91,12 @@ export function DocumentDropZone({ children, className = "", }) {
|
|
|
62
91
|
try {
|
|
63
92
|
const fileNode = await onDropFile(file, (progress) => {
|
|
64
93
|
if (progress.stage === "complete") {
|
|
65
|
-
|
|
94
|
+
cbToast(`Successfully uploaded ${file.name}`, {
|
|
66
95
|
type: "success",
|
|
67
96
|
});
|
|
68
97
|
}
|
|
69
98
|
else if (progress.stage === "failed") {
|
|
70
|
-
|
|
99
|
+
cbToast(`Failed to upload ${file.name}`, {
|
|
71
100
|
type: "error",
|
|
72
101
|
});
|
|
73
102
|
}
|
|
@@ -81,10 +110,10 @@ export function DocumentDropZone({ children, className = "", }) {
|
|
|
81
110
|
if (doc) {
|
|
82
111
|
const docType = doc.header.documentType;
|
|
83
112
|
if (docType === "powerhouse/expense-report") {
|
|
84
|
-
|
|
113
|
+
cbToast(`Expense report uploaded. It will be placed in the appropriate Reporting folder based on its period.`, { type: "info" });
|
|
85
114
|
}
|
|
86
115
|
else if (docType === "powerhouse/accounts") {
|
|
87
|
-
|
|
116
|
+
cbToast(`Accounts document uploaded. It will remain at the root level.`, { type: "info" });
|
|
88
117
|
}
|
|
89
118
|
}
|
|
90
119
|
}, 1000);
|
|
@@ -92,7 +121,7 @@ export function DocumentDropZone({ children, className = "", }) {
|
|
|
92
121
|
}
|
|
93
122
|
catch (error) {
|
|
94
123
|
console.error("Error dropping file:", error);
|
|
95
|
-
|
|
124
|
+
cbToast(`Error uploading ${file.name}`, { type: "error" });
|
|
96
125
|
}
|
|
97
126
|
});
|
|
98
127
|
await Promise.allSettled(filePromises);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DriveContents.d.ts","sourceRoot":"","sources":["../../../../editors/contributor-billing/components/DriveContents.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,UAAU,kBAAkB;IAC1B,cAAc,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAC1C,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,kBAAkB,GAAG,IAAI,KAAK,IAAI,CAAC;IACjE,oBAAoB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACjD;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,EAC5B,cAAc,EACd,cAAc,EACd,oBAAoB,GACrB,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"DriveContents.d.ts","sourceRoot":"","sources":["../../../../editors/contributor-billing/components/DriveContents.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,UAAU,kBAAkB;IAC1B,cAAc,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAC1C,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,kBAAkB,GAAG,IAAI,KAAK,IAAI,CAAC;IACjE,oBAAoB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACjD;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,EAC5B,cAAc,EACd,cAAc,EACd,oBAAoB,GACrB,EAAE,kBAAkB,2CA6FpB"}
|
|
@@ -13,8 +13,11 @@ export function DriveContents({ selectedFolder, onFolderSelect, onActiveNodeIdCh
|
|
|
13
13
|
return (_jsx("div", { className: "container mx-auto flex-1 p-4", children: _jsx(Suspense, { children: _jsx(DashboardHome, { onFolderSelect: onFolderSelect }) }) }));
|
|
14
14
|
}
|
|
15
15
|
// Payments folder - show invoice table
|
|
16
|
+
// All content is inside InvoiceTableContainer so its drop zone covers the
|
|
17
|
+
// entire view — drops on the header or stats area are handled by the same
|
|
18
|
+
// folder-aware logic that moves invoices to the correct Payments folder.
|
|
16
19
|
if (selectedFolder.folderType === "payments") {
|
|
17
|
-
return (
|
|
20
|
+
return (_jsx("div", { className: "container mx-auto flex-1 p-4", children: _jsx(Suspense, { children: _jsxs(InvoiceTableContainer, { folderId: selectedFolder.folderId, monthName: selectedFolder.monthName, reportingFolderId: selectedFolder.reportingFolderId, children: [_jsxs("div", { className: "mb-4", children: [_jsxs("h1", { className: "text-2xl font-bold text-gray-900", children: ["Payments - ", selectedFolder.monthName] }), _jsxs("p", { className: "text-gray-600", children: ["Manage invoices and billing statements for", " ", selectedFolder.monthName] })] }), _jsx(Suspense, { children: _jsx(HeaderStats, { folderId: selectedFolder.folderId }) })] }) }) }, selectedFolder.folderId));
|
|
18
21
|
}
|
|
19
22
|
// Reporting folder - show expense and snapshot reports
|
|
20
23
|
if (selectedFolder.folderType === "reporting") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DriveExplorer.d.ts","sourceRoot":"","sources":["../../../../editors/contributor-billing/components/DriveExplorer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"DriveExplorer.d.ts","sourceRoot":"","sources":["../../../../editors/contributor-billing/components/DriveExplorer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAkBlD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW,2CAqOtD"}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
import { useState, useEffect, useRef } from "react";
|
|
2
|
+
import { setName } from "document-model";
|
|
3
|
+
import { useState, useEffect, useRef, useCallback, useMemo } from "react";
|
|
4
|
+
import { useDocumentsInSelectedDrive, useSelectedDrive, addDocument, dispatchActions, setSelectedNode, } from "@powerhousedao/reactor-browser";
|
|
5
|
+
import { isValidName } from "document-drive";
|
|
6
|
+
import { setOperationalHubName } from "../../../document-models/operational-hub-profile/gen/configuration/creators.js";
|
|
7
|
+
import { ToastRenderer } from "./ToastRenderer.js";
|
|
4
8
|
import { DriveContents } from "./DriveContents.js";
|
|
5
9
|
import { FolderTree } from "./FolderTree.js";
|
|
6
10
|
import { FolderTreeErrorBoundary } from "./FolderTreeErrorBoundary.js";
|
|
@@ -12,6 +16,48 @@ import { DocumentDropZone } from "./DocumentDropZone.js";
|
|
|
12
16
|
export function DriveExplorer({ children }) {
|
|
13
17
|
// if a document is selected then its editor will be passed as children
|
|
14
18
|
const showDocumentEditor = !!children;
|
|
19
|
+
const documentsInSelectedDrive = useDocumentsInSelectedDrive();
|
|
20
|
+
const [selectedDrive] = useSelectedDrive();
|
|
21
|
+
const [hubName, setHubName] = useState("");
|
|
22
|
+
const [isCreating, setIsCreating] = useState(false);
|
|
23
|
+
// Check if operational hub profile document exists
|
|
24
|
+
const hasHubProfile = useMemo(() => {
|
|
25
|
+
if (!documentsInSelectedDrive)
|
|
26
|
+
return false;
|
|
27
|
+
return documentsInSelectedDrive.some((doc) => doc.header.documentType === "powerhouse/operational-hub-profile");
|
|
28
|
+
}, [documentsInSelectedDrive]);
|
|
29
|
+
const handleCreateHubProfile = useCallback(async () => {
|
|
30
|
+
const trimmedName = hubName.trim();
|
|
31
|
+
const driveId = selectedDrive?.header.id;
|
|
32
|
+
if (!trimmedName || !driveId || isCreating)
|
|
33
|
+
return;
|
|
34
|
+
setIsCreating(true);
|
|
35
|
+
try {
|
|
36
|
+
const createdNode = await addDocument(driveId, trimmedName, "powerhouse/operational-hub-profile", undefined, undefined, undefined, "operational-hub-profile-editor");
|
|
37
|
+
if (!createdNode?.id) {
|
|
38
|
+
console.error("Failed to create operational hub profile document");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
// Set the hub name in the document state
|
|
42
|
+
await dispatchActions(setOperationalHubName({ name: trimmedName }), createdNode.id);
|
|
43
|
+
// Set the document name to match
|
|
44
|
+
await dispatchActions(setName(trimmedName), createdNode.id);
|
|
45
|
+
// Deselect so the main drive view renders instead of the document editor
|
|
46
|
+
setSelectedNode("");
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
console.error("Error creating operational hub profile:", error);
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
setIsCreating(false);
|
|
53
|
+
}
|
|
54
|
+
}, [hubName, selectedDrive?.header.id, isCreating]);
|
|
55
|
+
const handleSubmit = useCallback((e) => {
|
|
56
|
+
e.preventDefault();
|
|
57
|
+
if (isValidName(hubName) && !isCreating) {
|
|
58
|
+
void handleCreateHubProfile();
|
|
59
|
+
}
|
|
60
|
+
}, [hubName, isCreating, handleCreateHubProfile]);
|
|
15
61
|
// Track which folder is selected for content routing
|
|
16
62
|
const [selectedFolder, setSelectedFolder] = useState(null);
|
|
17
63
|
// Track active node in sidebar for visual selection sync
|
|
@@ -47,7 +93,12 @@ export function DriveExplorer({ children }) {
|
|
|
47
93
|
setActiveNodeId(folderInfo.folderId);
|
|
48
94
|
}
|
|
49
95
|
};
|
|
50
|
-
|
|
96
|
+
// If no hub profile exists, show the creation form
|
|
97
|
+
if (!hasHubProfile) {
|
|
98
|
+
const isValid = isValidName(hubName);
|
|
99
|
+
return (_jsx("div", { className: "flex h-full items-center justify-center px-4 py-12", children: _jsxs("div", { className: "relative w-full max-w-2xl overflow-hidden rounded-2xl border border-slate-200/50 bg-gradient-to-br from-slate-50 via-purple-50/30 to-indigo-50/40 p-12 shadow-xl shadow-slate-200/50 backdrop-blur-sm", children: [_jsx("div", { className: "absolute -right-20 -top-20 h-64 w-64 rounded-full bg-gradient-to-br from-purple-400/20 to-indigo-400/20 blur-3xl" }), _jsx("div", { className: "absolute -bottom-16 -left-16 h-48 w-48 rounded-full bg-gradient-to-br from-indigo-300/20 to-purple-300/20 blur-2xl" }), _jsxs("div", { className: "relative z-10 text-center", children: [_jsx("div", { className: "mb-6 inline-flex items-center justify-center rounded-full bg-gradient-to-r from-purple-600 to-indigo-600 p-3 shadow-lg shadow-purple-500/30", children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", className: "text-white", children: _jsx("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }) }) }), _jsx("h2", { className: "mb-4 text-3xl font-bold tracking-tight text-slate-900", children: "Create your Operational Hub" }), _jsx("p", { className: "mb-8 text-lg leading-relaxed text-slate-600", children: "Get started by creating your operational hub to manage accounts, billing, and financial reporting." }), _jsxs("form", { onSubmit: handleSubmit, className: "mx-auto max-w-md", children: [!isValid && hubName && (_jsx("div", { className: "mb-2 text-sm text-red-500", children: "Document name must be valid URL characters." })), _jsx("input", { type: "text", value: hubName, onChange: (e) => setHubName(e.target.value), placeholder: "Operational Hub name", maxLength: 100, disabled: isCreating, className: "mb-6 w-full rounded-xl border border-slate-200 bg-white px-4 py-3 text-base text-slate-900 placeholder-slate-400 shadow-sm outline-none transition-all focus:border-purple-500 focus:ring-2 focus:ring-purple-500/20 disabled:opacity-50" }), _jsxs("button", { type: "submit", disabled: !isValid || isCreating, className: "group relative w-full overflow-hidden rounded-xl bg-gradient-to-r from-purple-600 to-indigo-600 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-purple-500/40 transition-all duration-300 hover:scale-105 hover:shadow-xl hover:shadow-purple-500/50 active:scale-100 disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:scale-100 disabled:hover:shadow-lg", children: [_jsxs("span", { className: "relative z-10 flex items-center justify-center gap-2", children: [_jsx("span", { children: isCreating ? "Creating..." : "Create Operational Hub" }), !isCreating && (_jsx("svg", { className: "h-5 w-5 transition-transform duration-300 group-hover:translate-x-1", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M13 7l5 5m0 0l-5 5m5-5H6" }) }))] }), _jsx("div", { className: "absolute inset-0 bg-gradient-to-r from-purple-700 to-indigo-700 opacity-0 transition-opacity duration-300 group-hover:opacity-100" })] })] })] })] }) }));
|
|
100
|
+
}
|
|
101
|
+
return (_jsxs("div", { className: "flex h-full w-full overflow-hidden", children: [_jsx(FolderTreeErrorBoundary, { children: _jsx(FolderTree, { onFolderSelect: handleFolderSelect, activeNodeId: activeNodeId, onActiveNodeIdChange: setActiveNodeId }) }), _jsx(ToastRenderer, {}), _jsx(DocumentDropZone, { className: "flex-1 min-w-0 h-full overflow-x-hidden overflow-y-auto", children: showDocumentEditor ? (
|
|
51
102
|
/* Document editor view */
|
|
52
103
|
_jsx("div", { className: "min-h-full", children: children })) : (
|
|
53
104
|
/* Folder content view */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FolderTree.d.ts","sourceRoot":"","sources":["../../../../editors/contributor-billing/components/FolderTree.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FolderTree.d.ts","sourceRoot":"","sources":["../../../../editors/contributor-billing/components/FolderTree.tsx"],"names":[],"mappings":"AA0CA,uCAAuC;AACvC,MAAM,MAAM,UAAU,GAClB,UAAU,GACV,WAAW,GACX,SAAS,GACT,eAAe,GACf,IAAI,CAAC;AAET,+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,2CA8bjB"}
|
|
@@ -4,7 +4,6 @@ import { addDocument, setSelectedNode, useDocumentsInSelectedDrive, useSelectedD
|
|
|
4
4
|
import { Wallet, FileText, Building2, Calendar, CreditCard, BarChart3, Camera, User, } from "lucide-react";
|
|
5
5
|
import { useCallback, useMemo, useState } from "react";
|
|
6
6
|
import { useBillingFolderStructure } from "../hooks/useBillingFolderStructure.js";
|
|
7
|
-
import { CreateHubProfileModal } from "./CreateHubProfileModal.js";
|
|
8
7
|
const ICON_SIZE = 16;
|
|
9
8
|
const SUBSCRIPTIONS_FOLDER_NAME = "Subscriptions";
|
|
10
9
|
/**
|
|
@@ -29,8 +28,6 @@ export function FolderTree({ onFolderSelect, activeNodeId: controlledActiveNodeI
|
|
|
29
28
|
const [localActiveNodeId, setLocalActiveNodeId] = useState("");
|
|
30
29
|
const activeNodeId = controlledActiveNodeId ?? localActiveNodeId;
|
|
31
30
|
const setActiveNodeId = onActiveNodeIdChange ?? setLocalActiveNodeId;
|
|
32
|
-
// State for custom create hub profile modal
|
|
33
|
-
const [showCreateHubModal, setShowCreateHubModal] = useState(false);
|
|
34
31
|
const documentsInDrive = useDocumentsInSelectedDrive();
|
|
35
32
|
const [driveDocument] = useSelectedDrive();
|
|
36
33
|
const { billingFolder, monthFolders, paymentsFolderIds, reportingFolderIds } = useBillingFolderStructure();
|
|
@@ -275,10 +272,6 @@ export function FolderTree({ onFolderSelect, activeNodeId: controlledActiveNodeI
|
|
|
275
272
|
onFolderSelect?.(null);
|
|
276
273
|
safeSetSelectedNode(operationalHubProfileDocument.header.id);
|
|
277
274
|
}
|
|
278
|
-
else {
|
|
279
|
-
safeSetSelectedNode("");
|
|
280
|
-
setShowCreateHubModal(true);
|
|
281
|
-
}
|
|
282
275
|
return;
|
|
283
276
|
}
|
|
284
277
|
// Check if this is an account-transactions child node
|
|
@@ -369,7 +362,7 @@ export function FolderTree({ onFolderSelect, activeNodeId: controlledActiveNodeI
|
|
|
369
362
|
// Use a stable key based on the drive ID only
|
|
370
363
|
// Previously this changed on every folder/document add, causing sidebar to remount and lose collapsed state
|
|
371
364
|
const sidebarKey = driveDocument?.header.id || "empty";
|
|
372
|
-
return (
|
|
365
|
+
return (_jsx(_Fragment, { children: _jsxs(SidebarProvider, { nodes: navigationSections, children: [_jsx("style", { children: `
|
|
373
366
|
.folder-tree-sidebar .sidebar__item-caret--no-children {
|
|
374
367
|
visibility: hidden;
|
|
375
368
|
}
|
|
@@ -377,11 +370,9 @@ export function FolderTree({ onFolderSelect, activeNodeId: controlledActiveNodeI
|
|
|
377
370
|
display: none;
|
|
378
371
|
}
|
|
379
372
|
` }), _jsx(Sidebar, { className: "pt-1 folder-tree-sidebar", nodes: navigationSections, activeNodeId: sanitizedActiveNodeId, onActiveNodeChange: handleActiveNodeChange, sidebarTitle: operationalHubProfileDocument?.state?.global?.name ||
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
onFolderSelect?.(null);
|
|
386
|
-
} })] }));
|
|
373
|
+
"Operational Hub", showSearchBar: false, resizable: true, allowPinning: false, showStatusFilter: false, initialWidth: 256, defaultLevel: 2, handleOnTitleClick: () => {
|
|
374
|
+
onFolderSelect?.(null);
|
|
375
|
+
safeSetSelectedNode("");
|
|
376
|
+
setActiveNodeId("");
|
|
377
|
+
} }, sidebarKey)] }) }));
|
|
387
378
|
}
|
|
@@ -33,6 +33,7 @@ interface HeaderControlsProps {
|
|
|
33
33
|
};
|
|
34
34
|
}>;
|
|
35
35
|
canExportSelectedRows: () => boolean;
|
|
36
|
+
onDeleteSelected?: (ids: string[]) => Promise<void>;
|
|
36
37
|
}
|
|
37
|
-
export declare const HeaderControls: ({ statusOptions, selectedStatuses, onStatusChange, onSearchChange, onExport, onExpenseReportExport, hasBillingStatements, onCreateOrOpenExpenseReport, selected, handleCreateBillingStatement, setSelected, invoices, billingStatements, canExportSelectedRows, }: HeaderControlsProps) => import("react/jsx-runtime").JSX.Element;
|
|
38
|
+
export declare const HeaderControls: ({ statusOptions, selectedStatuses, onStatusChange, onSearchChange, onExport, onExpenseReportExport, hasBillingStatements, onCreateOrOpenExpenseReport, selected, handleCreateBillingStatement, setSelected, invoices, billingStatements, canExportSelectedRows, onDeleteSelected, }: HeaderControlsProps) => import("react/jsx-runtime").JSX.Element;
|
|
38
39
|
//# 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":"
|
|
1
|
+
{"version":3,"file":"HeaderControls.d.ts","sourceRoot":"","sources":["../../../../../editors/contributor-billing/components/InvoiceTable/HeaderControls.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAY/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;IACrC,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrD;AAED,eAAO,MAAM,cAAc,GAAI,qRAgB5B,mBAAmB,4CA4SrB,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from "react";
|
|
3
3
|
import { Select } from "@powerhousedao/document-engineering/ui";
|
|
4
|
-
import {
|
|
4
|
+
import { cbToast } from "../cbToast.js";
|
|
5
5
|
import { ConfirmationModal } from "./ConfirmationModal.js";
|
|
6
6
|
const currencyOptions = [
|
|
7
7
|
{ label: "CHF", value: "CHF" },
|
|
@@ -10,19 +10,22 @@ 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, hasBillingStatements = false, onCreateOrOpenExpenseReport, selected = {}, handleCreateBillingStatement, setSelected, invoices = [], billingStatements = [], canExportSelectedRows, }) => {
|
|
13
|
+
export const HeaderControls = ({ statusOptions = [], selectedStatuses = [], onStatusChange, onSearchChange, onExport, onExpenseReportExport, hasBillingStatements = false, onCreateOrOpenExpenseReport, selected = {}, handleCreateBillingStatement, setSelected, invoices = [], billingStatements = [], canExportSelectedRows, onDeleteSelected, }) => {
|
|
14
14
|
const batchOptions = [
|
|
15
15
|
{ label: "Generate Bill Statements", value: "generate-bills" },
|
|
16
16
|
{
|
|
17
17
|
label: "Export CSV Expense Report",
|
|
18
18
|
value: "export-csv-expense-report",
|
|
19
19
|
},
|
|
20
|
+
{ label: "Delete Selected", value: "delete-selected" },
|
|
20
21
|
];
|
|
21
22
|
const [showCurrencyModal, setShowCurrencyModal] = useState(false);
|
|
22
23
|
const [selectedCurrency, setSelectedCurrency] = useState("CHF");
|
|
23
24
|
const [showExpenseReportCurrencyModal, setShowExpenseReportCurrencyModal] = useState(false);
|
|
24
25
|
const [selectedExpenseReportCurrency, setSelectedExpenseReportCurrency] = useState("CHF");
|
|
25
26
|
const [selectedBatchAction, setSelectedBatchAction] = useState(undefined);
|
|
27
|
+
const [showDeleteConfirmModal, setShowDeleteConfirmModal] = useState(false);
|
|
28
|
+
const [deleteIds, setDeleteIds] = useState([]);
|
|
26
29
|
const [isProcessing, setIsProcessing] = useState(false);
|
|
27
30
|
// Simple batch action handler - matches working old code pattern
|
|
28
31
|
const handleBatchAction = async (action) => {
|
|
@@ -30,10 +33,21 @@ export const HeaderControls = ({ statusOptions = [], selectedStatuses = [], onSt
|
|
|
30
33
|
setShowExpenseReportCurrencyModal(true);
|
|
31
34
|
return;
|
|
32
35
|
}
|
|
36
|
+
if (action === "delete-selected") {
|
|
37
|
+
const selectedIds = Object.keys(selected).filter((id) => selected[id]);
|
|
38
|
+
if (selectedIds.length === 0) {
|
|
39
|
+
cbToast("No documents selected", { type: "warning" });
|
|
40
|
+
setTimeout(() => setSelectedBatchAction(undefined), 0);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
setDeleteIds(selectedIds);
|
|
44
|
+
setShowDeleteConfirmModal(true);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
33
47
|
if (action === "generate-bills") {
|
|
34
48
|
const selectedIds = Object.keys(selected).filter((id) => selected[id]);
|
|
35
49
|
if (selectedIds.length === 0) {
|
|
36
|
-
|
|
50
|
+
cbToast("No invoices selected", { type: "warning" });
|
|
37
51
|
setTimeout(() => setSelectedBatchAction(undefined), 0);
|
|
38
52
|
return;
|
|
39
53
|
}
|
|
@@ -62,7 +76,7 @@ export const HeaderControls = ({ statusOptions = [], selectedStatuses = [], onSt
|
|
|
62
76
|
});
|
|
63
77
|
setSelected(updatedSelected);
|
|
64
78
|
const billNames = existingBills.join(", ");
|
|
65
|
-
|
|
79
|
+
cbToast(`Billing statements already exist for: ${billNames}`, {
|
|
66
80
|
type: "warning",
|
|
67
81
|
});
|
|
68
82
|
setTimeout(() => setSelectedBatchAction(undefined), 0);
|
|
@@ -75,7 +89,7 @@ export const HeaderControls = ({ statusOptions = [], selectedStatuses = [], onSt
|
|
|
75
89
|
updatedSelected[id] = false;
|
|
76
90
|
});
|
|
77
91
|
setSelected(updatedSelected);
|
|
78
|
-
|
|
92
|
+
cbToast("Invoice not ready, change status to ISSUED", {
|
|
79
93
|
type: "warning",
|
|
80
94
|
});
|
|
81
95
|
setTimeout(() => setSelectedBatchAction(undefined), 0);
|
|
@@ -120,5 +134,26 @@ export const HeaderControls = ({ statusOptions = [], selectedStatuses = [], onSt
|
|
|
120
134
|
}, header: "Select Base Currency", continueLabel: "Export", cancelLabel: "Cancel", children: [_jsx("p", { className: "text-red-600 text-sm mb-3 font-medium", children: "Warning: the chosen currency should match the base currency of the accounting system." }), _jsx("div", { className: "w-[200px]", children: _jsx(Select, { options: currencyOptions, onChange: (value) => setSelectedCurrency(value), placeholder: "Select Base Currency", value: selectedCurrency }) })] }), _jsxs(ConfirmationModal, { open: showExpenseReportCurrencyModal, onCancel: () => setShowExpenseReportCurrencyModal(false), onContinue: () => {
|
|
121
135
|
setShowExpenseReportCurrencyModal(false);
|
|
122
136
|
onExpenseReportExport?.(selectedExpenseReportCurrency);
|
|
123
|
-
}, header: "Select Base Currency", continueLabel: "Export", cancelLabel: "Cancel", children: [_jsx("p", { className: "text-red-600 text-sm mb-3 font-medium", children: "Warning: the chosen currency should match the base currency of the accounting system." }), _jsx("div", { className: "w-[200px]", children: _jsx(Select, { options: currencyOptions, onChange: (value) => setSelectedExpenseReportCurrency(value), placeholder: "Select Base Currency", value: selectedExpenseReportCurrency }) })] })
|
|
137
|
+
}, header: "Select Base Currency", continueLabel: "Export", cancelLabel: "Cancel", children: [_jsx("p", { className: "text-red-600 text-sm mb-3 font-medium", children: "Warning: the chosen currency should match the base currency of the accounting system." }), _jsx("div", { className: "w-[200px]", children: _jsx(Select, { options: currencyOptions, onChange: (value) => setSelectedExpenseReportCurrency(value), placeholder: "Select Base Currency", value: selectedExpenseReportCurrency }) })] }), _jsx(ConfirmationModal, { open: showDeleteConfirmModal, onCancel: () => {
|
|
138
|
+
setShowDeleteConfirmModal(false);
|
|
139
|
+
setDeleteIds([]);
|
|
140
|
+
setTimeout(() => setSelectedBatchAction(undefined), 0);
|
|
141
|
+
}, onContinue: async () => {
|
|
142
|
+
setShowDeleteConfirmModal(false);
|
|
143
|
+
setIsProcessing(true);
|
|
144
|
+
try {
|
|
145
|
+
await onDeleteSelected?.(deleteIds);
|
|
146
|
+
// Clear selection for deleted docs
|
|
147
|
+
const updatedSelected = { ...selected };
|
|
148
|
+
deleteIds.forEach((id) => {
|
|
149
|
+
delete updatedSelected[id];
|
|
150
|
+
});
|
|
151
|
+
setSelected(updatedSelected);
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
setDeleteIds([]);
|
|
155
|
+
setIsProcessing(false);
|
|
156
|
+
setTimeout(() => setSelectedBatchAction(undefined), 100);
|
|
157
|
+
}
|
|
158
|
+
}, header: "Delete Selected Documents", continueLabel: "Delete", cancelLabel: "Cancel", children: _jsxs("p", { className: "text-red-600 text-sm mb-3 font-medium", children: ["This will permanently delete ", deleteIds.length, " selected document", deleteIds.length !== 1 ? "s" : "", " from the drive. This action cannot be undone."] }) })] }));
|
|
124
159
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type VetraDocumentModelModule } from "@powerhousedao/reactor-browser";
|
|
2
2
|
import type { PHDocument } from "document-model";
|
|
3
|
-
import type
|
|
3
|
+
import { type FileNode } from "document-drive";
|
|
4
4
|
export declare const statusOptions: {
|
|
5
5
|
label: string;
|
|
6
6
|
value: string;
|
|
@@ -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;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,
|
|
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;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AA6E3D,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,yLAY1B,iBAAiB,4CAkvBnB,CAAC"}
|