@powerhousedao/contributor-billing 0.1.5 → 0.1.7

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.
@@ -24,7 +24,7 @@ export function LineItemTagsTable({ lineItems, onClose, dispatch, }) {
24
24
  id: item.id,
25
25
  description: e.target.value,
26
26
  }));
27
- }, className: "w-full text-xs" }) }), _jsx("td", { className: "border-b border-gray-200 p-2 w-50", children: _jsx(DatePicker, { name: "period", dateFormat: "YYYY-MM", autoClose: true, placeholder: "Select Period", value: item.lineItemTag.find((tag) => tag.dimension === "accounting-period")?.label || "", onChange: (e) => dispatch(actions.editLineItemTag({
27
+ }, className: "w-full text-xs" }) }), _jsx("td", { className: "border-b border-gray-200 p-2 w-50", children: _jsx(DatePicker, { name: "period", dateFormat: "YYYY-MM-DD", autoClose: true, placeholder: "Select Period", value: item.lineItemTag.find((tag) => tag.dimension === "accounting-period")?.label || "", onChange: (e) => dispatch(actions.editLineItemTag({
28
28
  lineItemId: item.id,
29
29
  dimension: "accounting-period",
30
30
  value: new Date(e.target.value)
@@ -1 +1 @@
1
- {"version":3,"file":"InvoiceTable.d.ts","sourceRoot":"","sources":["../../../../../editors/contributor-billing/components/InvoiceTable/InvoiceTable.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AA6B1D,KAAK,YAAY,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAExE,UAAU,iBAAiB;IACzB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,KAAK,EAAE,GAAG,EAAE,CAAC;IACb,QAAQ,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACpC,WAAW,EAAE,CACX,QAAQ,EACJ;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,GACzB,CAAC,CAAC,IAAI,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,KAAK;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,KACjE,IAAI,CAAC;IACV,sBAAsB,EAAE,mBAAmB,EAAE,CAAC;IAC9C,qBAAqB,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC5D,gBAAgB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,GAAG,CAAC;IACtC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;IACnD,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7E,qBAAqB,EAAE,MAAM,OAAO,CAAC;CACtC;AAED,eAAO,MAAM,YAAY,GAAI,uKAW1B,iBAAiB,4CAoqBnB,CAAC"}
1
+ {"version":3,"file":"InvoiceTable.d.ts","sourceRoot":"","sources":["../../../../../editors/contributor-billing/components/InvoiceTable/InvoiceTable.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AA6B1D,KAAK,YAAY,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAExE,UAAU,iBAAiB;IACzB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,KAAK,EAAE,GAAG,EAAE,CAAC;IACb,QAAQ,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACpC,WAAW,EAAE,CACX,QAAQ,EACJ;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,GACzB,CAAC,CAAC,IAAI,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,KAAK;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,KACjE,IAAI,CAAC;IACV,sBAAsB,EAAE,mBAAmB,EAAE,CAAC;IAC9C,qBAAqB,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC5D,gBAAgB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,GAAG,CAAC;IACtC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;IACnD,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7E,qBAAqB,EAAE,MAAM,OAAO,CAAC;CACtC;AAED,eAAO,MAAM,YAAY,GAAI,uKAW1B,iBAAiB,4CA8pBnB,CAAC"}
@@ -110,9 +110,6 @@ export const InvoiceTable = ({ files, state, selected, filteredDocumentModels, o
110
110
  notes: invoiceState.state.global.notes || "",
111
111
  };
112
112
  await dispatchActions(billingStatementActions.editBillingStatement(billingStatementData), createdNode.id);
113
- await dispatchActions(billingStatementActions.editStatus({
114
- status: invoiceState.state.global.status,
115
- }), createdNode.id);
116
113
  // add line items from invoiceState to billing statement
117
114
  invoiceState.state.global.lineItems.forEach(async (lineItem) => {
118
115
  await dispatchActions(billingStatementActions.addLineItem({
@@ -191,5 +191,5 @@ export function AddBillingStatementModal({ isOpen, onClose, walletAddress, dispa
191
191
  : "border-gray-300 dark:border-gray-600"}`, children: (isSelected || isAlreadyAdded) && (_jsx(Check, { className: "text-white", size: 14 })) }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-medium text-gray-900 dark:text-white truncate", children: statement.name }), _jsxs("span", { className: "text-xs text-gray-500 dark:text-gray-400 px-2 py-1 bg-gray-100 dark:bg-gray-700 rounded", children: [lineItemCount, " items"] }), isAlreadyAdded && (_jsx("span", { className: "text-xs text-amber-600 dark:text-amber-400 px-2 py-1 bg-amber-50 dark:bg-amber-900/20 rounded font-medium", children: "Already included" }))] }), _jsxs("div", { className: "flex items-center gap-4 mt-1 text-sm text-gray-600 dark:text-gray-400", children: [_jsxs("span", { children: ["Total: ", formatCurrency(totalCash)] }), _jsxs("span", { className: "text-xs font-mono", children: [statement.id.substring(0, 8), "..."] })] })] })] }, statement.id));
192
192
  }) })) : (_jsxs("div", { className: "flex flex-col items-center justify-center py-12 text-gray-500 dark:text-gray-400", children: [_jsx(FileText, { size: 48, className: "mb-4 opacity-50" }), _jsx("p", { className: "text-sm", children: searchTerm
193
193
  ? "No billing statements found matching your search"
194
- : "No billing statements available in this drive" })] })) }), _jsxs("div", { className: "flex items-center justify-between px-6 py-4 border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/50", children: [_jsxs("span", { className: "text-sm text-gray-600 dark:text-gray-400", children: [selectedStatements.size, " statement", selectedStatements.size !== 1 ? "s" : "", " selected"] }), _jsxs("div", { className: "flex gap-3", children: [_jsx(Button, { onClick: onClose, className: "px-4 py-2 text-red-600 dark:text-red-400 bg-red-50 dark:bg-red-900/20 hover:bg-red-100 dark:hover:bg-red-900/30", children: "Cancel" }), _jsxs(Button, { onClick: handleAddStatements, disabled: selectedStatements.size === 0, className: "px-4 py-2", children: ["Add", " ", selectedStatements.size > 0 && `(${selectedStatements.size})`] })] })] })] })] }));
194
+ : "No billing statements available in this drive" })] })) }), _jsxs("div", { className: "flex items-center justify-between px-6 py-4 border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/50", children: [_jsxs("span", { className: "text-sm text-gray-600 dark:text-gray-400", children: [selectedStatements.size, " statement", selectedStatements.size !== 1 ? "s" : "", " selected"] }), _jsxs("div", { className: "flex gap-3", children: [_jsx(Button, { onClick: onClose, variant: "secondary", children: "CANCEL" }), _jsxs(Button, { onClick: handleAddStatements, disabled: selectedStatements.size === 0, className: "bg-green-600 hover:bg-green-700 text-white", children: ["ADD", " ", selectedStatements.size > 0 && `(${selectedStatements.size})`] })] })] })] })] }));
195
195
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AggregatedExpensesTable.d.ts","sourceRoot":"","sources":["../../../../editors/expense-report/components/AggregatedExpensesTable.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAY,MAAM,sDAAsD,CAAC;AAI5G,UAAU,4BAA4B;IACpC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CACjC;AAQD,wBAAgB,uBAAuB,CAAC,EACtC,OAAO,EACP,MAAM,EACN,WAAW,EACX,SAAS,EACT,QAAQ,GACT,EAAE,4BAA4B,kDAmjB9B"}
1
+ {"version":3,"file":"AggregatedExpensesTable.d.ts","sourceRoot":"","sources":["../../../../editors/expense-report/components/AggregatedExpensesTable.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAY,MAAM,sDAAsD,CAAC;AAM5G,UAAU,4BAA4B;IACpC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CACjC;AAQD,wBAAgB,uBAAuB,CAAC,EACtC,OAAO,EACP,MAAM,EACN,WAAW,EACX,SAAS,EACT,QAAQ,GACT,EAAE,4BAA4B,kDAmzB9B"}
@@ -1,8 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useMemo, useState } from "react";
2
+ import { useMemo, useState, useRef, useEffect } from "react";
3
3
  import React from "react";
4
4
  import { actions } from "../../../document-models/expense-report/index.js";
5
- import { Textarea } from "@powerhousedao/document-engineering";
5
+ import { Textarea, Select, Button } from "@powerhousedao/document-engineering";
6
+ import { Plus, Trash2 } from "lucide-react";
7
+ import { generateId } from "document-model";
6
8
  export function AggregatedExpensesTable({ wallets, groups, periodStart, periodEnd, dispatch, }) {
7
9
  // State for active tab (selected wallet)
8
10
  const [activeWalletIndex, setActiveWalletIndex] = useState(0);
@@ -13,6 +15,122 @@ export function AggregatedExpensesTable({ wallets, groups, periodStart, periodEn
13
15
  // State for editing numeric fields
14
16
  const [editingField, setEditingField] = useState(null);
15
17
  const [editingValue, setEditingValue] = useState("");
18
+ // State for adding new line item
19
+ const [isAddingLineItem, setIsAddingLineItem] = useState(false);
20
+ const [selectedGroupId, setSelectedGroupId] = useState("");
21
+ const [duplicateCategoryError, setDuplicateCategoryError] = useState("");
22
+ // State for delete confirmation modal
23
+ const [deleteModalOpen, setDeleteModalOpen] = useState(false);
24
+ const [lineItemToDelete, setLineItemToDelete] = useState(null);
25
+ // Ref for line item editor to scroll into view
26
+ const lineItemEditorRef = useRef(null);
27
+ // Scroll to bottom of page when editor opens
28
+ useEffect(() => {
29
+ if (isAddingLineItem && lineItemEditorRef.current) {
30
+ // Use a slight delay to ensure the editor is rendered
31
+ setTimeout(() => {
32
+ // Find the scrollable container by traversing up from the ref
33
+ let element = lineItemEditorRef.current?.parentElement;
34
+ while (element) {
35
+ const style = window.getComputedStyle(element);
36
+ const isScrollable = style.overflow === 'auto' || style.overflow === 'scroll' ||
37
+ style.overflowY === 'auto' || style.overflowY === 'scroll';
38
+ if (isScrollable && element.scrollHeight > element.clientHeight) {
39
+ // Found the scrollable container, scroll to bottom
40
+ element.scrollTo({ top: element.scrollHeight, behavior: "smooth" });
41
+ break;
42
+ }
43
+ element = element.parentElement;
44
+ }
45
+ }, 150);
46
+ }
47
+ }, [isAddingLineItem]);
48
+ // Get existing category IDs for the active wallet
49
+ const existingCategoryIds = useMemo(() => {
50
+ const wallet = wallets[activeWalletIndex];
51
+ if (!wallet || !wallet.lineItems)
52
+ return new Set();
53
+ return new Set(wallet.lineItems
54
+ .filter((item) => item !== null && item !== undefined)
55
+ .map(item => item.group)
56
+ .filter((group) => !!group));
57
+ }, [wallets, activeWalletIndex]);
58
+ // Create group options for Select component
59
+ const groupOptions = useMemo(() => {
60
+ return groups.map((group) => ({
61
+ value: group.id,
62
+ label: group.label || group.id,
63
+ }));
64
+ }, [groups]);
65
+ // Handle category selection with duplicate check
66
+ const handleCategoryChange = (value) => {
67
+ setSelectedGroupId(value);
68
+ // Check if category already exists
69
+ if (existingCategoryIds.has(value)) {
70
+ const categoryLabel = groups.find(g => g.id === value)?.label || value;
71
+ setDuplicateCategoryError(`"${categoryLabel}" already exists in this wallet. Please select a different category.`);
72
+ }
73
+ else {
74
+ setDuplicateCategoryError("");
75
+ }
76
+ };
77
+ // Handle saving new line item
78
+ const handleSaveLineItem = () => {
79
+ const wallet = wallets[activeWalletIndex];
80
+ if (!wallet || !wallet.wallet || !selectedGroupId)
81
+ return;
82
+ // Prevent saving if duplicate
83
+ if (existingCategoryIds.has(selectedGroupId)) {
84
+ return;
85
+ }
86
+ const newLineItem = {
87
+ id: generateId(),
88
+ label: groups.find(g => g.id === selectedGroupId)?.label || "",
89
+ group: selectedGroupId,
90
+ budget: 0,
91
+ actuals: 0,
92
+ forecast: 0,
93
+ payments: 0,
94
+ comments: "",
95
+ };
96
+ dispatch(actions.addLineItem({
97
+ wallet: wallet.wallet,
98
+ lineItem: newLineItem,
99
+ }));
100
+ // Reset state
101
+ setIsAddingLineItem(false);
102
+ setSelectedGroupId("");
103
+ setDuplicateCategoryError("");
104
+ };
105
+ // Handle canceling new line item
106
+ const handleCancelLineItem = () => {
107
+ setIsAddingLineItem(false);
108
+ setSelectedGroupId("");
109
+ setDuplicateCategoryError("");
110
+ };
111
+ // Handle opening delete confirmation modal
112
+ const handleDeleteLineItem = (lineItemId, lineItemLabel) => {
113
+ setLineItemToDelete({ id: lineItemId, label: lineItemLabel });
114
+ setDeleteModalOpen(true);
115
+ };
116
+ // Handle confirming deletion
117
+ const handleConfirmDelete = () => {
118
+ const wallet = wallets[activeWalletIndex];
119
+ if (!wallet || !wallet.wallet || !lineItemToDelete)
120
+ return;
121
+ dispatch(actions.removeLineItem({
122
+ wallet: wallet.wallet,
123
+ lineItemId: lineItemToDelete.id,
124
+ }));
125
+ // Close modal and reset state
126
+ setDeleteModalOpen(false);
127
+ setLineItemToDelete(null);
128
+ };
129
+ // Handle canceling deletion
130
+ const handleCancelDelete = () => {
131
+ setDeleteModalOpen(false);
132
+ setLineItemToDelete(null);
133
+ };
16
134
  // Format period for title
17
135
  const periodTitle = useMemo(() => {
18
136
  if (!periodStart)
@@ -215,7 +333,7 @@ export function AggregatedExpensesTable({ wallets, groups, periodStart, periodEn
215
333
  ? "border-green-500 text-green-600 dark:text-green-400"
216
334
  : "border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-600"}
217
335
  `, children: wallet.name || formatWalletAddress(wallet.wallet || "") }, wallet.wallet || index));
218
- }) }) }), _jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "min-w-full divide-y divide-gray-200 dark:divide-gray-700", children: [_jsx("thead", { className: "bg-gray-50 dark:bg-gray-800", children: _jsxs("tr", { children: [_jsx("th", { className: "px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Expense Category" }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Mthly Budget" }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Forecast" }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Actuals" }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Difference" }), _jsx("th", { className: "px-3 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider w-96", children: "Comments" }), _jsx("th", { className: "px-3 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider w-32", children: "Payments" })] }) }), _jsxs("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-700", children: [sortedParentKeys.map((parentKey) => {
336
+ }) }) }), _jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "min-w-full divide-y divide-gray-200 dark:divide-gray-700", children: [_jsx("thead", { className: "bg-gray-50 dark:bg-gray-800", children: _jsxs("tr", { children: [_jsx("th", { className: "pl-6 pr-3 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { onClick: () => setIsAddingLineItem(true), className: "inline-flex items-center justify-center w-6 h-6 text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 bg-blue-50 dark:bg-blue-900/20 hover:bg-blue-100 dark:hover:bg-blue-900/30 rounded-md transition-colors", children: _jsx(Plus, { size: 14 }) }), _jsx("span", { children: "Expense Category" })] }) }), _jsx("th", { className: "px-3 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Mthly Budget" }), _jsx("th", { className: "px-3 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Forecast" }), _jsx("th", { className: "px-3 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Actuals" }), _jsx("th", { className: "px-3 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Difference" }), _jsx("th", { className: "px-3 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider w-96", children: "Comments" }), _jsx("th", { className: "px-3 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider w-32", children: "Payments" }), _jsx("th", { className: "px-2 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider w-16", children: "Actions" })] }) }), _jsxs("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-700", children: [sortedParentKeys.map((parentKey) => {
219
337
  const items = groupedAndAggregatedItems.get(parentKey) || [];
220
338
  if (items.length === 0)
221
339
  return null;
@@ -223,7 +341,7 @@ export function AggregatedExpensesTable({ wallets, groups, periodStart, periodEn
223
341
  const parentLabel = parentKey === "uncategorized"
224
342
  ? "Uncategorised"
225
343
  : items[0]?.parentGroupLabel || "Other";
226
- return (_jsxs(React.Fragment, { children: [_jsx("tr", { className: "bg-gray-100 dark:bg-gray-800", children: _jsx("td", { colSpan: 7, className: "px-6 py-3 text-sm font-bold text-gray-900 dark:text-white", children: parentLabel }) }), items.map((item) => {
344
+ 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) => {
227
345
  if (!item)
228
346
  return null;
229
347
  const difference = item.forecast - item.actuals;
@@ -244,7 +362,7 @@ export function AggregatedExpensesTable({ wallets, groups, periodStart, periodEn
244
362
  }
245
363
  return (_jsx("div", { className: "group cursor-pointer text-right", onClick: () => handleStartFieldEdit(item.lineItemId, field, value), children: _jsx("span", { className: "group-hover:bg-blue-50 dark:group-hover:bg-blue-900/20 inline-block px-1 py-0.5 rounded transition-colors min-w-[4rem]", children: formatNumber(value) }) }));
246
364
  };
247
- return (_jsxs("tr", { className: "bg-white dark:bg-gray-900 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors align-top", children: [_jsx("td", { className: "px-6 py-3 whitespace-nowrap text-sm text-gray-900 dark:text-white", children: item.groupLabel }), _jsx("td", { className: "px-6 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: renderEditableCell("budget", item.budget) }), _jsx("td", { className: "px-6 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: renderEditableCell("forecast", item.forecast) }), _jsx("td", { className: "px-6 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: renderEditableCell("actuals", item.actuals) }), _jsx("td", { className: `px-6 py-3 whitespace-nowrap text-right text-sm font-medium ${difference < 0
365
+ return (_jsxs("tr", { className: "bg-white dark:bg-gray-900 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors align-top", children: [_jsx("td", { className: "pl-6 pr-3 py-3 whitespace-nowrap text-sm text-gray-900 dark:text-white", children: item.groupLabel }), _jsx("td", { className: "px-3 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: renderEditableCell("budget", item.budget) }), _jsx("td", { className: "px-3 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: renderEditableCell("forecast", item.forecast) }), _jsx("td", { className: "px-3 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: renderEditableCell("actuals", item.actuals) }), _jsx("td", { className: `px-3 py-3 whitespace-nowrap text-right text-sm font-medium ${difference < 0
248
366
  ? "text-red-600 dark:text-red-400"
249
367
  : "text-gray-900 dark:text-white"}`, children: formatNumber(difference) }), _jsx("td", { className: "px-3 py-3 text-sm w-96", children: isEditingComment ? (_jsx(Textarea, { value: editingComment, onChange: (e) => setEditingComment(e.target.value), placeholder: "Add comment...", autoExpand: true, multiline: true, onKeyDown: (e) => {
250
368
  if (e.key === "Enter" && !e.shiftKey) {
@@ -258,11 +376,11 @@ export function AggregatedExpensesTable({ wallets, groups, periodStart, periodEn
258
376
  e.preventDefault();
259
377
  handleSaveComment();
260
378
  }
261
- }, onBlur: handleSaveComment, autoFocus: true, className: "w-full px-2 py-1 text-sm border border-blue-500 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-800 text-gray-900 dark:text-white max-h-32 overflow-y-auto" })) : (_jsx("div", { className: "group cursor-pointer w-full max-h-20 overflow-hidden", onClick: () => handleStartEdit(item.lineItemId, item.comment), title: item.comment || "No comments", children: _jsx("span", { className: "group-hover:bg-blue-50 dark:group-hover:bg-blue-900/20 px-1 py-0.5 rounded transition-colors block text-gray-600 dark:text-gray-400 break-words", children: item.comment || "No comments" }) })) }), _jsx("td", { className: "px-3 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white w-32", children: renderEditableCell("payments", item.payments) })] }, item.lineItemId));
262
- }), _jsxs("tr", { className: "bg-gray-50 dark:bg-gray-800/50 font-semibold align-top", children: [_jsx("td", { className: "px-6 py-3 whitespace-nowrap text-sm text-gray-900 dark:text-white", children: "Subtotal" }), _jsx("td", { className: "px-6 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(subtotals.budget) }) }) }), _jsx("td", { className: "px-6 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(subtotals.forecast) }) }) }), _jsx("td", { className: "px-6 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(subtotals.actuals) }) }) }), _jsx("td", { className: `px-6 py-3 whitespace-nowrap text-right text-sm font-bold ${subtotals.difference < 0
379
+ }, onBlur: handleSaveComment, autoFocus: true, className: "w-full px-2 py-1 text-sm border border-blue-500 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-800 text-gray-900 dark:text-white max-h-32 overflow-y-auto" })) : (_jsx("div", { className: "group cursor-pointer w-full max-h-20 overflow-hidden", onClick: () => handleStartEdit(item.lineItemId, item.comment), title: item.comment || "No comments", children: _jsx("span", { className: "group-hover:bg-blue-50 dark:group-hover:bg-blue-900/20 px-1 py-0.5 rounded transition-colors block text-gray-600 dark:text-gray-400 break-words", children: item.comment || "No comments" }) })) }), _jsx("td", { className: "px-3 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white w-32", children: renderEditableCell("payments", item.payments) }), _jsx("td", { className: "px-2 py-3 whitespace-nowrap text-center w-16", children: _jsx("button", { onClick: () => handleDeleteLineItem(item.lineItemId, item.groupLabel), className: "inline-flex items-center justify-center p-0.5 text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-300 hover:bg-red-50 dark:hover:bg-red-900/20 rounded transition-colors", title: "Delete line item", children: _jsx(Trash2, { size: 14 }) }) })] }, item.lineItemId));
380
+ }), _jsxs("tr", { className: "bg-gray-50 dark:bg-gray-800/50 font-semibold align-top", children: [_jsx("td", { className: "pl-6 pr-3 py-3 whitespace-nowrap text-sm text-gray-900 dark:text-white", children: "Subtotal" }), _jsx("td", { className: "px-3 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(subtotals.budget) }) }) }), _jsx("td", { className: "px-3 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(subtotals.forecast) }) }) }), _jsx("td", { className: "px-3 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(subtotals.actuals) }) }) }), _jsx("td", { className: `px-3 py-3 whitespace-nowrap text-right text-sm font-bold ${subtotals.difference < 0
263
381
  ? "text-red-600 dark:text-red-400"
264
- : "text-gray-900 dark:text-white"}`, children: formatNumber(subtotals.difference) }), _jsx("td", { className: "px-3 py-3" }), _jsx("td", { className: "px-3 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white w-32", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(subtotals.payments) }) }) })] })] }, parentKey));
265
- }), _jsxs("tr", { className: "bg-gray-100 dark:bg-gray-800 font-bold align-top", children: [_jsx("td", { className: "px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white", children: "Total" }), _jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(grandTotals.budget) }) }) }), _jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(grandTotals.forecast) }) }) }), _jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(grandTotals.actuals) }) }) }), _jsx("td", { className: `px-6 py-4 whitespace-nowrap text-right text-sm ${grandTotals.difference < 0
382
+ : "text-gray-900 dark:text-white"}`, children: formatNumber(subtotals.difference) }), _jsx("td", { className: "px-3 py-3" }), _jsx("td", { className: "px-3 py-3 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white w-32", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(subtotals.payments) }) }) }), _jsx("td", { className: "px-2 py-3" })] })] }, parentKey));
383
+ }), _jsxs("tr", { className: "bg-gray-100 dark:bg-gray-800 font-bold align-top", children: [_jsx("td", { className: "pl-6 pr-3 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white", children: "Total" }), _jsx("td", { className: "px-3 py-4 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(grandTotals.budget) }) }) }), _jsx("td", { className: "px-3 py-4 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(grandTotals.forecast) }) }) }), _jsx("td", { className: "px-3 py-4 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(grandTotals.actuals) }) }) }), _jsx("td", { className: `px-3 py-4 whitespace-nowrap text-right text-sm ${grandTotals.difference < 0
266
384
  ? "text-red-600 dark:text-red-400"
267
- : "text-gray-900 dark:text-white"}`, children: formatNumber(grandTotals.difference) }), _jsx("td", { className: "px-3 py-4" }), _jsx("td", { className: "px-3 py-4 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white w-32", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(grandTotals.payments) }) }) })] })] })] }) })] }));
385
+ : "text-gray-900 dark:text-white"}`, children: formatNumber(grandTotals.difference) }), _jsx("td", { className: "px-3 py-4" }), _jsx("td", { className: "px-3 py-4 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white w-32", children: _jsx("div", { className: "text-right", children: _jsx("span", { className: "inline-block px-1 py-0.5 min-w-[4rem]", children: formatNumber(grandTotals.payments) }) }) }), _jsx("td", { className: "px-2 py-4" })] }), isAddingLineItem && (_jsx("tr", { ref: lineItemEditorRef, className: "bg-white dark:bg-gray-900 border-t border-gray-900 dark:border-gray-100", children: _jsx("td", { colSpan: 8, className: "px-6 py-4", children: _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-end gap-4", children: [_jsxs("div", { className: "flex-1", children: [_jsx("label", { className: "block text-xs font-medium text-gray-700 dark:text-gray-300 mb-2", children: "Select Category" }), _jsx(Select, { name: "category", searchable: true, value: selectedGroupId, onChange: (value) => handleCategoryChange(value), options: groupOptions, placeholder: "Choose a category...", className: "w-full" })] }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { onClick: handleSaveLineItem, disabled: !selectedGroupId || !!duplicateCategoryError, className: "bg-green-600 hover:bg-green-700 text-white", children: "SAVE" }), _jsx(Button, { onClick: handleCancelLineItem, variant: "secondary", children: "CANCEL" })] })] }), duplicateCategoryError && (_jsx("div", { className: "flex items-start gap-2 p-3 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-md", children: _jsx("span", { className: "text-sm text-amber-800 dark:text-amber-200", children: duplicateCategoryError }) }))] }) }) }))] })] }) }), deleteModalOpen && lineItemToDelete && (_jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center", children: [_jsx("div", { className: "absolute inset-0 bg-black/50 backdrop-blur-sm", onClick: handleCancelDelete }), _jsxs("div", { className: "relative bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full mx-4 overflow-hidden", children: [_jsx("div", { className: "px-6 py-4 border-b border-gray-200 dark:border-gray-700", children: _jsx("h3", { className: "text-lg font-semibold text-gray-900 dark:text-white", children: "Delete Line Item" }) }), _jsx("div", { className: "px-6 py-4", children: _jsxs("p", { className: "text-sm text-gray-600 dark:text-gray-400", children: ["Are you sure you want to delete the line item", " ", _jsxs("span", { className: "font-semibold text-gray-900 dark:text-white", children: ["\"", lineItemToDelete.label, "\""] }), "? This action cannot be undone."] }) }), _jsxs("div", { className: "px-6 py-4 bg-gray-50 dark:bg-gray-800/50 border-t border-gray-200 dark:border-gray-700 flex justify-end gap-3", children: [_jsx(Button, { onClick: handleCancelDelete, variant: "secondary", children: "CANCEL" }), _jsx(Button, { onClick: handleConfirmDelete, className: "bg-red-600 hover:bg-red-700 text-white", children: "DELETE" })] })] })] }))] }));
268
386
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ExpenseReportPDF.d.ts","sourceRoot":"","sources":["../../../../editors/expense-report/components/ExpenseReportPDF.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,MAAM,EACN,aAAa,EAEd,MAAM,sDAAsD,CAAC;AAE9D,UAAU,qBAAqB;IAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAmKD,wBAAgB,gBAAgB,CAAC,EAC/B,WAAW,EACX,SAAS,EACT,OAAO,EACP,MAAM,GACP,EAAE,qBAAqB,2CAiVvB"}
1
+ {"version":3,"file":"ExpenseReportPDF.d.ts","sourceRoot":"","sources":["../../../../editors/expense-report/components/ExpenseReportPDF.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,MAAM,EACN,aAAa,EAEd,MAAM,sDAAsD,CAAC;AAE9D,UAAU,qBAAqB;IAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAmKD,wBAAgB,gBAAgB,CAAC,EAC/B,WAAW,EACX,SAAS,EACT,OAAO,EACP,MAAM,GACP,EAAE,qBAAqB,2CAqVvB"}
@@ -235,11 +235,11 @@ export function ExpenseReportPDF({ periodStart, periodEnd, wallets, groups, }) {
235
235
  actuals: acc.actuals + (item.actuals || 0),
236
236
  payments: acc.payments + (item.payments || 0),
237
237
  }), { budget: 0, forecast: 0, actuals: 0, payments: 0 });
238
- return (_jsxs(View, { wrap: false, break: walletIndex > 0, children: [_jsxs(Text, { style: styles.sectionTitle, children: [periodStart &&
239
- new Date(periodStart).toLocaleDateString("en-US", {
240
- month: "short",
241
- year: "numeric",
242
- }), " ", "Breakdown"] }), _jsxs(Text, { style: styles.walletInfo, children: [wallet.name && `${wallet.name} • `, wallet.wallet || "Unknown Wallet"] }), _jsxs(View, { style: styles.table, children: [_jsxs(View, { style: styles.tableHeader, children: [_jsx(Text, { style: [styles.headerCell, styles.categoryCol], children: "Category" }), _jsx(Text, { style: [styles.headerCell, styles.budgetCol], children: "Budget" }), _jsx(Text, { style: [styles.headerCell, styles.forecastCol], children: "Forecast" }), _jsx(Text, { style: [styles.headerCell, styles.actualsCol], children: "Actuals" }), _jsx(Text, { style: [styles.headerCell, styles.differenceCol], children: "Difference" }), _jsx(Text, { style: [styles.headerCell, styles.commentsCol], children: "Comments" }), _jsx(Text, { style: [styles.headerCell, styles.paymentsCol], children: "Payments" })] }), groupedItems.map((group, groupIndex) => {
238
+ return (_jsxs(View, { break: walletIndex > 0, children: [_jsxs(View, { wrap: false, children: [_jsxs(Text, { style: styles.sectionTitle, children: [periodStart &&
239
+ new Date(periodStart).toLocaleDateString("en-US", {
240
+ month: "short",
241
+ year: "numeric",
242
+ }), " ", "Breakdown"] }), _jsxs(Text, { style: styles.walletInfo, children: [wallet.name && `${wallet.name} • `, wallet.wallet || "Unknown Wallet"] })] }), _jsxs(View, { style: styles.table, children: [groupedItems.map((group, groupIndex) => {
243
243
  const subtotals = group.items.reduce((acc, item) => ({
244
244
  budget: acc.budget + (item.budget || 0),
245
245
  forecast: acc.forecast + (item.forecast || 0),
@@ -247,13 +247,13 @@ export function ExpenseReportPDF({ periodStart, periodEnd, wallets, groups, }) {
247
247
  payments: acc.payments + (item.payments || 0),
248
248
  }), { budget: 0, forecast: 0, actuals: 0, payments: 0 });
249
249
  const subtotalDifference = subtotals.forecast - subtotals.actuals;
250
- return (_jsxs(View, { children: [_jsx(View, { style: {
250
+ return (_jsxs(View, { children: [groupIndex === 0 && (_jsxs(View, { style: styles.tableHeader, wrap: false, children: [_jsx(Text, { style: [styles.headerCell, styles.categoryCol], children: "Category" }), _jsx(Text, { style: [styles.headerCell, styles.budgetCol], children: "Budget" }), _jsx(Text, { style: [styles.headerCell, styles.forecastCol], children: "Forecast" }), _jsx(Text, { style: [styles.headerCell, styles.actualsCol], children: "Actuals" }), _jsx(Text, { style: [styles.headerCell, styles.differenceCol], children: "Difference" }), _jsx(Text, { style: [styles.headerCell, styles.commentsCol], children: "Comments" }), _jsx(Text, { style: [styles.headerCell, styles.paymentsCol], children: "Payments" })] })), _jsx(View, { style: {
251
251
  paddingVertical: 6,
252
252
  paddingHorizontal: 6,
253
253
  backgroundColor: "#f9fafb",
254
254
  borderBottom: "1pt solid #e5e7eb",
255
255
  marginTop: groupIndex > 0 ? 8 : 0,
256
- }, children: _jsx(Text, { style: {
256
+ }, wrap: false, children: _jsx(Text, { style: {
257
257
  fontSize: 9,
258
258
  fontWeight: "bold",
259
259
  color: "#111827",
@@ -1 +1 @@
1
- {"version":3,"file":"WalletsTable.d.ts","sourceRoot":"","sources":["../../../../editors/expense-report/components/WalletsTable.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,sDAAsD,CAAC;AAKlG,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,qBAAqB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IACvD,QAAQ,EAAE,GAAG,CAAC;CACf;AAED,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,MAAM,EACN,qBAAqB,EACrB,QAAQ,GACT,EAAE,iBAAiB,2CA+XnB"}
1
+ {"version":3,"file":"WalletsTable.d.ts","sourceRoot":"","sources":["../../../../editors/expense-report/components/WalletsTable.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,sDAAsD,CAAC;AAKlG,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,qBAAqB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IACvD,QAAQ,EAAE,GAAG,CAAC;CACf;AAED,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,MAAM,EACN,qBAAqB,EACrB,QAAQ,GACT,EAAE,iBAAiB,2CAwanB"}
@@ -122,7 +122,19 @@ export function WalletsTable({ wallets, groups, onAddBillingStatement, dispatch,
122
122
  minimumFractionDigits: 2,
123
123
  }).format(value);
124
124
  };
125
- return (_jsxs("div", { className: "space-y-4", children: [wallets.length > 0 ? (_jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "min-w-full divide-y divide-gray-200 dark:divide-gray-700", children: [_jsx("thead", { className: "bg-gray-50 dark:bg-gray-800", children: _jsxs("tr", { children: [_jsx("th", { className: "px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Wallet" }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Monthly Budget" }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Forecast" }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Actuals" }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Difference" }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Payments" }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Actions" })] }) }), _jsx("tbody", { className: "bg-white dark:bg-gray-900 divide-y divide-gray-200 dark:divide-gray-700", children: wallets.map((wallet) => {
125
+ return (_jsxs("div", { className: "space-y-4", children: [wallets.length > 0 ? (_jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "min-w-full divide-y divide-gray-200 dark:divide-gray-700", children: [_jsx("thead", { className: "bg-gray-50 dark:bg-gray-800", children: _jsxs("tr", { children: [_jsx("th", { className: "px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Wallet" }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Monthly Budget" }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Forecast" }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: _jsxs("div", { className: "flex items-center justify-end gap-2", children: [needsSync && (_jsx("button", { onClick: () => {
126
+ // Sync all outdated wallets
127
+ [...tagChangedWallets, ...outdatedWallets].forEach((walletAddress) => {
128
+ const wallet = wallets.find(w => w.wallet === walletAddress);
129
+ if (wallet) {
130
+ handleSyncWallet(wallet);
131
+ }
132
+ });
133
+ }, disabled: syncingWallet !== null, className: `inline-flex items-center justify-center w-8 h-8 rounded-md transition-colors ${tagChangedWallets.length > 0
134
+ ? "text-red-600 dark:text-red-400 bg-red-50 dark:bg-red-900/20 hover:bg-red-100 dark:hover:bg-red-900/30 animate-pulse"
135
+ : "text-amber-600 dark:text-amber-400 bg-amber-50 dark:bg-amber-900/20 hover:bg-amber-100 dark:hover:bg-amber-900/30 animate-pulse"} disabled:opacity-50 disabled:cursor-not-allowed`, title: tagChangedWallets.length > 0
136
+ ? "ALERT: Tags have changed in billing statements - sync all wallets!"
137
+ : "Sync all wallets with latest billing statements", children: _jsx(RefreshCw, { size: 16, className: syncingWallet !== null ? "animate-spin" : "" }) })), _jsx("span", { children: "Actuals" })] }) }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Difference" }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Payments" }), _jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children: "Actions" })] }) }), _jsx("tbody", { className: "bg-white dark:bg-gray-900 divide-y divide-gray-200 dark:divide-gray-700", children: wallets.map((wallet) => {
126
138
  const totals = calculateWalletTotals(wallet);
127
139
  const isHovered = hoveredWallet === wallet.wallet;
128
140
  return (_jsxs("tr", { onMouseEnter: () => setHoveredWallet(wallet.wallet || null), onMouseLeave: () => setHoveredWallet(null), className: "hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors", children: [_jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: editingWallet === wallet.wallet ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(TextInput, { value: editingName, onChange: (e) => setEditingName(e.target.value), placeholder: "Enter wallet name", className: "flex-1", onKeyDown: (e) => {
@@ -132,23 +144,23 @@ export function WalletsTable({ wallets, groups, onAddBillingStatement, dispatch,
132
144
  else if (e.key === "Escape") {
133
145
  handleCancelEditName();
134
146
  }
135
- }, autoFocus: true }), _jsx("button", { onClick: () => handleSaveEditName(wallet.wallet || ""), className: "inline-flex items-center justify-center w-7 h-7 text-green-600 dark:text-green-400 hover:bg-green-50 dark:hover:bg-green-900/20 rounded-md transition-colors", title: "Save", children: _jsx(Check, { size: 14 }) }), _jsx("button", { onClick: handleCancelEditName, className: "inline-flex items-center justify-center w-7 h-7 text-gray-600 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-900/20 rounded-md transition-colors", title: "Cancel", children: _jsx(X, { size: 14 }) })] })) : (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-sm font-medium text-gray-900 dark:text-white", children: wallet.name || "Unnamed Wallet" }), _jsx("button", { onClick: () => handleStartEditName(wallet), className: "inline-flex items-center justify-center w-6 h-6 text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-md transition-colors", title: "Edit name", children: _jsx(Pencil, { size: 12 }) }), _jsxs("button", { onClick: () => handleCopyAddress(wallet.wallet || ""), className: "inline-flex items-center gap-1 px-2 py-1 text-xs text-gray-500 dark:text-gray-400 font-mono hover:bg-gray-100 dark:hover:bg-gray-700 rounded transition-colors", title: `Copy address: ${wallet.wallet}`, children: [formatAddress(wallet.wallet || ""), copiedWallet === wallet.wallet ? (_jsx(CheckCheck, { size: 12, className: "text-green-500" })) : (_jsx(Copy, { size: 12 }))] })] })) }), _jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: formatCurrency(totals.budget) }), _jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: formatCurrency(totals.forecast) }), _jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: formatCurrency(totals.actuals) }), _jsx("td", { className: `px-6 py-4 whitespace-nowrap text-right text-sm font-medium ${totals.difference > 0
136
- ? "text-red-600 dark:text-red-400"
137
- : totals.difference < 0
138
- ? "text-green-600 dark:text-green-400"
139
- : "text-gray-900 dark:text-white"}`, children: formatCurrency(totals.difference) }), _jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: formatCurrency(totals.payments) }), _jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm", children: _jsxs("div", { className: "flex items-center justify-end gap-2", children: [_jsxs("button", { onClick: () => onAddBillingStatement(wallet.wallet || ""), className: "inline-flex items-center gap-1 px-3 py-1 text-sm font-medium text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 bg-blue-50 dark:bg-blue-900/20 hover:bg-blue-100 dark:hover:bg-blue-900/30 rounded-md transition-colors", title: "Add billing statement", children: [_jsx(Plus, { size: 16 }), _jsx("span", { children: "Add Bills" })] }), wallet.billingStatements && wallet.billingStatements.length > 0 && (_jsxs("button", { onClick: () => handleSyncWallet(wallet), disabled: syncingWallet === wallet.wallet, className: `inline-flex items-center gap-1 px-3 py-1 text-sm font-medium rounded-md transition-colors ${tagChangedWallets.includes(wallet.wallet || "")
147
+ }, autoFocus: true }), _jsx("button", { onClick: () => handleSaveEditName(wallet.wallet || ""), className: "inline-flex items-center justify-center w-7 h-7 text-green-600 dark:text-green-400 hover:bg-green-50 dark:hover:bg-green-900/20 rounded-md transition-colors", title: "Save", children: _jsx(Check, { size: 14 }) }), _jsx("button", { onClick: handleCancelEditName, className: "inline-flex items-center justify-center w-7 h-7 text-gray-600 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-900/20 rounded-md transition-colors", title: "Cancel", children: _jsx(X, { size: 14 }) })] })) : (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-sm font-medium text-gray-900 dark:text-white", children: wallet.name || "Unnamed Wallet" }), _jsx("button", { onClick: () => handleStartEditName(wallet), className: "inline-flex items-center justify-center w-6 h-6 text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-md transition-colors", title: "Edit name", children: _jsx(Pencil, { size: 12 }) }), _jsxs("button", { onClick: () => handleCopyAddress(wallet.wallet || ""), className: "inline-flex items-center gap-1 px-2 py-1 text-xs text-gray-500 dark:text-gray-400 font-mono hover:bg-gray-100 dark:hover:bg-gray-700 rounded transition-colors", title: `Copy address: ${wallet.wallet}`, children: [formatAddress(wallet.wallet || ""), copiedWallet === wallet.wallet ? (_jsx(CheckCheck, { size: 12, className: "text-green-500" })) : (_jsx(Copy, { size: 12 }))] })] })) }), _jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: formatCurrency(totals.budget) }), _jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: formatCurrency(totals.forecast) }), _jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm", children: totals.actuals === 0 && (!wallet.billingStatements || wallet.billingStatements.length === 0) ? (
148
+ // When actuals is 0 and no billing statements, only show the Add Bills button
149
+ _jsx("div", { className: "flex items-center justify-end", children: _jsxs("button", { onClick: () => onAddBillingStatement(wallet.wallet || ""), className: "inline-flex items-center gap-1 px-3 py-1 text-sm font-medium text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 bg-blue-50 dark:bg-blue-900/20 hover:bg-blue-100 dark:hover:bg-blue-900/30 rounded-md transition-colors", title: "Add billing statement for this wallet", children: [_jsx(Plus, { size: 16 }), _jsx("span", { children: "Add Bills" })] }) })) : (
150
+ // When actuals is not 0 or has billing statements, show compact buttons + value horizontally
151
+ _jsxs("div", { className: "flex items-center justify-end gap-2", children: [_jsx("button", { onClick: () => onAddBillingStatement(wallet.wallet || ""), className: "inline-flex items-center justify-center w-8 h-8 text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 bg-blue-50 dark:bg-blue-900/20 hover:bg-blue-100 dark:hover:bg-blue-900/30 rounded-md transition-colors", title: "Add billing statement for this wallet", children: _jsx(Plus, { size: 16 }) }), wallet.billingStatements && wallet.billingStatements.length > 0 && (_jsx("button", { onClick: () => handleSyncWallet(wallet), disabled: syncingWallet === wallet.wallet, className: `inline-flex items-center justify-center w-8 h-8 rounded-md transition-colors ${tagChangedWallets.includes(wallet.wallet || "")
140
152
  ? "text-red-600 dark:text-red-400 bg-red-50 dark:bg-red-900/20 hover:bg-red-100 dark:hover:bg-red-900/30 animate-pulse"
141
153
  : outdatedWallets.includes(wallet.wallet || "")
142
154
  ? "text-amber-600 dark:text-amber-400 bg-amber-50 dark:bg-amber-900/20 hover:bg-amber-100 dark:hover:bg-amber-900/30 animate-pulse"
143
155
  : "text-gray-600 dark:text-gray-400 bg-gray-50 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-700"} disabled:opacity-50 disabled:cursor-not-allowed`, title: tagChangedWallets.includes(wallet.wallet || "")
144
- ? "ALERT: Tags have changed in billing statements - sync required!"
156
+ ? "ALERT: Tags have changed - sync required!"
145
157
  : outdatedWallets.includes(wallet.wallet || "")
146
- ? "Sync needed - billing statements have been updated"
147
- : "Sync with latest billing statements", children: [_jsx(RefreshCw, { size: 16, className: syncingWallet === wallet.wallet ? "animate-spin" : "" }), _jsx("span", { children: tagChangedWallets.includes(wallet.wallet || "")
148
- ? "Tags Changed!"
149
- : outdatedWallets.includes(wallet.wallet || "")
150
- ? "Sync"
151
- : "Synced" })] })), _jsx("button", { onClick: () => handleRemoveWallet(wallet.wallet || ""), className: "inline-flex items-center justify-center w-8 h-8 text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-md transition-colors", title: "Remove wallet", children: _jsx(Trash2, { size: 16 }) })] }) })] }, wallet.wallet));
158
+ ? "Sync needed - billing statements updated"
159
+ : "Sync with latest billing statements", children: _jsx(RefreshCw, { size: 16, className: syncingWallet === wallet.wallet ? "animate-spin" : "" }) })), _jsx("span", { className: "text-sm font-medium text-gray-900 dark:text-white", children: formatCurrency(totals.actuals) })] })) }), _jsx("td", { className: `px-6 py-4 whitespace-nowrap text-right text-sm font-medium ${totals.difference > 0
160
+ ? "text-red-600 dark:text-red-400"
161
+ : totals.difference < 0
162
+ ? "text-green-600 dark:text-green-400"
163
+ : "text-gray-900 dark:text-white"}`, children: formatCurrency(totals.difference) }), _jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm text-gray-900 dark:text-white", children: formatCurrency(totals.payments) }), _jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm", children: _jsx("div", { className: "flex items-center justify-end gap-2", children: _jsx("button", { onClick: () => handleRemoveWallet(wallet.wallet || ""), className: "inline-flex items-center justify-center w-8 h-8 text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-md transition-colors", title: "Remove wallet", children: _jsx(Trash2, { size: 16 }) }) }) })] }, wallet.wallet));
152
164
  }) })] }) })) : (_jsx("div", { className: "text-center py-12 text-gray-500 dark:text-gray-400", children: _jsx("p", { className: "text-sm", children: "No wallets added yet. Add a wallet to get started." }) })), _jsxs("div", { className: "flex items-end gap-3 pt-4 border-t border-gray-200 dark:border-gray-700", children: [_jsxs("div", { className: "flex-1", children: [_jsx("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1", children: "Wallet Name" }), _jsx(TextInput, { value: newWalletName, onChange: (e) => setNewWalletName(e.target.value), placeholder: "Enter wallet name (optional)", onKeyDown: (e) => {
153
165
  if (e.key === "Enter") {
154
166
  handleAddWallet();
@@ -1 +1 @@
1
- {"version":3,"file":"bankSection.d.ts","sourceRoot":"","sources":["../../../../editors/invoice/legalEntity/bankSection.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EAOtB,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAG5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAMtE,MAAM,MAAM,2BAA2B,GAAG,IAAI,CAC5C,qBAAqB,CAAC,KAAK,CAAC,EAC5B,UAAU,CACX,GAAG;IACF,QAAQ,CAAC,KAAK,EAAE,wBAAwB,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,IAAI,CAAC;IAC7D,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACrD,QAAQ,CAAC,cAAc,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClD,QAAQ,CAAC,aAAa,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACjD,QAAQ,CAAC,uBAAuB,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC3D,QAAQ,CAAC,kBAAkB,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACtD,QAAQ,CAAC,uBAAuB,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC3D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,CAAC;AAmCF,eAAO,MAAM,sBAAsB,qIA6hBlC,CAAC"}
1
+ {"version":3,"file":"bankSection.d.ts","sourceRoot":"","sources":["../../../../editors/invoice/legalEntity/bankSection.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EAOtB,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAG5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAMtE,MAAM,MAAM,2BAA2B,GAAG,IAAI,CAC5C,qBAAqB,CAAC,KAAK,CAAC,EAC5B,UAAU,CACX,GAAG;IACF,QAAQ,CAAC,KAAK,EAAE,wBAAwB,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,IAAI,CAAC;IAC7D,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACrD,QAAQ,CAAC,cAAc,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClD,QAAQ,CAAC,aAAa,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACjD,QAAQ,CAAC,uBAAuB,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC3D,QAAQ,CAAC,kBAAkB,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACtD,QAAQ,CAAC,uBAAuB,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC3D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,CAAC;AAmCF,eAAO,MAAM,sBAAsB,qIAoiBlC,CAAC"}
@@ -79,24 +79,24 @@ export const LegalEntityBankSection = forwardRef(function LegalEntityBankSection
79
79
  }
80
80
  const SEPA_SWIFT_CURRENCIES = ["EUR", "DKK", "GBP", "CHF", "JPY"];
81
81
  const usdIbanPayment = useMemo(() => isValidIBAN(localState.accountNum ?? "") && currency === "USD", [localState.accountNum, currency]);
82
- return (_jsxs("div", { ...divProps, className: twMerge("rounded-lg border border-gray-200 bg-white p-6", props.className), ref: ref, children: [_jsx("h3", { className: "mb-4 text-lg font-semibold text-gray-900", children: "Banking Information" }), _jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "space-y-4", children: [_jsx("div", { className: "space-y-2", children: _jsx(InputField
83
- // input={localState.accountNum ?? ""}
84
- , {
85
- // input={localState.accountNum ?? ""}
86
- value: localState.accountNum ?? "", label: "Account Number", placeholder: "Account Number", onBlur: createBlurHandler("accountNum"), handleInputChange: createInputHandler("accountNum"), className: "h-10 w-full text-md mb-2", validation:
87
- // Prefer the first failing validation between IBAN and generic account number
88
- (() => {
89
- const firstInvalid = (ibanvalidation &&
90
- !ibanvalidation.isValid &&
91
- ibanvalidation) ||
92
- (accountNumbervalidation &&
93
- !accountNumbervalidation.isValid &&
94
- accountNumbervalidation);
95
- return (firstInvalid ||
96
- ibanvalidation ||
97
- accountNumbervalidation ||
98
- null);
99
- })() }) }), _jsx("div", { className: "space-y-2", children: _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsx("div", { className: "space-y-2", children: _jsx(Select, { className: "h-10 w-full text-md mb-2", label: "Account Type", options: ACCOUNT_TYPES.map((type) => ({
82
+ return (_jsxs("div", { ...divProps, className: twMerge("rounded-lg border border-gray-200 bg-white p-6", props.className), ref: ref, children: [_jsx("h3", { className: "mb-4 text-lg font-semibold text-gray-900", children: "Banking Information" }), _jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "space-y-4", children: [_jsx("div", { className: "space-y-2", children: _jsxs("div", { children: [_jsxs("label", { className: "block text-sm font-medium text-gray-700 mb-1", children: ["Account Number", isValidIBAN(localState.accountNum ?? "") && (_jsx("span", { className: "ml-2 text-green-600 font-medium", children: "IBAN" }))] }), _jsx(InputField
83
+ // input={localState.accountNum ?? ""}
84
+ , {
85
+ // input={localState.accountNum ?? ""}
86
+ value: localState.accountNum ?? "", placeholder: "Account Number", onBlur: createBlurHandler("accountNum"), handleInputChange: createInputHandler("accountNum"), className: "h-10 w-full text-md mb-2", validation:
87
+ // Prefer the first failing validation between IBAN and generic account number
88
+ (() => {
89
+ const firstInvalid = (ibanvalidation &&
90
+ !ibanvalidation.isValid &&
91
+ ibanvalidation) ||
92
+ (accountNumbervalidation &&
93
+ !accountNumbervalidation.isValid &&
94
+ accountNumbervalidation);
95
+ return (firstInvalid ||
96
+ ibanvalidation ||
97
+ accountNumbervalidation ||
98
+ null);
99
+ })() })] }) }), _jsx("div", { className: "space-y-2", children: _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsx("div", { className: "space-y-2", children: _jsx(Select, { className: "h-10 w-full text-md mb-2", label: "Account Type", options: ACCOUNT_TYPES.map((type) => ({
100
100
  label: type,
101
101
  value: type,
102
102
  })), value: localState.accountType ?? "", onChange: (value) => {
@@ -49,7 +49,7 @@ export function LineItemTagsTable({ lineItems, onClose, dispatch, paymentAccount
49
49
  id: item.id,
50
50
  description: e.target.value,
51
51
  }));
52
- } }) }), _jsx("td", { className: "border-b border-gray-200 w-48", children: _jsx(DatePicker, { name: "period", dateFormat: "YYYY-MM", autoClose: true, placeholder: "Select Period", value: item.lineItemTag.find((tag) => tag.dimension === "accounting-period")?.label || "", onChange: (e) => dispatch(actions.setLineItemTag({
52
+ } }) }), _jsx("td", { className: "border-b border-gray-200 w-48", children: _jsx(DatePicker, { name: "period", dateFormat: "YYYY-MM-DD", autoClose: true, placeholder: "Select Period", value: item.lineItemTag.find((tag) => tag.dimension === "accounting-period")?.label || "", onChange: (e) => dispatch(actions.setLineItemTag({
53
53
  lineItemId: item.id,
54
54
  dimension: "accounting-period",
55
55
  value: new Date(e.target.value)
package/dist/style.css CHANGED
@@ -355,6 +355,9 @@
355
355
  max-width: 96rem;
356
356
  }
357
357
  }
358
+ .mx-4 {
359
+ margin-inline: calc(var(--spacing) * 4);
360
+ }
358
361
  .mx-auto {
359
362
  margin-inline: auto;
360
363
  }
@@ -825,6 +828,9 @@
825
828
  --tw-border-style: dashed;
826
829
  border-style: dashed;
827
830
  }
831
+ .border-amber-200 {
832
+ border-color: var(--color-amber-200);
833
+ }
828
834
  .border-blue-100 {
829
835
  border-color: var(--color-blue-100);
830
836
  }
@@ -846,6 +852,9 @@
846
852
  .border-gray-500 {
847
853
  border-color: var(--color-gray-500);
848
854
  }
855
+ .border-gray-900 {
856
+ border-color: var(--color-gray-900);
857
+ }
849
858
  .border-green-500 {
850
859
  border-color: var(--color-green-500);
851
860
  }
@@ -876,6 +885,12 @@
876
885
  background-color: color-mix(in oklab, var(--color-black) 30%, transparent);
877
886
  }
878
887
  }
888
+ .bg-black\/50 {
889
+ background-color: color-mix(in srgb, #000 50%, transparent);
890
+ @supports (color: color-mix(in lab, red, red)) {
891
+ background-color: color-mix(in oklab, var(--color-black) 50%, transparent);
892
+ }
893
+ }
879
894
  .bg-blue-50 {
880
895
  background-color: var(--color-blue-50);
881
896
  }
@@ -939,6 +954,9 @@
939
954
  .p-0 {
940
955
  padding: calc(var(--spacing) * 0);
941
956
  }
957
+ .p-0\.5 {
958
+ padding: calc(var(--spacing) * 0.5);
959
+ }
942
960
  .p-1 {
943
961
  padding: calc(var(--spacing) * 1);
944
962
  }
@@ -1011,9 +1029,15 @@
1011
1029
  .pt-6 {
1012
1030
  padding-top: calc(var(--spacing) * 6);
1013
1031
  }
1032
+ .pr-3 {
1033
+ padding-right: calc(var(--spacing) * 3);
1034
+ }
1014
1035
  .pb-2 {
1015
1036
  padding-bottom: calc(var(--spacing) * 2);
1016
1037
  }
1038
+ .pl-6 {
1039
+ padding-left: calc(var(--spacing) * 6);
1040
+ }
1017
1041
  .pl-11 {
1018
1042
  padding-left: calc(var(--spacing) * 11);
1019
1043
  }
@@ -1088,6 +1112,9 @@
1088
1112
  .text-amber-600 {
1089
1113
  color: var(--color-amber-600);
1090
1114
  }
1115
+ .text-amber-800 {
1116
+ color: var(--color-amber-800);
1117
+ }
1091
1118
  .text-black {
1092
1119
  color: var(--color-black);
1093
1120
  }
@@ -1432,6 +1459,13 @@
1432
1459
  }
1433
1460
  }
1434
1461
  }
1462
+ .hover\:text-red-800 {
1463
+ &:hover {
1464
+ @media (hover: hover) {
1465
+ color: var(--color-red-800);
1466
+ }
1467
+ }
1468
+ }
1435
1469
  .hover\:opacity-80 {
1436
1470
  &:hover {
1437
1471
  @media (hover: hover) {
@@ -1603,6 +1637,16 @@
1603
1637
  }
1604
1638
  }
1605
1639
  }
1640
+ .dark\:border-amber-800 {
1641
+ &:where(.dark, .dark *) {
1642
+ border-color: var(--color-amber-800);
1643
+ }
1644
+ }
1645
+ .dark\:border-gray-100 {
1646
+ &:where(.dark, .dark *) {
1647
+ border-color: var(--color-gray-100);
1648
+ }
1649
+ }
1606
1650
  .dark\:border-gray-500 {
1607
1651
  &:where(.dark, .dark *) {
1608
1652
  border-color: var(--color-gray-500);
@@ -1670,6 +1714,11 @@
1670
1714
  }
1671
1715
  }
1672
1716
  }
1717
+ .dark\:text-amber-200 {
1718
+ &:where(.dark, .dark *) {
1719
+ color: var(--color-amber-200);
1720
+ }
1721
+ }
1673
1722
  .dark\:text-amber-400 {
1674
1723
  &:where(.dark, .dark *) {
1675
1724
  color: var(--color-amber-400);
@@ -1850,6 +1899,15 @@
1850
1899
  }
1851
1900
  }
1852
1901
  }
1902
+ .dark\:hover\:text-red-300 {
1903
+ &:where(.dark, .dark *) {
1904
+ &:hover {
1905
+ @media (hover: hover) {
1906
+ color: var(--color-red-300);
1907
+ }
1908
+ }
1909
+ }
1910
+ }
1853
1911
  .dark\:focus\:ring-blue-400 {
1854
1912
  &:where(.dark, .dark *) {
1855
1913
  &:focus {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@powerhousedao/contributor-billing",
3
3
  "description": "Document models that help contributors of open organisations get paid anonymously for their work on a monthly basis.",
4
- "version": "0.1.5",
4
+ "version": "0.1.7",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",
7
7
  "files": [
@@ -93,6 +93,7 @@
93
93
  "@powerhousedao/reactor-local": "^5.0.0-staging.30",
94
94
  "@powerhousedao/scalars": "^1.33.1-staging.5",
95
95
  "@powerhousedao/switchboard": "^5.0.0-staging.30",
96
+ "@powerhousedao/vetra": "5.0.0-staging.30",
96
97
  "@tailwindcss/cli": "^4.1.4",
97
98
  "@testing-library/react": "^16.3.0",
98
99
  "@types/node": "^22.14.1",