braid-ui 1.0.49 → 1.0.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/css/braid-ui.css +10 -2
- package/dist/css/braid-ui.min.css +1 -1
- package/dist/index.cjs +743 -329
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +112 -14
- package/dist/index.d.ts +112 -14
- package/dist/index.js +743 -330
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1279,7 +1279,7 @@ var DialogOverlay = React15__namespace.forwardRef(({ className, ...props }, ref)
|
|
|
1279
1279
|
}
|
|
1280
1280
|
));
|
|
1281
1281
|
DialogOverlay.displayName = DialogPrimitive__namespace.Overlay.displayName;
|
|
1282
|
-
var DialogContent = React15__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(DialogPortal, { children: [
|
|
1282
|
+
var DialogContent = React15__namespace.forwardRef(({ className, children, hideCloseButton, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(DialogPortal, { children: [
|
|
1283
1283
|
/* @__PURE__ */ jsxRuntime.jsx(DialogOverlay, {}),
|
|
1284
1284
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1285
1285
|
DialogPrimitive__namespace.Content,
|
|
@@ -1292,7 +1292,7 @@ var DialogContent = React15__namespace.forwardRef(({ className, children, ...pro
|
|
|
1292
1292
|
...props,
|
|
1293
1293
|
children: [
|
|
1294
1294
|
children,
|
|
1295
|
-
/* @__PURE__ */ jsxRuntime.jsxs(DialogPrimitive__namespace.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground", children: [
|
|
1295
|
+
!hideCloseButton && /* @__PURE__ */ jsxRuntime.jsxs(DialogPrimitive__namespace.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground", children: [
|
|
1296
1296
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" }),
|
|
1297
1297
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
|
|
1298
1298
|
] })
|
|
@@ -3099,7 +3099,7 @@ function AppSidebar() {
|
|
|
3099
3099
|
] });
|
|
3100
3100
|
}
|
|
3101
3101
|
var MainLayout = ({ children }) => {
|
|
3102
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex
|
|
3102
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-screen w-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("main", { className: "flex-1 overflow-hidden", children }) });
|
|
3103
3103
|
};
|
|
3104
3104
|
var useEditState = ({ initialEditing = false, onToggleEdit, onSave, onCancel }) => {
|
|
3105
3105
|
const [localEditing, setLocalEditing] = React15.useState(initialEditing);
|
|
@@ -8257,7 +8257,7 @@ var StatementView = ({
|
|
|
8257
8257
|
] });
|
|
8258
8258
|
};
|
|
8259
8259
|
var ACHDetailsSection = ({ data }) => {
|
|
8260
|
-
const
|
|
8260
|
+
const formatCurrency3 = (value) => {
|
|
8261
8261
|
return new Intl.NumberFormat("en-US", {
|
|
8262
8262
|
style: "currency",
|
|
8263
8263
|
currency: "USD",
|
|
@@ -8293,7 +8293,7 @@ var ACHDetailsSection = ({ data }) => {
|
|
|
8293
8293
|
layout: "horizontal"
|
|
8294
8294
|
}
|
|
8295
8295
|
),
|
|
8296
|
-
/* @__PURE__ */ jsxRuntime.jsx(InfoField, { label: "Amount", value:
|
|
8296
|
+
/* @__PURE__ */ jsxRuntime.jsx(InfoField, { label: "Amount", value: formatCurrency3(data.amount), layout: "horizontal" }),
|
|
8297
8297
|
/* @__PURE__ */ jsxRuntime.jsx(InfoField, { label: "SEC Code", value: data.secCode, layout: "horizontal" }),
|
|
8298
8298
|
/* @__PURE__ */ jsxRuntime.jsx(InfoField, { label: "Company Entry Description", value: data.companyEntryDescription, layout: "horizontal" }),
|
|
8299
8299
|
data.companyDiscretionaryData && /* @__PURE__ */ jsxRuntime.jsx(InfoField, { label: "Company Discretionary Data", value: data.companyDiscretionaryData, layout: "horizontal" }),
|
|
@@ -8376,6 +8376,37 @@ var WireDetailsSection = ({ data }) => {
|
|
|
8376
8376
|
) })
|
|
8377
8377
|
] });
|
|
8378
8378
|
};
|
|
8379
|
+
var formatCurrency = (value) => {
|
|
8380
|
+
const numValue = typeof value === "string" ? parseFloat(value) : value;
|
|
8381
|
+
if (isNaN(numValue)) return "";
|
|
8382
|
+
return new Intl.NumberFormat("en-US", {
|
|
8383
|
+
style: "currency",
|
|
8384
|
+
currency: "USD",
|
|
8385
|
+
minimumFractionDigits: 2
|
|
8386
|
+
}).format(numValue);
|
|
8387
|
+
};
|
|
8388
|
+
var CurrencyInput = ({ value, onChange, ...props }) => {
|
|
8389
|
+
const [isFocused, setIsFocused] = React15__namespace.useState(false);
|
|
8390
|
+
const displayValue = value ? isFocused ? value : formatCurrency(value) : "";
|
|
8391
|
+
const handleChange = (e) => {
|
|
8392
|
+
const rawValue = e.target.value.replace(/[^0-9.]/g, "");
|
|
8393
|
+
const parts = rawValue.split(".");
|
|
8394
|
+
const sanitized = parts[0] + (parts.length > 1 ? "." + parts[1]?.slice(0, 2) : "");
|
|
8395
|
+
onChange(sanitized);
|
|
8396
|
+
};
|
|
8397
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8398
|
+
EnhancedInput,
|
|
8399
|
+
{
|
|
8400
|
+
...props,
|
|
8401
|
+
value: displayValue,
|
|
8402
|
+
onChange: handleChange,
|
|
8403
|
+
onFocus: () => setIsFocused(true),
|
|
8404
|
+
onBlur: () => setIsFocused(false),
|
|
8405
|
+
inputMode: "decimal",
|
|
8406
|
+
placeholder: props.placeholder || "$0.00"
|
|
8407
|
+
}
|
|
8408
|
+
);
|
|
8409
|
+
};
|
|
8379
8410
|
var Checkbox = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
8380
8411
|
CheckboxPrimitive__namespace.Root,
|
|
8381
8412
|
{
|
|
@@ -8395,21 +8426,29 @@ var Checkbox = React15__namespace.forwardRef(({ className, ...props }, ref) => /
|
|
|
8395
8426
|
}
|
|
8396
8427
|
));
|
|
8397
8428
|
Checkbox.displayName = CheckboxPrimitive__namespace.Root.displayName;
|
|
8429
|
+
var formatCurrency2 = (value) => {
|
|
8430
|
+
const numValue = typeof value === "string" ? parseFloat(value) : value;
|
|
8431
|
+
if (isNaN(numValue)) return "-";
|
|
8432
|
+
return new Intl.NumberFormat("en-US", {
|
|
8433
|
+
style: "currency",
|
|
8434
|
+
currency: "USD",
|
|
8435
|
+
minimumFractionDigits: 2
|
|
8436
|
+
}).format(numValue);
|
|
8437
|
+
};
|
|
8398
8438
|
var TRANSACTION_TYPES = [
|
|
8399
8439
|
{ value: "transfer", label: "Transfer", icon: lucideReact.ArrowLeftRight },
|
|
8400
8440
|
{ value: "adjustment", label: "Adjustment", icon: lucideReact.Settings },
|
|
8401
8441
|
{ value: "ach", label: "ACH", icon: lucideReact.Building2 },
|
|
8402
8442
|
{ value: "wire", label: "Wire", icon: lucideReact.Zap }
|
|
8403
8443
|
];
|
|
8404
|
-
var
|
|
8405
|
-
{ value: "
|
|
8406
|
-
{ value: "
|
|
8407
|
-
|
|
8408
|
-
|
|
8409
|
-
{ value: "
|
|
8410
|
-
{ value: "
|
|
8411
|
-
{ value: "
|
|
8412
|
-
{ value: "CNY", label: "CNY - Chinese Yuan" }
|
|
8444
|
+
var ADJUSTMENT_DIRECTION_OPTIONS = [
|
|
8445
|
+
{ value: "debit", label: "Debit" },
|
|
8446
|
+
{ value: "credit", label: "Credit" }
|
|
8447
|
+
];
|
|
8448
|
+
var ADJUSTMENT_TYPE_OPTIONS = [
|
|
8449
|
+
{ value: "collection", label: "Collection" },
|
|
8450
|
+
{ value: "transaction_reversal", label: "Transaction Reversal" },
|
|
8451
|
+
{ value: "transaction_adjustment", label: "Transaction Adjustment" }
|
|
8413
8452
|
];
|
|
8414
8453
|
var NewTransactionView = ({
|
|
8415
8454
|
form,
|
|
@@ -8421,19 +8460,41 @@ var NewTransactionView = ({
|
|
|
8421
8460
|
submissionStatus,
|
|
8422
8461
|
errorMessage,
|
|
8423
8462
|
transactionId,
|
|
8463
|
+
isAccountLoading,
|
|
8464
|
+
isCounterpartyLoading,
|
|
8465
|
+
isSubmitting,
|
|
8466
|
+
counterpartySearchResults,
|
|
8467
|
+
isCounterpartySearching,
|
|
8468
|
+
showCounterpartyDropdown,
|
|
8424
8469
|
onAccountLookup,
|
|
8425
|
-
onCounterpartyLookup,
|
|
8426
8470
|
onEditAccount,
|
|
8427
8471
|
onEditCounterparty,
|
|
8472
|
+
onTransactionTypeChange,
|
|
8428
8473
|
onSubmit,
|
|
8429
8474
|
onCancel,
|
|
8430
8475
|
onConfirmationClose,
|
|
8431
|
-
onConfirmationOpenChange
|
|
8476
|
+
onConfirmationOpenChange,
|
|
8477
|
+
onNewTransaction,
|
|
8478
|
+
onCounterpartySearchChange,
|
|
8479
|
+
onCounterpartySelect,
|
|
8480
|
+
onCounterpartyDropdownClose,
|
|
8481
|
+
receiverAccountLookedUp,
|
|
8482
|
+
receiverAccountData,
|
|
8483
|
+
isReceiverAccountLoading,
|
|
8484
|
+
onReceiverAccountLookup,
|
|
8485
|
+
onEditReceiverAccount,
|
|
8486
|
+
isReviewReady
|
|
8432
8487
|
}) => {
|
|
8433
8488
|
const transactionType = form.watch("transactionType");
|
|
8434
8489
|
const accountNumber = form.watch("accountNumber");
|
|
8435
8490
|
const counterpartyName = form.watch("counterpartyName");
|
|
8436
8491
|
const amount = form.watch("amount");
|
|
8492
|
+
const receiverAccountNumber = form.watch("receiverAccountNumber");
|
|
8493
|
+
const adjustmentDirection = form.watch("adjustmentDirection");
|
|
8494
|
+
const adjustmentType = form.watch("adjustmentType");
|
|
8495
|
+
const requiresCounterparty = ["ach", "wire"].includes(transactionType);
|
|
8496
|
+
const isTransfer = transactionType === "transfer";
|
|
8497
|
+
const isAdjustment = transactionType === "adjustment";
|
|
8437
8498
|
const accountDataGrid = accountData ? [
|
|
8438
8499
|
{
|
|
8439
8500
|
title: "Account Information",
|
|
@@ -8453,292 +8514,401 @@ var NewTransactionView = ({
|
|
|
8453
8514
|
items: [
|
|
8454
8515
|
{ label: "Counterparty Name", value: counterpartyData.counterpartyName },
|
|
8455
8516
|
{ label: "Counterparty ID", value: counterpartyData.counterpartyId },
|
|
8456
|
-
{ label: "Type", value: counterpartyData.
|
|
8457
|
-
{ label: "Status", value: counterpartyData.status },
|
|
8458
|
-
{ label: "Tax ID", value: counterpartyData.taxId },
|
|
8459
|
-
{ label: "Primary Contact", value: counterpartyData.primaryContact },
|
|
8517
|
+
{ label: "Instrument Type", value: counterpartyData.paymentInstrumentType?.toUpperCase() || "-" },
|
|
8460
8518
|
{ label: "Contact Email", value: counterpartyData.contactEmail },
|
|
8461
|
-
{ label: "Contact Phone", value: counterpartyData.contactPhone }
|
|
8462
|
-
{ label: "Address", value: counterpartyData.address }
|
|
8519
|
+
{ label: "Contact Phone", value: counterpartyData.contactPhone }
|
|
8463
8520
|
]
|
|
8464
8521
|
}
|
|
8465
8522
|
] : [];
|
|
8466
|
-
const
|
|
8523
|
+
const receiverAccountDataGrid = receiverAccountData ? [
|
|
8467
8524
|
{
|
|
8468
|
-
title: "
|
|
8525
|
+
title: "Receiver Account Information",
|
|
8469
8526
|
items: [
|
|
8470
|
-
{ label: "
|
|
8471
|
-
{ label: "Account
|
|
8472
|
-
{ label: "
|
|
8473
|
-
{ label: "
|
|
8474
|
-
{ label: "
|
|
8527
|
+
{ label: "Account Number", value: receiverAccountData.accountNumber },
|
|
8528
|
+
{ label: "Account Name", value: receiverAccountData.accountName },
|
|
8529
|
+
{ label: "Account Type", value: receiverAccountData.accountType },
|
|
8530
|
+
{ label: "Customer Name", value: receiverAccountData.customerName },
|
|
8531
|
+
{ label: "Customer ID", value: receiverAccountData.customerId }
|
|
8475
8532
|
]
|
|
8476
8533
|
}
|
|
8534
|
+
] : [];
|
|
8535
|
+
const reviewItems = [
|
|
8536
|
+
{ label: "Transaction Type", value: TRANSACTION_TYPES.find((t) => t.value === transactionType)?.label || "-" },
|
|
8537
|
+
{ label: "Account Number", value: accountNumber || "-" },
|
|
8538
|
+
...isAdjustment ? [
|
|
8539
|
+
{ label: "Direction", value: adjustmentDirection === "debit" ? "Debit" : adjustmentDirection === "credit" ? "Credit" : "-" },
|
|
8540
|
+
{ label: "Adjustment Type", value: ADJUSTMENT_TYPE_OPTIONS.find((t) => t.value === adjustmentType)?.label || "-" }
|
|
8541
|
+
] : [],
|
|
8542
|
+
...isTransfer ? [{ label: "Receiver Account", value: receiverAccountNumber || "-" }] : [],
|
|
8543
|
+
...requiresCounterparty ? [{ label: "Counterparty", value: counterpartyName || "-" }] : [],
|
|
8544
|
+
{ label: "Amount", value: amount ? formatCurrency2(amount) : "-" },
|
|
8545
|
+
{ label: "Description", value: form.watch("description") || "N/A" }
|
|
8477
8546
|
];
|
|
8478
|
-
|
|
8479
|
-
|
|
8480
|
-
|
|
8481
|
-
|
|
8482
|
-
|
|
8547
|
+
const reviewData = [
|
|
8548
|
+
{
|
|
8549
|
+
title: "Transaction Summary",
|
|
8550
|
+
items: reviewItems
|
|
8551
|
+
}
|
|
8552
|
+
];
|
|
8553
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "container mx-auto p-6 space-y-6", children: [
|
|
8554
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-3xl font-bold tracking-tight", children: "New Transaction" }) }),
|
|
8555
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-4xl space-y-6", children: [
|
|
8556
|
+
/* @__PURE__ */ jsxRuntime.jsx(FormProvider, { form, children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: (e) => e.preventDefault(), children: [
|
|
8557
|
+
!accountLookedUp ? /* @__PURE__ */ jsxRuntime.jsx(FormCard, { title: "Account Lookup", variant: "default", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3 items-start w-full", children: [
|
|
8558
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8559
|
+
FormInput,
|
|
8560
|
+
{
|
|
8561
|
+
name: "accountNumber",
|
|
8562
|
+
placeholder: "Enter account number"
|
|
8563
|
+
}
|
|
8564
|
+
) }),
|
|
8565
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8566
|
+
Button,
|
|
8567
|
+
{
|
|
8568
|
+
onClick: onAccountLookup,
|
|
8569
|
+
disabled: !accountNumber || isAccountLoading,
|
|
8570
|
+
className: "shrink-0 mt-0 w-48",
|
|
8571
|
+
children: isAccountLoading ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8572
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 mr-2 animate-spin" }),
|
|
8573
|
+
"Looking up..."
|
|
8574
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8575
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "h-4 w-4 mr-2" }),
|
|
8576
|
+
"Lookup Account"
|
|
8577
|
+
] })
|
|
8578
|
+
}
|
|
8579
|
+
)
|
|
8580
|
+
] }) }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8581
|
+
FormCard,
|
|
8483
8582
|
{
|
|
8484
|
-
|
|
8485
|
-
|
|
8583
|
+
title: "Account Information",
|
|
8584
|
+
variant: "subtle",
|
|
8585
|
+
headerActions: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8586
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "h-5 w-5 text-success" }),
|
|
8587
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "ghost", size: "sm", onClick: onEditAccount, children: [
|
|
8588
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Edit, { className: "h-4 w-4 mr-1" }),
|
|
8589
|
+
"Edit"
|
|
8590
|
+
] })
|
|
8591
|
+
] }),
|
|
8592
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(DataGrid, { data: accountDataGrid, columns: 2 })
|
|
8486
8593
|
}
|
|
8487
|
-
)
|
|
8488
|
-
/* @__PURE__ */ jsxRuntime.
|
|
8489
|
-
|
|
8594
|
+
),
|
|
8595
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8596
|
+
FormCard,
|
|
8597
|
+
{
|
|
8598
|
+
title: "Transaction Type",
|
|
8599
|
+
variant: "default",
|
|
8600
|
+
className: cn(!accountLookedUp && "opacity-50 pointer-events-none"),
|
|
8601
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 lg:grid-cols-4 gap-3 lg:gap-4", children: TRANSACTION_TYPES.map((type) => {
|
|
8602
|
+
const Icon2 = type.icon;
|
|
8603
|
+
const isSelected = transactionType === type.value;
|
|
8604
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8605
|
+
"button",
|
|
8606
|
+
{
|
|
8607
|
+
type: "button",
|
|
8608
|
+
onClick: () => onTransactionTypeChange(type.value),
|
|
8609
|
+
disabled: !accountLookedUp,
|
|
8610
|
+
className: cn(
|
|
8611
|
+
"flex flex-col items-center justify-center p-4 lg:p-3 rounded-lg border-2 transition-all",
|
|
8612
|
+
"hover:border-primary/50 hover:shadow-md",
|
|
8613
|
+
isSelected ? "border-primary bg-primary/5 shadow-sm" : "border-border bg-card"
|
|
8614
|
+
),
|
|
8615
|
+
children: [
|
|
8616
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon2, { className: cn(
|
|
8617
|
+
"h-6 w-6 lg:h-5 lg:w-5 mb-2",
|
|
8618
|
+
isSelected ? "text-primary" : "text-muted-foreground"
|
|
8619
|
+
) }),
|
|
8620
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
8621
|
+
"text-sm font-medium",
|
|
8622
|
+
isSelected ? "text-primary" : "text-foreground"
|
|
8623
|
+
), children: type.label })
|
|
8624
|
+
]
|
|
8625
|
+
},
|
|
8626
|
+
type.value
|
|
8627
|
+
);
|
|
8628
|
+
}) })
|
|
8629
|
+
}
|
|
8630
|
+
),
|
|
8631
|
+
requiresCounterparty && (!counterpartyLookedUp ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8632
|
+
FormCard,
|
|
8490
8633
|
{
|
|
8491
|
-
|
|
8492
|
-
|
|
8493
|
-
className: "
|
|
8634
|
+
title: "Counterparty Search",
|
|
8635
|
+
variant: "default",
|
|
8636
|
+
className: cn(!transactionType && "opacity-50 pointer-events-none"),
|
|
8494
8637
|
children: [
|
|
8495
|
-
/* @__PURE__ */ jsxRuntime.
|
|
8496
|
-
|
|
8638
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
8639
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
8640
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8641
|
+
"input",
|
|
8642
|
+
{
|
|
8643
|
+
type: "text",
|
|
8644
|
+
placeholder: "Start typing to search counterparties...",
|
|
8645
|
+
value: counterpartyName,
|
|
8646
|
+
onChange: (e) => onCounterpartySearchChange(e.target.value),
|
|
8647
|
+
disabled: !transactionType,
|
|
8648
|
+
className: cn(
|
|
8649
|
+
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm",
|
|
8650
|
+
"ring-offset-background placeholder:text-muted-foreground",
|
|
8651
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
8652
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
8653
|
+
isCounterpartySearching && "pr-10"
|
|
8654
|
+
)
|
|
8655
|
+
}
|
|
8656
|
+
),
|
|
8657
|
+
isCounterpartySearching && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-3 top-1/2 -translate-y-1/2", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin text-muted-foreground" }) })
|
|
8658
|
+
] }),
|
|
8659
|
+
showCounterpartyDropdown && counterpartySearchResults.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute z-50 w-full mt-1 bg-popover border border-border rounded-md shadow-lg max-h-60 overflow-auto", children: counterpartySearchResults.map((result) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8660
|
+
"button",
|
|
8661
|
+
{
|
|
8662
|
+
type: "button",
|
|
8663
|
+
onClick: () => onCounterpartySelect(result),
|
|
8664
|
+
className: "w-full px-3 py-2 text-left hover:bg-accent transition-colors",
|
|
8665
|
+
children: [
|
|
8666
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-sm", children: result.name }),
|
|
8667
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-muted-foreground", children: result.id })
|
|
8668
|
+
]
|
|
8669
|
+
},
|
|
8670
|
+
result.id
|
|
8671
|
+
)) }),
|
|
8672
|
+
showCounterpartyDropdown && counterpartySearchResults.length === 0 && !isCounterpartySearching && counterpartyName.length >= 2 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute z-50 w-full mt-1 bg-popover border border-border rounded-md shadow-lg p-3", children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
8673
|
+
'No counterparties found matching "',
|
|
8674
|
+
counterpartyName,
|
|
8675
|
+
'"'
|
|
8676
|
+
] }) })
|
|
8677
|
+
] }),
|
|
8678
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mt-2", children: "Type at least 2 characters to search" })
|
|
8497
8679
|
]
|
|
8498
8680
|
}
|
|
8499
|
-
)
|
|
8500
|
-
|
|
8501
|
-
|
|
8502
|
-
|
|
8503
|
-
|
|
8504
|
-
|
|
8505
|
-
|
|
8506
|
-
|
|
8507
|
-
|
|
8508
|
-
|
|
8509
|
-
|
|
8510
|
-
] })
|
|
8511
|
-
|
|
8512
|
-
|
|
8513
|
-
|
|
8514
|
-
|
|
8515
|
-
|
|
8516
|
-
|
|
8517
|
-
|
|
8518
|
-
|
|
8519
|
-
|
|
8520
|
-
|
|
8521
|
-
|
|
8522
|
-
const Icon2 = type.icon;
|
|
8523
|
-
const isSelected = transactionType === type.value;
|
|
8524
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8525
|
-
"button",
|
|
8526
|
-
{
|
|
8527
|
-
type: "button",
|
|
8528
|
-
onClick: () => form.setValue("transactionType", type.value),
|
|
8529
|
-
disabled: !accountLookedUp,
|
|
8530
|
-
className: cn(
|
|
8531
|
-
"flex flex-col items-center justify-center p-4 lg:p-3 rounded-lg border-2 transition-all",
|
|
8532
|
-
"hover:border-primary/50 hover:shadow-md",
|
|
8533
|
-
isSelected ? "border-primary bg-primary/5 shadow-sm" : "border-border bg-card"
|
|
8534
|
-
),
|
|
8535
|
-
children: [
|
|
8536
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon2, { className: cn(
|
|
8537
|
-
"h-6 w-6 lg:h-5 lg:w-5 mb-2",
|
|
8538
|
-
isSelected ? "text-primary" : "text-muted-foreground"
|
|
8539
|
-
) }),
|
|
8540
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
8541
|
-
"text-sm font-medium",
|
|
8542
|
-
isSelected ? "text-primary" : "text-foreground"
|
|
8543
|
-
), children: type.label })
|
|
8544
|
-
]
|
|
8545
|
-
},
|
|
8546
|
-
type.value
|
|
8547
|
-
);
|
|
8548
|
-
}) })
|
|
8549
|
-
}
|
|
8550
|
-
),
|
|
8551
|
-
!counterpartyLookedUp ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8552
|
-
FormCard,
|
|
8553
|
-
{
|
|
8554
|
-
title: "Counterparty Lookup",
|
|
8555
|
-
variant: "default",
|
|
8556
|
-
className: cn(!transactionType && "opacity-50 pointer-events-none"),
|
|
8557
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3 items-start w-full", children: [
|
|
8558
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8559
|
-
FormInput,
|
|
8560
|
-
{
|
|
8561
|
-
name: "counterpartyName",
|
|
8562
|
-
placeholder: "Enter counterparty name",
|
|
8563
|
-
disabled: !transactionType
|
|
8564
|
-
}
|
|
8565
|
-
) }),
|
|
8566
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8567
|
-
Button,
|
|
8568
|
-
{
|
|
8569
|
-
onClick: onCounterpartyLookup,
|
|
8570
|
-
disabled: !transactionType || !counterpartyName,
|
|
8571
|
-
className: "shrink-0 mt-0 w-48",
|
|
8572
|
-
children: [
|
|
8573
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "h-4 w-4 mr-2" }),
|
|
8574
|
-
"Lookup Counterparty"
|
|
8575
|
-
]
|
|
8576
|
-
}
|
|
8577
|
-
)
|
|
8578
|
-
] })
|
|
8579
|
-
}
|
|
8580
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8581
|
-
FormCard,
|
|
8582
|
-
{
|
|
8583
|
-
title: "Counterparty Information",
|
|
8584
|
-
variant: "subtle",
|
|
8585
|
-
headerActions: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8586
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "h-5 w-5 text-success" }),
|
|
8587
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "ghost", size: "sm", onClick: onEditCounterparty, children: [
|
|
8588
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Edit, { className: "h-4 w-4 mr-1" }),
|
|
8589
|
-
"Edit"
|
|
8590
|
-
] })
|
|
8591
|
-
] }),
|
|
8592
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(DataGrid, { data: counterpartyDataGrid, columns: 2 })
|
|
8593
|
-
}
|
|
8594
|
-
),
|
|
8595
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8596
|
-
FormCard,
|
|
8597
|
-
{
|
|
8598
|
-
title: "Transaction Details",
|
|
8599
|
-
variant: "default",
|
|
8600
|
-
className: cn(!counterpartyLookedUp && "opacity-50 pointer-events-none"),
|
|
8601
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
8602
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-[1fr_auto] gap-4", children: [
|
|
8603
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8681
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8682
|
+
FormCard,
|
|
8683
|
+
{
|
|
8684
|
+
title: "Counterparty Information",
|
|
8685
|
+
variant: "subtle",
|
|
8686
|
+
headerActions: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8687
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "h-5 w-5 text-success" }),
|
|
8688
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "ghost", size: "sm", onClick: onEditCounterparty, children: [
|
|
8689
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Edit, { className: "h-4 w-4 mr-1" }),
|
|
8690
|
+
"Edit"
|
|
8691
|
+
] })
|
|
8692
|
+
] }),
|
|
8693
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(DataGrid, { data: counterpartyDataGrid, columns: 2 })
|
|
8694
|
+
}
|
|
8695
|
+
)),
|
|
8696
|
+
isTransfer && (!receiverAccountLookedUp ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8697
|
+
FormCard,
|
|
8698
|
+
{
|
|
8699
|
+
title: "Receiver Account",
|
|
8700
|
+
variant: "default",
|
|
8701
|
+
className: cn(!transactionType && "opacity-50 pointer-events-none"),
|
|
8702
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3 items-start w-full", children: [
|
|
8703
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8604
8704
|
FormInput,
|
|
8605
8705
|
{
|
|
8606
|
-
name: "
|
|
8607
|
-
|
|
8608
|
-
|
|
8609
|
-
type: "number",
|
|
8610
|
-
disabled: !counterpartyLookedUp
|
|
8706
|
+
name: "receiverAccountNumber",
|
|
8707
|
+
placeholder: "Enter receiver account number",
|
|
8708
|
+
disabled: !transactionType
|
|
8611
8709
|
}
|
|
8612
|
-
),
|
|
8710
|
+
) }),
|
|
8613
8711
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8614
|
-
|
|
8712
|
+
Button,
|
|
8615
8713
|
{
|
|
8616
|
-
|
|
8617
|
-
|
|
8618
|
-
|
|
8619
|
-
|
|
8620
|
-
|
|
8714
|
+
onClick: onReceiverAccountLookup,
|
|
8715
|
+
disabled: !receiverAccountNumber || isReceiverAccountLoading,
|
|
8716
|
+
className: "shrink-0 mt-0 w-48",
|
|
8717
|
+
children: isReceiverAccountLoading ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8718
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 mr-2 animate-spin" }),
|
|
8719
|
+
"Looking up..."
|
|
8720
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8721
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "h-4 w-4 mr-2" }),
|
|
8722
|
+
"Lookup Receiver"
|
|
8723
|
+
] })
|
|
8621
8724
|
}
|
|
8622
8725
|
)
|
|
8726
|
+
] })
|
|
8727
|
+
}
|
|
8728
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8729
|
+
FormCard,
|
|
8730
|
+
{
|
|
8731
|
+
title: "Receiver Account Information",
|
|
8732
|
+
variant: "subtle",
|
|
8733
|
+
headerActions: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8734
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "h-5 w-5 text-success" }),
|
|
8735
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "ghost", size: "sm", onClick: onEditReceiverAccount, children: [
|
|
8736
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Edit, { className: "h-4 w-4 mr-1" }),
|
|
8737
|
+
"Edit"
|
|
8738
|
+
] })
|
|
8623
8739
|
] }),
|
|
8624
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8625
|
-
|
|
8626
|
-
|
|
8627
|
-
|
|
8628
|
-
|
|
8629
|
-
placeholder: "Enter transaction description",
|
|
8630
|
-
disabled: !counterpartyLookedUp
|
|
8631
|
-
}
|
|
8632
|
-
)
|
|
8633
|
-
] })
|
|
8634
|
-
}
|
|
8635
|
-
),
|
|
8636
|
-
/* @__PURE__ */ jsxRuntime.jsx(FormCard, { title: "Review & Submit", variant: "default", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
8637
|
-
/* @__PURE__ */ jsxRuntime.jsx(DataGrid, { data: reviewData, columns: 2 }),
|
|
8638
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-muted/30 rounded-lg p-4 border border-border/50", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8639
|
-
reactHookForm.Controller,
|
|
8740
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(DataGrid, { data: receiverAccountDataGrid, columns: 2 })
|
|
8741
|
+
}
|
|
8742
|
+
)),
|
|
8743
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8744
|
+
FormCard,
|
|
8640
8745
|
{
|
|
8641
|
-
|
|
8642
|
-
|
|
8643
|
-
|
|
8644
|
-
|
|
8746
|
+
title: "Transaction Details",
|
|
8747
|
+
variant: "default",
|
|
8748
|
+
className: cn(
|
|
8749
|
+
requiresCounterparty ? !counterpartyLookedUp && "opacity-50 pointer-events-none" : isTransfer ? !receiverAccountLookedUp && "opacity-50 pointer-events-none" : !transactionType && "opacity-50 pointer-events-none"
|
|
8750
|
+
),
|
|
8751
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
8752
|
+
isAdjustment && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4", children: [
|
|
8645
8753
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8646
|
-
|
|
8754
|
+
FormSelect,
|
|
8647
8755
|
{
|
|
8648
|
-
|
|
8649
|
-
|
|
8650
|
-
|
|
8756
|
+
name: "adjustmentDirection",
|
|
8757
|
+
label: "Direction",
|
|
8758
|
+
placeholder: "Select direction",
|
|
8759
|
+
options: ADJUSTMENT_DIRECTION_OPTIONS,
|
|
8760
|
+
disabled: !transactionType
|
|
8651
8761
|
}
|
|
8652
8762
|
),
|
|
8653
8763
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8654
|
-
|
|
8764
|
+
FormSelect,
|
|
8655
8765
|
{
|
|
8656
|
-
|
|
8657
|
-
|
|
8658
|
-
|
|
8766
|
+
name: "adjustmentType",
|
|
8767
|
+
label: "Adjustment Type",
|
|
8768
|
+
placeholder: "Select type",
|
|
8769
|
+
options: ADJUSTMENT_TYPE_OPTIONS,
|
|
8770
|
+
disabled: !transactionType
|
|
8659
8771
|
}
|
|
8660
8772
|
)
|
|
8661
8773
|
] }),
|
|
8662
|
-
|
|
8774
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8775
|
+
reactHookForm.Controller,
|
|
8776
|
+
{
|
|
8777
|
+
name: "amount",
|
|
8778
|
+
control: form.control,
|
|
8779
|
+
render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
8780
|
+
CurrencyInput,
|
|
8781
|
+
{
|
|
8782
|
+
label: "Amount",
|
|
8783
|
+
value: field.value,
|
|
8784
|
+
onChange: field.onChange,
|
|
8785
|
+
disabled: requiresCounterparty ? !counterpartyLookedUp : isTransfer ? !receiverAccountLookedUp : !transactionType,
|
|
8786
|
+
error: form.formState.errors.amount?.message
|
|
8787
|
+
}
|
|
8788
|
+
)
|
|
8789
|
+
}
|
|
8790
|
+
),
|
|
8791
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8792
|
+
FormInput,
|
|
8793
|
+
{
|
|
8794
|
+
name: "description",
|
|
8795
|
+
label: "Description (Optional)",
|
|
8796
|
+
placeholder: "Enter transaction description",
|
|
8797
|
+
disabled: requiresCounterparty ? !counterpartyLookedUp : isTransfer ? !receiverAccountLookedUp : !transactionType
|
|
8798
|
+
}
|
|
8799
|
+
)
|
|
8663
8800
|
] })
|
|
8664
8801
|
}
|
|
8665
|
-
)
|
|
8666
|
-
/* @__PURE__ */ jsxRuntime.
|
|
8667
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8668
|
-
/* @__PURE__ */ jsxRuntime.
|
|
8802
|
+
),
|
|
8803
|
+
/* @__PURE__ */ jsxRuntime.jsx(FormCard, { title: "Review & Submit", variant: "default", className: cn(!isReviewReady && "opacity-50 pointer-events-none"), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
8804
|
+
/* @__PURE__ */ jsxRuntime.jsx(DataGrid, { data: reviewData, columns: 2 }),
|
|
8805
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-muted/30 rounded-lg p-4 border border-border/50", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8806
|
+
reactHookForm.Controller,
|
|
8807
|
+
{
|
|
8808
|
+
name: "certifyInformation",
|
|
8809
|
+
control: form.control,
|
|
8810
|
+
render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
8811
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
|
|
8812
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8813
|
+
Checkbox,
|
|
8814
|
+
{
|
|
8815
|
+
id: "certifyInformation",
|
|
8816
|
+
checked: field.value,
|
|
8817
|
+
onCheckedChange: field.onChange
|
|
8818
|
+
}
|
|
8819
|
+
),
|
|
8820
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8821
|
+
"label",
|
|
8822
|
+
{
|
|
8823
|
+
htmlFor: "certifyInformation",
|
|
8824
|
+
className: "text-sm font-medium leading-relaxed cursor-pointer select-none",
|
|
8825
|
+
children: "I certify that all information entered is correct and accurate to the best of my knowledge"
|
|
8826
|
+
}
|
|
8827
|
+
)
|
|
8828
|
+
] }),
|
|
8829
|
+
form.formState.errors.certifyInformation && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-destructive ml-7", children: form.formState.errors.certifyInformation.message })
|
|
8830
|
+
] })
|
|
8831
|
+
}
|
|
8832
|
+
) }),
|
|
8833
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3 justify-end pt-4 border-t border-border", children: [
|
|
8834
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", variant: "outline", onClick: onCancel, className: "w-32", children: "Cancel" }),
|
|
8835
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8836
|
+
Button,
|
|
8837
|
+
{
|
|
8838
|
+
type: "button",
|
|
8839
|
+
onClick: onSubmit,
|
|
8840
|
+
className: "w-48",
|
|
8841
|
+
disabled: !transactionType || !accountNumber || requiresCounterparty && !counterpartyName || isTransfer && !receiverAccountLookedUp || isAdjustment && (!adjustmentDirection || !adjustmentType) || !amount || !form.watch("certifyInformation") || isSubmitting,
|
|
8842
|
+
children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8843
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 mr-2 animate-spin" }),
|
|
8844
|
+
"Submitting..."
|
|
8845
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8846
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "h-4 w-4 mr-2" }),
|
|
8847
|
+
"Submit Transaction"
|
|
8848
|
+
] })
|
|
8849
|
+
}
|
|
8850
|
+
)
|
|
8851
|
+
] })
|
|
8852
|
+
] }) })
|
|
8853
|
+
] }) }),
|
|
8854
|
+
/* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: confirmationOpen, onOpenChange: () => {
|
|
8855
|
+
}, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "sm:max-w-md", hideCloseButton: true, children: [
|
|
8856
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
|
|
8857
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 mb-2", children: [
|
|
8858
|
+
submissionStatus === "success" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-12 w-12 rounded-full bg-success/10 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "h-6 w-6 text-success" }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-12 w-12 rounded-full bg-destructive/10 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XCircle, { className: "h-6 w-6 text-destructive" }) }),
|
|
8859
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "text-xl", children: submissionStatus === "success" ? "Transaction Successful" : "Transaction Failed" })
|
|
8860
|
+
] }),
|
|
8861
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { className: "text-left", children: submissionStatus === "success" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 pt-2", children: [
|
|
8862
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-foreground", children: "Your transaction has been successfully submitted and is being processed." }),
|
|
8863
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-muted/50 rounded-lg p-4 space-y-2", children: [
|
|
8864
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between text-sm", children: [
|
|
8865
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Transaction ID:" }),
|
|
8866
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-medium", children: transactionId })
|
|
8867
|
+
] }),
|
|
8868
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between text-sm", children: [
|
|
8869
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Amount:" }),
|
|
8870
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: formatCurrency2(amount) })
|
|
8871
|
+
] }),
|
|
8872
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between text-sm", children: [
|
|
8873
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Type:" }),
|
|
8874
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: TRANSACTION_TYPES.find((t) => t.value === transactionType)?.label })
|
|
8875
|
+
] }),
|
|
8876
|
+
requiresCounterparty && counterpartyName && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between text-sm", children: [
|
|
8877
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Counterparty:" }),
|
|
8878
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: counterpartyName })
|
|
8879
|
+
] })
|
|
8880
|
+
] }),
|
|
8881
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 p-3 bg-blue-500/10 border border-blue-500/20 rounded-lg", children: [
|
|
8882
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "h-5 w-5 text-blue-500 mt-0.5 flex-shrink-0" }),
|
|
8883
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-blue-700 dark:text-blue-300", children: "You will receive a confirmation email once the transaction is completed." })
|
|
8884
|
+
] })
|
|
8885
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 pt-2", children: [
|
|
8886
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 p-4 bg-destructive/10 border border-destructive/20 rounded-lg", children: [
|
|
8887
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.XCircle, { className: "h-5 w-5 text-destructive mt-0.5 flex-shrink-0" }),
|
|
8888
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
8889
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-destructive", children: "Error Processing Transaction" }),
|
|
8890
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: errorMessage })
|
|
8891
|
+
] })
|
|
8892
|
+
] }),
|
|
8893
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Please review the error message above and try again. If the problem persists, contact support." })
|
|
8894
|
+
] }) })
|
|
8895
|
+
] }),
|
|
8896
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogFooter, { className: "sm:justify-end gap-2", children: [
|
|
8897
|
+
submissionStatus === "error" && /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", variant: "outline", onClick: () => onConfirmationOpenChange(false), children: "Edit" }),
|
|
8898
|
+
submissionStatus === "success" && /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", variant: "outline", onClick: onNewTransaction, children: "New Transaction" }),
|
|
8899
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8669
8900
|
Button,
|
|
8670
8901
|
{
|
|
8671
8902
|
type: "button",
|
|
8672
|
-
onClick:
|
|
8673
|
-
|
|
8674
|
-
|
|
8675
|
-
children: [
|
|
8676
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "h-4 w-4 mr-2" }),
|
|
8677
|
-
"Submit Transaction"
|
|
8678
|
-
]
|
|
8903
|
+
onClick: onConfirmationClose,
|
|
8904
|
+
variant: submissionStatus === "success" ? "default" : "outline",
|
|
8905
|
+
children: submissionStatus === "success" ? "View Transaction" : "Close"
|
|
8679
8906
|
}
|
|
8680
8907
|
)
|
|
8681
8908
|
] })
|
|
8682
8909
|
] }) })
|
|
8683
|
-
] })
|
|
8684
|
-
|
|
8685
|
-
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
|
|
8686
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 mb-2", children: [
|
|
8687
|
-
submissionStatus === "success" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-12 w-12 rounded-full bg-success/10 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "h-6 w-6 text-success" }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-12 w-12 rounded-full bg-destructive/10 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XCircle, { className: "h-6 w-6 text-destructive" }) }),
|
|
8688
|
-
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "text-xl", children: submissionStatus === "success" ? "Transaction Successful" : "Transaction Failed" })
|
|
8689
|
-
] }),
|
|
8690
|
-
/* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { className: "text-left", children: submissionStatus === "success" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 pt-2", children: [
|
|
8691
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-foreground", children: "Your transaction has been successfully submitted and is being processed." }),
|
|
8692
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-muted/50 rounded-lg p-4 space-y-2", children: [
|
|
8693
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between text-sm", children: [
|
|
8694
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Transaction ID:" }),
|
|
8695
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-medium", children: transactionId })
|
|
8696
|
-
] }),
|
|
8697
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between text-sm", children: [
|
|
8698
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Amount:" }),
|
|
8699
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
|
|
8700
|
-
"$",
|
|
8701
|
-
amount
|
|
8702
|
-
] })
|
|
8703
|
-
] }),
|
|
8704
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between text-sm", children: [
|
|
8705
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Type:" }),
|
|
8706
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: TRANSACTION_TYPES.find((t) => t.value === transactionType)?.label })
|
|
8707
|
-
] }),
|
|
8708
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between text-sm", children: [
|
|
8709
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Counterparty:" }),
|
|
8710
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: counterpartyName })
|
|
8711
|
-
] })
|
|
8712
|
-
] }),
|
|
8713
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 p-3 bg-blue-500/10 border border-blue-500/20 rounded-lg", children: [
|
|
8714
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "h-5 w-5 text-blue-500 mt-0.5 flex-shrink-0" }),
|
|
8715
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-blue-700 dark:text-blue-300", children: "You will receive a confirmation email once the transaction is completed." })
|
|
8716
|
-
] })
|
|
8717
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 pt-2", children: [
|
|
8718
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 p-4 bg-destructive/10 border border-destructive/20 rounded-lg", children: [
|
|
8719
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.XCircle, { className: "h-5 w-5 text-destructive mt-0.5 flex-shrink-0" }),
|
|
8720
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
8721
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-destructive", children: "Error Processing Transaction" }),
|
|
8722
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: errorMessage })
|
|
8723
|
-
] })
|
|
8724
|
-
] }),
|
|
8725
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Please review the error message above and try again. If the problem persists, contact support." })
|
|
8726
|
-
] }) })
|
|
8727
|
-
] }),
|
|
8728
|
-
/* @__PURE__ */ jsxRuntime.jsxs(DialogFooter, { className: "sm:justify-end gap-2", children: [
|
|
8729
|
-
submissionStatus === "error" && /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", variant: "outline", onClick: () => onConfirmationOpenChange(false), children: "Try Again" }),
|
|
8730
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8731
|
-
Button,
|
|
8732
|
-
{
|
|
8733
|
-
type: "button",
|
|
8734
|
-
onClick: onConfirmationClose,
|
|
8735
|
-
variant: submissionStatus === "success" ? "default" : "outline",
|
|
8736
|
-
children: submissionStatus === "success" ? "View Transactions" : "Close"
|
|
8737
|
-
}
|
|
8738
|
-
)
|
|
8739
|
-
] })
|
|
8740
|
-
] }) })
|
|
8741
|
-
] }) });
|
|
8910
|
+
] })
|
|
8911
|
+
] });
|
|
8742
8912
|
};
|
|
8743
8913
|
var typeIcons = {
|
|
8744
8914
|
checking: lucideReact.CreditCard,
|
|
@@ -13827,7 +13997,7 @@ var TransactionHistory = () => {
|
|
|
13827
13997
|
setRowsPerPage(value);
|
|
13828
13998
|
setCurrentPage(1);
|
|
13829
13999
|
};
|
|
13830
|
-
const
|
|
14000
|
+
const formatCurrency3 = (value) => {
|
|
13831
14001
|
const formatted = new Intl.NumberFormat("en-US", {
|
|
13832
14002
|
style: "currency",
|
|
13833
14003
|
currency: "USD",
|
|
@@ -14004,23 +14174,19 @@ var TransactionHistory = () => {
|
|
|
14004
14174
|
),
|
|
14005
14175
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
14006
14176
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14007
|
-
|
|
14177
|
+
CurrencyInput,
|
|
14008
14178
|
{
|
|
14009
14179
|
label: "Min Amount",
|
|
14010
|
-
type: "number",
|
|
14011
14180
|
value: filters.minAmount,
|
|
14012
|
-
onChange: (
|
|
14013
|
-
placeholder: "0.00"
|
|
14181
|
+
onChange: (value) => handleFilterChange("minAmount", value)
|
|
14014
14182
|
}
|
|
14015
14183
|
),
|
|
14016
14184
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14017
|
-
|
|
14185
|
+
CurrencyInput,
|
|
14018
14186
|
{
|
|
14019
14187
|
label: "Max Amount",
|
|
14020
|
-
type: "number",
|
|
14021
14188
|
value: filters.maxAmount,
|
|
14022
|
-
onChange: (
|
|
14023
|
-
placeholder: "0.00"
|
|
14189
|
+
onChange: (value) => handleFilterChange("maxAmount", value)
|
|
14024
14190
|
}
|
|
14025
14191
|
)
|
|
14026
14192
|
] }),
|
|
@@ -14120,7 +14286,7 @@ var TransactionHistory = () => {
|
|
|
14120
14286
|
children: [
|
|
14121
14287
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 text-xs", children: transaction.created }),
|
|
14122
14288
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 text-xs", children: transaction.accountNumber }),
|
|
14123
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 text-xs text-right", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: transaction.amount < 0 ? "text-destructive" : "", children:
|
|
14289
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 text-xs text-right", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: transaction.amount < 0 ? "text-destructive" : "", children: formatCurrency3(transaction.amount) }) }),
|
|
14124
14290
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2", children: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "link", className: "h-auto p-0 font-normal text-xs", children: transaction.customer }) }),
|
|
14125
14291
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2", children: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "link", className: "h-auto p-0 font-normal text-xs", children: transaction.counterparty }) }),
|
|
14126
14292
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 text-xs truncate", children: transaction.description }),
|
|
@@ -14187,13 +14353,42 @@ var TransactionHistory_default = TransactionHistory;
|
|
|
14187
14353
|
var newTransactionSchema = zod.z.object({
|
|
14188
14354
|
transactionType: zod.z.string().min(1, "Transaction type is required"),
|
|
14189
14355
|
accountNumber: zod.z.string().min(1, "Account number is required"),
|
|
14190
|
-
counterpartyName: zod.z.string().
|
|
14356
|
+
counterpartyName: zod.z.string().optional(),
|
|
14191
14357
|
amount: zod.z.string().min(1, "Amount is required"),
|
|
14192
|
-
currency: zod.z.string().min(1, "Currency is required"),
|
|
14193
14358
|
description: zod.z.string().optional(),
|
|
14194
14359
|
certifyInformation: zod.z.boolean().refine((val) => val === true, {
|
|
14195
14360
|
message: "You must certify the information is correct"
|
|
14196
|
-
})
|
|
14361
|
+
}),
|
|
14362
|
+
// Adjustment-specific fields
|
|
14363
|
+
adjustmentDirection: zod.z.string().optional(),
|
|
14364
|
+
adjustmentType: zod.z.string().optional(),
|
|
14365
|
+
// Transfer-specific fields
|
|
14366
|
+
receiverAccountNumber: zod.z.string().optional()
|
|
14367
|
+
}).refine((data) => {
|
|
14368
|
+
const requiresCounterparty = ["ach", "wire"].includes(data.transactionType);
|
|
14369
|
+
if (requiresCounterparty && !data.counterpartyName) {
|
|
14370
|
+
return false;
|
|
14371
|
+
}
|
|
14372
|
+
return true;
|
|
14373
|
+
}, {
|
|
14374
|
+
message: "Counterparty is required for ACH and Wire transactions",
|
|
14375
|
+
path: ["counterpartyName"]
|
|
14376
|
+
}).refine((data) => {
|
|
14377
|
+
if (data.transactionType === "adjustment") {
|
|
14378
|
+
if (!data.adjustmentDirection || !data.adjustmentType) return false;
|
|
14379
|
+
}
|
|
14380
|
+
return true;
|
|
14381
|
+
}, {
|
|
14382
|
+
message: "Direction and Type are required for Adjustment transactions",
|
|
14383
|
+
path: ["adjustmentDirection"]
|
|
14384
|
+
}).refine((data) => {
|
|
14385
|
+
if (data.transactionType === "transfer") {
|
|
14386
|
+
if (!data.receiverAccountNumber) return false;
|
|
14387
|
+
}
|
|
14388
|
+
return true;
|
|
14389
|
+
}, {
|
|
14390
|
+
message: "Receiver account number is required for Transfer transactions",
|
|
14391
|
+
path: ["receiverAccountNumber"]
|
|
14197
14392
|
});
|
|
14198
14393
|
var mockAccountData = {
|
|
14199
14394
|
accountNumber: "****1234",
|
|
@@ -14204,27 +14399,25 @@ var mockAccountData = {
|
|
|
14204
14399
|
customerId: "CUST-001",
|
|
14205
14400
|
customerType: "Business"
|
|
14206
14401
|
};
|
|
14207
|
-
var mockCounterpartyData = {
|
|
14208
|
-
counterpartyName: "Global Tech Solutions Inc.",
|
|
14209
|
-
counterpartyId: "CP-5678",
|
|
14210
|
-
counterpartyType: "Business",
|
|
14211
|
-
status: "Active",
|
|
14212
|
-
taxId: "98-7654321",
|
|
14213
|
-
primaryContact: "Sarah Johnson",
|
|
14214
|
-
contactEmail: "sarah.johnson@globaltech.com",
|
|
14215
|
-
contactPhone: "+1 (555) 987-6543",
|
|
14216
|
-
address: "456 Innovation Drive, San Francisco, CA 94105"
|
|
14217
|
-
};
|
|
14218
14402
|
function NewTransaction() {
|
|
14219
14403
|
const navigate = reactRouterDom.useNavigate();
|
|
14220
14404
|
const [accountLookedUp, setAccountLookedUp] = React15.useState(false);
|
|
14221
14405
|
const [accountData, setAccountData] = React15.useState(null);
|
|
14222
14406
|
const [counterpartyLookedUp, setCounterpartyLookedUp] = React15.useState(false);
|
|
14223
14407
|
const [counterpartyData, setCounterpartyData] = React15.useState(null);
|
|
14408
|
+
const [counterpartySearchResults, setCounterpartySearchResults] = React15.useState([]);
|
|
14409
|
+
const [isCounterpartySearching, setIsCounterpartySearching] = React15.useState(false);
|
|
14410
|
+
const [showCounterpartyDropdown, setShowCounterpartyDropdown] = React15.useState(false);
|
|
14224
14411
|
const [confirmationOpen, setConfirmationOpen] = React15.useState(false);
|
|
14225
14412
|
const [submissionStatus, setSubmissionStatus] = React15.useState(null);
|
|
14226
14413
|
const [errorMessage, setErrorMessage] = React15.useState("");
|
|
14227
14414
|
const [transactionId, setTransactionId] = React15.useState("");
|
|
14415
|
+
const [isAccountLoading, setIsAccountLoading] = React15.useState(false);
|
|
14416
|
+
const [isCounterpartyLoading, setIsCounterpartyLoading] = React15.useState(false);
|
|
14417
|
+
const [isSubmitting, setIsSubmitting] = React15.useState(false);
|
|
14418
|
+
const [receiverAccountLookedUp, setReceiverAccountLookedUp] = React15.useState(false);
|
|
14419
|
+
const [receiverAccountData, setReceiverAccountData] = React15.useState(null);
|
|
14420
|
+
const [isReceiverAccountLoading, setIsReceiverAccountLoading] = React15.useState(false);
|
|
14228
14421
|
const form = reactHookForm.useForm({
|
|
14229
14422
|
resolver: zod$1.zodResolver(newTransactionSchema),
|
|
14230
14423
|
defaultValues: {
|
|
@@ -14232,30 +14425,131 @@ function NewTransaction() {
|
|
|
14232
14425
|
accountNumber: "",
|
|
14233
14426
|
counterpartyName: "",
|
|
14234
14427
|
amount: "",
|
|
14235
|
-
currency: "USD",
|
|
14236
14428
|
description: "",
|
|
14237
|
-
certifyInformation: false
|
|
14429
|
+
certifyInformation: false,
|
|
14430
|
+
adjustmentDirection: "",
|
|
14431
|
+
adjustmentType: "",
|
|
14432
|
+
receiverAccountNumber: ""
|
|
14238
14433
|
}
|
|
14239
14434
|
});
|
|
14240
|
-
const handleAccountLookup = () => {
|
|
14435
|
+
const handleAccountLookup = async () => {
|
|
14241
14436
|
const accNum = form.getValues("accountNumber");
|
|
14242
14437
|
if (!accNum) {
|
|
14243
14438
|
sonner.toast.error("Please enter an account number");
|
|
14244
14439
|
return;
|
|
14245
14440
|
}
|
|
14246
|
-
|
|
14247
|
-
|
|
14248
|
-
|
|
14441
|
+
setIsAccountLoading(true);
|
|
14442
|
+
try {
|
|
14443
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
14444
|
+
setAccountData(mockAccountData);
|
|
14445
|
+
setAccountLookedUp(true);
|
|
14446
|
+
sonner.toast.success("Account found");
|
|
14447
|
+
} catch (error) {
|
|
14448
|
+
sonner.toast.error("Failed to lookup account");
|
|
14449
|
+
} finally {
|
|
14450
|
+
setIsAccountLoading(false);
|
|
14451
|
+
}
|
|
14249
14452
|
};
|
|
14250
|
-
const
|
|
14251
|
-
|
|
14252
|
-
|
|
14253
|
-
|
|
14254
|
-
|
|
14453
|
+
const mockSearchResults = [
|
|
14454
|
+
{ id: "CP-5678", name: "Global Tech Solutions Inc.", type: "Business", paymentInstrumentType: "wire" },
|
|
14455
|
+
{ id: "CP-1234", name: "Global Industries LLC", type: "Business", paymentInstrumentType: "ach" },
|
|
14456
|
+
{ id: "CP-9012", name: "GlobalCorp Partners", type: "Business", paymentInstrumentType: "both" },
|
|
14457
|
+
{ id: "CP-3456", name: "Acme Corporation", type: "Business", paymentInstrumentType: "wire" },
|
|
14458
|
+
{ id: "CP-7890", name: "Tech Innovations Ltd", type: "Business", paymentInstrumentType: "ach" }
|
|
14459
|
+
];
|
|
14460
|
+
const isCounterpartyCompatible = (instrumentType, transactionType) => {
|
|
14461
|
+
if (instrumentType === "both") return true;
|
|
14462
|
+
if (transactionType === "ach" && instrumentType === "ach") return true;
|
|
14463
|
+
if (transactionType === "wire" && instrumentType === "wire") return true;
|
|
14464
|
+
return false;
|
|
14465
|
+
};
|
|
14466
|
+
const debouncedSearch = React15.useMemo(
|
|
14467
|
+
() => lodash.debounce(async (query, txType) => {
|
|
14468
|
+
if (query.length < 2) {
|
|
14469
|
+
setCounterpartySearchResults([]);
|
|
14470
|
+
setShowCounterpartyDropdown(false);
|
|
14471
|
+
return;
|
|
14472
|
+
}
|
|
14473
|
+
setIsCounterpartySearching(true);
|
|
14474
|
+
try {
|
|
14475
|
+
await new Promise((resolve) => setTimeout(resolve, 350));
|
|
14476
|
+
let results = mockSearchResults.filter(
|
|
14477
|
+
(cp) => cp.name.toLowerCase().includes(query.toLowerCase())
|
|
14478
|
+
);
|
|
14479
|
+
if (txType === "ach") {
|
|
14480
|
+
results = results.filter(
|
|
14481
|
+
(cp) => cp.paymentInstrumentType === "ach" || cp.paymentInstrumentType === "both"
|
|
14482
|
+
);
|
|
14483
|
+
} else if (txType === "wire") {
|
|
14484
|
+
results = results.filter(
|
|
14485
|
+
(cp) => cp.paymentInstrumentType === "wire" || cp.paymentInstrumentType === "both"
|
|
14486
|
+
);
|
|
14487
|
+
}
|
|
14488
|
+
setCounterpartySearchResults(results);
|
|
14489
|
+
setShowCounterpartyDropdown(true);
|
|
14490
|
+
} finally {
|
|
14491
|
+
setIsCounterpartySearching(false);
|
|
14492
|
+
}
|
|
14493
|
+
}, 350),
|
|
14494
|
+
[]
|
|
14495
|
+
);
|
|
14496
|
+
React15.useEffect(() => {
|
|
14497
|
+
return () => {
|
|
14498
|
+
debouncedSearch.cancel();
|
|
14499
|
+
};
|
|
14500
|
+
}, [debouncedSearch]);
|
|
14501
|
+
const handleCounterpartySearchChange = (value) => {
|
|
14502
|
+
form.setValue("counterpartyName", value);
|
|
14503
|
+
if (counterpartyLookedUp) {
|
|
14504
|
+
setCounterpartyLookedUp(false);
|
|
14505
|
+
setCounterpartyData(null);
|
|
14255
14506
|
}
|
|
14256
|
-
|
|
14257
|
-
|
|
14258
|
-
|
|
14507
|
+
debouncedSearch(value, form.getValues("transactionType"));
|
|
14508
|
+
};
|
|
14509
|
+
const handleTransactionTypeChange = (newType) => {
|
|
14510
|
+
form.setValue("transactionType", newType);
|
|
14511
|
+
if (counterpartyData && counterpartyLookedUp) {
|
|
14512
|
+
const requiresCounterparty = ["ach", "wire"].includes(newType);
|
|
14513
|
+
if (requiresCounterparty) {
|
|
14514
|
+
const isCompatible = isCounterpartyCompatible(
|
|
14515
|
+
counterpartyData.paymentInstrumentType,
|
|
14516
|
+
newType
|
|
14517
|
+
);
|
|
14518
|
+
if (!isCompatible) {
|
|
14519
|
+
setCounterpartyLookedUp(false);
|
|
14520
|
+
setCounterpartyData(null);
|
|
14521
|
+
setCounterpartySearchResults([]);
|
|
14522
|
+
form.setValue("counterpartyName", "");
|
|
14523
|
+
const typeLabel = newType === "ach" ? "ACH" : "Wire";
|
|
14524
|
+
sonner.toast.warning(
|
|
14525
|
+
`${counterpartyData.counterpartyName} doesn't support ${typeLabel} transactions. Please select a different counterparty.`
|
|
14526
|
+
);
|
|
14527
|
+
}
|
|
14528
|
+
}
|
|
14529
|
+
}
|
|
14530
|
+
};
|
|
14531
|
+
const handleCounterpartySelect = (result) => {
|
|
14532
|
+
form.setValue("counterpartyName", result.name);
|
|
14533
|
+
setShowCounterpartyDropdown(false);
|
|
14534
|
+
setCounterpartySearchResults([]);
|
|
14535
|
+
setIsCounterpartyLoading(true);
|
|
14536
|
+
setTimeout(() => {
|
|
14537
|
+
setCounterpartyData({
|
|
14538
|
+
counterpartyName: result.name,
|
|
14539
|
+
counterpartyId: result.id,
|
|
14540
|
+
counterpartyType: result.type,
|
|
14541
|
+
status: "Active",
|
|
14542
|
+
taxId: "XX-XXXXXXX",
|
|
14543
|
+
primaryContact: "Contact Name",
|
|
14544
|
+
contactEmail: "contact@example.com",
|
|
14545
|
+
contactPhone: "+1 (555) 123-4567",
|
|
14546
|
+
address: "123 Business Ave, City, ST 12345",
|
|
14547
|
+
paymentInstrumentType: result.paymentInstrumentType
|
|
14548
|
+
});
|
|
14549
|
+
setCounterpartyLookedUp(true);
|
|
14550
|
+
setIsCounterpartyLoading(false);
|
|
14551
|
+
sonner.toast.success("Counterparty selected");
|
|
14552
|
+
}, 500);
|
|
14259
14553
|
};
|
|
14260
14554
|
const handleEditAccount = () => {
|
|
14261
14555
|
setAccountLookedUp(false);
|
|
@@ -14266,50 +14560,153 @@ function NewTransaction() {
|
|
|
14266
14560
|
form.setValue("counterpartyName", "");
|
|
14267
14561
|
form.setValue("amount", "");
|
|
14268
14562
|
form.setValue("description", "");
|
|
14563
|
+
form.setValue("adjustmentDirection", "");
|
|
14564
|
+
form.setValue("adjustmentType", "");
|
|
14565
|
+
setReceiverAccountLookedUp(false);
|
|
14566
|
+
setReceiverAccountData(null);
|
|
14567
|
+
form.setValue("receiverAccountNumber", "");
|
|
14568
|
+
};
|
|
14569
|
+
const handleReceiverAccountLookup = async () => {
|
|
14570
|
+
const receiverNum = form.getValues("receiverAccountNumber");
|
|
14571
|
+
if (!receiverNum) {
|
|
14572
|
+
sonner.toast.error("Please enter a receiver account number");
|
|
14573
|
+
return;
|
|
14574
|
+
}
|
|
14575
|
+
setIsReceiverAccountLoading(true);
|
|
14576
|
+
try {
|
|
14577
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
14578
|
+
setReceiverAccountData({
|
|
14579
|
+
accountNumber: "****" + receiverNum.slice(-4),
|
|
14580
|
+
accountName: "Receiver Account",
|
|
14581
|
+
accountType: "Checking",
|
|
14582
|
+
balance: "$45,230.00",
|
|
14583
|
+
customerName: "Receiver Corp",
|
|
14584
|
+
customerId: "CUST-RCV-001",
|
|
14585
|
+
customerType: "Business"
|
|
14586
|
+
});
|
|
14587
|
+
setReceiverAccountLookedUp(true);
|
|
14588
|
+
sonner.toast.success("Receiver account found");
|
|
14589
|
+
} catch (error) {
|
|
14590
|
+
sonner.toast.error("Failed to lookup receiver account");
|
|
14591
|
+
} finally {
|
|
14592
|
+
setIsReceiverAccountLoading(false);
|
|
14593
|
+
}
|
|
14594
|
+
};
|
|
14595
|
+
const handleEditReceiverAccount = () => {
|
|
14596
|
+
setReceiverAccountLookedUp(false);
|
|
14597
|
+
setReceiverAccountData(null);
|
|
14598
|
+
form.setValue("receiverAccountNumber", "");
|
|
14269
14599
|
};
|
|
14270
14600
|
const handleEditCounterparty = () => {
|
|
14271
14601
|
setCounterpartyLookedUp(false);
|
|
14272
14602
|
setCounterpartyData(null);
|
|
14603
|
+
setCounterpartySearchResults([]);
|
|
14604
|
+
setShowCounterpartyDropdown(false);
|
|
14605
|
+
form.setValue("counterpartyName", "");
|
|
14273
14606
|
form.setValue("amount", "");
|
|
14274
14607
|
form.setValue("description", "");
|
|
14275
14608
|
};
|
|
14276
|
-
const handleSubmit = () => {
|
|
14609
|
+
const handleSubmit = async () => {
|
|
14277
14610
|
const data = form.getValues();
|
|
14278
|
-
|
|
14611
|
+
const requiresCounterparty = ["ach", "wire"].includes(data.transactionType);
|
|
14612
|
+
if (!data.transactionType || !data.accountNumber || !data.amount) {
|
|
14279
14613
|
sonner.toast.error("Please complete all required fields");
|
|
14280
14614
|
return;
|
|
14281
14615
|
}
|
|
14282
|
-
if (!
|
|
14283
|
-
sonner.toast.error("Please lookup
|
|
14616
|
+
if (requiresCounterparty && (!data.counterpartyName || !counterpartyLookedUp)) {
|
|
14617
|
+
sonner.toast.error("Please lookup counterparty for this transaction type");
|
|
14284
14618
|
return;
|
|
14285
14619
|
}
|
|
14286
|
-
|
|
14287
|
-
|
|
14288
|
-
|
|
14289
|
-
|
|
14290
|
-
|
|
14291
|
-
|
|
14292
|
-
"
|
|
14293
|
-
|
|
14294
|
-
|
|
14295
|
-
|
|
14296
|
-
|
|
14297
|
-
|
|
14298
|
-
|
|
14299
|
-
|
|
14300
|
-
|
|
14620
|
+
if (!accountLookedUp) {
|
|
14621
|
+
sonner.toast.error("Please lookup account");
|
|
14622
|
+
return;
|
|
14623
|
+
}
|
|
14624
|
+
if (data.transactionType === "adjustment") {
|
|
14625
|
+
if (!data.adjustmentDirection || !data.adjustmentType) {
|
|
14626
|
+
sonner.toast.error("Please select direction and type for adjustment");
|
|
14627
|
+
return;
|
|
14628
|
+
}
|
|
14629
|
+
}
|
|
14630
|
+
if (data.transactionType === "transfer") {
|
|
14631
|
+
if (!data.receiverAccountNumber || !receiverAccountLookedUp) {
|
|
14632
|
+
sonner.toast.error("Please lookup receiver account for transfer");
|
|
14633
|
+
return;
|
|
14634
|
+
}
|
|
14635
|
+
}
|
|
14636
|
+
setIsSubmitting(true);
|
|
14637
|
+
try {
|
|
14638
|
+
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
14639
|
+
const hasError = Math.random() > 0.7;
|
|
14640
|
+
if (hasError) {
|
|
14641
|
+
const errorScenarios = [
|
|
14642
|
+
"Insufficient funds. Current balance: $125,450.00, Required: $" + parseFloat(data.amount).toFixed(2),
|
|
14643
|
+
"Transaction limit exceeded. Daily limit: $50,000.00",
|
|
14644
|
+
"Counterparty account is temporarily unavailable. Please try again later.",
|
|
14645
|
+
"Invalid routing number for the selected transaction type."
|
|
14646
|
+
];
|
|
14647
|
+
setSubmissionStatus("error");
|
|
14648
|
+
setErrorMessage(errorScenarios[Math.floor(Math.random() * errorScenarios.length)]);
|
|
14649
|
+
} else {
|
|
14650
|
+
const txId = "TXN-" + Math.random().toString(36).substr(2, 9).toUpperCase();
|
|
14651
|
+
setTransactionId(txId);
|
|
14652
|
+
setSubmissionStatus("success");
|
|
14653
|
+
}
|
|
14301
14654
|
setConfirmationOpen(true);
|
|
14655
|
+
} finally {
|
|
14656
|
+
setIsSubmitting(false);
|
|
14302
14657
|
}
|
|
14303
14658
|
};
|
|
14659
|
+
const resetForm = () => {
|
|
14660
|
+
form.reset({
|
|
14661
|
+
transactionType: "",
|
|
14662
|
+
accountNumber: "",
|
|
14663
|
+
counterpartyName: "",
|
|
14664
|
+
amount: "",
|
|
14665
|
+
description: "",
|
|
14666
|
+
certifyInformation: false,
|
|
14667
|
+
adjustmentDirection: "",
|
|
14668
|
+
adjustmentType: "",
|
|
14669
|
+
receiverAccountNumber: ""
|
|
14670
|
+
});
|
|
14671
|
+
setAccountLookedUp(false);
|
|
14672
|
+
setAccountData(null);
|
|
14673
|
+
setCounterpartyLookedUp(false);
|
|
14674
|
+
setCounterpartyData(null);
|
|
14675
|
+
setCounterpartySearchResults([]);
|
|
14676
|
+
setShowCounterpartyDropdown(false);
|
|
14677
|
+
setReceiverAccountLookedUp(false);
|
|
14678
|
+
setReceiverAccountData(null);
|
|
14679
|
+
setSubmissionStatus(null);
|
|
14680
|
+
setErrorMessage("");
|
|
14681
|
+
setTransactionId("");
|
|
14682
|
+
};
|
|
14304
14683
|
const handleConfirmationClose = () => {
|
|
14305
14684
|
setConfirmationOpen(false);
|
|
14306
14685
|
if (submissionStatus === "success") {
|
|
14307
|
-
navigate(
|
|
14686
|
+
navigate(`/transactions/${transactionId}`);
|
|
14308
14687
|
}
|
|
14309
14688
|
};
|
|
14689
|
+
const handleNewTransaction = () => {
|
|
14690
|
+
setConfirmationOpen(false);
|
|
14691
|
+
resetForm();
|
|
14692
|
+
};
|
|
14310
14693
|
const handleCancel = () => {
|
|
14311
14694
|
navigate("/dashboard");
|
|
14312
14695
|
};
|
|
14696
|
+
const isReviewReady = React15.useMemo(() => {
|
|
14697
|
+
const data = form.watch();
|
|
14698
|
+
const requiresCounterparty = ["ach", "wire"].includes(data.transactionType);
|
|
14699
|
+
if (!data.transactionType || !data.accountNumber || !data.amount) return false;
|
|
14700
|
+
if (requiresCounterparty && (!data.counterpartyName || !counterpartyLookedUp)) return false;
|
|
14701
|
+
if (!accountLookedUp) return false;
|
|
14702
|
+
if (data.transactionType === "adjustment") {
|
|
14703
|
+
if (!data.adjustmentDirection || !data.adjustmentType) return false;
|
|
14704
|
+
}
|
|
14705
|
+
if (data.transactionType === "transfer") {
|
|
14706
|
+
if (!data.receiverAccountNumber || !receiverAccountLookedUp) return false;
|
|
14707
|
+
}
|
|
14708
|
+
return true;
|
|
14709
|
+
}, [form.watch(), accountLookedUp, counterpartyLookedUp, receiverAccountLookedUp]);
|
|
14313
14710
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14314
14711
|
NewTransactionView,
|
|
14315
14712
|
{
|
|
@@ -14322,14 +14719,30 @@ function NewTransaction() {
|
|
|
14322
14719
|
submissionStatus,
|
|
14323
14720
|
errorMessage,
|
|
14324
14721
|
transactionId,
|
|
14722
|
+
isAccountLoading,
|
|
14723
|
+
isCounterpartyLoading,
|
|
14724
|
+
isSubmitting,
|
|
14325
14725
|
onAccountLookup: handleAccountLookup,
|
|
14326
|
-
onCounterpartyLookup: handleCounterpartyLookup,
|
|
14327
14726
|
onEditAccount: handleEditAccount,
|
|
14727
|
+
counterpartySearchResults,
|
|
14728
|
+
isCounterpartySearching,
|
|
14729
|
+
showCounterpartyDropdown,
|
|
14730
|
+
onCounterpartySearchChange: handleCounterpartySearchChange,
|
|
14731
|
+
onCounterpartySelect: handleCounterpartySelect,
|
|
14732
|
+
onCounterpartyDropdownClose: () => setShowCounterpartyDropdown(false),
|
|
14328
14733
|
onEditCounterparty: handleEditCounterparty,
|
|
14734
|
+
onTransactionTypeChange: handleTransactionTypeChange,
|
|
14329
14735
|
onSubmit: handleSubmit,
|
|
14330
14736
|
onCancel: handleCancel,
|
|
14331
14737
|
onConfirmationClose: handleConfirmationClose,
|
|
14332
|
-
onConfirmationOpenChange: setConfirmationOpen
|
|
14738
|
+
onConfirmationOpenChange: setConfirmationOpen,
|
|
14739
|
+
onNewTransaction: handleNewTransaction,
|
|
14740
|
+
receiverAccountLookedUp,
|
|
14741
|
+
receiverAccountData,
|
|
14742
|
+
isReceiverAccountLoading,
|
|
14743
|
+
onReceiverAccountLookup: handleReceiverAccountLookup,
|
|
14744
|
+
onEditReceiverAccount: handleEditReceiverAccount,
|
|
14745
|
+
isReviewReady
|
|
14333
14746
|
}
|
|
14334
14747
|
);
|
|
14335
14748
|
}
|
|
@@ -14380,7 +14793,7 @@ var TransactionDetail = () => {
|
|
|
14380
14793
|
return "outline";
|
|
14381
14794
|
}
|
|
14382
14795
|
};
|
|
14383
|
-
const
|
|
14796
|
+
const formatCurrency3 = (value) => {
|
|
14384
14797
|
return new Intl.NumberFormat("en-US", {
|
|
14385
14798
|
style: "currency",
|
|
14386
14799
|
currency: "USD",
|
|
@@ -14396,7 +14809,7 @@ var TransactionDetail = () => {
|
|
|
14396
14809
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
14397
14810
|
"font-semibold",
|
|
14398
14811
|
transaction.amount < 0 ? "text-destructive" : "text-success"
|
|
14399
|
-
), children:
|
|
14812
|
+
), children: formatCurrency3(transaction.amount) }),
|
|
14400
14813
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14401
14814
|
TransactionTypeBadge,
|
|
14402
14815
|
{
|
|
@@ -15018,11 +15431,11 @@ function CreateVelocityLimit() {
|
|
|
15018
15431
|
case "round_number":
|
|
15019
15432
|
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
15020
15433
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15021
|
-
|
|
15434
|
+
CurrencyInput,
|
|
15022
15435
|
{
|
|
15023
15436
|
label: "Amount Threshold",
|
|
15024
|
-
|
|
15025
|
-
onChange: (
|
|
15437
|
+
value: formData.amountThreshold || "",
|
|
15438
|
+
onChange: (value) => handleFieldChange("amountThreshold", value)
|
|
15026
15439
|
}
|
|
15027
15440
|
),
|
|
15028
15441
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -15135,11 +15548,11 @@ function CreateVelocityLimit() {
|
|
|
15135
15548
|
}
|
|
15136
15549
|
),
|
|
15137
15550
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15138
|
-
|
|
15551
|
+
CurrencyInput,
|
|
15139
15552
|
{
|
|
15140
15553
|
label: "Max Transaction Amount",
|
|
15141
|
-
|
|
15142
|
-
onChange: (
|
|
15554
|
+
value: formData.maxAmount || "",
|
|
15555
|
+
onChange: (value) => handleFieldChange("maxAmount", value)
|
|
15143
15556
|
}
|
|
15144
15557
|
),
|
|
15145
15558
|
formData.aggregationLevel !== "transaction" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -16366,6 +16779,8 @@ exports.ACHBankCard = ACHBankCard;
|
|
|
16366
16779
|
exports.ACHBasicInfoCard = ACHBasicInfoCard;
|
|
16367
16780
|
exports.ACHDetailsSection = ACHDetailsSection;
|
|
16368
16781
|
exports.ACHTransferSection = ACHTransferSection;
|
|
16782
|
+
exports.ADJUSTMENT_DIRECTION_OPTIONS = ADJUSTMENT_DIRECTION_OPTIONS;
|
|
16783
|
+
exports.ADJUSTMENT_TYPE_OPTIONS = ADJUSTMENT_TYPE_OPTIONS;
|
|
16369
16784
|
exports.AccountCard = AccountCard;
|
|
16370
16785
|
exports.AccountDetail = AccountDetail_default;
|
|
16371
16786
|
exports.Accounts = Accounts_default;
|
|
@@ -16396,7 +16811,6 @@ exports.BusinessTypeBadge = BusinessTypeBadge;
|
|
|
16396
16811
|
exports.Businesses = Businesses_default;
|
|
16397
16812
|
exports.Button = Button;
|
|
16398
16813
|
exports.CIPStatusBadge = CIPStatusBadge;
|
|
16399
|
-
exports.CURRENCY_OPTIONS = CURRENCY_OPTIONS;
|
|
16400
16814
|
exports.Calendar = Calendar;
|
|
16401
16815
|
exports.Card = Card;
|
|
16402
16816
|
exports.CardContent = CardContent;
|