@powerhousedao/contributor-billing 0.0.68 → 0.0.69

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.
@@ -412,4 +412,4 @@ const PaymentSectionCrypto = ({ paymentRouting, }) => (_jsx(View, { style: style
412
412
  {
413
413
  /* New component for line items */
414
414
  }
415
- const InvoiceLineItem = ({ item, currency, }) => (_jsxs(View, { style: styles.tableRow, children: [_jsxs(View, { style: styles.tableCol40, children: [_jsx(Text, { style: styles.itemName, children: item.description }), item.longDescription && (_jsx(Text, { style: styles.itemDescription, children: item.longDescription }))] }), _jsx(Text, { style: styles.tableCol15, children: item.quantity }), _jsx(Text, { style: styles.tableCol15, children: formatCurrency(item.unitPriceTaxExcl, currency) }), _jsx(Text, { style: styles.tableCol15, children: formatCurrency(item.unitPriceTaxIncl - item.unitPriceTaxExcl, currency) }), _jsx(Text, { style: styles.tableCol15, children: formatCurrency(item.quantity * item.unitPriceTaxIncl, currency) })] }));
415
+ const InvoiceLineItem = ({ item, currency, }) => (_jsxs(View, { style: styles.tableRow, children: [_jsxs(View, { style: styles.tableCol40, children: [_jsx(Text, { style: styles.itemName, children: item.description }), item.longDescription && (_jsx(Text, { style: styles.itemDescription, children: item.longDescription }))] }), _jsx(Text, { style: styles.tableCol15, children: item.quantity % 1 === 0 ? item.quantity.toString() : item.quantity.toFixed(2) }), _jsx(Text, { style: styles.tableCol15, children: formatCurrency(item.unitPriceTaxExcl, currency) }), _jsx(Text, { style: styles.tableCol15, children: formatCurrency(item.unitPriceTaxIncl - item.unitPriceTaxExcl, currency) }), _jsx(Text, { style: styles.tableCol15, children: formatCurrency(item.quantity * item.unitPriceTaxIncl, currency) })] }));
@@ -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://switchboard.powerhouse.xyz/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)
@@ -3,8 +3,8 @@ import { useState } from "react";
3
3
  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
- if (!window.document.baseURI.includes('localhost')) {
7
- GRAPHQL_URL = 'https://switchboard.powerhouse.xyz/graphql/invoice';
6
+ if (!window.document.baseURI.includes("localhost")) {
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);
@@ -157,7 +157,7 @@ const InvoiceToGnosis = ({ docState, dispatch, }) => {
157
157
  ? "Processing..."
158
158
  : invoiceStatus === "ACCEPTED"
159
159
  ? "Schedule Payment in Gnosis Safe"
160
- : "Reschedule Payment in Gnosis Safe" })), error && (_jsx("div", { className: "text-red-500 bg-red-50 p-3 rounded-md", children: error })), safeTxHash && (_jsxs("div", { className: "bg-gray-50 mt-4 rounded-md space-y-2", children: [_jsx("a", { href: `https://app.safe.global/transactions/queue?safe=${urlChainName}:0xF130f741d4E3185b29412c65397363f8c23A0460`, target: "_blank", rel: "noopener noreferrer", className: "text-blue-500 hover:text-blue-600 underline block", children: linkText }), _jsxs("p", { className: "font-medium", children: ["Safe Transaction Hash:", _jsx("span", { className: "font-mono text-sm ml-2 break-all", children: safeTxHash })] })] })), !safeTxHash &&
160
+ : "Reschedule Payment in Gnosis Safe" })), error && (_jsx("div", { className: "text-red-500 bg-red-50 p-3 rounded-md", children: error })), safeTxHash && (_jsxs("div", { className: "bg-gray-50 mt-4 rounded-md space-y-2", children: [_jsx("a", { href: `https://app.safe.global/transactions/queue?safe=${urlChainName}:0x1FB6bEF04230d67aF0e3455B997a28AFcCe1F45e`, target: "_blank", rel: "noopener noreferrer", className: "text-blue-500 hover:text-blue-600 underline block", children: linkText }), _jsxs("p", { className: "font-medium", children: ["Safe Transaction Hash:", _jsx("span", { className: "font-mono text-sm ml-2 break-all", children: safeTxHash })] })] })), !safeTxHash &&
161
161
  !error &&
162
162
  invoiceStatus === "PAYMENTSCHEDULED" &&
163
163
  docState.payments.length > 0 && (_jsx(_Fragment, { children: docState.payments[docState.payments.length - 1].issue !== "" ? (_jsx("div", { className: "mt-4", children: _jsxs("p", { className: "text-red-700 font-medium", children: ["Issue: ", docState.payments[docState.payments.length - 1].issue] }) })) : (_jsxs("div", { className: "mt-4", children: [_jsx("div", { className: "invoice-link text-blue-900 hover:text-blue-600", children: _jsx("a", { className: "view-invoice-button", href: `https://app.safe.global/transactions/queue?safe=${urlChainName}:0x1FB6bEF04230d67aF0e3455B997a28AFcCe1F45e`, target: "_blank", rel: "noopener noreferrer", children: linkText }) }), _jsxs("p", { className: "mt-4 font-medium", children: ["Safe Transaction Hash:", _jsx("span", { className: "font-mono text-sm ml-2 break-all", children: docState.payments[docState.payments.length - 1]
@@ -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;AA+aF,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,2CA+LrB"}
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,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { RWAButton } from "@powerhousedao/design-system";
2
+ import { RWAButton, toast } from "@powerhousedao/design-system";
3
3
  import { forwardRef, useState, useMemo, useRef, useEffect, } from "react";
4
4
  import { generateId } from "document-model";
5
5
  import { Tag } from "lucide-react";
@@ -21,7 +21,7 @@ const EditableLineItem = forwardRef(function EditableLineItem(props, ref) {
21
21
  const [editedItem, setEditedItem] = useState({
22
22
  ...item,
23
23
  currency,
24
- quantity: item.quantity ?? "",
24
+ quantity: item.quantity ?? 1,
25
25
  taxPercent: item.taxPercent ?? "",
26
26
  unitPriceTaxExcl: item.unitPriceTaxExcl ?? "",
27
27
  totalPriceTaxExcl: item.totalPriceTaxExcl ?? "",
@@ -30,9 +30,9 @@ const EditableLineItem = forwardRef(function EditableLineItem(props, ref) {
30
30
  const calculatedValues = useMemo(() => {
31
31
  const quantity = typeof editedItem.quantity === "string"
32
32
  ? editedItem.quantity === ""
33
- ? 0
34
- : Number(editedItem.quantity)
35
- : (editedItem.quantity ?? 0);
33
+ ? 1
34
+ : Number(editedItem.quantity) || 1
35
+ : (editedItem.quantity ?? 1);
36
36
  const unitPriceTaxExcl = typeof editedItem.unitPriceTaxExcl === "string"
37
37
  ? editedItem.unitPriceTaxExcl === ""
38
38
  ? 0
@@ -147,15 +147,21 @@ const EditableLineItem = forwardRef(function EditableLineItem(props, ref) {
147
147
  setEditedItem((prev) => ({ ...prev, [field]: value }));
148
148
  return;
149
149
  }
150
- // For numeric fields
151
- if (value === "" || value === "0") {
150
+ // For numeric fields (except quantity which is handled separately)
151
+ if (field !== "quantity" && (value === "" || value === "0")) {
152
152
  setEditedItem((prev) => ({ ...prev, [field]: value }));
153
153
  return;
154
154
  }
155
155
  if (field === "quantity") {
156
- // Allow only integers for quantity
157
- if (/^\d+$/.test(value)) {
158
- setEditedItem((prev) => ({ ...prev, [field]: value }));
156
+ // Allow up to 2 decimal places for quantity, default to 1 if empty or invalid
157
+ if (value === "" || value === "0") {
158
+ setEditedItem((prev) => ({ ...prev, [field]: 1 }));
159
+ }
160
+ else if (/^\d*\.?\d{0,2}$/.test(value)) {
161
+ setEditedItem((prev) => ({
162
+ ...prev,
163
+ [field]: parseFloat(value) || 1,
164
+ }));
159
165
  }
160
166
  }
161
167
  else if (field === "taxPercent") {
@@ -268,9 +274,9 @@ const EditableLineItem = forwardRef(function EditableLineItem(props, ref) {
268
274
  }
269
275
  return (_jsxs("tr", { ref: ref, className: "hover:bg-gray-50 table-row", children: [_jsx("td", { className: "border border-gray-200 p-3 table-cell", children: _jsx(InputField, { onBlur: () => { }, handleInputChange: (e) => {
270
276
  setEditedItem((prev) => ({ ...prev, description: e.target.value }));
271
- }, value: editedItem.description ?? "", placeholder: "Description", className: "" }) }), _jsx("td", { className: "border border-gray-200 p-3 table-cell", children: _jsx(NumberForm, { number: calculatedValues.quantity, precision: 0, handleInputChange: handleInputChange("quantity"), placeholder: "Quantity", className: "" }) }), _jsx("td", { className: "border border-gray-200 p-3 table-cell", children: _jsx(NumberForm, { number: calculatedValues.unitPriceTaxExcl % 1 === 0
277
+ }, value: editedItem.description ?? "", placeholder: "Description", className: "" }) }), _jsx("td", { className: "border border-gray-200 p-3 table-cell", children: _jsx(NumberForm, { number: calculatedValues.quantity || 1, precision: 2, handleInputChange: handleInputChange("quantity"), placeholder: "Quantity", className: "" }) }), _jsx("td", { className: "border border-gray-200 p-3 table-cell", children: _jsx(NumberForm, { number: calculatedValues.unitPriceTaxExcl % 1 === 0
272
278
  ? calculatedValues.unitPriceTaxExcl.toString()
273
- : calculatedValues.unitPriceTaxExcl.toFixed(2), precision: 2, handleInputChange: handleInputChange("unitPriceTaxExcl"), pattern: "^-?\\d*\\.?\\d*$", placeholder: "Unit Price (excl. tax)", className: "" }) }), _jsx("td", { className: "border border-gray-200 p-3 table-cell", children: _jsx(NumberForm, { number: calculatedValues.taxPercent, precision: 0, pattern: "^(100|[1-9]?[0-9])$", handleInputChange: handleInputChange("taxPercent"), placeholder: "Tax %", className: "" }) }), _jsx("td", { className: "border border-gray-200 p-3 text-right font-medium table-cell", children: _jsx(NumberForm, { number: calculatedValues.totalPriceTaxExcl % 1 === 0
279
+ : calculatedValues.unitPriceTaxExcl.toFixed(2), precision: 2, handleInputChange: handleInputChange("unitPriceTaxExcl"), pattern: "^-?\\d*\\.?\\d*$", placeholder: "Unit Price (excl. tax)", className: "" }) }), _jsx("td", { className: "border border-gray-200 p-3 text-right font-medium table-cell", children: _jsx(NumberForm, { number: calculatedValues.taxPercent, precision: 0, pattern: "^(100|[1-9]?[0-9])$", handleInputChange: handleInputChange("taxPercent"), placeholder: "Tax %", className: "" }) }), _jsx("td", { className: "border border-gray-200 p-3 text-right font-medium table-cell", children: _jsx(NumberForm, { number: calculatedValues.totalPriceTaxExcl % 1 === 0
274
280
  ? calculatedValues.totalPriceTaxExcl.toString()
275
281
  : calculatedValues.totalPriceTaxExcl.toFixed(2), precision: 2, handleInputChange: handleInputChange("totalPriceTaxExcl"), pattern: "^-?\\d*\\.?\\d*$", placeholder: "Total (excl. tax)", className: "" }) }), _jsx("td", { className: "border border-gray-200 p-3 text-right font-medium table-cell", children: _jsx(NumberForm, { number: calculatedValues.totalPriceTaxIncl % 1 === 0
276
282
  ? calculatedValues.totalPriceTaxIncl.toString()
@@ -288,7 +294,41 @@ export function LineItemsTable({ lineItems, currency, onAddItem, onUpdateItem, o
288
294
  setIsAddingNew(true);
289
295
  }
290
296
  function handleSaveNewItem(item) {
291
- onAddItem(item);
297
+ try {
298
+ onAddItem(item);
299
+ }
300
+ catch (error) {
301
+ if (error?.message?.includes("Invalid action input:")) {
302
+ try {
303
+ const errorPart = error.message.split("Invalid action input: ")[1];
304
+ const zodError = JSON.parse(errorPart);
305
+ if (Array.isArray(zodError) && zodError.length > 0) {
306
+ const firstError = zodError[0];
307
+ const errorJSX = (_jsxs("div", { children: [_jsx("p", { className: "font-semibold", children: "Failed to add 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)))] }));
308
+ toast(errorJSX, {
309
+ type: "error",
310
+ });
311
+ return;
312
+ }
313
+ }
314
+ catch (parseError) {
315
+ console.error("Failed to parse Zod error:", parseError);
316
+ toast("Invalid input data", {
317
+ type: "error",
318
+ });
319
+ return;
320
+ }
321
+ }
322
+ else if (error?.message) {
323
+ toast(error.message, {
324
+ type: "error",
325
+ });
326
+ return;
327
+ }
328
+ toast("Failed to add line item", {
329
+ type: "error",
330
+ });
331
+ }
292
332
  setIsAddingNew(false);
293
333
  }
294
334
  function handleCancelNewItem() {
@@ -313,9 +353,46 @@ export function LineItemsTable({ lineItems, currency, onAddItem, onUpdateItem, o
313
353
  color: "white",
314
354
  fill: "#475264",
315
355
  } })] }) })] }) }), _jsxs("tbody", { children: [lineItems.map((item) => editingId === item.id ? (_jsx(EditableLineItem, { currency: currency, item: item, onCancel: () => setEditingId(null), onSave: (updatedItem) => {
316
- onUpdateItem(updatedItem);
317
- setEditingId(null);
318
- }, 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 }), _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"
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, {
370
+ type: "error",
371
+ });
372
+ return;
373
+ }
374
+ }
375
+ catch (parseError) {
376
+ console.error("Failed to parse Zod error:", parseError);
377
+ toast("Invalid input data", {
378
+ type: "error",
379
+ });
380
+ return;
381
+ }
382
+ }
383
+ else if (error?.message) {
384
+ toast(error.message, {
385
+ type: "error",
386
+ });
387
+ return;
388
+ }
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"
319
396
  ? Math.round(item.taxPercent)
320
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] })] }) })] }) }));
321
398
  }
@@ -1 +1 @@
1
- {"version":3,"file":"requestFinance.d.ts","sourceRoot":"","sources":["../../../editors/invoice/requestFinance.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAUxC,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,GAAG,CAAC;IACd,QAAQ,EAAE,GAAG,CAAC;CACf;AAED,QAAA,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAgQjD,CAAC;AAEF,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"requestFinance.d.ts","sourceRoot":"","sources":["../../../editors/invoice/requestFinance.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAUxC,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,GAAG,CAAC;IACd,QAAQ,EAAE,GAAG,CAAC;CACf;AAED,QAAA,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAgRjD,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -3,8 +3,8 @@ import { useState } from "react";
3
3
  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
- if (!window.document.baseURI.includes('localhost')) {
7
- GRAPHQL_URL = 'https://switchboard.powerhouse.xyz/graphql/invoice';
6
+ if (!window.document.baseURI.includes("localhost")) {
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);
@@ -73,6 +73,14 @@ const RequestFinance = ({ docState, dispatch, }) => {
73
73
  "Liberty",
74
74
  bicSwift: docState.issuer.paymentRouting.bank.BIC,
75
75
  };
76
+ const getDecimalPlaces = (currency) => {
77
+ const formatter = new Intl.NumberFormat("en-US", {
78
+ style: "currency",
79
+ currency,
80
+ minimumFractionDigits: 0, // Ensure we get the default for the currency
81
+ });
82
+ return formatter.resolvedOptions().maximumFractionDigits ?? 2;
83
+ };
76
84
  try {
77
85
  const invoiceData = {
78
86
  meta: {
@@ -80,12 +88,18 @@ const RequestFinance = ({ docState, dispatch, }) => {
80
88
  version: "0.0.3",
81
89
  },
82
90
  creationDate: docState.dateIssued,
83
- invoiceItems: docState.lineItems.map((item) => ({
84
- currency: bankDetails.currency,
85
- name: item.description,
86
- quantity: item.quantity,
87
- unitPrice: item.totalPriceTaxIncl * 100,
88
- })),
91
+ invoiceItems: docState.lineItems.map((item) => {
92
+ const currency = bankDetails.currency;
93
+ const decimalPlaces = getDecimalPlaces(currency);
94
+ const multiplier = Math.pow(10, decimalPlaces);
95
+ const unitPriceInt = Math.round(item.unitPriceTaxIncl * multiplier);
96
+ return {
97
+ currency,
98
+ name: item.description,
99
+ quantity: item.quantity,
100
+ unitPrice: unitPriceInt,
101
+ };
102
+ }),
89
103
  invoiceNumber: docState.invoiceNo,
90
104
  buyerInfo: {
91
105
  // email: docState.payer.contactInfo.email,
@@ -135,7 +149,7 @@ const RequestFinance = ({ docState, dispatch, }) => {
135
149
  };
136
150
  // Instead of calling the API endpoint directly, use the createDirectPayment function
137
151
  const directPaymentResult = await createDirectPayment(invoiceData);
138
- console.log("Direct payment created:", directPaymentResult);
152
+ console.log("Direct payment created: (unitPrice in cents)", directPaymentResult);
139
153
  // Process the response
140
154
  if (directPaymentResult?.response?.invoiceLinks?.pay) {
141
155
  setInvoiceLink(directPaymentResult.response.invoiceLinks.pay);
@@ -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://switchboard.powerhouse.xyz/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) {
@@ -4,7 +4,7 @@ import { OperationType } from '@safe-global/types-kit';
4
4
  import { ethers, AbiCoder } from 'ethers';
5
5
  import dotenv from 'dotenv';
6
6
  dotenv.config();
7
- const safeAddress = process.env.PRODUCTION_SAFE_ADDRESS;
7
+ const safeAddress = process.env.DEV_STAGING_SAFE_ADDRESS;
8
8
  if (!safeAddress) {
9
9
  throw new Error('Missing SAFE_ADDRESS in .env');
10
10
  }
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.68",
4
+ "version": "0.0.69",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",
7
7
  "files": [