@powerhousedao/contributor-billing 0.0.98 → 0.0.99

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/editors/invoice/components/lineItemCard.d.ts +21 -0
  2. package/dist/editors/invoice/components/lineItemCard.d.ts.map +1 -0
  3. package/dist/editors/invoice/components/lineItemCard.js +23 -0
  4. package/dist/editors/invoice/components/lineItemMobileModal.d.ts +33 -0
  5. package/dist/editors/invoice/components/lineItemMobileModal.d.ts.map +1 -0
  6. package/dist/editors/invoice/components/lineItemMobileModal.js +73 -0
  7. package/dist/editors/invoice/components/lineItemsEmptyState.d.ts +6 -0
  8. package/dist/editors/invoice/components/lineItemsEmptyState.d.ts.map +1 -0
  9. package/dist/editors/invoice/components/lineItemsEmptyState.js +5 -0
  10. package/dist/editors/invoice/editor.d.ts.map +1 -1
  11. package/dist/editors/invoice/editor.js +37 -19
  12. package/dist/editors/invoice/ingestPDF.js +1 -1
  13. package/dist/editors/invoice/invoiceToGnosis.js +1 -1
  14. package/dist/editors/invoice/lineItemTags/lineItemTags.d.ts.map +1 -1
  15. package/dist/editors/invoice/lineItemTags/lineItemTags.js +25 -3
  16. package/dist/editors/invoice/lineItemTags/tagCard.d.ts +15 -0
  17. package/dist/editors/invoice/lineItemTags/tagCard.d.ts.map +1 -0
  18. package/dist/editors/invoice/lineItemTags/tagCard.js +13 -0
  19. package/dist/editors/invoice/lineItemTags/tagMobileModal.d.ts +18 -0
  20. package/dist/editors/invoice/lineItemTags/tagMobileModal.d.ts.map +1 -0
  21. package/dist/editors/invoice/lineItemTags/tagMobileModal.js +71 -0
  22. package/dist/editors/invoice/lineItems.d.ts.map +1 -1
  23. package/dist/editors/invoice/lineItems.js +73 -37
  24. package/dist/editors/invoice/requestFinance.js +1 -1
  25. package/dist/editors/invoice/uploadPdfChunked.js +1 -1
  26. package/dist/style.css +171 -6
  27. package/dist/tailwind.config.js +1 -0
  28. package/package.json +13 -12
@@ -0,0 +1,21 @@
1
+ type LineItem = {
2
+ currency: string;
3
+ description: string;
4
+ id: string;
5
+ quantity: number;
6
+ taxPercent: number;
7
+ totalPriceTaxExcl: number;
8
+ totalPriceTaxIncl: number;
9
+ unitPriceTaxExcl: number;
10
+ unitPriceTaxIncl: number;
11
+ lineItemTag: any[];
12
+ };
13
+ type LineItemCardProps = {
14
+ item: LineItem;
15
+ onEdit: () => void;
16
+ onDelete: () => void;
17
+ currency: string;
18
+ };
19
+ export declare function LineItemCard({ item, onEdit, onDelete, currency, }: LineItemCardProps): import("react/jsx-runtime").JSX.Element;
20
+ export {};
21
+ //# sourceMappingURL=lineItemCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lineItemCard.d.ts","sourceRoot":"","sources":["../../../../editors/invoice/components/lineItemCard.tsx"],"names":[],"mappings":"AAIA,KAAK,QAAQ,GAAG;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,GAAG,EAAE,CAAC;CACpB,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,QAAQ,GACT,EAAE,iBAAiB,2CAkGnB"}
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Edit, Trash2, MoreVertical } from "lucide-react";
3
+ import { formatNumber } from "../lineItems.js";
4
+ import { useState } from "react";
5
+ export function LineItemCard({ item, onEdit, onDelete, currency, }) {
6
+ const [isExpanded, setIsExpanded] = useState(false);
7
+ const [showMenu, setShowMenu] = useState(false);
8
+ const tagCount = item.lineItemTag?.length || 0;
9
+ return (_jsxs("div", { className: "bg-white border border-gray-200 rounded-lg mb-3 overflow-hidden", children: [_jsxs("div", { className: "p-4 cursor-pointer", onClick: () => setIsExpanded(!isExpanded), children: [_jsxs("div", { className: "flex items-start justify-between mb-2", children: [_jsx("div", { className: "flex-1", children: _jsx("h5", { className: "font-medium text-gray-900 text-sm", children: item.description || "Untitled Item" }) }), _jsx("button", { className: "p-1 hover:bg-gray-100 rounded", onClick: (e) => {
10
+ e.stopPropagation();
11
+ setShowMenu(!showMenu);
12
+ }, children: _jsx(MoreVertical, { className: "w-5 h-5 text-gray-500" }) })] }), _jsxs("div", { className: "flex items-center justify-between text-sm", children: [_jsxs("div", { className: "flex items-center gap-4 text-gray-600", children: [_jsxs("span", { children: ["Qty: ", item.quantity] }), _jsx("span", { children: "\u2022" }), _jsxs("span", { children: [currency, " ", formatNumber(item.unitPriceTaxExcl)] })] }), _jsxs("div", { className: "font-semibold text-gray-900", children: [currency, " ", formatNumber(item.totalPriceTaxIncl)] })] }), isExpanded && (_jsxs("div", { className: "mt-3 pt-3 border-t border-gray-100 space-y-2 text-sm", children: [_jsxs("div", { className: "flex justify-between", children: [_jsx("span", { className: "text-gray-600", children: "Tax %:" }), _jsxs("span", { className: "text-gray-900", children: [item.taxPercent, "%"] })] }), _jsxs("div", { className: "flex justify-between", children: [_jsx("span", { className: "text-gray-600", children: "Total (excl. tax):" }), _jsxs("span", { className: "text-gray-900", children: [currency, " ", formatNumber(item.totalPriceTaxExcl)] })] }), _jsxs("div", { className: "flex justify-between", children: [_jsx("span", { className: "text-gray-600", children: "Unit Price (incl. tax):" }), _jsxs("span", { className: "text-gray-900", children: [currency, " ", formatNumber(item.unitPriceTaxIncl)] })] })] }))] }), showMenu && (_jsxs("div", { className: "border-t border-gray-200 bg-gray-50", children: [_jsxs("button", { className: "w-full flex items-center gap-3 px-4 py-3 text-sm text-left hover:bg-gray-100 transition-colors", onClick: (e) => {
13
+ e.stopPropagation();
14
+ onEdit();
15
+ setShowMenu(false);
16
+ }, children: [_jsx(Edit, { className: "w-4 h-4 text-blue-600" }), _jsx("span", { children: "Edit Line Item" })] }), _jsxs("button", { className: "w-full flex items-center gap-3 px-4 py-3 text-sm text-left hover:bg-red-50 text-red-600 transition-colors", onClick: (e) => {
17
+ e.stopPropagation();
18
+ if (confirm("Delete this line item?")) {
19
+ onDelete();
20
+ }
21
+ setShowMenu(false);
22
+ }, children: [_jsx(Trash2, { className: "w-4 h-4" }), _jsx("span", { children: "Delete" })] })] }))] }));
23
+ }
@@ -0,0 +1,33 @@
1
+ type LineItem = {
2
+ currency: string;
3
+ description: string;
4
+ id: string;
5
+ quantity: number;
6
+ taxPercent: number;
7
+ totalPriceTaxExcl: number;
8
+ totalPriceTaxIncl: number;
9
+ unitPriceTaxExcl: number;
10
+ unitPriceTaxIncl: number;
11
+ lineItemTag: any[];
12
+ };
13
+ type EditLineItemInput = {
14
+ id: string;
15
+ currency?: string;
16
+ description?: string;
17
+ quantity?: number;
18
+ taxPercent?: number;
19
+ totalPriceTaxExcl?: number;
20
+ totalPriceTaxIncl?: number;
21
+ unitPriceTaxExcl?: number;
22
+ unitPriceTaxIncl?: number;
23
+ };
24
+ type LineItemMobileModalProps = {
25
+ item?: Partial<LineItem>;
26
+ currency: string;
27
+ onSave: (item: EditLineItemInput) => void;
28
+ onCancel: () => void;
29
+ isNew?: boolean;
30
+ };
31
+ export declare function LineItemMobileModal({ item, currency, onSave, onCancel, isNew, }: LineItemMobileModalProps): import("react/jsx-runtime").JSX.Element;
32
+ export {};
33
+ //# sourceMappingURL=lineItemMobileModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lineItemMobileModal.d.ts","sourceRoot":"","sources":["../../../../editors/invoice/components/lineItemMobileModal.tsx"],"names":[],"mappings":"AAMA,KAAK,QAAQ,GAAG;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,GAAG,EAAE,CAAC;CACpB,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,KAAK,wBAAwB,GAAG;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC1C,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,KAAa,GACd,EAAE,wBAAwB,2CA6M1B"}
@@ -0,0 +1,73 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { X } from "lucide-react";
3
+ import { useState, useMemo, useEffect } from "react";
4
+ import { generateId } from "document-model";
5
+ import { InputField } from "./inputField.js";
6
+ import { NumberForm } from "./numberForm.js";
7
+ export function LineItemMobileModal({ item, currency, onSave, onCancel, isNew = false, }) {
8
+ const [description, setDescription] = useState(item?.description ?? "");
9
+ const [quantity, setQuantity] = useState(item?.quantity ?? 1);
10
+ const [unitPriceTaxExcl, setUnitPriceTaxExcl] = useState(item?.unitPriceTaxExcl ?? 0);
11
+ const [taxPercent, setTaxPercent] = useState(item?.taxPercent ?? 0);
12
+ // Update state when item changes
13
+ useEffect(() => {
14
+ setDescription(item?.description ?? "");
15
+ setQuantity(item?.quantity ?? 1);
16
+ setUnitPriceTaxExcl(item?.unitPriceTaxExcl ?? 0);
17
+ setTaxPercent(item?.taxPercent ?? 0);
18
+ }, [item]);
19
+ // Calculate totals
20
+ const calculatedValues = useMemo(() => {
21
+ const qty = typeof quantity === "string" ? parseFloat(quantity) || 1 : quantity;
22
+ const unitPrice = typeof unitPriceTaxExcl === "string"
23
+ ? parseFloat(unitPriceTaxExcl) || 0
24
+ : unitPriceTaxExcl;
25
+ const tax = typeof taxPercent === "string" ? parseFloat(taxPercent) || 0 : taxPercent;
26
+ const taxRate = tax / 100;
27
+ const unitPriceTaxIncl = unitPrice * (1 + taxRate);
28
+ const totalPriceTaxExcl = qty * unitPrice;
29
+ const totalPriceTaxIncl = qty * unitPriceTaxIncl;
30
+ return {
31
+ quantity: qty,
32
+ unitPriceTaxExcl: unitPrice,
33
+ unitPriceTaxIncl,
34
+ taxPercent: tax,
35
+ totalPriceTaxExcl,
36
+ totalPriceTaxIncl,
37
+ };
38
+ }, [quantity, unitPriceTaxExcl, taxPercent]);
39
+ const handleSave = () => {
40
+ // For edit: use existing ID (if valid), For new or empty ID: generate ID
41
+ const needsNewId = isNew || !item?.id || item.id === '';
42
+ const lineItem = {
43
+ id: needsNewId ? generateId() : item.id,
44
+ currency,
45
+ description,
46
+ quantity: calculatedValues.quantity,
47
+ unitPriceTaxExcl: calculatedValues.unitPriceTaxExcl,
48
+ unitPriceTaxIncl: calculatedValues.unitPriceTaxIncl,
49
+ taxPercent: calculatedValues.taxPercent,
50
+ totalPriceTaxExcl: calculatedValues.totalPriceTaxExcl,
51
+ totalPriceTaxIncl: calculatedValues.totalPriceTaxIncl,
52
+ };
53
+ onSave(lineItem);
54
+ };
55
+ // Prevent body scroll when modal is open
56
+ useEffect(() => {
57
+ document.body.style.overflow = "hidden";
58
+ return () => {
59
+ document.body.style.overflow = "unset";
60
+ };
61
+ }, []);
62
+ return (_jsxs("div", { className: "fixed inset-0 z-50 bg-white flex flex-col", children: [_jsxs("div", { className: "flex items-center justify-between p-4 border-b border-gray-200 bg-white", children: [_jsx("button", { onClick: onCancel, className: "p-2 hover:bg-gray-100 rounded-full transition-colors", "aria-label": "Cancel", children: _jsx(X, { className: "w-5 h-5" }) }), _jsx("h2", { className: "text-lg font-semibold", children: isNew ? "Add Line Item" : "Edit Line Item" }), _jsx("button", { onClick: handleSave, className: "px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors font-medium text-sm", children: "Save" })] }), _jsxs("div", { className: "flex-1 overflow-y-auto p-4 space-y-4", children: [_jsxs("div", { children: [_jsx("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Description *" }), _jsx(InputField, { value: description, handleInputChange: (e) => setDescription(e.target.value), onBlur: () => { }, placeholder: "Enter item description", className: "w-full" })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { children: [_jsx("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Quantity *" }), _jsx(NumberForm, { number: quantity, handleInputChange: (e) => setQuantity(e.target.value), precision: 0, className: "w-full" })] }), _jsxs("div", { children: [_jsx("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Unit Price *" }), _jsx(NumberForm, { number: unitPriceTaxExcl, handleInputChange: (e) => setUnitPriceTaxExcl(e.target.value), precision: 2, className: "w-full" })] })] }), _jsxs("div", { children: [_jsx("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Tax %" }), _jsx(NumberForm, { number: taxPercent, handleInputChange: (e) => setTaxPercent(e.target.value), precision: 2, className: "w-full" })] }), _jsxs("div", { className: "bg-gray-50 rounded-lg p-4 space-y-3", children: [_jsx("h3", { className: "text-sm font-semibold text-gray-900 mb-2", children: "Calculated Totals" }), _jsxs("div", { className: "flex justify-between text-sm", children: [_jsx("span", { className: "text-gray-600", children: "Total (excl. tax):" }), _jsxs("span", { className: "font-medium text-gray-900", children: [currency, " ", calculatedValues.totalPriceTaxExcl.toLocaleString("en-US", {
63
+ minimumFractionDigits: 2,
64
+ maximumFractionDigits: 2,
65
+ })] })] }), _jsxs("div", { className: "flex justify-between text-sm", children: [_jsx("span", { className: "text-gray-600", children: "Tax amount:" }), _jsxs("span", { className: "font-medium text-gray-900", children: [currency, " ", (calculatedValues.totalPriceTaxIncl -
66
+ calculatedValues.totalPriceTaxExcl).toLocaleString("en-US", {
67
+ minimumFractionDigits: 2,
68
+ maximumFractionDigits: 2,
69
+ })] })] }), _jsxs("div", { className: "flex justify-between text-sm pt-2 border-t border-gray-200", children: [_jsx("span", { className: "text-gray-900 font-semibold", children: "Total (incl. tax):" }), _jsxs("span", { className: "font-bold text-gray-900", children: [currency, " ", calculatedValues.totalPriceTaxIncl.toLocaleString("en-US", {
70
+ minimumFractionDigits: 2,
71
+ maximumFractionDigits: 2,
72
+ })] })] })] })] }), _jsxs("div", { className: "border-t border-gray-200 p-4 bg-white flex gap-3", children: [_jsx("button", { onClick: onCancel, className: "flex-1 px-4 py-3 border border-gray-300 rounded-md hover:bg-gray-50 transition-colors font-medium text-gray-700", children: "Cancel" }), _jsx("button", { onClick: handleSave, className: "flex-1 px-4 py-3 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors font-medium", children: "Save Line Item" })] })] }));
73
+ }
@@ -0,0 +1,6 @@
1
+ type LineItemsEmptyStateProps = {
2
+ onAddItem: () => void;
3
+ };
4
+ export declare function LineItemsEmptyState({ onAddItem }: LineItemsEmptyStateProps): import("react/jsx-runtime").JSX.Element;
5
+ export {};
6
+ //# sourceMappingURL=lineItemsEmptyState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lineItemsEmptyState.d.ts","sourceRoot":"","sources":["../../../../editors/invoice/components/lineItemsEmptyState.tsx"],"names":[],"mappings":"AAEA,KAAK,wBAAwB,GAAG;IAC9B,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,EAAE,SAAS,EAAE,EAAE,wBAAwB,2CAoB1E"}
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { FileText } from "lucide-react";
3
+ export function LineItemsEmptyState({ onAddItem }) {
4
+ return (_jsxs("div", { className: "flex flex-col items-center justify-center py-6 px-4 bg-gray-50 rounded-lg border-2 border-dashed border-gray-300", children: [_jsx("div", { className: "w-10 h-10 mb-3 bg-gray-100 rounded-full flex items-center justify-center", children: _jsx(FileText, { className: "w-5 h-5 text-gray-400" }) }), _jsx("h3", { className: "text-base font-semibold text-gray-900 mb-1", children: "No line items yet" }), _jsx("p", { className: "text-sm text-gray-600 mb-4 text-center max-w-xs", children: "Add your first line item to start building your invoice" }), _jsx("button", { onClick: onAddItem, className: "inline-flex items-center px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors font-medium text-sm", children: "Add Your First Line Item" })] }));
5
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../../editors/invoice/editor.tsx"],"names":[],"mappings":"AA6CA,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,KAAK,EAAE,GAAG,kDAi7BxC"}
1
+ {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../../editors/invoice/editor.tsx"],"names":[],"mappings":"AA6CA,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,KAAK,EAAE,GAAG,kDA0mCxC"}
@@ -30,6 +30,8 @@ function isFiatCurrency(currency) {
30
30
  export default function Editor(props) {
31
31
  const [doc, dispatch] = useDocumentById(props.documentId);
32
32
  const state = doc?.state.global;
33
+ // Mobile header menu state
34
+ const [mobileHeaderOpen, setMobileHeaderOpen] = useState(false);
33
35
  if (!state) {
34
36
  console.log("Document state not found from document id", props.documentId);
35
37
  return null;
@@ -363,23 +365,39 @@ export default function Editor(props) {
363
365
  reportPaymentIssue: "Confirm",
364
366
  // Add more labels as needed
365
367
  };
366
- return (_jsxs("div", { className: "editor-container", children: [_jsx(ToastContainer, { position: "bottom-right", autoClose: 5000, hideProgressBar: false, newestOnTop: false, closeOnClick: false, rtl: false, pauseOnFocusLoss: true, draggable: true, pauseOnHover: true, theme: "light" }), _jsxs("div", { className: "flex items-center justify-between gap-4 mb-6", children: [_jsxs("div", { className: "flex items-center gap-4 flex-nowrap", children: [_jsx("h1", { className: "text-3xl font-bold whitespace-nowrap", children: "Invoice" }), _jsx(InputField, { placeholder: "Add invoice number", value: invoiceNoInput, handleInputChange: (e) => setInvoiceNoInput(e.target.value), onBlur: (e) => {
367
- const newValue = e.target.value;
368
- if (newValue !== state.invoiceNo) {
369
- dispatch(actions.editInvoice({ invoiceNo: newValue }));
370
- }
371
- }, input: invoiceNoInput, validation: invoiceValidation }), _jsxs("div", { className: "relative", ref: uploadDropdownRef, children: [_jsxs("button", { onClick: () => setUploadDropdownOpen(!uploadDropdownOpen), className: "inline-flex items-center h-10 px-4 rounded bg-blue-500 hover:bg-blue-600 text-white font-medium transition-colors whitespace-nowrap cursor-pointer", disabled: isPdfLoading, children: [isPdfLoading ? "Processing..." : "Upload File", _jsx("svg", { className: "w-4 h-4 ml-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })] }), uploadDropdownOpen && !isPdfLoading && (_jsx("div", { className: "absolute z-10 mt-1 w-48 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5", children: _jsxs("div", { className: "py-1", role: "menu", "aria-orientation": "vertical", children: [_jsxs("label", { className: "block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 cursor-pointer", children: ["Upload UBL", _jsx("input", { accept: ".xml", className: "hidden", onChange: (e) => {
372
- handleFileUpload(e);
373
- setUploadDropdownOpen(false);
374
- }, type: "file" })] }), _jsx(PDFUploader, { dispatch: dispatch, changeDropdownOpen: setUploadDropdownOpen })] }) }))] }), _jsxs("div", { className: "relative", ref: exportDropdownRef, children: [_jsxs("button", { onClick: () => setExportDropdownOpen(!exportDropdownOpen), className: "inline-flex items-center h-10 px-4 rounded bg-black hover:bg-gray-800 text-white font-medium transition-colors whitespace-nowrap cursor-pointer", children: ["Export File", _jsx("svg", { className: "w-4 h-4 ml-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })] }), exportDropdownOpen && (_jsx("div", { className: "absolute z-10 mt-1 w-48 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5", children: _jsxs("div", { className: "py-1", role: "menu", "aria-orientation": "vertical", children: [_jsx("button", { onClick: () => {
375
- handleExportUBL();
376
- setExportDropdownOpen(false);
377
- }, className: "block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 cursor-pointer", children: "Export UBL" }), _jsx("button", { onClick: () => {
378
- handleExportPDF();
379
- setExportDropdownOpen(false);
380
- }, className: "block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 cursor-pointer", children: "Export PDF" })] }) }))] })] }), _jsx("div", { className: "flex items-center gap-2", children: _jsx(CurrencyForm, { currency: state.currency, handleInputChange: (e) => {
381
- handleCurrencyChange(e.target.value);
382
- }, validation: currencyValidation }) }), _jsx(SelectField, { options: STATUS_OPTIONS, value: state.status, onChange: (value) => handleStatusChange(value) })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "border border-gray-200 rounded-lg p-4", children: [_jsx("h3", { className: "text-lg font-semibold mb-4", children: "Issuer" }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "mb-2", children: [_jsx("label", { className: "block mb-1 text-sm", children: "Issue Date:" }), _jsx(DatePicker, { name: "issueDate", className: String.raw `w-full p-0`, onChange: (e) => {
368
+ return (_jsxs("div", { className: "editor-container", children: [_jsx(ToastContainer, { position: "bottom-right", autoClose: 5000, hideProgressBar: false, newestOnTop: false, closeOnClick: false, rtl: false, pauseOnFocusLoss: true, draggable: true, pauseOnHover: true, theme: "light" }), _jsxs("div", { className: "mb-6", children: [_jsxs("div", { className: "hidden md:flex flex-row items-center justify-between gap-4", children: [_jsxs("div", { className: "flex flex-row items-center gap-4 flex-wrap", children: [_jsx("h1", { className: "text-3xl font-bold whitespace-nowrap", children: "Invoice" }), _jsx(InputField, { placeholder: "Add invoice number", value: invoiceNoInput, handleInputChange: (e) => setInvoiceNoInput(e.target.value), onBlur: (e) => {
369
+ const newValue = e.target.value;
370
+ if (newValue !== state.invoiceNo) {
371
+ dispatch(actions.editInvoice({ invoiceNo: newValue }));
372
+ }
373
+ }, input: invoiceNoInput, validation: invoiceValidation }), _jsxs("div", { className: "relative", ref: uploadDropdownRef, children: [_jsxs("button", { onClick: () => setUploadDropdownOpen(!uploadDropdownOpen), className: "inline-flex items-center h-10 px-4 rounded bg-blue-500 hover:bg-blue-600 text-white font-medium transition-colors whitespace-nowrap cursor-pointer", disabled: isPdfLoading, children: [isPdfLoading ? "Processing..." : "Upload File", _jsx("svg", { className: "w-4 h-4 ml-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })] }), uploadDropdownOpen && !isPdfLoading && (_jsx("div", { className: "absolute z-10 mt-1 w-48 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5", children: _jsxs("div", { className: "py-1", role: "menu", "aria-orientation": "vertical", children: [_jsxs("label", { className: "block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 cursor-pointer", children: ["Upload UBL", _jsx("input", { accept: ".xml", className: "hidden", onChange: (e) => {
374
+ handleFileUpload(e);
375
+ setUploadDropdownOpen(false);
376
+ }, type: "file" })] }), _jsx(PDFUploader, { dispatch: dispatch, changeDropdownOpen: setUploadDropdownOpen })] }) }))] }), _jsxs("div", { className: "relative", ref: exportDropdownRef, children: [_jsxs("button", { onClick: () => setExportDropdownOpen(!exportDropdownOpen), className: "inline-flex items-center h-10 px-4 rounded bg-black hover:bg-gray-800 text-white font-medium transition-colors whitespace-nowrap cursor-pointer", children: ["Export File", _jsx("svg", { className: "w-4 h-4 ml-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })] }), exportDropdownOpen && (_jsx("div", { className: "absolute z-10 mt-1 w-48 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5", children: _jsxs("div", { className: "py-1", role: "menu", "aria-orientation": "vertical", children: [_jsx("button", { onClick: () => {
377
+ handleExportUBL();
378
+ setExportDropdownOpen(false);
379
+ }, className: "block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 cursor-pointer", children: "Export UBL" }), _jsx("button", { onClick: () => {
380
+ handleExportPDF();
381
+ setExportDropdownOpen(false);
382
+ }, className: "block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 cursor-pointer", children: "Export PDF" })] }) }))] })] }), _jsxs("div", { className: "flex flex-row items-center gap-4", children: [_jsx(CurrencyForm, { currency: state.currency, handleInputChange: (e) => {
383
+ handleCurrencyChange(e.target.value);
384
+ }, validation: currencyValidation }), _jsx(SelectField, { options: STATUS_OPTIONS, value: state.status, onChange: (value) => handleStatusChange(value) })] })] }), _jsxs("div", { className: "md:hidden", children: [_jsxs("div", { className: "flex items-center justify-between mb-4", children: [_jsx("h1", { className: "text-2xl font-bold", children: "Invoice" }), _jsx("button", { onClick: () => setMobileHeaderOpen(!mobileHeaderOpen), className: "inline-flex items-center justify-center w-10 h-10 rounded-lg bg-gray-100 hover:bg-gray-200 transition-colors cursor-pointer", "aria-label": "Toggle invoice settings", children: mobileHeaderOpen ? (_jsx("svg", { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M6 18L18 6M6 6l12 12" }) })) : (_jsx("svg", { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4" }) })) })] }), !mobileHeaderOpen && (_jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-600 mb-2", children: [_jsx("span", { className: "font-medium", children: state.invoiceNo || "No invoice #" }), _jsx("span", { children: "\u2022" }), _jsx("span", { children: state.currency }), _jsx("span", { children: "\u2022" }), _jsx("span", { className: "inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-blue-100 text-blue-800", children: state.status })] })), mobileHeaderOpen && (_jsxs("div", { className: "bg-white border border-gray-200 rounded-lg p-4 space-y-4 shadow-sm", children: [_jsxs("div", { children: [_jsx("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Invoice Number" }), _jsx(InputField, { placeholder: "Add invoice number", value: invoiceNoInput, handleInputChange: (e) => setInvoiceNoInput(e.target.value), onBlur: (e) => {
385
+ const newValue = e.target.value;
386
+ if (newValue !== state.invoiceNo) {
387
+ dispatch(actions.editInvoice({ invoiceNo: newValue }));
388
+ }
389
+ }, input: invoiceNoInput, validation: invoiceValidation })] }), _jsxs("div", { children: [_jsx("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Currency" }), _jsx(CurrencyForm, { currency: state.currency, handleInputChange: (e) => {
390
+ handleCurrencyChange(e.target.value);
391
+ }, validation: currencyValidation })] }), _jsxs("div", { children: [_jsx("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Status" }), _jsx(SelectField, { options: STATUS_OPTIONS, value: state.status, onChange: (value) => handleStatusChange(value) })] }), _jsxs("div", { className: "space-y-2 pt-2 border-t border-gray-200", children: [_jsxs("div", { className: "relative", ref: uploadDropdownRef, children: [_jsxs("button", { onClick: () => setUploadDropdownOpen(!uploadDropdownOpen), className: "w-full inline-flex items-center justify-center h-10 px-4 rounded bg-blue-500 hover:bg-blue-600 text-white font-medium transition-colors cursor-pointer", disabled: isPdfLoading, children: [isPdfLoading ? "Processing..." : "Upload File", _jsx("svg", { className: "w-4 h-4 ml-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })] }), uploadDropdownOpen && !isPdfLoading && (_jsx("div", { className: "absolute z-10 mt-1 w-full rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5", children: _jsxs("div", { className: "py-1", role: "menu", children: [_jsxs("label", { className: "block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 cursor-pointer", children: ["Upload UBL", _jsx("input", { accept: ".xml", className: "hidden", onChange: (e) => {
392
+ handleFileUpload(e);
393
+ setUploadDropdownOpen(false);
394
+ }, type: "file" })] }), _jsx(PDFUploader, { dispatch: dispatch, changeDropdownOpen: setUploadDropdownOpen })] }) }))] }), _jsxs("div", { className: "relative", ref: exportDropdownRef, children: [_jsxs("button", { onClick: () => setExportDropdownOpen(!exportDropdownOpen), className: "w-full inline-flex items-center justify-center h-10 px-4 rounded bg-black hover:bg-gray-800 text-white font-medium transition-colors cursor-pointer", children: ["Export File", _jsx("svg", { className: "w-4 h-4 ml-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })] }), exportDropdownOpen && (_jsx("div", { className: "absolute z-10 mt-1 w-full rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5", children: _jsxs("div", { className: "py-1", role: "menu", children: [_jsx("button", { onClick: () => {
395
+ handleExportUBL();
396
+ setExportDropdownOpen(false);
397
+ }, className: "block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 cursor-pointer", children: "Export UBL" }), _jsx("button", { onClick: () => {
398
+ handleExportPDF();
399
+ setExportDropdownOpen(false);
400
+ }, className: "block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 cursor-pointer", children: "Export PDF" })] }) }))] })] })] }))] })] }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-0 lg:gap-4", children: [_jsxs("div", { className: "border-0 lg:border lg:border-gray-200 lg:rounded-lg p-0 lg:p-4", children: [_jsx("h3", { className: "text-lg font-semibold mb-4", children: "Issuer" }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "mb-2", children: [_jsx("label", { className: "block mb-1 text-sm", children: "Issue Date:" }), _jsx(DatePicker, { name: "issueDate", className: String.raw `w-full p-0`, onChange: (e) => {
383
401
  const newDate = e.target.value.split("T")[0];
384
402
  dispatch(actions.editInvoice({
385
403
  dateIssued: newDate,
@@ -389,7 +407,7 @@ export default function Editor(props) {
389
407
  if (newValue !== state.dateDelivered) {
390
408
  dispatch(actions.editInvoice({ dateDelivered: newValue }));
391
409
  }
392
- }, value: state.dateDelivered || "" })] })] }), _jsx(LegalEntityForm, { legalEntity: state.issuer, onChangeInfo: (input) => dispatch(actions.editIssuer(input)), onChangeBank: (input) => dispatch(actions.editIssuerBank(input)), onChangeWallet: (input) => dispatch(actions.editIssuerWallet(input)), basicInfoDisabled: false, bankDisabled: !fiatMode, walletDisabled: fiatMode, currency: state.currency, status: state.status, walletvalidation: walletValidation, mainCountryValidation: mainCountryValidation, bankCountryValidation: bankCountryValidation, ibanvalidation: ibanValidation, bicvalidation: bicValidation, banknamevalidation: bankNameValidation, streetaddressvalidation: streetAddressValidation, cityvalidation: cityValidation, postalcodevalidation: postalCodeValidation, payeremailvalidation: payerEmailValidation, routingNumbervalidation: routingNumberValidation })] }), _jsxs("div", { className: "border border-gray-200 rounded-lg p-4", children: [_jsx("h3", { className: "text-lg font-semibold mb-4", children: "Payer" }), _jsxs("div", { className: "mb-2 w-64", children: [_jsx("label", { className: "block mb-1 text-sm", children: "Due Date:" }), _jsx(DatePicker, { name: "dateDue", className: String.raw `w-full p-0`, onChange: (e) => dispatch(actions.editInvoice({
410
+ }, value: state.dateDelivered || "" })] })] }), _jsx(LegalEntityForm, { legalEntity: state.issuer, onChangeInfo: (input) => dispatch(actions.editIssuer(input)), onChangeBank: (input) => dispatch(actions.editIssuerBank(input)), onChangeWallet: (input) => dispatch(actions.editIssuerWallet(input)), basicInfoDisabled: false, bankDisabled: !fiatMode, walletDisabled: fiatMode, currency: state.currency, status: state.status, walletvalidation: walletValidation, mainCountryValidation: mainCountryValidation, bankCountryValidation: bankCountryValidation, ibanvalidation: ibanValidation, bicvalidation: bicValidation, banknamevalidation: bankNameValidation, streetaddressvalidation: streetAddressValidation, cityvalidation: cityValidation, postalcodevalidation: postalCodeValidation, payeremailvalidation: payerEmailValidation, routingNumbervalidation: routingNumberValidation })] }), _jsxs("div", { className: "border-0 lg:border lg:border-gray-200 lg:rounded-lg p-0 lg:p-4", children: [_jsx("h3", { className: "text-lg font-semibold mb-4", children: "Payer" }), _jsxs("div", { className: "mb-2 w-64", children: [_jsx("label", { className: "block mb-1 text-sm", children: "Due Date:" }), _jsx(DatePicker, { name: "dateDue", className: String.raw `w-full p-0`, onChange: (e) => dispatch(actions.editInvoice({
393
411
  dateDue: e.target.value.split("T")[0],
394
412
  })), value: state.dateDue })] }), _jsx(LegalEntityForm, { bankDisabled: true, legalEntity: state.payer, onChangeInfo: (input) => dispatch(actions.editPayer(input)), currency: state.currency, status: state.status, payeremailvalidation: payerEmailValidation })] })] }), _jsx("div", { className: "mb-8", children: _jsx(LineItemsTable, { currency: state.currency, lineItems: state.lineItems.map((item) => ({
395
413
  ...item,
@@ -397,7 +415,7 @@ export default function Editor(props) {
397
415
  })), onAddItem: (item) => dispatch(actions.addLineItem(item)), onDeleteItem: (input) => dispatch(actions.deleteLineItem(input)), onUpdateCurrency: (input) => {
398
416
  setFiatMode(input.currency !== "USDS");
399
417
  dispatch(actions.editInvoice(input));
400
- }, onUpdateItem: (item) => dispatch(actions.editLineItem(item)), onEditingItemChange: setEditingItemValues, dispatch: dispatch, paymentAccounts: state.invoiceTags || [] }) }), _jsxs("div", { className: "grid grid-cols-2 md:grid-cols-2 gap-4", children: [_jsx("div", { className: "col-span-1", children: _jsx("div", { className: "", children: _jsx(Textarea, { label: "Notes", placeholder: "Add notes", autoExpand: false, rows: 4, multiline: true, value: notes, onBlur: (e) => {
418
+ }, onUpdateItem: (item) => dispatch(actions.editLineItem(item)), onEditingItemChange: setEditingItemValues, dispatch: dispatch, paymentAccounts: state.invoiceTags || [] }) }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [_jsx("div", { className: "col-span-1", children: _jsx("div", { className: "", children: _jsx(Textarea, { label: "Notes", placeholder: "Add notes", autoExpand: false, rows: 4, multiline: true, value: notes, onBlur: (e) => {
401
419
  const newValue = e.target.value;
402
420
  if (newValue !== state.notes) {
403
421
  dispatch(actions.editInvoice({ notes: newValue }));
@@ -6,7 +6,7 @@ import { uploadPdfChunked } from "./uploadPdfChunked.js";
6
6
  import { getCountryCodeFromName } from "./utils/utils.js";
7
7
  let GRAPHQL_URL = 'http://localhost:4001/graphql/invoice';
8
8
  if (!window.document.baseURI.includes('localhost')) {
9
- GRAPHQL_URL = 'https://jetstream.powerhouse.io/api/graphql/invoice';
9
+ GRAPHQL_URL = 'https://switchboard-dev.powerhouse.xyz/graphql/invoice';
10
10
  }
11
11
  export async function loadPDFFile({ file, dispatch, }) {
12
12
  if (!file)
@@ -4,7 +4,7 @@ import { actions } from "../../document-models/invoice/index.js";
4
4
  import { generateId } from "document-model";
5
5
  let GRAPHQL_URL = "http://localhost:4001/graphql/invoice";
6
6
  if (!window.document.baseURI.includes('localhost')) {
7
- GRAPHQL_URL = 'https://jetstream.powerhouse.io/api/graphql/invoice';
7
+ GRAPHQL_URL = 'https://switchboard-dev.powerhouse.xyz/graphql/invoice';
8
8
  }
9
9
  const InvoiceToGnosis = ({ docState, dispatch, }) => {
10
10
  const [isLoading, setIsLoading] = useState(false);
@@ -1 +1 @@
1
- {"version":3,"file":"lineItemTags.d.ts","sourceRoot":"","sources":["../../../../editors/invoice/lineItemTags/lineItemTags.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAKjC,OAAO,EAAW,UAAU,EAAE,MAAM,2CAA2C,CAAC;AAGhF,UAAU,gBAAgB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED,UAAU,sBAAsB;IAC9B,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;IACxB,eAAe,EAAE,UAAU,EAAE,CAAC;CAC/B;AAED,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,OAAO,EACP,QAAQ,EACR,eAAe,GAChB,EAAE,sBAAsB,2CA2LxB"}
1
+ {"version":3,"file":"lineItemTags.d.ts","sourceRoot":"","sources":["../../../../editors/invoice/lineItemTags/lineItemTags.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAY,MAAM,OAAO,CAAC;AAK3C,OAAO,EAAW,UAAU,EAAE,MAAM,2CAA2C,CAAC;AAKhF,UAAU,gBAAgB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED,UAAU,sBAAsB;IAC9B,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;IACxB,eAAe,EAAE,UAAU,EAAE,CAAC;CAC/B;AAED,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,OAAO,EACP,QAAQ,EACR,eAAe,GAChB,EAAE,sBAAsB,2CA0PxB"}
@@ -1,11 +1,16 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
2
3
  import { X, Tag } from "lucide-react";
3
4
  import { Button } from "@powerhousedao/design-system";
4
5
  import { Select, DatePicker } from "@powerhousedao/document-engineering/ui";
5
6
  import { expenseAccountOptions, paymentAccountOptions } from "./tagMapping.js";
6
7
  import { actions } from "../../../document-models/invoice/index.js";
7
8
  import { InputField } from "../components/inputField.js";
9
+ import { TagCard } from "./tagCard.js";
10
+ import { TagMobileModal } from "./tagMobileModal.js";
8
11
  export function LineItemTagsTable({ lineItems, onClose, dispatch, paymentAccounts, }) {
12
+ const [mobileEditItem, setMobileEditItem] = useState(null);
13
+ const [showMobileModal, setShowMobileModal] = useState(false);
9
14
  const handleReset = () => {
10
15
  // Resetting all tags to empty values
11
16
  lineItems.forEach((item) => {
@@ -27,11 +32,19 @@ export function LineItemTagsTable({ lineItems, onClose, dispatch, paymentAccount
27
32
  }));
28
33
  });
29
34
  };
35
+ const handleMobileEdit = (item) => {
36
+ setMobileEditItem(item);
37
+ setShowMobileModal(true);
38
+ };
39
+ const handleCloseMobileModal = () => {
40
+ setShowMobileModal(false);
41
+ setMobileEditItem(null);
42
+ };
30
43
  // Get the last payment account value from the paymentAccounts to display in the payment account select
31
44
  const selectedPaymentAccountValue = paymentAccounts && paymentAccounts.length > 0
32
45
  ? (paymentAccounts[paymentAccounts.length - 1].value ?? "")
33
46
  : "";
34
- return (_jsxs("div", { className: "w-full", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-gray-200 p-6 bg-white z-10", children: [_jsxs("span", { className: "flex items-center gap-2", children: [_jsx("h2", { className: "text-2xl font-semibold text-gray-900", children: "Assign Tags " }), _jsx(Tag, { style: { width: 28, height: 28, color: "white", fill: "#475264" } })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Button, { color: "light", size: "medium", onClick: handleReset, children: ["Reset", " "] }), _jsx("button", { onClick: onClose, className: "rounded-full p-2 hover:bg-gray-100", children: _jsx(X, { size: 24, className: "text-gray-500" }) })] })] }), _jsx("div", { className: "overflow-x-auto rounded-lg border border-gray-200", children: _jsxs("table", { className: "w-full border-collapse bg-white", children: [_jsx("thead", { className: "bg-gray-50 z-10", children: _jsxs("tr", { children: [_jsx("th", { className: "border-b border-gray-200 p-3 text-left", children: "Item" }), _jsx("th", { className: "border-b border-gray-200 p-3 text-left", children: "Period" }), _jsx("th", { className: "border-b border-gray-200 p-3 text-left", children: "Xero Expense Account" }), _jsx("th", { className: "border-b border-gray-200 p-3 text-right", children: "Total" })] }) }), _jsx("tbody", { children: lineItems.map((item) => (_jsxs("tr", { className: "hover:bg-gray-50", children: [_jsx("td", { className: "border-b border-gray-200 p-3", children: _jsx(InputField, { value: item.item, handleInputChange: (e) => { }, onBlur: (e) => {
47
+ return (_jsxs("div", { className: "w-full", children: [showMobileModal && mobileEditItem && (_jsx(TagMobileModal, { item: mobileEditItem, onClose: handleCloseMobileModal, dispatch: dispatch })), _jsxs("div", { className: "flex items-center justify-between border-b border-gray-200 p-6 bg-white z-10", children: [_jsxs("span", { className: "flex items-center gap-2", children: [_jsx("h2", { className: "text-2xl font-semibold text-gray-900", children: "Assign Tags " }), _jsx(Tag, { style: { width: 28, height: 28, color: "white", fill: "#475264" } })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Button, { color: "light", size: "medium", onClick: handleReset, children: ["Reset", " "] }), _jsx("button", { onClick: onClose, className: "rounded-full p-2 hover:bg-gray-100", children: _jsx(X, { size: 24, className: "text-gray-500" }) })] })] }), _jsx("div", { className: "hidden md:block overflow-x-auto rounded-lg border border-gray-200", children: _jsxs("table", { className: "w-full border-collapse bg-white", children: [_jsx("thead", { className: "bg-gray-50 z-10", children: _jsxs("tr", { children: [_jsx("th", { className: "border-b border-gray-200 p-3 text-left", children: "Item" }), _jsx("th", { className: "border-b border-gray-200 p-3 text-left", children: "Period" }), _jsx("th", { className: "border-b border-gray-200 p-3 text-left", children: "Xero Expense Account" }), _jsx("th", { className: "border-b border-gray-200 p-3 text-right", children: "Total" })] }) }), _jsx("tbody", { children: lineItems.map((item) => (_jsxs("tr", { className: "hover:bg-gray-50", children: [_jsx("td", { className: "border-b border-gray-200 p-3", children: _jsx(InputField, { value: item.item, handleInputChange: (e) => { }, onBlur: (e) => {
35
48
  dispatch(actions.editLineItem({
36
49
  id: item.id,
37
50
  description: e.target.value,
@@ -58,7 +71,16 @@ export function LineItemTagsTable({ lineItems, onClose, dispatch, paymentAccount
58
71
  value: value,
59
72
  label: expenseAccountOptions.find((option) => option.value === value)?.label,
60
73
  }));
61
- } }) }), _jsx("td", { className: "border-b border-gray-200 p-3 text-right font-medium", children: item.total })] }, item.id))) })] }) }), _jsx("div", { className: "border-t border-gray-200 p-6", children: _jsxs("div", { className: "flex items-center justify-end gap-4", children: [_jsx("label", { className: "text-lg font-medium text-gray-900", children: "Payment Account" }), _jsx(Select, { options: paymentAccountOptions, value: paymentAccountOptions.find((option) => option.value === selectedPaymentAccountValue)?.value ?? "", placeholder: "Select Payment Account", searchable: true, onChange: (value) => {
74
+ } }) }), _jsx("td", { className: "border-b border-gray-200 p-3 text-right font-medium", children: item.total })] }, item.id))) })] }) }), _jsx("div", { className: "md:hidden p-4 space-y-3", children: lineItems.map((item) => (_jsx(TagCard, { item: item, onEdit: () => handleMobileEdit(item) }, item.id))) }), _jsx("div", { className: "hidden md:block border-t border-gray-200 p-6", children: _jsxs("div", { className: "flex items-center justify-end gap-4", children: [_jsx("label", { className: "text-lg font-medium text-gray-900", children: "Payment Account" }), _jsx(Select, { options: paymentAccountOptions, value: paymentAccountOptions.find((option) => option.value === selectedPaymentAccountValue)?.value ?? "", placeholder: "Select Payment Account", searchable: true, onChange: (value) => {
75
+ const selectedLabel = paymentAccountOptions.find((option) => option.value === value)
76
+ ?.label || "";
77
+ const cleanLabel = selectedLabel.replace(/\s+\w+$/, "").trim();
78
+ dispatch(actions.setInvoiceTag({
79
+ dimension: "xero-payment-account",
80
+ value: value,
81
+ label: cleanLabel,
82
+ }));
83
+ }, style: { width: "230px" } })] }) }), _jsx("div", { className: "md:hidden p-4 border-t border-gray-200", children: _jsxs("div", { className: "space-y-2", children: [_jsx("label", { className: "block text-sm font-medium text-gray-700", children: "Payment Account" }), _jsx(Select, { options: paymentAccountOptions, value: paymentAccountOptions.find((option) => option.value === selectedPaymentAccountValue)?.value ?? "", placeholder: "Select Payment Account", searchable: true, onChange: (value) => {
62
84
  const selectedLabel = paymentAccountOptions.find((option) => option.value === value)
63
85
  ?.label || "";
64
86
  const cleanLabel = selectedLabel.replace(/\s+\w+$/, "").trim();
@@ -67,5 +89,5 @@ export function LineItemTagsTable({ lineItems, onClose, dispatch, paymentAccount
67
89
  value: value,
68
90
  label: cleanLabel,
69
91
  }));
70
- }, style: { width: "230px" } })] }) })] }));
92
+ } })] }) })] }));
71
93
  }
@@ -0,0 +1,15 @@
1
+ type TagAssignmentRow = {
2
+ id: string;
3
+ item: string;
4
+ period: string;
5
+ expenseAccount: string;
6
+ total: string;
7
+ lineItemTag: any[];
8
+ };
9
+ type TagCardProps = {
10
+ item: TagAssignmentRow;
11
+ onEdit: () => void;
12
+ };
13
+ export declare function TagCard({ item, onEdit }: TagCardProps): import("react/jsx-runtime").JSX.Element;
14
+ export {};
15
+ //# sourceMappingURL=tagCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tagCard.d.ts","sourceRoot":"","sources":["../../../../editors/invoice/lineItemTags/tagCard.tsx"],"names":[],"mappings":"AAGA,KAAK,gBAAgB,GAAG;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,GAAG,EAAE,CAAC;CACpB,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE,gBAAgB,CAAC;IACvB,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB,CAAC;AAEF,wBAAgB,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,YAAY,2CAoErD"}
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { MoreVertical, Edit } from "lucide-react";
3
+ import { useState } from "react";
4
+ export function TagCard({ item, onEdit }) {
5
+ const [isExpanded, setIsExpanded] = useState(false);
6
+ // Get tag values
7
+ const periodTag = item.lineItemTag.find((tag) => tag.dimension === "accounting-period");
8
+ const expenseTag = item.lineItemTag.find((tag) => tag.dimension === "xero-expense-account");
9
+ return (_jsxs("div", { className: "bg-white border border-gray-200 rounded-lg mb-3 overflow-hidden", children: [_jsxs("div", { className: "p-4 cursor-pointer", onClick: () => setIsExpanded(!isExpanded), children: [_jsxs("div", { className: "flex items-start justify-between mb-2", children: [_jsx("div", { className: "flex-1", children: _jsx("h5", { className: "font-medium text-gray-900 text-sm", children: item.item || "Untitled Item" }) }), _jsx("button", { className: "p-1 hover:bg-gray-100 rounded", onClick: (e) => {
10
+ e.stopPropagation();
11
+ onEdit();
12
+ }, children: _jsx(MoreVertical, { className: "w-5 h-5 text-gray-500" }) })] }), _jsxs("div", { className: "flex items-center justify-between text-sm", children: [_jsx("div", { className: "text-gray-600", children: periodTag?.label || "No period set" }), _jsx("div", { className: "font-semibold text-gray-900", children: item.total })] }), isExpanded && (_jsx("div", { className: "mt-3 pt-3 border-t border-gray-100 space-y-2 text-sm", children: _jsxs("div", { className: "flex justify-between", children: [_jsx("span", { className: "text-gray-600", children: "Expense Account:" }), _jsx("span", { className: "text-gray-900 text-right max-w-[60%]", children: expenseTag?.label || "Not set" })] }) }))] }), _jsx("div", { className: "border-t border-gray-200 bg-gray-50", children: _jsxs("button", { className: "w-full flex items-center justify-center gap-3 px-4 py-3 text-sm hover:bg-gray-100 transition-colors", onClick: onEdit, children: [_jsx(Edit, { className: "w-4 h-4 text-blue-600" }), _jsx("span", { children: "Edit Tags" })] }) })] }));
13
+ }
@@ -0,0 +1,18 @@
1
+ import { Dispatch } from "react";
2
+ import { InvoiceTag } from "../../../document-models/invoice/index.js";
3
+ type TagAssignmentRow = {
4
+ id: string;
5
+ item: string;
6
+ period: string;
7
+ expenseAccount: string;
8
+ total: string;
9
+ lineItemTag: InvoiceTag[];
10
+ };
11
+ type TagMobileModalProps = {
12
+ item: TagAssignmentRow;
13
+ onClose: () => void;
14
+ dispatch: Dispatch<any>;
15
+ };
16
+ export declare function TagMobileModal({ item, onClose, dispatch, }: TagMobileModalProps): import("react/jsx-runtime").JSX.Element;
17
+ export {};
18
+ //# sourceMappingURL=tagMobileModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tagMobileModal.d.ts","sourceRoot":"","sources":["../../../../editors/invoice/lineItemTags/tagMobileModal.tsx"],"names":[],"mappings":"AACA,OAAO,EAAuB,QAAQ,EAAE,MAAM,OAAO,CAAC;AAOtD,OAAO,EAAW,UAAU,EAAE,MAAM,2CAA2C,CAAC;AAEhF,KAAK,gBAAgB,GAAG;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;CACzB,CAAC;AAEF,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,OAAO,EACP,QAAQ,GACT,EAAE,mBAAmB,2CAkLrB"}
@@ -0,0 +1,71 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { X } from "lucide-react";
3
+ import { useState, useEffect } from "react";
4
+ import { InputField } from "../components/inputField.js";
5
+ import { Select, DatePicker } from "@powerhousedao/document-engineering/ui";
6
+ import { expenseAccountOptions, } from "./tagMapping.js";
7
+ import { actions } from "../../../document-models/invoice/index.js";
8
+ export function TagMobileModal({ item, onClose, dispatch, }) {
9
+ const [description, setDescription] = useState(item.item);
10
+ // Get current tag values
11
+ const periodTag = item.lineItemTag.find((tag) => tag.dimension === "accounting-period");
12
+ const expenseTag = item.lineItemTag.find((tag) => tag.dimension === "xero-expense-account");
13
+ const [periodValue, setPeriodValue] = useState(periodTag?.label || "");
14
+ const [periodStoredValue, setPeriodStoredValue] = useState(periodTag?.value || "");
15
+ const [expenseValue, setExpenseValue] = useState(expenseTag?.value || "");
16
+ const [expenseLabel, setExpenseLabel] = useState(expenseTag?.label || "");
17
+ // Prevent body scroll when modal is open
18
+ useEffect(() => {
19
+ document.body.style.overflow = "hidden";
20
+ return () => {
21
+ document.body.style.overflow = "unset";
22
+ };
23
+ }, []);
24
+ const handleSave = () => {
25
+ // Save description if changed
26
+ if (description !== item.item) {
27
+ dispatch(actions.editLineItem({
28
+ id: item.id,
29
+ description: description,
30
+ }));
31
+ }
32
+ // Save period if changed
33
+ if (periodStoredValue !== periodTag?.value) {
34
+ dispatch(actions.setLineItemTag({
35
+ lineItemId: item.id,
36
+ dimension: "accounting-period",
37
+ value: periodStoredValue,
38
+ label: periodValue,
39
+ }));
40
+ }
41
+ // Save expense account if changed
42
+ if (expenseValue !== expenseTag?.value) {
43
+ dispatch(actions.setLineItemTag({
44
+ lineItemId: item.id,
45
+ dimension: "xero-expense-account",
46
+ value: expenseValue,
47
+ label: expenseLabel,
48
+ }));
49
+ }
50
+ onClose();
51
+ };
52
+ return (_jsxs("div", { className: "fixed inset-0 z-50 bg-white flex flex-col", children: [_jsxs("div", { className: "flex items-center justify-between p-4 border-b border-gray-200 bg-white", children: [_jsx("button", { onClick: onClose, className: "p-2 hover:bg-gray-100 rounded-full transition-colors", "aria-label": "Cancel", children: _jsx(X, { className: "w-5 h-5" }) }), _jsx("h2", { className: "text-lg font-semibold", children: "Edit Tags" }), _jsx("button", { onClick: handleSave, className: "px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors font-medium text-sm", children: "Save" })] }), _jsxs("div", { className: "flex-1 overflow-y-auto p-4 space-y-4", children: [_jsxs("div", { children: [_jsx("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Item Description" }), _jsx(InputField, { value: description, handleInputChange: (e) => setDescription(e.target.value), onBlur: () => { }, placeholder: "Enter item description", className: "w-full" })] }), _jsxs("div", { children: [_jsx("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Accounting Period" }), _jsx(DatePicker, { name: "period", dateFormat: "YYYY-MM", autoClose: true, placeholder: "Select Period", value: periodValue, onChange: (e) => {
53
+ const newValue = new Date(e.target.value)
54
+ .toLocaleDateString("en-US", {
55
+ year: "numeric",
56
+ month: "numeric",
57
+ })
58
+ .split("/")
59
+ .reverse()
60
+ .join("/");
61
+ const newLabel = new Date(e.target.value).toLocaleDateString("en-US", {
62
+ month: "long",
63
+ year: "numeric",
64
+ });
65
+ setPeriodValue(newLabel);
66
+ setPeriodStoredValue(newValue);
67
+ } })] }), _jsxs("div", { children: [_jsx("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Xero Expense Account" }), _jsx(Select, { options: expenseAccountOptions, value: expenseValue, placeholder: "Select Expense Account", searchable: true, onChange: (value) => {
68
+ setExpenseValue(value);
69
+ setExpenseLabel(expenseAccountOptions.find((option) => option.value === value)?.label || "");
70
+ } })] }), _jsx("div", { className: "bg-gray-50 rounded-lg p-4", children: _jsxs("div", { className: "flex justify-between items-center", children: [_jsx("span", { className: "text-sm text-gray-600", children: "Total:" }), _jsx("span", { className: "text-lg font-bold text-gray-900", children: item.total })] }) })] }), _jsxs("div", { className: "border-t border-gray-200 p-4 bg-white flex gap-3", children: [_jsx("button", { onClick: onClose, className: "flex-1 px-4 py-3 border border-gray-300 rounded-md hover:bg-gray-50 transition-colors font-medium text-gray-700", children: "Cancel" }), _jsx("button", { onClick: handleSave, className: "flex-1 px-4 py-3 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors font-medium", children: "Save Tags" })] })] }));
71
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"lineItems.d.ts","sourceRoot":"","sources":["../../../editors/invoice/lineItems.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,UAAU,EAChB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAKL,KAAK,QAAQ,EAEd,MAAM,OAAO,CAAC;AAYf,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKlD;AAED,KAAK,QAAQ,GAAG;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B,CAAC;AAobF,KAAK,mBAAmB,GAAG;IACzB,QAAQ,CAAC,SAAS,EAAE,QAAQ,EAAE,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC7C,QAAQ,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAChD,QAAQ,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC5D,QAAQ,CAAC,gBAAgB,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC7D,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAC7B,MAAM,EAAE;QACN,EAAE,EAAE,MAAM,CAAC;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,gBAAgB,EAAE,MAAM,CAAC;QACzB,gBAAgB,EAAE,MAAM,CAAC;KAC1B,GAAG,IAAI,KACL,IAAI,CAAC;IACV,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;IACjC,QAAQ,CAAC,eAAe,EAAE,UAAU,EAAE,CAAC;CACxC,CAAC;AAEF,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,QAAQ,EACR,eAAe,GAChB,EAAE,mBAAmB,2CAsSrB"}
1
+ {"version":3,"file":"lineItems.d.ts","sourceRoot":"","sources":["../../../editors/invoice/lineItems.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,UAAU,EAChB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAKL,KAAK,QAAQ,EAEd,MAAM,OAAO,CAAC;AAef,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKlD;AAED,KAAK,QAAQ,GAAG;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B,CAAC;AAobF,KAAK,mBAAmB,GAAG;IACzB,QAAQ,CAAC,SAAS,EAAE,QAAQ,EAAE,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC7C,QAAQ,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAChD,QAAQ,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC5D,QAAQ,CAAC,gBAAgB,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC7D,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAC7B,MAAM,EAAE;QACN,EAAE,EAAE,MAAM,CAAC;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,gBAAgB,EAAE,MAAM,CAAC;QACzB,gBAAgB,EAAE,MAAM,CAAC;KAC1B,GAAG,IAAI,KACL,IAAI,CAAC;IACV,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;IACjC,QAAQ,CAAC,eAAe,EAAE,UAAU,EAAE,CAAC;CACxC,CAAC;AAEF,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,QAAQ,EACR,eAAe,GAChB,EAAE,mBAAmB,2CA8ZrB"}
@@ -6,6 +6,9 @@ import { Tag } from "lucide-react";
6
6
  import { NumberForm } from "./components/numberForm.js";
7
7
  import { InputField } from "./components/inputField.js";
8
8
  import { LineItemTagsTable } from "./lineItemTags/lineItemTags.js";
9
+ import { LineItemCard } from "./components/lineItemCard.js";
10
+ import { LineItemMobileModal } from "./components/lineItemMobileModal.js";
11
+ import { LineItemsEmptyState } from "./components/lineItemsEmptyState.js";
9
12
  // Helper function to get precision based on currency
10
13
  function getCurrencyPrecision(currency) {
11
14
  return currency === "USDS" || currency === "DAI" ? 6 : 2;
@@ -286,6 +289,8 @@ export function LineItemsTable({ lineItems, currency, onAddItem, onUpdateItem, o
286
289
  const [editingId, setEditingId] = useState(null);
287
290
  const [isAddingNew, setIsAddingNew] = useState(false);
288
291
  const [showTagTable, setShowTagTable] = useState(false);
292
+ const [mobileEditItem, setMobileEditItem] = useState(null);
293
+ const [showMobileModal, setShowMobileModal] = useState(false);
289
294
  const containerRef = useRef(null);
290
295
  const tableContainerRef = useRef(null);
291
296
  const tableRef = useRef(null);
@@ -346,53 +351,84 @@ export function LineItemsTable({ lineItems, currency, onAddItem, onUpdateItem, o
346
351
  if (showTagTable) {
347
352
  return (_jsx(LineItemTagsTable, { lineItems: tagAssignmentRows, onClose: () => setShowTagTable(false), dispatch: dispatch, paymentAccounts: paymentAccounts }));
348
353
  }
349
- return (_jsx("div", { ref: containerRef, className: "relative w-full", children: _jsxs("div", { className: "mt-4", children: [_jsxs("div", { className: "mb-4 flex items-center justify-between", children: [_jsx("div", { className: "flex items-center gap-4", children: _jsx("h4", { className: "text-xl font-semibold text-gray-900", children: "Line Items" }) }), _jsx(RWAButton, { className: "mb-2", disabled: isAddingNew, onClick: handleAddClick, children: "Add Line Item" })] }), _jsx("div", { ref: tableContainerRef, className: "overflow-x-auto rounded-lg border border-gray-200", children: _jsxs("table", { ref: tableRef, className: "w-full table-fixed border-collapse bg-white", children: [_jsxs("colgroup", { children: [_jsx("col", { style: { width: "30%" } }), _jsx("col", { style: { width: "10%" } }), _jsx("col", { style: { width: "12%" } }), _jsx("col", { style: { width: "8%" } }), _jsx("col", {}), _jsx("col", {}), _jsx("col", {})] }), _jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "border-b border-gray-200 p-3 text-left", children: "Description" }), _jsx("th", { className: "border-b border-gray-200 p-3 text-right", children: "Quantity" }), _jsx("th", { className: "border-b border-gray-200 p-3 text-right", children: "Unit Price (excl. tax)" }), _jsx("th", { className: "border-b border-gray-200 p-3 text-right", children: "Tax %" }), _jsx("th", { className: "border-b border-gray-200 p-3 text-right", children: "Total (excl. tax)" }), _jsx("th", { className: "border-b border-gray-200 p-3 text-right", children: "Total (incl. tax)" }), _jsx("th", { className: "border-b border-gray-200 p-3 text-center", children: _jsxs("span", { className: "flex items-center justify-center gap-2", children: [_jsx("span", { className: "text-sm", children: "Actions" }), _jsx(Tag, { onClick: () => setShowTagTable(true), style: {
350
- cursor: "pointer",
351
- width: 28,
352
- height: 28,
353
- color: "white",
354
- fill: "#475264",
355
- } })] }) })] }) }), _jsxs("tbody", { children: [lineItems.map((item) => editingId === item.id ? (_jsx(EditableLineItem, { currency: currency, item: item, onCancel: () => setEditingId(null), onSave: (updatedItem) => {
356
- try {
357
- onUpdateItem(updatedItem);
358
- setEditingId(null);
359
- }
360
- catch (error) {
361
- console.error(error);
362
- if (error?.message?.includes("Invalid action input:")) {
363
- try {
364
- const zodError = JSON.parse(error.message.split("Invalid action input: ")[1]);
365
- if (Array.isArray(zodError) &&
366
- zodError.length > 0) {
367
- const firstError = zodError[0];
368
- const errorJSX = (_jsxs("div", { children: [_jsx("p", { className: "font-semibold", children: "Failed to update line item" }), _jsxs("p", { children: [firstError.message, ": "] }), zodError.map((err, index) => (_jsx("ul", { children: _jsxs("li", { className: "text-red-500 font-semibold", children: ["- ", err.path.join(".")] }) }, index)))] }));
369
- toast(errorJSX, {
354
+ // Calculate totals for mobile footer
355
+ const totalPriceTaxExcl = lineItems.reduce((sum, item) => sum + item.totalPriceTaxExcl, 0);
356
+ const totalPriceTaxIncl = lineItems.reduce((sum, item) => sum + item.totalPriceTaxIncl, 0);
357
+ return (_jsxs("div", { ref: containerRef, className: "relative w-full", children: [showMobileModal && (_jsx(LineItemMobileModal, { item: mobileEditItem || {}, currency: currency, isNew: !mobileEditItem?.id || mobileEditItem.id === '', onSave: (item) => {
358
+ try {
359
+ // If editing an item with empty ID, delete it first, then add new one
360
+ if (mobileEditItem?.id === '') {
361
+ onDeleteItem({ id: '' });
362
+ onAddItem(item);
363
+ }
364
+ else if (mobileEditItem?.id) {
365
+ onUpdateItem(item);
366
+ }
367
+ else {
368
+ onAddItem(item);
369
+ }
370
+ setShowMobileModal(false);
371
+ setMobileEditItem(null);
372
+ }
373
+ catch (error) {
374
+ toast(error.message || "Failed to save line item", { type: "error" });
375
+ }
376
+ }, onCancel: () => {
377
+ setShowMobileModal(false);
378
+ setMobileEditItem(null);
379
+ } }, mobileEditItem?.id || 'new')), _jsxs("div", { className: "mt-4", children: [_jsxs("div", { className: "mb-4 flex items-center justify-between", children: [_jsx("h4", { className: "text-xl font-semibold text-gray-900", children: "Line Items" }), _jsxs("div", { className: "hidden md:flex items-center gap-3", children: [_jsxs("button", { onClick: () => setShowTagTable(true), className: "flex items-center gap-2 px-4 py-2 border border-gray-300 rounded-md hover:bg-gray-50 transition-colors text-sm font-medium text-gray-700", title: "Manage Tags for All Line Items", children: [_jsx(Tag, { className: "w-4 h-4" }), _jsx("span", { className: "hidden md:inline", children: "Manage Tags" })] }), _jsx(RWAButton, { className: "hidden md:block", disabled: isAddingNew, onClick: handleAddClick, children: "Add Line Item" })] })] }), lineItems.length === 0 && !isAddingNew && (_jsx("div", { className: "md:hidden", children: _jsx(LineItemsEmptyState, { onAddItem: () => {
380
+ setMobileEditItem({});
381
+ setShowMobileModal(true);
382
+ } }) })), lineItems.length === 0 && !isAddingNew && (_jsx("div", { className: "hidden md:block", children: _jsx(LineItemsEmptyState, { onAddItem: handleAddClick }) })), lineItems.length > 0 && (_jsxs("div", { className: "md:hidden space-y-3", children: [_jsxs("div", { className: "flex gap-2 mb-4", children: [_jsxs("button", { onClick: () => setShowTagTable(true), className: "flex items-center justify-center gap-2 px-4 py-3 border border-gray-300 rounded-md hover:bg-gray-50 transition-colors font-medium text-gray-700", title: "Manage Tags for All Line Items", children: [_jsx(Tag, { className: "w-4 h-4" }), _jsx("span", { children: "Tags" })] }), _jsx("button", { onClick: () => {
383
+ setMobileEditItem({});
384
+ setShowMobileModal(true);
385
+ }, className: "flex-1 py-3 px-4 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors font-medium", children: "Add Line Item" })] }), lineItems.map((item) => (_jsx(LineItemCard, { item: item, currency: currency, onEdit: () => {
386
+ setMobileEditItem(item);
387
+ setShowMobileModal(true);
388
+ }, onDelete: () => {
389
+ const input = { id: item.id };
390
+ onDeleteItem(input);
391
+ } }, item.id)))] })), (lineItems.length > 0 || isAddingNew) && (_jsx("div", { ref: tableContainerRef, className: "hidden md:block overflow-x-auto rounded-lg border border-gray-200", children: _jsxs("table", { ref: tableRef, className: "w-full table-fixed border-collapse bg-white", children: [_jsxs("colgroup", { children: [_jsx("col", { style: { width: "30%" } }), _jsx("col", { style: { width: "10%" } }), _jsx("col", { style: { width: "12%" } }), _jsx("col", { style: { width: "8%" } }), _jsx("col", {}), _jsx("col", {}), _jsx("col", {})] }), _jsx("thead", { children: _jsxs("tr", { className: "bg-gray-50", children: [_jsx("th", { className: "border-b border-gray-200 p-3 text-left", children: "Description" }), _jsx("th", { className: "border-b border-gray-200 p-3 text-right", children: "Quantity" }), _jsx("th", { className: "border-b border-gray-200 p-3 text-right", children: "Unit Price (excl. tax)" }), _jsx("th", { className: "border-b border-gray-200 p-3 text-right", children: "Tax %" }), _jsx("th", { className: "border-b border-gray-200 p-3 text-right", children: "Total (excl. tax)" }), _jsx("th", { className: "border-b border-gray-200 p-3 text-right", children: "Total (incl. tax)" }), _jsx("th", { className: "border-b border-gray-200 p-3 text-center", children: "Actions" })] }) }), _jsxs("tbody", { children: [lineItems.map((item) => editingId === item.id ? (_jsx(EditableLineItem, { currency: currency, item: item, onCancel: () => setEditingId(null), onSave: (updatedItem) => {
392
+ try {
393
+ onUpdateItem(updatedItem);
394
+ setEditingId(null);
395
+ }
396
+ catch (error) {
397
+ console.error(error);
398
+ if (error?.message?.includes("Invalid action input:")) {
399
+ try {
400
+ const zodError = JSON.parse(error.message.split("Invalid action input: ")[1]);
401
+ if (Array.isArray(zodError) &&
402
+ zodError.length > 0) {
403
+ const firstError = zodError[0];
404
+ const errorJSX = (_jsxs("div", { children: [_jsx("p", { className: "font-semibold", children: "Failed to update line item" }), _jsxs("p", { children: [firstError.message, ": "] }), zodError.map((err, index) => (_jsx("ul", { children: _jsxs("li", { className: "text-red-500 font-semibold", children: ["- ", err.path.join(".")] }) }, index)))] }));
405
+ toast(errorJSX, {
406
+ type: "error",
407
+ });
408
+ return;
409
+ }
410
+ }
411
+ catch (parseError) {
412
+ console.error("Failed to parse Zod error:", parseError);
413
+ toast("Invalid input data", {
370
414
  type: "error",
371
415
  });
372
416
  return;
373
417
  }
374
418
  }
375
- catch (parseError) {
376
- console.error("Failed to parse Zod error:", parseError);
377
- toast("Invalid input data", {
419
+ else if (error?.message) {
420
+ toast(error.message, {
378
421
  type: "error",
379
422
  });
380
423
  return;
381
424
  }
382
- }
383
- else if (error?.message) {
384
- toast(error.message, {
425
+ toast("Failed to update line item", {
385
426
  type: "error",
386
427
  });
387
- return;
388
428
  }
389
- toast("Failed to update line item", {
390
- type: "error",
391
- });
392
- }
393
- }, onEditingItemChange: onEditingItemChange }, item.id)) : (_jsxs("tr", { className: "hover:bg-gray-50 table-row", children: [_jsx("td", { className: "border-b border-gray-200 p-3 table-cell", children: item.description }), _jsx("td", { className: "border-b border-gray-200 p-3 text-right table-cell", children: item.quantity % 1 === 0
394
- ? item.quantity.toString()
395
- : item.quantity.toFixed(2) }), _jsx("td", { className: "border-b border-gray-200 p-3 text-right table-cell", children: formatNumber(item.unitPriceTaxExcl) }), _jsxs("td", { className: "border-b border-gray-200 p-3 text-right table-cell", children: [typeof item.taxPercent === "number"
396
- ? Math.round(item.taxPercent)
397
- : 0, "%"] }), _jsx("td", { className: "border-b border-gray-200 p-3 text-right font-medium table-cell", children: formatNumber(item.totalPriceTaxExcl) }), _jsx("td", { className: "border-b border-gray-200 p-3 text-right font-medium table-cell", children: formatNumber(item.totalPriceTaxIncl) }), _jsx("td", { className: "border-b border-gray-200 p-3 table-cell", children: _jsxs("div", { className: "flex justify-center space-x-2", children: [_jsx("button", { className: "rounded bg-blue-500 px-3 py-1 text-white hover:bg-blue-200", onClick: () => setEditingId(item.id), children: "Edit" }), _jsx("button", { className: "rounded bg-red-600 px-3 py-1 text-white hover:bg-red-700", onClick: () => onDeleteItem({ id: item.id }), children: "Delete" })] }) })] }, item.id))), isAddingNew ? (_jsx(EditableLineItem, { currency: currency, item: {}, onCancel: handleCancelNewItem, onSave: handleSaveNewItem, onEditingItemChange: onEditingItemChange })) : null] })] }) })] }) }));
429
+ }, onEditingItemChange: onEditingItemChange }, item.id)) : (_jsxs("tr", { className: "hover:bg-gray-50 table-row", children: [_jsx("td", { className: "border-b border-gray-200 p-3 table-cell", children: item.description }), _jsx("td", { className: "border-b border-gray-200 p-3 text-right table-cell", children: item.quantity % 1 === 0
430
+ ? item.quantity.toString()
431
+ : item.quantity.toFixed(2) }), _jsx("td", { className: "border-b border-gray-200 p-3 text-right table-cell", children: formatNumber(item.unitPriceTaxExcl) }), _jsxs("td", { className: "border-b border-gray-200 p-3 text-right table-cell", children: [typeof item.taxPercent === "number"
432
+ ? Math.round(item.taxPercent)
433
+ : 0, "%"] }), _jsx("td", { className: "border-b border-gray-200 p-3 text-right font-medium table-cell", children: formatNumber(item.totalPriceTaxExcl) }), _jsx("td", { className: "border-b border-gray-200 p-3 text-right font-medium table-cell", children: formatNumber(item.totalPriceTaxIncl) }), _jsx("td", { className: "border-b border-gray-200 p-3 table-cell", children: _jsxs("div", { className: "flex justify-center space-x-2", children: [_jsx("button", { className: "rounded bg-blue-500 px-3 py-1 text-white hover:bg-blue-200", onClick: () => setEditingId(item.id), children: "Edit" }), _jsx("button", { className: "rounded bg-red-600 px-3 py-1 text-white hover:bg-red-700", onClick: () => onDeleteItem({ id: item.id }), children: "Delete" })] }) })] }, item.id))), isAddingNew ? (_jsx(EditableLineItem, { currency: currency, item: {}, onCancel: handleCancelNewItem, onSave: handleSaveNewItem, onEditingItemChange: onEditingItemChange })) : null] })] }) }))] }), lineItems.length > 0 && (_jsxs("div", { className: "md:hidden mt-4 bg-white border border-gray-200 rounded-lg p-4 space-y-2", children: [_jsxs("div", { className: "flex justify-between text-sm", children: [_jsx("span", { className: "text-gray-600", children: "Subtotal (excl. tax):" }), _jsxs("span", { className: "font-medium text-gray-900", children: [currency, " ", formatNumber(totalPriceTaxExcl)] })] }), _jsxs("div", { className: "flex justify-between text-sm", children: [_jsx("span", { className: "text-gray-600", children: "Total tax:" }), _jsxs("span", { className: "font-medium text-gray-900", children: [currency, " ", formatNumber(totalPriceTaxIncl - totalPriceTaxExcl)] })] }), _jsxs("div", { className: "flex justify-between text-base pt-2 border-t border-gray-200", children: [_jsx("span", { className: "font-semibold text-gray-900", children: "Total (incl. tax):" }), _jsxs("span", { className: "font-bold text-gray-900", children: [currency, " ", formatNumber(totalPriceTaxIncl)] })] })] }))] }));
398
434
  }
@@ -4,7 +4,7 @@ import { actions } from "../../document-models/invoice/index.js";
4
4
  import { generateId } from "document-model";
5
5
  let GRAPHQL_URL = "http://localhost:4001/graphql/invoice";
6
6
  if (!window.document.baseURI.includes('localhost')) {
7
- GRAPHQL_URL = 'https://jetstream.powerhouse.io/api/graphql/invoice';
7
+ GRAPHQL_URL = 'https://switchboard-dev.powerhouse.xyz/graphql/invoice';
8
8
  }
9
9
  const RequestFinance = ({ docState, dispatch, }) => {
10
10
  const [isLoading, setIsLoading] = useState(false);
@@ -7,7 +7,7 @@
7
7
  */
8
8
  let GRAPHQL_URL = 'http://localhost:4001/graphql/invoice';
9
9
  if (!window.document.baseURI.includes('localhost')) {
10
- GRAPHQL_URL = 'https://jetstream.powerhouse.io/api/graphql/invoice';
10
+ GRAPHQL_URL = 'https://switchboard-dev.powerhouse.xyz/graphql/invoice';
11
11
  }
12
12
  export async function uploadPdfChunked(pdfData, endpoint = GRAPHQL_URL, chunkSize = 500 * 1024, // 500KB chunks
13
13
  onProgress) {
package/dist/style.css CHANGED
@@ -354,6 +354,9 @@
354
354
  .mt-2 {
355
355
  margin-top: calc(var(--spacing) * 2);
356
356
  }
357
+ .mt-3 {
358
+ margin-top: calc(var(--spacing) * 3);
359
+ }
357
360
  .mt-4 {
358
361
  margin-top: calc(var(--spacing) * 4);
359
362
  }
@@ -372,6 +375,9 @@
372
375
  .mb-2 {
373
376
  margin-bottom: calc(var(--spacing) * 2);
374
377
  }
378
+ .mb-3 {
379
+ margin-bottom: calc(var(--spacing) * 3);
380
+ }
375
381
  .mb-4 {
376
382
  margin-bottom: calc(var(--spacing) * 4);
377
383
  }
@@ -427,6 +433,12 @@
427
433
  .h-4 {
428
434
  height: calc(var(--spacing) * 4);
429
435
  }
436
+ .h-5 {
437
+ height: calc(var(--spacing) * 5);
438
+ }
439
+ .h-6 {
440
+ height: calc(var(--spacing) * 6);
441
+ }
430
442
  .h-8 {
431
443
  height: calc(var(--spacing) * 8);
432
444
  }
@@ -460,6 +472,12 @@
460
472
  .w-4 {
461
473
  width: calc(var(--spacing) * 4);
462
474
  }
475
+ .w-5 {
476
+ width: calc(var(--spacing) * 5);
477
+ }
478
+ .w-6 {
479
+ width: calc(var(--spacing) * 6);
480
+ }
463
481
  .w-8 {
464
482
  width: calc(var(--spacing) * 8);
465
483
  }
@@ -496,6 +514,9 @@
496
514
  .w-full {
497
515
  width: 100%;
498
516
  }
517
+ .max-w-\[60\%\] {
518
+ max-width: 60%;
519
+ }
499
520
  .max-w-\[200px\] {
500
521
  max-width: 200px;
501
522
  }
@@ -508,6 +529,9 @@
508
529
  .max-w-xl {
509
530
  max-width: var(--container-xl);
510
531
  }
532
+ .max-w-xs {
533
+ max-width: var(--container-xs);
534
+ }
511
535
  .min-w-\[142px\] {
512
536
  min-width: 142px;
513
537
  }
@@ -566,12 +590,18 @@
566
590
  .flex-col {
567
591
  flex-direction: column;
568
592
  }
569
- .flex-nowrap {
570
- flex-wrap: nowrap;
593
+ .flex-row {
594
+ flex-direction: row;
595
+ }
596
+ .flex-wrap {
597
+ flex-wrap: wrap;
571
598
  }
572
599
  .items-center {
573
600
  align-items: center;
574
601
  }
602
+ .items-start {
603
+ align-items: flex-start;
604
+ }
575
605
  .justify-between {
576
606
  justify-content: space-between;
577
607
  }
@@ -581,6 +611,9 @@
581
611
  .justify-end {
582
612
  justify-content: flex-end;
583
613
  }
614
+ .gap-0 {
615
+ gap: calc(var(--spacing) * 0);
616
+ }
584
617
  .gap-1 {
585
618
  gap: calc(var(--spacing) * 1);
586
619
  }
@@ -600,6 +633,13 @@
600
633
  margin-block-end: calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)));
601
634
  }
602
635
  }
636
+ .space-y-3 {
637
+ :where(& > :not(:last-child)) {
638
+ --tw-space-y-reverse: 0;
639
+ margin-block-start: calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));
640
+ margin-block-end: calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)));
641
+ }
642
+ }
603
643
  .space-y-4 {
604
644
  :where(& > :not(:last-child)) {
605
645
  --tw-space-y-reverse: 0;
@@ -640,6 +680,9 @@
640
680
  .overflow-x-auto {
641
681
  overflow-x: auto;
642
682
  }
683
+ .overflow-y-auto {
684
+ overflow-y: auto;
685
+ }
643
686
  .rounded {
644
687
  border-radius: 0.25rem;
645
688
  }
@@ -665,6 +708,14 @@
665
708
  border-style: var(--tw-border-style);
666
709
  border-width: 1px;
667
710
  }
711
+ .border-0 {
712
+ border-style: var(--tw-border-style);
713
+ border-width: 0px;
714
+ }
715
+ .border-2 {
716
+ border-style: var(--tw-border-style);
717
+ border-width: 2px;
718
+ }
668
719
  .border-t {
669
720
  border-top-style: var(--tw-border-style);
670
721
  border-top-width: 1px;
@@ -677,12 +728,19 @@
677
728
  border-bottom-style: var(--tw-border-style);
678
729
  border-bottom-width: 2px;
679
730
  }
731
+ .border-dashed {
732
+ --tw-border-style: dashed;
733
+ border-style: dashed;
734
+ }
680
735
  .border-blue-100 {
681
736
  border-color: var(--color-blue-100);
682
737
  }
683
738
  .border-blue-500 {
684
739
  border-color: var(--color-blue-500);
685
740
  }
741
+ .border-gray-100 {
742
+ border-color: var(--color-gray-100);
743
+ }
686
744
  .border-gray-200 {
687
745
  border-color: var(--color-gray-200);
688
746
  }
@@ -770,6 +828,9 @@
770
828
  .p-0 {
771
829
  padding: calc(var(--spacing) * 0);
772
830
  }
831
+ .p-1 {
832
+ padding: calc(var(--spacing) * 1);
833
+ }
773
834
  .p-2 {
774
835
  padding: calc(var(--spacing) * 2);
775
836
  }
@@ -800,6 +861,9 @@
800
861
  .px-6 {
801
862
  padding-inline: calc(var(--spacing) * 6);
802
863
  }
864
+ .py-0\.5 {
865
+ padding-block: calc(var(--spacing) * 0.5);
866
+ }
803
867
  .py-1 {
804
868
  padding-block: calc(var(--spacing) * 1);
805
869
  }
@@ -809,9 +873,15 @@
809
873
  .py-3 {
810
874
  padding-block: calc(var(--spacing) * 3);
811
875
  }
876
+ .py-6 {
877
+ padding-block: calc(var(--spacing) * 6);
878
+ }
812
879
  .pt-2 {
813
880
  padding-top: calc(var(--spacing) * 2);
814
881
  }
882
+ .pt-3 {
883
+ padding-top: calc(var(--spacing) * 3);
884
+ }
815
885
  .pt-4 {
816
886
  padding-top: calc(var(--spacing) * 4);
817
887
  }
@@ -888,12 +958,18 @@
888
958
  .text-blue-600 {
889
959
  color: var(--color-blue-600);
890
960
  }
961
+ .text-blue-800 {
962
+ color: var(--color-blue-800);
963
+ }
891
964
  .text-blue-900 {
892
965
  color: var(--color-blue-900);
893
966
  }
894
967
  .text-gray-50 {
895
968
  color: var(--color-gray-50);
896
969
  }
970
+ .text-gray-400 {
971
+ color: var(--color-gray-400);
972
+ }
897
973
  .text-gray-500 {
898
974
  color: var(--color-gray-500);
899
975
  }
@@ -1089,6 +1165,13 @@
1089
1165
  }
1090
1166
  }
1091
1167
  }
1168
+ .hover\:bg-red-50 {
1169
+ &:hover {
1170
+ @media (hover: hover) {
1171
+ background-color: var(--color-red-50);
1172
+ }
1173
+ }
1174
+ }
1092
1175
  .hover\:bg-red-700 {
1093
1176
  &:hover {
1094
1177
  @media (hover: hover) {
@@ -1216,6 +1299,26 @@
1216
1299
  line-height: var(--tw-leading, var(--text-base--line-height));
1217
1300
  }
1218
1301
  }
1302
+ .md\:block {
1303
+ @media (width >= 48rem) {
1304
+ display: block;
1305
+ }
1306
+ }
1307
+ .md\:flex {
1308
+ @media (width >= 48rem) {
1309
+ display: flex;
1310
+ }
1311
+ }
1312
+ .md\:hidden {
1313
+ @media (width >= 48rem) {
1314
+ display: none;
1315
+ }
1316
+ }
1317
+ .md\:inline {
1318
+ @media (width >= 48rem) {
1319
+ display: inline;
1320
+ }
1321
+ }
1219
1322
  .md\:grid-cols-2 {
1220
1323
  @media (width >= 48rem) {
1221
1324
  grid-template-columns: repeat(2, minmax(0, 1fr));
@@ -1227,6 +1330,32 @@
1227
1330
  line-height: var(--tw-leading, var(--text-2xl--line-height));
1228
1331
  }
1229
1332
  }
1333
+ .lg\:gap-4 {
1334
+ @media (width >= 64rem) {
1335
+ gap: calc(var(--spacing) * 4);
1336
+ }
1337
+ }
1338
+ .lg\:rounded-lg {
1339
+ @media (width >= 64rem) {
1340
+ border-radius: var(--radius-lg);
1341
+ }
1342
+ }
1343
+ .lg\:border {
1344
+ @media (width >= 64rem) {
1345
+ border-style: var(--tw-border-style);
1346
+ border-width: 1px;
1347
+ }
1348
+ }
1349
+ .lg\:border-gray-200 {
1350
+ @media (width >= 64rem) {
1351
+ border-color: var(--color-gray-200);
1352
+ }
1353
+ }
1354
+ .lg\:p-4 {
1355
+ @media (width >= 64rem) {
1356
+ padding: calc(var(--spacing) * 4);
1357
+ }
1358
+ }
1230
1359
  }
1231
1360
  /*! tailwindcss v4.1.12 | MIT License | https://tailwindcss.com */
1232
1361
  @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap");
@@ -19139,15 +19268,15 @@ input[type="number"] {
19139
19268
  }
19140
19269
  @media (max-width: 640px) {
19141
19270
  .editor-container {
19142
- padding: 0.25rem;
19143
- transform: scale(0.95);
19271
+ padding: 0.125rem;
19272
+ transform: none;
19144
19273
  transform-origin: top left;
19145
19274
  }
19146
19275
  }
19147
19276
  @media (min-width: 641px) and (max-width: 1023px) {
19148
19277
  .editor-container {
19149
- padding: 0.5rem;
19150
- transform: scale(0.9);
19278
+ padding: 0.25rem;
19279
+ transform: none;
19151
19280
  transform-origin: top left;
19152
19281
  }
19153
19282
  }
@@ -19160,6 +19289,42 @@ input[type="number"] {
19160
19289
  transform: none;
19161
19290
  }
19162
19291
  }
19292
+ @media (min-width: 768px) {
19293
+ .md\:grid-cols-2 {
19294
+ grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
19295
+ }
19296
+ }
19297
+ @media (min-width: 768px) {
19298
+ .md\:flex {
19299
+ display: flex !important;
19300
+ }
19301
+ .md\:hidden {
19302
+ display: none !important;
19303
+ }
19304
+ .md\:block {
19305
+ display: block !important;
19306
+ }
19307
+ .md\:inline {
19308
+ display: inline !important;
19309
+ }
19310
+ }
19311
+ @media (min-width: 1024px) {
19312
+ .lg\:gap-4 {
19313
+ gap: 1rem !important;
19314
+ }
19315
+ .lg\:border {
19316
+ border-width: 1px !important;
19317
+ }
19318
+ .lg\:border-gray-200 {
19319
+ border-color: rgb(229, 231, 235) !important;
19320
+ }
19321
+ .lg\:rounded-lg {
19322
+ border-radius: 0.5rem !important;
19323
+ }
19324
+ .lg\:p-4 {
19325
+ padding: 1rem !important;
19326
+ }
19327
+ }
19163
19328
  @property --tw-border-spacing-x {
19164
19329
  syntax: "<length>";
19165
19330
  inherits: false;
@@ -3,6 +3,7 @@ export default {
3
3
  content: [
4
4
  "./index.html",
5
5
  "./src/**/*.{js,ts,jsx,tsx}",
6
+ "./editors/**/*.{js,ts,jsx,tsx}",
6
7
  ],
7
8
  theme: {
8
9
  extend: {
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.0.98",
4
+ "version": "0.0.99",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",
7
7
  "files": [
@@ -57,9 +57,9 @@
57
57
  },
58
58
  "dependencies": {
59
59
  "@google-cloud/documentai": "^8.12.0",
60
- "@powerhousedao/builder-tools": "^5.0.0-staging.21",
61
- "@powerhousedao/common": "^5.0.0-staging.21",
62
- "@powerhousedao/design-system": "^5.0.0-staging.21",
60
+ "@powerhousedao/builder-tools": "^5.0.0-staging.22",
61
+ "@powerhousedao/common": "^5.0.0-staging.22",
62
+ "@powerhousedao/design-system": "^5.0.0-staging.22",
63
63
  "@powerhousedao/document-engineering": "^1.38.0",
64
64
  "@react-pdf/renderer": "^4.3.0",
65
65
  "@safe-global/api-kit": "^3.0.1",
@@ -69,7 +69,7 @@
69
69
  "@types/cors": "^2.8.17",
70
70
  "axios": "^1.9.0",
71
71
  "cors": "^2.8.5",
72
- "document-model": "^5.0.0-staging.21",
72
+ "document-model": "^5.0.0-staging.22",
73
73
  "dotenv": "^16.5.0",
74
74
  "error": "^10.4.0",
75
75
  "ethers": "^6.14.0",
@@ -84,20 +84,21 @@
84
84
  "devDependencies": {
85
85
  "@electric-sql/pglite": "^0.2.12",
86
86
  "@eslint/js": "^9.25.0",
87
+ "@playwright/test": "^1.56.0",
87
88
  "@powerhousedao/analytics-engine-core": "^0.5.0",
88
- "@powerhousedao/codegen": "^5.0.0-staging.21",
89
- "@powerhousedao/ph-cli": "^5.0.0-staging.21",
90
- "@powerhousedao/reactor-api": "^5.0.0-staging.21",
91
- "@powerhousedao/reactor-browser": "^5.0.0-staging.21",
92
- "@powerhousedao/reactor-local": "^5.0.0-staging.21",
89
+ "@powerhousedao/codegen": "^5.0.0-staging.22",
90
+ "@powerhousedao/ph-cli": "^5.0.0-staging.22",
91
+ "@powerhousedao/reactor-api": "^5.0.0-staging.22",
92
+ "@powerhousedao/reactor-browser": "^5.0.0-staging.22",
93
+ "@powerhousedao/reactor-local": "^5.0.0-staging.22",
93
94
  "@powerhousedao/scalars": "^1.33.1-staging.5",
94
- "@powerhousedao/switchboard": "^5.0.0-staging.21",
95
+ "@powerhousedao/switchboard": "^5.0.0-staging.22",
95
96
  "@tailwindcss/cli": "^4.1.4",
96
97
  "@testing-library/react": "^16.3.0",
97
98
  "@types/node": "^22.14.1",
98
99
  "@types/react": "^18.3.20",
99
100
  "@vitejs/plugin-react": "^4.4.1",
100
- "document-drive": "^5.0.0-staging.21",
101
+ "document-drive": "^5.0.0-staging.22",
101
102
  "eslint": "^9.25.0",
102
103
  "eslint-plugin-react": "^7.37.5",
103
104
  "eslint-plugin-react-hooks": "^5.2.0",