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/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 min-h-screen w-full", children: /* @__PURE__ */ jsxRuntime.jsx("main", { className: "flex-1", children }) });
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 formatCurrency = (value) => {
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: formatCurrency(data.amount), layout: "horizontal" }),
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 CURRENCY_OPTIONS = [
8405
- { value: "USD", label: "USD - US Dollar" },
8406
- { value: "EUR", label: "EUR - Euro" },
8407
- { value: "GBP", label: "GBP - British Pound" },
8408
- { value: "JPY", label: "JPY - Japanese Yen" },
8409
- { value: "CAD", label: "CAD - Canadian Dollar" },
8410
- { value: "AUD", label: "AUD - Australian Dollar" },
8411
- { value: "CHF", label: "CHF - Swiss Franc" },
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.counterpartyType },
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 reviewData = [
8523
+ const receiverAccountDataGrid = receiverAccountData ? [
8467
8524
  {
8468
- title: "Transaction Summary",
8525
+ title: "Receiver Account Information",
8469
8526
  items: [
8470
- { label: "Transaction Type", value: TRANSACTION_TYPES.find((t) => t.value === transactionType)?.label || "-" },
8471
- { label: "Account Number", value: accountNumber || "-" },
8472
- { label: "Counterparty", value: counterpartyName || "-" },
8473
- { label: "Amount", value: amount ? `$${amount}` : "-" },
8474
- { label: "Description", value: form.watch("description") || "N/A" }
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
- return /* @__PURE__ */ jsxRuntime.jsx(PageLayout, { title: "New Transaction", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-4xl mx-auto space-y-6", children: [
8479
- /* @__PURE__ */ jsxRuntime.jsx(FormProvider, { form, children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: (e) => e.preventDefault(), children: [
8480
- !accountLookedUp ? /* @__PURE__ */ jsxRuntime.jsx(FormCard, { title: "Account Lookup", variant: "default", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3 items-start w-full", children: [
8481
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
8482
- FormInput,
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
- name: "accountNumber",
8485
- placeholder: "Enter account number"
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.jsxs(
8489
- Button,
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
- onClick: onAccountLookup,
8492
- disabled: !accountNumber,
8493
- className: "shrink-0 mt-0 w-48",
8634
+ title: "Counterparty Search",
8635
+ variant: "default",
8636
+ className: cn(!transactionType && "opacity-50 pointer-events-none"),
8494
8637
  children: [
8495
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "h-4 w-4 mr-2" }),
8496
- "Lookup Account"
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
- ] }) }) : /* @__PURE__ */ jsxRuntime.jsx(
8501
- FormCard,
8502
- {
8503
- title: "Account Information",
8504
- variant: "subtle",
8505
- headerActions: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
8506
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "h-5 w-5 text-success" }),
8507
- /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "ghost", size: "sm", onClick: onEditAccount, children: [
8508
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Edit, { className: "h-4 w-4 mr-1" }),
8509
- "Edit"
8510
- ] })
8511
- ] }),
8512
- children: /* @__PURE__ */ jsxRuntime.jsx(DataGrid, { data: accountDataGrid, columns: 2 })
8513
- }
8514
- ),
8515
- /* @__PURE__ */ jsxRuntime.jsx(
8516
- FormCard,
8517
- {
8518
- title: "Transaction Type",
8519
- variant: "default",
8520
- className: cn(!accountLookedUp && "opacity-50 pointer-events-none"),
8521
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 lg:grid-cols-4 gap-3 lg:gap-4", children: TRANSACTION_TYPES.map((type) => {
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: "amount",
8607
- label: "Amount",
8608
- placeholder: "0.00",
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
- FormSelect,
8712
+ Button,
8615
8713
  {
8616
- name: "currency",
8617
- label: "Currency",
8618
- options: CURRENCY_OPTIONS,
8619
- disabled: !counterpartyLookedUp,
8620
- className: "w-48"
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
- FormInput,
8626
- {
8627
- name: "description",
8628
- label: "Description (Optional)",
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
- name: "certifyInformation",
8642
- control: form.control,
8643
- render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
8644
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
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
- Checkbox,
8754
+ FormSelect,
8647
8755
  {
8648
- id: "certifyInformation",
8649
- checked: field.value,
8650
- onCheckedChange: field.onChange
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
- "label",
8764
+ FormSelect,
8655
8765
  {
8656
- htmlFor: "certifyInformation",
8657
- className: "text-sm font-medium leading-relaxed cursor-pointer select-none",
8658
- children: "I certify that all information entered is correct and accurate to the best of my knowledge"
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
- form.formState.errors.certifyInformation && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-destructive ml-7", children: form.formState.errors.certifyInformation.message })
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.jsxs("div", { className: "flex gap-3 justify-end pt-4 border-t border-border", children: [
8667
- /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", variant: "outline", onClick: onCancel, className: "w-32", children: "Cancel" }),
8668
- /* @__PURE__ */ jsxRuntime.jsxs(
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: onSubmit,
8673
- className: "w-48",
8674
- disabled: !transactionType || !accountNumber || !counterpartyName || !amount || !form.watch("certifyInformation"),
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
- /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: confirmationOpen, onOpenChange: onConfirmationOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "sm:max-w-md", children: [
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 formatCurrency = (value) => {
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
- EnhancedInput,
14177
+ CurrencyInput,
14008
14178
  {
14009
14179
  label: "Min Amount",
14010
- type: "number",
14011
14180
  value: filters.minAmount,
14012
- onChange: (e) => handleFilterChange("minAmount", e.target.value),
14013
- placeholder: "0.00"
14181
+ onChange: (value) => handleFilterChange("minAmount", value)
14014
14182
  }
14015
14183
  ),
14016
14184
  /* @__PURE__ */ jsxRuntime.jsx(
14017
- EnhancedInput,
14185
+ CurrencyInput,
14018
14186
  {
14019
14187
  label: "Max Amount",
14020
- type: "number",
14021
14188
  value: filters.maxAmount,
14022
- onChange: (e) => handleFilterChange("maxAmount", e.target.value),
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: formatCurrency(transaction.amount) }) }),
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().min(1, "Counterparty name is required"),
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
- setAccountData(mockAccountData);
14247
- setAccountLookedUp(true);
14248
- sonner.toast.success("Account found");
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 handleCounterpartyLookup = () => {
14251
- const cpName = form.getValues("counterpartyName");
14252
- if (!cpName) {
14253
- sonner.toast.error("Please enter a counterparty name");
14254
- return;
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
- setCounterpartyData(mockCounterpartyData);
14257
- setCounterpartyLookedUp(true);
14258
- sonner.toast.success("Counterparty found");
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
- if (!data.transactionType || !data.accountNumber || !data.counterpartyName || !data.amount) {
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 (!accountLookedUp || !counterpartyLookedUp) {
14283
- sonner.toast.error("Please lookup both account and counterparty");
14616
+ if (requiresCounterparty && (!data.counterpartyName || !counterpartyLookedUp)) {
14617
+ sonner.toast.error("Please lookup counterparty for this transaction type");
14284
14618
  return;
14285
14619
  }
14286
- const hasError = Math.random() > 0.7;
14287
- if (hasError) {
14288
- const errorScenarios = [
14289
- "Insufficient funds. Current balance: $125,450.00, Required: $" + parseFloat(data.amount).toFixed(2),
14290
- "Transaction limit exceeded. Daily limit: $50,000.00",
14291
- "Counterparty account is temporarily unavailable. Please try again later.",
14292
- "Invalid routing number for the selected transaction type."
14293
- ];
14294
- setSubmissionStatus("error");
14295
- setErrorMessage(errorScenarios[Math.floor(Math.random() * errorScenarios.length)]);
14296
- setConfirmationOpen(true);
14297
- } else {
14298
- const txId = "TXN-" + Math.random().toString(36).substr(2, 9).toUpperCase();
14299
- setTransactionId(txId);
14300
- setSubmissionStatus("success");
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("/transactions/history");
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 formatCurrency = (value) => {
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: formatCurrency(transaction.amount) }),
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
- EnhancedInput,
15434
+ CurrencyInput,
15022
15435
  {
15023
15436
  label: "Amount Threshold",
15024
- placeholder: "Enter amount",
15025
- onChange: (e) => handleFieldChange("amountThreshold", e.target.value)
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
- EnhancedInput,
15551
+ CurrencyInput,
15139
15552
  {
15140
15553
  label: "Max Transaction Amount",
15141
- placeholder: "Enter amount",
15142
- onChange: (e) => handleFieldChange("maxAmount", e.target.value)
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;