@burdenoff/microfe-billing 2026.625.2 → 2026.625.3
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/billing/modules/billing/pages/TransactionsPage.js +26 -37
- package/dist/billing/modules/billing/pages/TransactionsPage.js.map +1 -1
- package/dist/billing/modules/credits/pages/CreditTransactionsPage.js +41 -40
- package/dist/billing/modules/credits/pages/CreditTransactionsPage.js.map +1 -1
- package/dist/billing/modules/dashboard/pages/OverviewPage.js +234 -225
- package/dist/billing/modules/dashboard/pages/OverviewPage.js.map +1 -1
- package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js +1 -0
- package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js.map +1 -1
- package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js +1 -0
- package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js.map +1 -1
- package/dist/billing/shared/ui/StatusPill.js +1 -1
- package/dist/billing/shared/ui/StatusPill.js.map +1 -1
- package/package.json +2 -2
|
@@ -17,13 +17,13 @@ import { ArrowLeft as _, Calendar as v, CheckCircle as y, ChevronLeft as b, Chev
|
|
|
17
17
|
import { useParams as k } from "react-router-dom";
|
|
18
18
|
import { Fragment as A, jsx as j, jsxs as M } from "react/jsx-runtime";
|
|
19
19
|
import { useI18n as N } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
20
|
-
import { Dialog as P, DialogContent as F, DialogFooter as I, DialogHeader as L, DialogTitle as R,
|
|
20
|
+
import { Dialog as P, DialogContent as F, DialogFooter as I, DialogHeader as L, DialogTitle as R, IllustratedEmptyState as z, ResponsiveTable as B } from "@burdenoff/fe-libs/ui";
|
|
21
21
|
//#region src/billing/modules/billing/pages/TransactionsPage.tsx
|
|
22
|
-
var
|
|
22
|
+
var V = {
|
|
23
23
|
payment: "Payment",
|
|
24
24
|
refund: "Refund",
|
|
25
25
|
adjustment: "Adjustment"
|
|
26
|
-
},
|
|
26
|
+
}, H = (e) => V[e.toLowerCase()] ?? e, U = ({ transaction: e, onViewDetails: t, onViewInvoice: n, hasInvoiceUrl: r }) => {
|
|
27
27
|
let [i, a] = g(!1), o = h(null);
|
|
28
28
|
return m(() => {
|
|
29
29
|
let e = (e) => {
|
|
@@ -58,7 +58,7 @@ var B = {
|
|
|
58
58
|
})]
|
|
59
59
|
})]
|
|
60
60
|
});
|
|
61
|
-
},
|
|
61
|
+
}, W = ({ transaction: e, onClose: t, onViewInvoice: n, invoiceUrl: r, invoiceProvider: c }) => {
|
|
62
62
|
if (!e) return null;
|
|
63
63
|
let l = e.metadata, f = l?.subtotal, p = l?.taxAmount, m = l?.taxRate, h = l?.taxType, g = l?.total, _ = l?.invoiceNumber, v = l?.invoiceStatus, y = e.type === "refund", b = l?.refundRecordId, x = l?.originalTransactionId, S = l?.creditNoteId, C = l?.creditNoteNumber, T = l?.creditNotePdfUrl, E = l?.reason, D = l?.purchaseType, O = l?.purchaseDetail, k = g && p !== void 0 && p > 0;
|
|
64
64
|
return /* @__PURE__ */ j(P, {
|
|
@@ -90,7 +90,7 @@ var B = {
|
|
|
90
90
|
children: "Type"
|
|
91
91
|
}), /* @__PURE__ */ j("p", {
|
|
92
92
|
className: "text-sm capitalize",
|
|
93
|
-
children:
|
|
93
|
+
children: H(e.type)
|
|
94
94
|
})] })]
|
|
95
95
|
}),
|
|
96
96
|
/* @__PURE__ */ j("div", {
|
|
@@ -285,17 +285,17 @@ var B = {
|
|
|
285
285
|
]
|
|
286
286
|
})
|
|
287
287
|
});
|
|
288
|
-
},
|
|
288
|
+
}, G = () => {
|
|
289
289
|
let { t: m } = N(), h = (e, t) => {
|
|
290
290
|
let n = m(e);
|
|
291
291
|
return n === e ? t : n;
|
|
292
|
-
}, { billingAccountId: C } = k(), E = l(), A = f(), { billingAccount: P, transactions: F, pagination: I, isLoading: L, error: R, refetch:
|
|
292
|
+
}, { billingAccountId: C } = k(), E = l(), A = f(), { billingAccount: P, transactions: F, pagination: I, isLoading: L, error: R, refetch: G, goToNextPage: K, goToPreviousPage: q } = p(C), [J, ee] = g("all"), [Y, X] = g(null), Z = (e) => {
|
|
293
293
|
let t = e.metadata;
|
|
294
294
|
return t?.zohoBooksInvoiceUrl ? t.zohoBooksInvoiceUrl : t?.invoiceUrl ? t.invoiceUrl : t?.invoicePdf ? t.invoicePdf : null;
|
|
295
|
-
},
|
|
295
|
+
}, te = (e) => {
|
|
296
296
|
let t = e.metadata;
|
|
297
297
|
return t?.total && typeof t.total == "number" ? t.total : e.amount;
|
|
298
|
-
},
|
|
298
|
+
}, ne = (e) => {
|
|
299
299
|
let t = e.metadata;
|
|
300
300
|
return t?.zohoBooksInvoiceUrl ? "Zoho Books" : t?.invoiceUrl || t?.invoicePdf ? "Stripe" : null;
|
|
301
301
|
}, Q = (e) => {
|
|
@@ -327,11 +327,11 @@ var B = {
|
|
|
327
327
|
children: /* @__PURE__ */ j(r, {
|
|
328
328
|
title: h("billing.transactions.serverUnavailable", "Server Unavailable"),
|
|
329
329
|
message: h("billing.transactions.serverUnavailableMessage", "Unable to load transactions. The server might be down or experiencing issues."),
|
|
330
|
-
onRetry: () =>
|
|
330
|
+
onRetry: () => G(),
|
|
331
331
|
showRetry: !0
|
|
332
332
|
})
|
|
333
333
|
});
|
|
334
|
-
let $ =
|
|
334
|
+
let $ = J === "all" ? F : F.filter((e) => e.type === J);
|
|
335
335
|
return L ? /* @__PURE__ */ M("div", {
|
|
336
336
|
className: "space-y-6 p-6",
|
|
337
337
|
children: [/* @__PURE__ */ j("div", { className: "h-8 w-48 bg-bg-sunken animate-pulse rounded" }), /* @__PURE__ */ j("div", {
|
|
@@ -436,30 +436,19 @@ var B = {
|
|
|
436
436
|
"adjustment"
|
|
437
437
|
].map((e) => /* @__PURE__ */ j("button", {
|
|
438
438
|
type: "button",
|
|
439
|
-
onClick: () =>
|
|
440
|
-
className: `px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${
|
|
441
|
-
children: e === "all" ? "All" :
|
|
439
|
+
onClick: () => ee(e),
|
|
440
|
+
className: `px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${J === e ? "bg-bg-surface text-text-primary shadow-sm" : "text-text-secondary hover:text-text-primary"}`,
|
|
441
|
+
children: e === "all" ? "All" : V[e]
|
|
442
442
|
}, e))
|
|
443
443
|
})
|
|
444
444
|
}),
|
|
445
|
-
$.length === 0 ? /* @__PURE__ */ j(
|
|
446
|
-
|
|
447
|
-
className: "size-6 text-text-secondary",
|
|
448
|
-
fill: "none",
|
|
449
|
-
viewBox: "0 0 24 24",
|
|
450
|
-
stroke: "currentColor",
|
|
451
|
-
children: /* @__PURE__ */ j("path", {
|
|
452
|
-
strokeLinecap: "round",
|
|
453
|
-
strokeLinejoin: "round",
|
|
454
|
-
strokeWidth: 2,
|
|
455
|
-
d: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"
|
|
456
|
-
})
|
|
457
|
-
}),
|
|
445
|
+
$.length === 0 ? /* @__PURE__ */ j(z, {
|
|
446
|
+
illustration: J === "all" ? "empty-data" : "empty-search",
|
|
458
447
|
title: h("billing.transactions.noTransactionsFound", "No transactions found"),
|
|
459
|
-
description:
|
|
448
|
+
description: J === "all" ? h("billing.transactions.noTransactionsYet", "Your transaction history will appear here.") : h("billing.transactions.noTransactionsFiltered", "No transactions match your filter.")
|
|
460
449
|
}) : /* @__PURE__ */ j("div", {
|
|
461
450
|
className: "border border-border-subtle rounded-lg overflow-visible",
|
|
462
|
-
children: /* @__PURE__ */ j(
|
|
451
|
+
children: /* @__PURE__ */ j(B, {
|
|
463
452
|
columns: [
|
|
464
453
|
{
|
|
465
454
|
key: "date",
|
|
@@ -477,7 +466,7 @@ var B = {
|
|
|
477
466
|
cellClassName: "whitespace-nowrap",
|
|
478
467
|
cell: (e) => /* @__PURE__ */ j("span", {
|
|
479
468
|
className: "text-sm text-text-primary capitalize",
|
|
480
|
-
children:
|
|
469
|
+
children: H(e.type)
|
|
481
470
|
})
|
|
482
471
|
},
|
|
483
472
|
{
|
|
@@ -495,7 +484,7 @@ var B = {
|
|
|
495
484
|
cellClassName: "text-right whitespace-nowrap",
|
|
496
485
|
cell: (e) => /* @__PURE__ */ M("span", {
|
|
497
486
|
className: `text-sm font-medium tabular-nums ${e.type === "refund" ? "text-status-error-text" : "text-text-primary"}`,
|
|
498
|
-
children: [e.type === "refund" ? "-" : "", i(
|
|
487
|
+
children: [e.type === "refund" ? "-" : "", i(te(e), e.currency)]
|
|
499
488
|
})
|
|
500
489
|
},
|
|
501
490
|
{
|
|
@@ -511,7 +500,7 @@ var B = {
|
|
|
511
500
|
],
|
|
512
501
|
data: $,
|
|
513
502
|
rowKey: (e) => e.id,
|
|
514
|
-
rowActions: (e) => /* @__PURE__ */ j(
|
|
503
|
+
rowActions: (e) => /* @__PURE__ */ j(U, {
|
|
515
504
|
transaction: e,
|
|
516
505
|
onViewDetails: () => X(e),
|
|
517
506
|
onViewInvoice: () => Q(e),
|
|
@@ -539,7 +528,7 @@ var B = {
|
|
|
539
528
|
children: [
|
|
540
529
|
/* @__PURE__ */ M("button", {
|
|
541
530
|
type: "button",
|
|
542
|
-
onClick:
|
|
531
|
+
onClick: q,
|
|
543
532
|
disabled: !I.hasPrevious,
|
|
544
533
|
className: "inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-md border border-border-subtle bg-bg-surface hover:bg-bg-sunken/50 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
|
|
545
534
|
children: [/* @__PURE__ */ j(b, { className: "size-4" }), "Previous"]
|
|
@@ -555,7 +544,7 @@ var B = {
|
|
|
555
544
|
}),
|
|
556
545
|
/* @__PURE__ */ M("button", {
|
|
557
546
|
type: "button",
|
|
558
|
-
onClick:
|
|
547
|
+
onClick: K,
|
|
559
548
|
disabled: !I.hasMore,
|
|
560
549
|
className: "inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-md border border-border-subtle bg-bg-surface hover:bg-bg-sunken/50 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
|
|
561
550
|
children: ["Next", /* @__PURE__ */ j(x, { className: "size-4" })]
|
|
@@ -563,17 +552,17 @@ var B = {
|
|
|
563
552
|
]
|
|
564
553
|
})]
|
|
565
554
|
}),
|
|
566
|
-
/* @__PURE__ */ j(
|
|
555
|
+
/* @__PURE__ */ j(W, {
|
|
567
556
|
transaction: Y,
|
|
568
557
|
onClose: () => X(null),
|
|
569
558
|
onViewInvoice: Q,
|
|
570
559
|
invoiceUrl: Y ? Z(Y) : null,
|
|
571
|
-
invoiceProvider: Y ?
|
|
560
|
+
invoiceProvider: Y ? ne(Y) : null
|
|
572
561
|
})
|
|
573
562
|
]
|
|
574
563
|
});
|
|
575
564
|
};
|
|
576
565
|
//#endregion
|
|
577
|
-
export {
|
|
566
|
+
export { G as TransactionsPage };
|
|
578
567
|
|
|
579
568
|
//# sourceMappingURL=TransactionsPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransactionsPage.js","names":[],"sources":["../../../../../src/billing/modules/billing/pages/TransactionsPage.tsx"],"sourcesContent":["/**\n * Billing Module - Transactions Page\n * Displays all billing transactions for a specific billing account\n */\n\nimport { useState, useRef, useEffect, type FC } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n ArrowLeft,\n MoreHorizontal,\n Eye,\n FileText,\n CreditCard,\n Mail,\n Wallet,\n ChevronLeft,\n ChevronRight,\n Calendar,\n CheckCircle,\n XCircle,\n} from 'lucide-react';\nimport { useBillingPermissions } from '../../../hooks/useBillingPermissions';\nimport { useBillingNavigate } from '../../../hooks/useBillingNavigate';\nimport { useTransactions } from '../hooks';\nimport { nativeImpact, nativeOpenUrl } from '../../../../utils/nativeBridge';\nimport { AccessDenied, PageHeader, EmptyState, ServerError } from '../../../shared/components';\nimport { formatCurrency, formatDateTime, isServerError } from '../../../shared/utils';\nimport { getTransactionStatusColor, getStatusBadgeClasses } from '../../../shared/utils/status';\nimport type { Transaction, TransactionType } from '../../../shared/types';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n ResponsiveTable,\n type ResponsiveTableColumn,\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogFooter,\n} from '@burdenoff/fe-libs/ui';\n\ntype FilterType = 'all' | TransactionType;\n\nconst TYPE_LABELS: Record<TransactionType, string> = {\n payment: 'Payment',\n refund: 'Refund',\n adjustment: 'Adjustment',\n};\n\n// Helper to get label for transaction type (case-insensitive)\nconst getTypeLabel = (type: string): string => {\n const normalized = type.toLowerCase() as TransactionType;\n return TYPE_LABELS[normalized] ?? type;\n};\n\n// Transaction Actions Dropdown Component\ninterface TransactionActionsDropdownProps {\n transaction: Transaction;\n onViewDetails: () => void;\n onViewInvoice: () => void;\n hasInvoiceUrl: boolean;\n}\n\nconst TransactionActionsDropdown: FC<TransactionActionsDropdownProps> = ({\n transaction,\n onViewDetails,\n onViewInvoice,\n hasInvoiceUrl,\n}) => {\n const [isOpen, setIsOpen] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, []);\n\n return (\n <div className=\"relative overflow-visible\" ref={dropdownRef}>\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n className=\"p-1.5 rounded-md hover:bg-bg-sunken/50 transition-colors\"\n aria-label=\"Transaction actions\"\n >\n <MoreHorizontal className=\"size-4 text-text-secondary\" />\n </button>\n\n {isOpen && (\n <div className=\"absolute right-0 top-full mt-1 z-50 min-w-[160px] bg-popover border border-border-subtle rounded-md shadow-lg py-1\">\n <button\n type=\"button\"\n onClick={() => {\n onViewDetails();\n setIsOpen(false);\n }}\n className=\"w-full flex items-center gap-2 px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken/50 transition-colors whitespace-nowrap\"\n >\n <Eye className=\"size-4\" />\n View Details\n </button>\n {transaction.type === 'payment' && hasInvoiceUrl && (\n <button\n type=\"button\"\n onClick={() => {\n onViewInvoice();\n setIsOpen(false);\n }}\n className=\"w-full flex items-center gap-2 px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken/50 transition-colors whitespace-nowrap\"\n >\n <FileText className=\"size-4\" />\n View Invoice\n </button>\n )}\n </div>\n )}\n </div>\n );\n};\n\n// Transaction Details Modal Component\ninterface TransactionDetailsModalProps {\n transaction: Transaction | null;\n onClose: () => void;\n onViewInvoice?: (transaction: Transaction) => void;\n invoiceUrl?: string | null;\n invoiceProvider?: string | null;\n}\n\nconst TransactionDetailsModal: FC<TransactionDetailsModalProps> = ({\n transaction,\n onClose,\n onViewInvoice,\n invoiceUrl,\n invoiceProvider,\n}) => {\n if (!transaction) return null;\n\n // Extract tax information from metadata\n const metadata = transaction.metadata as Record<string, unknown> | null;\n const subtotal = metadata?.subtotal as number | undefined;\n const taxAmount = metadata?.taxAmount as number | undefined;\n const taxRate = metadata?.taxRate as number | undefined;\n const taxType = metadata?.taxType as string | undefined;\n const total = metadata?.total as number | undefined;\n const invoiceNumber = metadata?.invoiceNumber as string | undefined;\n const invoiceStatus = metadata?.invoiceStatus as string | undefined;\n\n // Extract refund-specific information\n const isRefund = transaction.type === 'refund';\n const refundRecordId = metadata?.refundRecordId as string | undefined;\n const originalTransactionId = metadata?.originalTransactionId as string | undefined;\n const creditNoteId = metadata?.creditNoteId as string | undefined;\n const creditNoteNumber = metadata?.creditNoteNumber as string | undefined;\n const creditNotePdfUrl = metadata?.creditNotePdfUrl as string | undefined;\n const refundReason = metadata?.reason as string | undefined;\n const purchaseType = metadata?.purchaseType as string | undefined;\n const purchaseDetail = metadata?.purchaseDetail as string | undefined;\n\n // Determine if we should show tax breakdown\n const showTaxBreakdown = total && taxAmount !== undefined && taxAmount > 0;\n\n return (\n <Dialog open={!!transaction} onOpenChange={(open) => !open && onClose()}>\n <DialogContent className=\"max-w-md max-h-[90vh] overflow-auto p-0\">\n <DialogHeader className=\"p-4 border-b border-border-subtle\">\n <DialogTitle className=\"text-lg font-semibold\">Transaction Details</DialogTitle>\n </DialogHeader>\n\n <div className=\"p-4 space-y-4\">\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Transaction ID</p>\n <p className=\"text-sm font-mono break-all\">{transaction.id}</p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Type</p>\n <p className=\"text-sm capitalize\">{getTypeLabel(transaction.type)}</p>\n </div>\n </div>\n\n {/* Amount Section with Tax Breakdown */}\n <div className=\"space-y-2\">\n {showTaxBreakdown ? (\n <>\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">Subtotal</span>\n <span>\n {formatCurrency(subtotal || transaction.amount, transaction.currency)}\n </span>\n </div>\n {taxAmount > 0 && (\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">\n {taxType || 'Tax'} {taxRate ? `(${(taxRate * 100).toFixed(0)}%)` : ''}\n </span>\n <span>{formatCurrency(taxAmount, transaction.currency)}</span>\n </div>\n )}\n <div className=\"flex justify-between text-sm font-semibold border-t border-border-subtle pt-2\">\n <span>Total</span>\n <span className={transaction.type === 'refund' ? 'text-status-error-text' : ''}>\n {transaction.type === 'refund' ? '-' : ''}\n {formatCurrency(total, transaction.currency)}\n </span>\n </div>\n </>\n ) : (\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Amount</p>\n <p\n className={`text-sm font-medium ${transaction.type === 'refund' ? 'text-status-error-text' : ''}`}\n >\n {transaction.type === 'refund' ? '-' : ''}\n {formatCurrency(total || transaction.amount, transaction.currency)}\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Status</p>\n <span\n className={`px-2 py-0.5 text-xs font-medium rounded ${getStatusBadgeClasses(\n getTransactionStatusColor(transaction.status)\n )}`}\n >\n {transaction.status}\n </span>\n </div>\n </div>\n )}\n </div>\n\n {/* Status (if tax breakdown shown) */}\n {showTaxBreakdown && (\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Status</p>\n <span\n className={`px-2 py-0.5 text-xs font-medium rounded ${getStatusBadgeClasses(\n getTransactionStatusColor(transaction.status)\n )}`}\n >\n {transaction.status}\n </span>\n </div>\n )}\n\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Date & Time</p>\n <p className=\"text-sm\">{formatDateTime(transaction.createdAt)}</p>\n </div>\n\n {transaction.description && (\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Description</p>\n <p className=\"text-sm\">{transaction.description}</p>\n </div>\n )}\n\n {/* Invoice Information */}\n {invoiceNumber && (\n <div className=\"p-3 bg-bg-sunken/50 rounded-lg space-y-2\">\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Invoice</p>\n <p className=\"text-sm font-mono\">{invoiceNumber}</p>\n </div>\n {invoiceStatus && (\n <span\n className={`px-2 py-0.5 text-xs font-medium rounded ${\n invoiceStatus === 'PAID'\n ? 'bg-status-success-bg-subtle text-status-success-text'\n : 'bg-status-warning-bg-subtle text-status-warning-text'\n }`}\n >\n {invoiceStatus}\n </span>\n )}\n </div>\n {invoiceProvider && (\n <p className=\"text-xs text-text-secondary\">Provider: {invoiceProvider}</p>\n )}\n {invoiceUrl && onViewInvoice && (\n <button\n type=\"button\"\n onClick={() => onViewInvoice(transaction)}\n className=\"flex items-center gap-2 text-sm text-primary hover:underline\"\n >\n <FileText className=\"size-4\" />\n View Invoice\n </button>\n )}\n </div>\n )}\n\n {/* Fallback invoice button if no invoice number but URL exists */}\n {!invoiceNumber && invoiceUrl && onViewInvoice && (\n <div className=\"p-3 bg-bg-sunken/50 rounded-lg\">\n <button\n type=\"button\"\n onClick={() => onViewInvoice(transaction)}\n className=\"flex items-center gap-2 text-sm text-primary hover:underline\"\n >\n <FileText className=\"size-4\" />\n View Invoice {invoiceProvider && `(${invoiceProvider})`}\n </button>\n </div>\n )}\n\n {/* Refund-Specific Information */}\n {isRefund && (creditNoteId || refundReason || purchaseType) && (\n <div className=\"p-3 bg-status-error-bg-subtle/20 border border-border-subtle rounded-lg space-y-3\">\n <div className=\"flex items-center gap-2\">\n <div className=\"size-1.5 rounded-full bg-status-error-bg\" />\n <p className=\"text-sm font-semibold text-status-error-text\">Refund Information</p>\n </div>\n\n {/* Credit Note Section */}\n {creditNoteNumber && (\n <div className=\"space-y-2\">\n <div>\n <p className=\"text-xs text-status-error-text mb-1\">Credit Note</p>\n <p className=\"text-sm font-mono text-status-error-text\">{creditNoteNumber}</p>\n </div>\n {creditNotePdfUrl && (\n <button\n type=\"button\"\n onClick={() => {\n void nativeImpact('light');\n void nativeOpenUrl(creditNotePdfUrl);\n }}\n className=\"flex items-center gap-2 text-sm text-status-error-text hover:underline\"\n >\n <FileText className=\"size-4\" />\n Download Credit Note PDF\n </button>\n )}\n </div>\n )}\n\n {/* Purchase Type & Detail */}\n {purchaseType && (\n <div>\n <p className=\"text-xs text-status-error-text mb-1\">Purchase Type</p>\n <p className=\"text-sm text-status-error-text\">\n {purchaseType}\n {purchaseDetail && ` - ${purchaseDetail}`}\n </p>\n </div>\n )}\n\n {/* Refund Reason */}\n {refundReason && (\n <div>\n <p className=\"text-xs text-status-error-text mb-1\">Reason</p>\n <p className=\"text-sm text-status-error-text\">{refundReason}</p>\n </div>\n )}\n\n {/* Original Transaction Reference */}\n {originalTransactionId && (\n <div>\n <p className=\"text-xs text-status-error-text mb-1\">Original Transaction</p>\n <p className=\"text-sm font-mono text-status-error-text break-all\">\n {originalTransactionId}\n </p>\n </div>\n )}\n\n {/* Refund Record ID */}\n {refundRecordId && (\n <div>\n <p className=\"text-xs text-status-error-text mb-1\">Refund Record ID</p>\n <p className=\"text-sm font-mono text-status-error-text break-all\">\n {refundRecordId}\n </p>\n </div>\n )}\n </div>\n )}\n\n {transaction.stripePaymentId && (\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Stripe Payment ID</p>\n <p className=\"text-sm font-mono break-all\">{transaction.stripePaymentId}</p>\n </div>\n )}\n\n {transaction.razorpayPaymentId && (\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Razorpay Payment ID</p>\n <p className=\"text-sm font-mono break-all\">{transaction.razorpayPaymentId}</p>\n </div>\n )}\n </div>\n\n <DialogFooter className=\"p-4 border-t border-border-subtle\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"w-full py-2 px-4 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg/90 transition-colors\"\n >\n Close\n </button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n};\n\nexport const TransactionsPage: FC = () => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const { billingAccountId } = useParams<{ billingAccountId: string }>();\n const permissions = useBillingPermissions();\n const navigateTo = useBillingNavigate();\n const {\n billingAccount,\n transactions,\n pagination,\n isLoading,\n error,\n refetch,\n goToNextPage,\n goToPreviousPage,\n } = useTransactions(billingAccountId);\n const [filterType, setFilterType] = useState<FilterType>('all');\n const [selectedTransaction, setSelectedTransaction] = useState<Transaction | null>(null);\n\n // Get invoice URL from transaction metadata (supports both Zoho and Stripe)\n const getInvoiceUrl = (transaction: Transaction): string | null => {\n const metadata = transaction.metadata as Record<string, unknown> | null;\n // Check for Zoho Books invoice first (INR payments)\n if (metadata?.zohoBooksInvoiceUrl) {\n return metadata.zohoBooksInvoiceUrl as string;\n }\n // Check for Stripe invoice (international payments)\n if (metadata?.invoiceUrl) {\n return metadata.invoiceUrl as string;\n }\n // Check for Stripe PDF (fallback)\n if (metadata?.invoicePdf) {\n return metadata.invoicePdf as string;\n }\n return null;\n };\n\n // Get total amount (with tax) from metadata if available\n const getTotalAmount = (transaction: Transaction): number => {\n const metadata = transaction.metadata as Record<string, unknown> | null;\n // Check for total in metadata (includes tax)\n if (metadata?.total && typeof metadata.total === 'number') {\n return metadata.total;\n }\n // Fallback to transaction amount\n return transaction.amount;\n };\n\n // Get invoice provider name for display\n const getInvoiceProvider = (transaction: Transaction): string | null => {\n const metadata = transaction.metadata as Record<string, unknown> | null;\n if (metadata?.zohoBooksInvoiceUrl) return 'Zoho Books';\n if (metadata?.invoiceUrl || metadata?.invoicePdf) return 'Stripe';\n return null;\n };\n\n const handleViewInvoice = (transaction: Transaction) => {\n const invoiceUrl = getInvoiceUrl(transaction);\n if (invoiceUrl) {\n void nativeImpact('light');\n void nativeOpenUrl(invoiceUrl);\n }\n };\n\n if (!permissions.canViewPayments) {\n return (\n <AccessDenied\n message={tr(\n 'billing.transactions.noPermission',\n \"You don't have permission to view transaction history.\"\n )}\n />\n );\n }\n\n // Show error if no billing account ID provided\n if (!billingAccountId) {\n return (\n <div className=\"p-6\">\n <EmptyState\n icon={\n <svg\n className=\"size-6 text-text-secondary\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n }\n title={tr('billing.transactions.noAccountSelected', 'No billing account selected')}\n description={tr(\n 'billing.transactions.noAccountSelectedDesc',\n 'Please select a billing account from the overview page to view transactions.'\n )}\n />\n </div>\n );\n }\n\n // Show server error if backend is down\n if (error && isServerError(error)) {\n return (\n <div className=\"p-6\">\n <ServerError\n title={tr('billing.transactions.serverUnavailable', 'Server Unavailable')}\n message={tr(\n 'billing.transactions.serverUnavailableMessage',\n 'Unable to load transactions. The server might be down or experiencing issues.'\n )}\n onRetry={() => refetch()}\n showRetry\n />\n </div>\n );\n }\n const filteredTransactions =\n filterType === 'all' ? transactions : transactions.filter((t) => t.type === filterType);\n\n if (isLoading) {\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"h-8 w-48 bg-bg-sunken animate-pulse rounded\" />\n <div className=\"space-y-2\">\n {[1, 2, 3, 4, 5].map((i) => (\n <div key={i} className=\"h-16 bg-bg-sunken animate-pulse rounded\" />\n ))}\n </div>\n </div>\n );\n }\n\n const transactionColumns: ResponsiveTableColumn<Transaction>[] = [\n {\n key: 'date',\n header: 'Date',\n priority: 'primary',\n cellClassName: 'whitespace-nowrap',\n cell: (transaction) => (\n <span className=\"text-sm text-text-primary\">{formatDateTime(transaction.createdAt)}</span>\n ),\n },\n {\n key: 'type',\n header: 'Type',\n cellClassName: 'whitespace-nowrap',\n cell: (transaction) => (\n <span className=\"text-sm text-text-primary capitalize\">\n {getTypeLabel(transaction.type)}\n </span>\n ),\n },\n {\n key: 'description',\n header: 'Description',\n cell: (transaction) => (\n <span className=\"text-sm text-text-secondary\">{transaction.description ?? '-'}</span>\n ),\n },\n {\n key: 'amount',\n header: 'Amount',\n headerClassName: 'text-right',\n cellClassName: 'text-right whitespace-nowrap',\n cell: (transaction) => (\n <span\n className={`text-sm font-medium tabular-nums ${\n transaction.type === 'refund' ? 'text-status-error-text' : 'text-text-primary'\n }`}\n >\n {transaction.type === 'refund' ? '-' : ''}\n {formatCurrency(getTotalAmount(transaction), transaction.currency)}\n </span>\n ),\n },\n {\n key: 'status',\n header: 'Status',\n headerClassName: 'text-center',\n cellClassName: 'text-center whitespace-nowrap',\n cell: (transaction) => (\n <span\n className={`px-1.5 py-0.5 text-xs font-medium rounded ${getStatusBadgeClasses(\n getTransactionStatusColor(transaction.status)\n )}`}\n >\n {transaction.status}\n </span>\n ),\n },\n ];\n\n const renderTransactionActions = (transaction: Transaction) => (\n <TransactionActionsDropdown\n transaction={transaction}\n onViewDetails={() => setSelectedTransaction(transaction)}\n onViewInvoice={() => handleViewInvoice(transaction)}\n hasInvoiceUrl={!!getInvoiceUrl(transaction)}\n />\n );\n\n return (\n <div className=\"space-y-6 p-6\">\n {/* Back Button */}\n <button\n type=\"button\"\n onClick={() => navigateTo('/overview')}\n className=\"inline-flex items-center gap-2 text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n Back to Overview\n </button>\n\n <PageHeader\n title={tr('billing.transactions.title', 'Transaction History')}\n description={\n billingAccount\n ? `Transactions for ${billingAccount.name}`\n : 'View all your billing transactions'\n }\n />\n\n {/* Billing Account Info Card */}\n {billingAccount && (\n <div className=\"border border-border-subtle rounded-lg p-4 bg-bg-surface\">\n <div className=\"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-4\">\n {/* Account Name & Status */}\n <div className=\"flex items-start gap-2\">\n <CreditCard className=\"size-4 text-text-secondary mt-0.5\" />\n <div>\n <p className=\"text-xs text-text-secondary mb-0.5\">Account</p>\n <p className=\"text-sm font-medium\">{billingAccount.name}</p>\n {billingAccount.isActive ? (\n <span className=\"inline-flex items-center gap-1 mt-1 px-1.5 py-0.5 text-xs font-medium rounded bg-status-success-bg-subtle text-status-success-text\">\n <CheckCircle className=\"size-3\" />\n Active\n </span>\n ) : (\n <span className=\"inline-flex items-center gap-1 mt-1 px-1.5 py-0.5 text-xs font-medium rounded bg-status-error-bg-subtle text-status-error-text\">\n <XCircle className=\"size-3\" />\n Inactive\n </span>\n )}\n </div>\n </div>\n\n {/* Email */}\n <div className=\"flex items-start gap-2\">\n <Mail className=\"size-4 text-text-secondary mt-0.5\" />\n <div>\n <p className=\"text-xs text-text-secondary mb-0.5\">Email</p>\n <p className=\"text-sm font-medium break-all\">\n {billingAccount.billingEmail || billingAccount.email}\n </p>\n </div>\n </div>\n\n {/* Credit Balance */}\n <div className=\"flex items-start gap-2\">\n <Wallet className=\"size-4 text-text-secondary mt-0.5\" />\n <div>\n <p className=\"text-xs text-text-secondary mb-0.5\">Credits Balance</p>\n <p className=\"text-sm font-semibold text-text-primary\">\n {(billingAccount.creditAmount || 0).toLocaleString()} Credits\n </p>\n </div>\n </div>\n\n {/* Tax ID */}\n <div className=\"flex items-start gap-2\">\n <FileText className=\"size-4 text-text-secondary mt-0.5\" />\n <div>\n <p className=\"text-xs text-text-secondary mb-0.5\">Tax ID</p>\n <p className=\"text-sm font-medium\">{billingAccount.taxId || '-'}</p>\n </div>\n </div>\n\n {/* Account Created */}\n <div className=\"flex items-start gap-2\">\n <Calendar className=\"size-4 text-text-secondary mt-0.5\" />\n <div>\n <p className=\"text-xs text-text-secondary mb-0.5\">Member Since</p>\n <p className=\"text-sm font-medium\">\n {billingAccount.createdAt ? formatDateTime(billingAccount.createdAt) : '-'}\n </p>\n </div>\n </div>\n </div>\n </div>\n )}\n\n {/* Filters */}\n <div className=\"flex items-center gap-4\">\n <div className=\"inline-flex rounded-lg border border-border-subtle p-1 bg-bg-sunken/50\">\n {(['all', 'payment', 'refund', 'adjustment'] as FilterType[]).map((type) => (\n <button\n type=\"button\"\n key={type}\n onClick={() => setFilterType(type)}\n className={`px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${\n filterType === type\n ? 'bg-bg-surface text-text-primary shadow-sm'\n : 'text-text-secondary hover:text-text-primary'\n }`}\n >\n {type === 'all' ? 'All' : TYPE_LABELS[type as TransactionType]}\n </button>\n ))}\n </div>\n </div>\n\n {/* Transactions List */}\n {filteredTransactions.length === 0 ? (\n <EmptyState\n icon={\n <svg\n className=\"size-6 text-text-secondary\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"\n />\n </svg>\n }\n title={tr('billing.transactions.noTransactionsFound', 'No transactions found')}\n description={\n filterType !== 'all'\n ? tr(\n 'billing.transactions.noTransactionsFiltered',\n 'No transactions match your filter.'\n )\n : tr(\n 'billing.transactions.noTransactionsYet',\n 'Your transaction history will appear here.'\n )\n }\n />\n ) : (\n <div className=\"border border-border-subtle rounded-lg overflow-visible\">\n <ResponsiveTable<Transaction>\n columns={transactionColumns}\n data={filteredTransactions}\n rowKey={(transaction) => transaction.id}\n rowActions={renderTransactionActions}\n />\n </div>\n )}\n\n {/* Pagination Controls */}\n {pagination.totalCount > 0 && (\n <div className=\"flex items-center justify-between border-t border-border-subtle pt-4\">\n <p className=\"text-sm text-text-secondary\">\n Showing {pagination.page * pagination.pageSize + 1} to{' '}\n {Math.min((pagination.page + 1) * pagination.pageSize, pagination.totalCount)} of{' '}\n {pagination.totalCount} transactions\n </p>\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={goToPreviousPage}\n disabled={!pagination.hasPrevious}\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-md border border-border-subtle bg-bg-surface hover:bg-bg-sunken/50 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n <ChevronLeft className=\"size-4\" />\n Previous\n </button>\n <span className=\"text-sm text-text-secondary px-2\">\n Page {pagination.page + 1} of {Math.ceil(pagination.totalCount / pagination.pageSize)}\n </span>\n <button\n type=\"button\"\n onClick={goToNextPage}\n disabled={!pagination.hasMore}\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-md border border-border-subtle bg-bg-surface hover:bg-bg-sunken/50 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n Next\n <ChevronRight className=\"size-4\" />\n </button>\n </div>\n </div>\n )}\n\n {/* Transaction Details Modal */}\n <TransactionDetailsModal\n transaction={selectedTransaction}\n onClose={() => setSelectedTransaction(null)}\n onViewInvoice={handleViewInvoice}\n invoiceUrl={selectedTransaction ? getInvoiceUrl(selectedTransaction) : null}\n invoiceProvider={selectedTransaction ? getInvoiceProvider(selectedTransaction) : null}\n />\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TransactionsPage.js","names":[],"sources":["../../../../../src/billing/modules/billing/pages/TransactionsPage.tsx"],"sourcesContent":["/**\n * Billing Module - Transactions Page\n * Displays all billing transactions for a specific billing account\n */\n\nimport { useState, useRef, useEffect, type FC } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n ArrowLeft,\n MoreHorizontal,\n Eye,\n FileText,\n CreditCard,\n Mail,\n Wallet,\n ChevronLeft,\n ChevronRight,\n Calendar,\n CheckCircle,\n XCircle,\n} from 'lucide-react';\nimport { useBillingPermissions } from '../../../hooks/useBillingPermissions';\nimport { useBillingNavigate } from '../../../hooks/useBillingNavigate';\nimport { useTransactions } from '../hooks';\nimport { nativeImpact, nativeOpenUrl } from '../../../../utils/nativeBridge';\nimport { AccessDenied, PageHeader, EmptyState, ServerError } from '../../../shared/components';\nimport { formatCurrency, formatDateTime, isServerError } from '../../../shared/utils';\nimport { getTransactionStatusColor, getStatusBadgeClasses } from '../../../shared/utils/status';\nimport type { Transaction, TransactionType } from '../../../shared/types';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n ResponsiveTable,\n type ResponsiveTableColumn,\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogFooter,\n IllustratedEmptyState,\n} from '@burdenoff/fe-libs/ui';\n\ntype FilterType = 'all' | TransactionType;\n\nconst TYPE_LABELS: Record<TransactionType, string> = {\n payment: 'Payment',\n refund: 'Refund',\n adjustment: 'Adjustment',\n};\n\n// Helper to get label for transaction type (case-insensitive)\nconst getTypeLabel = (type: string): string => {\n const normalized = type.toLowerCase() as TransactionType;\n return TYPE_LABELS[normalized] ?? type;\n};\n\n// Transaction Actions Dropdown Component\ninterface TransactionActionsDropdownProps {\n transaction: Transaction;\n onViewDetails: () => void;\n onViewInvoice: () => void;\n hasInvoiceUrl: boolean;\n}\n\nconst TransactionActionsDropdown: FC<TransactionActionsDropdownProps> = ({\n transaction,\n onViewDetails,\n onViewInvoice,\n hasInvoiceUrl,\n}) => {\n const [isOpen, setIsOpen] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, []);\n\n return (\n <div className=\"relative overflow-visible\" ref={dropdownRef}>\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n className=\"p-1.5 rounded-md hover:bg-bg-sunken/50 transition-colors\"\n aria-label=\"Transaction actions\"\n >\n <MoreHorizontal className=\"size-4 text-text-secondary\" />\n </button>\n\n {isOpen && (\n <div className=\"absolute right-0 top-full mt-1 z-50 min-w-[160px] bg-popover border border-border-subtle rounded-md shadow-lg py-1\">\n <button\n type=\"button\"\n onClick={() => {\n onViewDetails();\n setIsOpen(false);\n }}\n className=\"w-full flex items-center gap-2 px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken/50 transition-colors whitespace-nowrap\"\n >\n <Eye className=\"size-4\" />\n View Details\n </button>\n {transaction.type === 'payment' && hasInvoiceUrl && (\n <button\n type=\"button\"\n onClick={() => {\n onViewInvoice();\n setIsOpen(false);\n }}\n className=\"w-full flex items-center gap-2 px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken/50 transition-colors whitespace-nowrap\"\n >\n <FileText className=\"size-4\" />\n View Invoice\n </button>\n )}\n </div>\n )}\n </div>\n );\n};\n\n// Transaction Details Modal Component\ninterface TransactionDetailsModalProps {\n transaction: Transaction | null;\n onClose: () => void;\n onViewInvoice?: (transaction: Transaction) => void;\n invoiceUrl?: string | null;\n invoiceProvider?: string | null;\n}\n\nconst TransactionDetailsModal: FC<TransactionDetailsModalProps> = ({\n transaction,\n onClose,\n onViewInvoice,\n invoiceUrl,\n invoiceProvider,\n}) => {\n if (!transaction) return null;\n\n // Extract tax information from metadata\n const metadata = transaction.metadata as Record<string, unknown> | null;\n const subtotal = metadata?.subtotal as number | undefined;\n const taxAmount = metadata?.taxAmount as number | undefined;\n const taxRate = metadata?.taxRate as number | undefined;\n const taxType = metadata?.taxType as string | undefined;\n const total = metadata?.total as number | undefined;\n const invoiceNumber = metadata?.invoiceNumber as string | undefined;\n const invoiceStatus = metadata?.invoiceStatus as string | undefined;\n\n // Extract refund-specific information\n const isRefund = transaction.type === 'refund';\n const refundRecordId = metadata?.refundRecordId as string | undefined;\n const originalTransactionId = metadata?.originalTransactionId as string | undefined;\n const creditNoteId = metadata?.creditNoteId as string | undefined;\n const creditNoteNumber = metadata?.creditNoteNumber as string | undefined;\n const creditNotePdfUrl = metadata?.creditNotePdfUrl as string | undefined;\n const refundReason = metadata?.reason as string | undefined;\n const purchaseType = metadata?.purchaseType as string | undefined;\n const purchaseDetail = metadata?.purchaseDetail as string | undefined;\n\n // Determine if we should show tax breakdown\n const showTaxBreakdown = total && taxAmount !== undefined && taxAmount > 0;\n\n return (\n <Dialog open={!!transaction} onOpenChange={(open) => !open && onClose()}>\n <DialogContent className=\"max-w-md max-h-[90vh] overflow-auto p-0\">\n <DialogHeader className=\"p-4 border-b border-border-subtle\">\n <DialogTitle className=\"text-lg font-semibold\">Transaction Details</DialogTitle>\n </DialogHeader>\n\n <div className=\"p-4 space-y-4\">\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Transaction ID</p>\n <p className=\"text-sm font-mono break-all\">{transaction.id}</p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Type</p>\n <p className=\"text-sm capitalize\">{getTypeLabel(transaction.type)}</p>\n </div>\n </div>\n\n {/* Amount Section with Tax Breakdown */}\n <div className=\"space-y-2\">\n {showTaxBreakdown ? (\n <>\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">Subtotal</span>\n <span>\n {formatCurrency(subtotal || transaction.amount, transaction.currency)}\n </span>\n </div>\n {taxAmount > 0 && (\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">\n {taxType || 'Tax'} {taxRate ? `(${(taxRate * 100).toFixed(0)}%)` : ''}\n </span>\n <span>{formatCurrency(taxAmount, transaction.currency)}</span>\n </div>\n )}\n <div className=\"flex justify-between text-sm font-semibold border-t border-border-subtle pt-2\">\n <span>Total</span>\n <span className={transaction.type === 'refund' ? 'text-status-error-text' : ''}>\n {transaction.type === 'refund' ? '-' : ''}\n {formatCurrency(total, transaction.currency)}\n </span>\n </div>\n </>\n ) : (\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Amount</p>\n <p\n className={`text-sm font-medium ${transaction.type === 'refund' ? 'text-status-error-text' : ''}`}\n >\n {transaction.type === 'refund' ? '-' : ''}\n {formatCurrency(total || transaction.amount, transaction.currency)}\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Status</p>\n <span\n className={`px-2 py-0.5 text-xs font-medium rounded ${getStatusBadgeClasses(\n getTransactionStatusColor(transaction.status)\n )}`}\n >\n {transaction.status}\n </span>\n </div>\n </div>\n )}\n </div>\n\n {/* Status (if tax breakdown shown) */}\n {showTaxBreakdown && (\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Status</p>\n <span\n className={`px-2 py-0.5 text-xs font-medium rounded ${getStatusBadgeClasses(\n getTransactionStatusColor(transaction.status)\n )}`}\n >\n {transaction.status}\n </span>\n </div>\n )}\n\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Date & Time</p>\n <p className=\"text-sm\">{formatDateTime(transaction.createdAt)}</p>\n </div>\n\n {transaction.description && (\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Description</p>\n <p className=\"text-sm\">{transaction.description}</p>\n </div>\n )}\n\n {/* Invoice Information */}\n {invoiceNumber && (\n <div className=\"p-3 bg-bg-sunken/50 rounded-lg space-y-2\">\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Invoice</p>\n <p className=\"text-sm font-mono\">{invoiceNumber}</p>\n </div>\n {invoiceStatus && (\n <span\n className={`px-2 py-0.5 text-xs font-medium rounded ${\n invoiceStatus === 'PAID'\n ? 'bg-status-success-bg-subtle text-status-success-text'\n : 'bg-status-warning-bg-subtle text-status-warning-text'\n }`}\n >\n {invoiceStatus}\n </span>\n )}\n </div>\n {invoiceProvider && (\n <p className=\"text-xs text-text-secondary\">Provider: {invoiceProvider}</p>\n )}\n {invoiceUrl && onViewInvoice && (\n <button\n type=\"button\"\n onClick={() => onViewInvoice(transaction)}\n className=\"flex items-center gap-2 text-sm text-primary hover:underline\"\n >\n <FileText className=\"size-4\" />\n View Invoice\n </button>\n )}\n </div>\n )}\n\n {/* Fallback invoice button if no invoice number but URL exists */}\n {!invoiceNumber && invoiceUrl && onViewInvoice && (\n <div className=\"p-3 bg-bg-sunken/50 rounded-lg\">\n <button\n type=\"button\"\n onClick={() => onViewInvoice(transaction)}\n className=\"flex items-center gap-2 text-sm text-primary hover:underline\"\n >\n <FileText className=\"size-4\" />\n View Invoice {invoiceProvider && `(${invoiceProvider})`}\n </button>\n </div>\n )}\n\n {/* Refund-Specific Information */}\n {isRefund && (creditNoteId || refundReason || purchaseType) && (\n <div className=\"p-3 bg-status-error-bg-subtle/20 border border-border-subtle rounded-lg space-y-3\">\n <div className=\"flex items-center gap-2\">\n <div className=\"size-1.5 rounded-full bg-status-error-bg\" />\n <p className=\"text-sm font-semibold text-status-error-text\">Refund Information</p>\n </div>\n\n {/* Credit Note Section */}\n {creditNoteNumber && (\n <div className=\"space-y-2\">\n <div>\n <p className=\"text-xs text-status-error-text mb-1\">Credit Note</p>\n <p className=\"text-sm font-mono text-status-error-text\">{creditNoteNumber}</p>\n </div>\n {creditNotePdfUrl && (\n <button\n type=\"button\"\n onClick={() => {\n void nativeImpact('light');\n void nativeOpenUrl(creditNotePdfUrl);\n }}\n className=\"flex items-center gap-2 text-sm text-status-error-text hover:underline\"\n >\n <FileText className=\"size-4\" />\n Download Credit Note PDF\n </button>\n )}\n </div>\n )}\n\n {/* Purchase Type & Detail */}\n {purchaseType && (\n <div>\n <p className=\"text-xs text-status-error-text mb-1\">Purchase Type</p>\n <p className=\"text-sm text-status-error-text\">\n {purchaseType}\n {purchaseDetail && ` - ${purchaseDetail}`}\n </p>\n </div>\n )}\n\n {/* Refund Reason */}\n {refundReason && (\n <div>\n <p className=\"text-xs text-status-error-text mb-1\">Reason</p>\n <p className=\"text-sm text-status-error-text\">{refundReason}</p>\n </div>\n )}\n\n {/* Original Transaction Reference */}\n {originalTransactionId && (\n <div>\n <p className=\"text-xs text-status-error-text mb-1\">Original Transaction</p>\n <p className=\"text-sm font-mono text-status-error-text break-all\">\n {originalTransactionId}\n </p>\n </div>\n )}\n\n {/* Refund Record ID */}\n {refundRecordId && (\n <div>\n <p className=\"text-xs text-status-error-text mb-1\">Refund Record ID</p>\n <p className=\"text-sm font-mono text-status-error-text break-all\">\n {refundRecordId}\n </p>\n </div>\n )}\n </div>\n )}\n\n {transaction.stripePaymentId && (\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Stripe Payment ID</p>\n <p className=\"text-sm font-mono break-all\">{transaction.stripePaymentId}</p>\n </div>\n )}\n\n {transaction.razorpayPaymentId && (\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">Razorpay Payment ID</p>\n <p className=\"text-sm font-mono break-all\">{transaction.razorpayPaymentId}</p>\n </div>\n )}\n </div>\n\n <DialogFooter className=\"p-4 border-t border-border-subtle\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"w-full py-2 px-4 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg/90 transition-colors\"\n >\n Close\n </button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n};\n\nexport const TransactionsPage: FC = () => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const { billingAccountId } = useParams<{ billingAccountId: string }>();\n const permissions = useBillingPermissions();\n const navigateTo = useBillingNavigate();\n const {\n billingAccount,\n transactions,\n pagination,\n isLoading,\n error,\n refetch,\n goToNextPage,\n goToPreviousPage,\n } = useTransactions(billingAccountId);\n const [filterType, setFilterType] = useState<FilterType>('all');\n const [selectedTransaction, setSelectedTransaction] = useState<Transaction | null>(null);\n\n // Get invoice URL from transaction metadata (supports both Zoho and Stripe)\n const getInvoiceUrl = (transaction: Transaction): string | null => {\n const metadata = transaction.metadata as Record<string, unknown> | null;\n // Check for Zoho Books invoice first (INR payments)\n if (metadata?.zohoBooksInvoiceUrl) {\n return metadata.zohoBooksInvoiceUrl as string;\n }\n // Check for Stripe invoice (international payments)\n if (metadata?.invoiceUrl) {\n return metadata.invoiceUrl as string;\n }\n // Check for Stripe PDF (fallback)\n if (metadata?.invoicePdf) {\n return metadata.invoicePdf as string;\n }\n return null;\n };\n\n // Get total amount (with tax) from metadata if available\n const getTotalAmount = (transaction: Transaction): number => {\n const metadata = transaction.metadata as Record<string, unknown> | null;\n // Check for total in metadata (includes tax)\n if (metadata?.total && typeof metadata.total === 'number') {\n return metadata.total;\n }\n // Fallback to transaction amount\n return transaction.amount;\n };\n\n // Get invoice provider name for display\n const getInvoiceProvider = (transaction: Transaction): string | null => {\n const metadata = transaction.metadata as Record<string, unknown> | null;\n if (metadata?.zohoBooksInvoiceUrl) return 'Zoho Books';\n if (metadata?.invoiceUrl || metadata?.invoicePdf) return 'Stripe';\n return null;\n };\n\n const handleViewInvoice = (transaction: Transaction) => {\n const invoiceUrl = getInvoiceUrl(transaction);\n if (invoiceUrl) {\n void nativeImpact('light');\n void nativeOpenUrl(invoiceUrl);\n }\n };\n\n if (!permissions.canViewPayments) {\n return (\n <AccessDenied\n message={tr(\n 'billing.transactions.noPermission',\n \"You don't have permission to view transaction history.\"\n )}\n />\n );\n }\n\n // Show error if no billing account ID provided\n if (!billingAccountId) {\n return (\n <div className=\"p-6\">\n <EmptyState\n icon={\n <svg\n className=\"size-6 text-text-secondary\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n }\n title={tr('billing.transactions.noAccountSelected', 'No billing account selected')}\n description={tr(\n 'billing.transactions.noAccountSelectedDesc',\n 'Please select a billing account from the overview page to view transactions.'\n )}\n />\n </div>\n );\n }\n\n // Show server error if backend is down\n if (error && isServerError(error)) {\n return (\n <div className=\"p-6\">\n <ServerError\n title={tr('billing.transactions.serverUnavailable', 'Server Unavailable')}\n message={tr(\n 'billing.transactions.serverUnavailableMessage',\n 'Unable to load transactions. The server might be down or experiencing issues.'\n )}\n onRetry={() => refetch()}\n showRetry\n />\n </div>\n );\n }\n const filteredTransactions =\n filterType === 'all' ? transactions : transactions.filter((t) => t.type === filterType);\n\n if (isLoading) {\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"h-8 w-48 bg-bg-sunken animate-pulse rounded\" />\n <div className=\"space-y-2\">\n {[1, 2, 3, 4, 5].map((i) => (\n <div key={i} className=\"h-16 bg-bg-sunken animate-pulse rounded\" />\n ))}\n </div>\n </div>\n );\n }\n\n const transactionColumns: ResponsiveTableColumn<Transaction>[] = [\n {\n key: 'date',\n header: 'Date',\n priority: 'primary',\n cellClassName: 'whitespace-nowrap',\n cell: (transaction) => (\n <span className=\"text-sm text-text-primary\">{formatDateTime(transaction.createdAt)}</span>\n ),\n },\n {\n key: 'type',\n header: 'Type',\n cellClassName: 'whitespace-nowrap',\n cell: (transaction) => (\n <span className=\"text-sm text-text-primary capitalize\">\n {getTypeLabel(transaction.type)}\n </span>\n ),\n },\n {\n key: 'description',\n header: 'Description',\n cell: (transaction) => (\n <span className=\"text-sm text-text-secondary\">{transaction.description ?? '-'}</span>\n ),\n },\n {\n key: 'amount',\n header: 'Amount',\n headerClassName: 'text-right',\n cellClassName: 'text-right whitespace-nowrap',\n cell: (transaction) => (\n <span\n className={`text-sm font-medium tabular-nums ${\n transaction.type === 'refund' ? 'text-status-error-text' : 'text-text-primary'\n }`}\n >\n {transaction.type === 'refund' ? '-' : ''}\n {formatCurrency(getTotalAmount(transaction), transaction.currency)}\n </span>\n ),\n },\n {\n key: 'status',\n header: 'Status',\n headerClassName: 'text-center',\n cellClassName: 'text-center whitespace-nowrap',\n cell: (transaction) => (\n <span\n className={`px-1.5 py-0.5 text-xs font-medium rounded ${getStatusBadgeClasses(\n getTransactionStatusColor(transaction.status)\n )}`}\n >\n {transaction.status}\n </span>\n ),\n },\n ];\n\n const renderTransactionActions = (transaction: Transaction) => (\n <TransactionActionsDropdown\n transaction={transaction}\n onViewDetails={() => setSelectedTransaction(transaction)}\n onViewInvoice={() => handleViewInvoice(transaction)}\n hasInvoiceUrl={!!getInvoiceUrl(transaction)}\n />\n );\n\n return (\n <div className=\"space-y-6 p-6\">\n {/* Back Button */}\n <button\n type=\"button\"\n onClick={() => navigateTo('/overview')}\n className=\"inline-flex items-center gap-2 text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n Back to Overview\n </button>\n\n <PageHeader\n title={tr('billing.transactions.title', 'Transaction History')}\n description={\n billingAccount\n ? `Transactions for ${billingAccount.name}`\n : 'View all your billing transactions'\n }\n />\n\n {/* Billing Account Info Card */}\n {billingAccount && (\n <div className=\"border border-border-subtle rounded-lg p-4 bg-bg-surface\">\n <div className=\"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-4\">\n {/* Account Name & Status */}\n <div className=\"flex items-start gap-2\">\n <CreditCard className=\"size-4 text-text-secondary mt-0.5\" />\n <div>\n <p className=\"text-xs text-text-secondary mb-0.5\">Account</p>\n <p className=\"text-sm font-medium\">{billingAccount.name}</p>\n {billingAccount.isActive ? (\n <span className=\"inline-flex items-center gap-1 mt-1 px-1.5 py-0.5 text-xs font-medium rounded bg-status-success-bg-subtle text-status-success-text\">\n <CheckCircle className=\"size-3\" />\n Active\n </span>\n ) : (\n <span className=\"inline-flex items-center gap-1 mt-1 px-1.5 py-0.5 text-xs font-medium rounded bg-status-error-bg-subtle text-status-error-text\">\n <XCircle className=\"size-3\" />\n Inactive\n </span>\n )}\n </div>\n </div>\n\n {/* Email */}\n <div className=\"flex items-start gap-2\">\n <Mail className=\"size-4 text-text-secondary mt-0.5\" />\n <div>\n <p className=\"text-xs text-text-secondary mb-0.5\">Email</p>\n <p className=\"text-sm font-medium break-all\">\n {billingAccount.billingEmail || billingAccount.email}\n </p>\n </div>\n </div>\n\n {/* Credit Balance */}\n <div className=\"flex items-start gap-2\">\n <Wallet className=\"size-4 text-text-secondary mt-0.5\" />\n <div>\n <p className=\"text-xs text-text-secondary mb-0.5\">Credits Balance</p>\n <p className=\"text-sm font-semibold text-text-primary\">\n {(billingAccount.creditAmount || 0).toLocaleString()} Credits\n </p>\n </div>\n </div>\n\n {/* Tax ID */}\n <div className=\"flex items-start gap-2\">\n <FileText className=\"size-4 text-text-secondary mt-0.5\" />\n <div>\n <p className=\"text-xs text-text-secondary mb-0.5\">Tax ID</p>\n <p className=\"text-sm font-medium\">{billingAccount.taxId || '-'}</p>\n </div>\n </div>\n\n {/* Account Created */}\n <div className=\"flex items-start gap-2\">\n <Calendar className=\"size-4 text-text-secondary mt-0.5\" />\n <div>\n <p className=\"text-xs text-text-secondary mb-0.5\">Member Since</p>\n <p className=\"text-sm font-medium\">\n {billingAccount.createdAt ? formatDateTime(billingAccount.createdAt) : '-'}\n </p>\n </div>\n </div>\n </div>\n </div>\n )}\n\n {/* Filters */}\n <div className=\"flex items-center gap-4\">\n <div className=\"inline-flex rounded-lg border border-border-subtle p-1 bg-bg-sunken/50\">\n {(['all', 'payment', 'refund', 'adjustment'] as FilterType[]).map((type) => (\n <button\n type=\"button\"\n key={type}\n onClick={() => setFilterType(type)}\n className={`px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${\n filterType === type\n ? 'bg-bg-surface text-text-primary shadow-sm'\n : 'text-text-secondary hover:text-text-primary'\n }`}\n >\n {type === 'all' ? 'All' : TYPE_LABELS[type as TransactionType]}\n </button>\n ))}\n </div>\n </div>\n\n {/* Transactions List */}\n {filteredTransactions.length === 0 ? (\n <IllustratedEmptyState\n illustration={filterType !== 'all' ? 'empty-search' : 'empty-data'}\n title={tr('billing.transactions.noTransactionsFound', 'No transactions found')}\n description={\n filterType !== 'all'\n ? tr(\n 'billing.transactions.noTransactionsFiltered',\n 'No transactions match your filter.'\n )\n : tr(\n 'billing.transactions.noTransactionsYet',\n 'Your transaction history will appear here.'\n )\n }\n />\n ) : (\n <div className=\"border border-border-subtle rounded-lg overflow-visible\">\n <ResponsiveTable<Transaction>\n columns={transactionColumns}\n data={filteredTransactions}\n rowKey={(transaction) => transaction.id}\n rowActions={renderTransactionActions}\n />\n </div>\n )}\n\n {/* Pagination Controls */}\n {pagination.totalCount > 0 && (\n <div className=\"flex items-center justify-between border-t border-border-subtle pt-4\">\n <p className=\"text-sm text-text-secondary\">\n Showing {pagination.page * pagination.pageSize + 1} to{' '}\n {Math.min((pagination.page + 1) * pagination.pageSize, pagination.totalCount)} of{' '}\n {pagination.totalCount} transactions\n </p>\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={goToPreviousPage}\n disabled={!pagination.hasPrevious}\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-md border border-border-subtle bg-bg-surface hover:bg-bg-sunken/50 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n <ChevronLeft className=\"size-4\" />\n Previous\n </button>\n <span className=\"text-sm text-text-secondary px-2\">\n Page {pagination.page + 1} of {Math.ceil(pagination.totalCount / pagination.pageSize)}\n </span>\n <button\n type=\"button\"\n onClick={goToNextPage}\n disabled={!pagination.hasMore}\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-md border border-border-subtle bg-bg-surface hover:bg-bg-sunken/50 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n Next\n <ChevronRight className=\"size-4\" />\n </button>\n </div>\n </div>\n )}\n\n {/* Transaction Details Modal */}\n <TransactionDetailsModal\n transaction={selectedTransaction}\n onClose={() => setSelectedTransaction(null)}\n onViewInvoice={handleViewInvoice}\n invoiceUrl={selectedTransaction ? getInvoiceUrl(selectedTransaction) : null}\n invoiceProvider={selectedTransaction ? getInvoiceProvider(selectedTransaction) : null}\n />\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -16,18 +16,19 @@ import { ArrowLeft as h, Calendar as g, CheckCircle as _, ChevronLeft as v, Chev
|
|
|
16
16
|
import { useParams as D } from "react-router-dom";
|
|
17
17
|
import { jsx as O, jsxs as k } from "react/jsx-runtime";
|
|
18
18
|
import { useI18n as A } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
19
|
+
import { IllustratedEmptyState as j } from "@burdenoff/fe-libs/ui";
|
|
19
20
|
//#region src/billing/modules/credits/pages/CreditTransactionsPage.tsx
|
|
20
|
-
var
|
|
21
|
+
var M = () => {
|
|
21
22
|
let { t: o } = A(), s = (e, t) => {
|
|
22
23
|
let n = o(e);
|
|
23
24
|
return n === e ? t : n;
|
|
24
|
-
}, { billingAccountId: c } = D(), w = u(), T = f(), [
|
|
25
|
+
}, { billingAccountId: c } = D(), w = u(), T = f(), [M, P] = m(30), [F, I] = m("all"), [L, R] = m(1), { data: z, loading: B } = d({
|
|
25
26
|
variables: { id: c },
|
|
26
27
|
skip: !c
|
|
27
|
-
}),
|
|
28
|
+
}), V = z?.getBillingAccount, { transactions: H, pagination: U, isLoading: W, error: G, refetch: K } = p({
|
|
28
29
|
billingAccountId: c || "",
|
|
29
|
-
days:
|
|
30
|
-
page:
|
|
30
|
+
days: M,
|
|
31
|
+
page: L,
|
|
31
32
|
pageSize: 20
|
|
32
33
|
});
|
|
33
34
|
if (!w.canViewCredits) return /* @__PURE__ */ O(e, { message: "You don't have permission to view credit history." });
|
|
@@ -50,17 +51,17 @@ var j = () => {
|
|
|
50
51
|
description: "Please select a billing account from the overview page to view credit history."
|
|
51
52
|
})
|
|
52
53
|
});
|
|
53
|
-
if (
|
|
54
|
+
if (G && l(G)) return /* @__PURE__ */ O("div", {
|
|
54
55
|
className: "p-6",
|
|
55
56
|
children: /* @__PURE__ */ O(r, {
|
|
56
57
|
title: "Server Unavailable",
|
|
57
58
|
message: "Unable to load credit transactions. The server might be down or experiencing issues.",
|
|
58
|
-
onRetry: () =>
|
|
59
|
+
onRetry: () => K(),
|
|
59
60
|
showRetry: !0
|
|
60
61
|
})
|
|
61
62
|
});
|
|
62
|
-
let
|
|
63
|
-
return
|
|
63
|
+
let q = B || W, J = F === "all" ? H : H.filter((e) => e.type === F), Y = Math.ceil(U.totalCount / 20);
|
|
64
|
+
return q && !V ? /* @__PURE__ */ k("div", {
|
|
64
65
|
className: "space-y-6 px-6 lg:px-8 py-6",
|
|
65
66
|
children: [/* @__PURE__ */ O("div", { className: "h-8 w-48 bg-bg-sunken animate-pulse rounded" }), /* @__PURE__ */ O("div", {
|
|
66
67
|
className: "space-y-2",
|
|
@@ -83,9 +84,9 @@ var j = () => {
|
|
|
83
84
|
}),
|
|
84
85
|
/* @__PURE__ */ O(t, {
|
|
85
86
|
title: "Credit History",
|
|
86
|
-
description:
|
|
87
|
+
description: V ? `Credit transactions for ${V.name}` : "View your credit transaction history"
|
|
87
88
|
}),
|
|
88
|
-
|
|
89
|
+
V && /* @__PURE__ */ O("div", {
|
|
89
90
|
className: "border border-border-subtle rounded-lg p-4 bg-bg-surface",
|
|
90
91
|
children: /* @__PURE__ */ k("div", {
|
|
91
92
|
className: "grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-4",
|
|
@@ -99,9 +100,9 @@ var j = () => {
|
|
|
99
100
|
}),
|
|
100
101
|
/* @__PURE__ */ O("p", {
|
|
101
102
|
className: "text-sm font-medium",
|
|
102
|
-
children:
|
|
103
|
+
children: V.name
|
|
103
104
|
}),
|
|
104
|
-
|
|
105
|
+
V.isActive ? /* @__PURE__ */ k("span", {
|
|
105
106
|
className: "inline-flex items-center gap-1 mt-1 px-1.5 py-0.5 text-xs font-medium rounded bg-status-success-bg-subtle text-status-success-text",
|
|
106
107
|
children: [/* @__PURE__ */ O(_, { className: "size-3" }), "Active"]
|
|
107
108
|
}) : /* @__PURE__ */ k("span", {
|
|
@@ -117,7 +118,7 @@ var j = () => {
|
|
|
117
118
|
children: "Email"
|
|
118
119
|
}), /* @__PURE__ */ O("p", {
|
|
119
120
|
className: "text-sm font-medium break-all",
|
|
120
|
-
children:
|
|
121
|
+
children: V.billingEmail || V.email
|
|
121
122
|
})] })]
|
|
122
123
|
}),
|
|
123
124
|
/* @__PURE__ */ k("div", {
|
|
@@ -127,7 +128,7 @@ var j = () => {
|
|
|
127
128
|
children: "Credit Balance"
|
|
128
129
|
}), /* @__PURE__ */ k("p", {
|
|
129
130
|
className: "text-sm font-semibold text-text-primary",
|
|
130
|
-
children: [(
|
|
131
|
+
children: [(V.creditAmount || 0).toLocaleString(), " Credits"]
|
|
131
132
|
})] })]
|
|
132
133
|
}),
|
|
133
134
|
/* @__PURE__ */ k("div", {
|
|
@@ -137,7 +138,7 @@ var j = () => {
|
|
|
137
138
|
children: "Tax ID"
|
|
138
139
|
}), /* @__PURE__ */ O("p", {
|
|
139
140
|
className: "text-sm font-medium",
|
|
140
|
-
children:
|
|
141
|
+
children: V.taxId || "-"
|
|
141
142
|
})] })]
|
|
142
143
|
}),
|
|
143
144
|
/* @__PURE__ */ k("div", {
|
|
@@ -147,7 +148,7 @@ var j = () => {
|
|
|
147
148
|
children: "Member Since"
|
|
148
149
|
}), /* @__PURE__ */ O("p", {
|
|
149
150
|
className: "text-sm font-medium",
|
|
150
|
-
children:
|
|
151
|
+
children: V.createdAt ? a(V.createdAt) : "-"
|
|
151
152
|
})] })]
|
|
152
153
|
})
|
|
153
154
|
]
|
|
@@ -165,9 +166,9 @@ var j = () => {
|
|
|
165
166
|
].map((e) => /* @__PURE__ */ k("button", {
|
|
166
167
|
type: "button",
|
|
167
168
|
onClick: () => {
|
|
168
|
-
|
|
169
|
+
P(e), R(1);
|
|
169
170
|
},
|
|
170
|
-
className: `px-3 py-1.5 text-sm font-medium rounded-button transition-colors ${
|
|
171
|
+
className: `px-3 py-1.5 text-sm font-medium rounded-button transition-colors ${M === e ? "bg-bg-surface text-text-primary shadow-sm" : "text-text-secondary hover:text-text-primary"}`,
|
|
171
172
|
children: [e, "d"]
|
|
172
173
|
}, e))
|
|
173
174
|
}),
|
|
@@ -181,46 +182,46 @@ var j = () => {
|
|
|
181
182
|
].map((e) => /* @__PURE__ */ O("button", {
|
|
182
183
|
type: "button",
|
|
183
184
|
onClick: () => {
|
|
184
|
-
|
|
185
|
+
I(e), R(1);
|
|
185
186
|
},
|
|
186
|
-
className: `px-3 py-1.5 text-sm font-medium rounded-button transition-colors capitalize ${
|
|
187
|
+
className: `px-3 py-1.5 text-sm font-medium rounded-button transition-colors capitalize ${F === e ? "bg-bg-surface text-text-primary shadow-sm" : "text-text-secondary hover:text-text-primary"}`,
|
|
187
188
|
children: e === "all" ? "All" : i(e)
|
|
188
189
|
}, e))
|
|
189
190
|
}),
|
|
190
191
|
/* @__PURE__ */ k("div", {
|
|
191
192
|
className: "ml-auto text-sm text-text-secondary",
|
|
192
193
|
children: [
|
|
193
|
-
|
|
194
|
+
U.totalCount,
|
|
194
195
|
" transaction",
|
|
195
|
-
|
|
196
|
+
U.totalCount === 1 ? "" : "s",
|
|
196
197
|
" in last ",
|
|
197
|
-
|
|
198
|
+
M,
|
|
198
199
|
" ",
|
|
199
200
|
"days"
|
|
200
201
|
]
|
|
201
202
|
})
|
|
202
203
|
]
|
|
203
204
|
}),
|
|
204
|
-
|
|
205
|
-
|
|
205
|
+
J.length === 0 ? /* @__PURE__ */ O(j, {
|
|
206
|
+
illustration: F === "all" ? "empty-data" : "empty-search",
|
|
206
207
|
title: "No credit transactions found",
|
|
207
|
-
description:
|
|
208
|
+
description: F === "all" ? "Your credit transaction history will appear here." : "No transactions match your filter."
|
|
208
209
|
}) : /* @__PURE__ */ O("div", {
|
|
209
210
|
className: "space-y-3",
|
|
210
|
-
children:
|
|
211
|
+
children: J.map((e) => /* @__PURE__ */ O(N, { transaction: e }, e.id))
|
|
211
212
|
}),
|
|
212
|
-
|
|
213
|
+
U.totalCount > 0 && /* @__PURE__ */ k("div", {
|
|
213
214
|
className: "flex items-center justify-between border-t border-border-subtle pt-4",
|
|
214
215
|
children: [/* @__PURE__ */ k("p", {
|
|
215
216
|
className: "text-sm text-text-secondary",
|
|
216
217
|
children: [
|
|
217
218
|
"Showing ",
|
|
218
|
-
(
|
|
219
|
+
(L - 1) * 20 + 1,
|
|
219
220
|
" to",
|
|
220
221
|
" ",
|
|
221
|
-
Math.min(
|
|
222
|
+
Math.min(L * 20, U.totalCount),
|
|
222
223
|
" of ",
|
|
223
|
-
|
|
224
|
+
U.totalCount,
|
|
224
225
|
" ",
|
|
225
226
|
"transactions"
|
|
226
227
|
]
|
|
@@ -230,9 +231,9 @@ var j = () => {
|
|
|
230
231
|
/* @__PURE__ */ k("button", {
|
|
231
232
|
type: "button",
|
|
232
233
|
onClick: () => {
|
|
233
|
-
|
|
234
|
+
L > 1 && R((e) => e - 1);
|
|
234
235
|
},
|
|
235
|
-
disabled:
|
|
236
|
+
disabled: L <= 1,
|
|
236
237
|
className: "inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-button border border-border-subtle bg-bg-surface hover:bg-bg-sunken disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
|
|
237
238
|
children: [/* @__PURE__ */ O(v, { className: "size-4" }), "Previous"]
|
|
238
239
|
}),
|
|
@@ -240,17 +241,17 @@ var j = () => {
|
|
|
240
241
|
className: "text-sm text-text-secondary px-2",
|
|
241
242
|
children: [
|
|
242
243
|
"Page ",
|
|
243
|
-
|
|
244
|
+
L,
|
|
244
245
|
" of ",
|
|
245
|
-
|
|
246
|
+
Y || 1
|
|
246
247
|
]
|
|
247
248
|
}),
|
|
248
249
|
/* @__PURE__ */ k("button", {
|
|
249
250
|
type: "button",
|
|
250
251
|
onClick: () => {
|
|
251
|
-
|
|
252
|
+
U.hasMore && R((e) => e + 1);
|
|
252
253
|
},
|
|
253
|
-
disabled: !
|
|
254
|
+
disabled: !U.hasMore,
|
|
254
255
|
className: "inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-button border border-border-subtle bg-bg-surface hover:bg-bg-sunken disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
|
|
255
256
|
children: ["Next", /* @__PURE__ */ O(y, { className: "size-4" })]
|
|
256
257
|
})
|
|
@@ -259,7 +260,7 @@ var j = () => {
|
|
|
259
260
|
})
|
|
260
261
|
]
|
|
261
262
|
});
|
|
262
|
-
},
|
|
263
|
+
}, N = ({ transaction: e }) => {
|
|
263
264
|
let t = s(e.status), n = Number(e.amount), r = n > 0, l = Math.abs(n);
|
|
264
265
|
return /* @__PURE__ */ k("div", {
|
|
265
266
|
className: "flex items-center gap-4 p-4 border border-border-seam rounded-card bg-bg-surface shadow-elevation-1 hover:shadow-sm transition-shadow",
|
|
@@ -331,6 +332,6 @@ var j = () => {
|
|
|
331
332
|
});
|
|
332
333
|
};
|
|
333
334
|
//#endregion
|
|
334
|
-
export {
|
|
335
|
+
export { M as CreditTransactionsPage };
|
|
335
336
|
|
|
336
337
|
//# sourceMappingURL=CreditTransactionsPage.js.map
|