@djangocfg/ext-payments 1.0.6 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/config.cjs +2 -1
  2. package/dist/config.js +2 -1
  3. package/dist/hooks.cjs +558 -542
  4. package/dist/hooks.js +557 -542
  5. package/dist/index.cjs +558 -542
  6. package/dist/index.d.cts +0 -97
  7. package/dist/index.d.ts +0 -97
  8. package/dist/index.js +557 -542
  9. package/package.json +9 -8
  10. package/src/api/generated/ext_payments/CLAUDE.md +76 -0
  11. package/src/api/generated/ext_payments/_utils/fetchers/ext_payments__payments.ts +1 -8
  12. package/src/api/generated/ext_payments/_utils/fetchers/index.ts +1 -8
  13. package/src/api/generated/ext_payments/_utils/hooks/ext_payments__payments.ts +1 -8
  14. package/src/api/generated/ext_payments/_utils/hooks/index.ts +1 -8
  15. package/src/api/generated/ext_payments/_utils/schemas/index.ts +1 -8
  16. package/src/api/generated/ext_payments/api-instance.ts +1 -8
  17. package/src/api/generated/ext_payments/enums.ts +1 -8
  18. package/src/api/generated/ext_payments/errors.ts +1 -8
  19. package/src/api/generated/ext_payments/ext_payments__payments/index.ts +1 -8
  20. package/src/api/generated/ext_payments/ext_payments__payments/models.ts +1 -8
  21. package/src/api/generated/ext_payments/http.ts +1 -8
  22. package/src/api/generated/ext_payments/index.ts +1 -8
  23. package/src/api/generated/ext_payments/logger.ts +1 -8
  24. package/src/api/generated/ext_payments/retry.ts +1 -8
  25. package/src/api/generated/ext_payments/storage.ts +1 -8
  26. package/src/api/generated/ext_payments/validation-events.ts +1 -8
  27. package/src/api/index.ts +2 -1
  28. package/src/config.ts +1 -0
  29. package/src/contexts/BalancesContext.tsx +2 -1
  30. package/src/contexts/CurrenciesContext.tsx +2 -1
  31. package/src/contexts/OverviewContext.tsx +5 -5
  32. package/src/contexts/PaymentsContext.tsx +6 -5
  33. package/src/contexts/PaymentsExtensionProvider.tsx +3 -2
  34. package/src/contexts/RootPaymentsContext.tsx +2 -1
  35. package/src/layouts/PaymentsLayout/PaymentsLayout.tsx +5 -7
  36. package/src/layouts/PaymentsLayout/components/CreatePaymentDialog.tsx +10 -27
  37. package/src/layouts/PaymentsLayout/components/PaymentDetailsDialog.tsx +15 -18
  38. package/src/layouts/PaymentsLayout/views/overview/components/BalanceCard.tsx +6 -13
  39. package/src/layouts/PaymentsLayout/views/overview/components/RecentPayments.tsx +8 -11
  40. package/src/layouts/PaymentsLayout/views/overview/index.tsx +1 -0
  41. package/src/layouts/PaymentsLayout/views/payments/components/PaymentsList.tsx +43 -42
  42. package/src/layouts/PaymentsLayout/views/payments/index.tsx +1 -0
  43. package/src/layouts/PaymentsLayout/views/transactions/components/TransactionsList.tsx +71 -84
  44. package/src/layouts/PaymentsLayout/views/transactions/index.tsx +1 -0
package/dist/index.js CHANGED
@@ -2,13 +2,14 @@ import { createConsola, consola } from 'consola';
2
2
  import pRetry, { AbortError } from 'p-retry';
3
3
  import { z } from 'zod';
4
4
  import { createExtensionAPI } from '@djangocfg/ext-base/api';
5
+ import { Wallet, CreditCard, History, RefreshCw, Plus, XCircle, ExternalLink, Search, Filter, Clock, AlertCircle, CheckCircle2, ArrowDownLeft, ArrowUpRight } from 'lucide-react';
6
+ import { Tabs, TabsList, TabsTrigger, TabsContent, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Form, FormField, FormItem, FormLabel, FormControl, Input, FormDescription, FormMessage, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, TokenIcon, DialogFooter, Button, CopyButton, Card, CardHeader, CardTitle, Skeleton, CardContent, Badge, useDRFPagination, Table, TableHeader, TableRow, TableHead, TableBody, TableCell, StaticPagination } from '@djangocfg/ui-nextjs';
5
7
  import { createContext, useState, useMemo, useEffect, useContext } from 'react';
6
8
  import useSWR, { SWRConfig, useSWRConfig } from 'swr';
7
9
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
- import { Tabs, TabsList, TabsTrigger, TabsContent, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Form, FormField, FormItem, FormLabel, FormControl, Input, FormDescription, FormMessage, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, TokenIcon, DialogFooter, Button, CopyButton, Card, CardHeader, CardTitle, Skeleton, CardContent, Badge, useDRFPagination, Table, TableHeader, TableRow, TableHead, TableBody, TableCell, StaticPagination } from '@djangocfg/ui-nextjs';
9
- import { Wallet, CreditCard, History, RefreshCw, Plus, XCircle, ExternalLink, Search, Filter, Clock, AlertCircle, CheckCircle2, ArrowDownLeft, ArrowUpRight } from 'lucide-react';
10
10
  import { useForm } from 'react-hook-form';
11
11
  import { zodResolver } from '@hookform/resolvers/zod';
12
+ import moment from 'moment';
12
13
  import { createExtensionConfig } from '@djangocfg/ext-base';
13
14
 
14
15
  var __defProp = Object.defineProperty;
@@ -1583,6 +1584,11 @@ function useRootPaymentsContext() {
1583
1584
  }
1584
1585
  return context;
1585
1586
  }
1587
+ var isDevelopment = process.env.NODE_ENV === "development";
1588
+ var logger = createConsola({
1589
+ level: isDevelopment ? 4 : 1
1590
+ }).withTag("ext-payments");
1591
+ var paymentsLogger = logger;
1586
1592
 
1587
1593
  // src/layouts/PaymentsLayout/events.ts
1588
1594
  var PAYMENT_EVENTS = {
@@ -1603,156 +1609,526 @@ var openPaymentDetailsDialog = (id) => {
1603
1609
  var closePaymentsDialog = () => {
1604
1610
  window.dispatchEvent(new Event(PAYMENT_EVENTS.CLOSE_DIALOG));
1605
1611
  };
1606
- var BalanceCard = () => {
1607
- const {
1608
- balance,
1609
- isLoadingBalance,
1610
- refreshBalance
1611
- } = useOverviewContext();
1612
- const formatCurrency = (amount) => {
1613
- if (amount === null || amount === void 0) return "$0.00";
1614
- return new Intl.NumberFormat("en-US", {
1615
- style: "currency",
1616
- currency: "USD",
1617
- minimumFractionDigits: 2
1618
- }).format(amount);
1612
+ var PaymentCreateSchema = z.object({
1613
+ amount_usd: z.number().min(0.01, "Amount must be at least $0.01"),
1614
+ currency_code: z.string().min(1, "Please select a currency")
1615
+ });
1616
+ var CreatePaymentDialog = () => {
1617
+ const [open, setOpen] = useState(false);
1618
+ const [isSubmitting, setIsSubmitting] = useState(false);
1619
+ const { createPayment } = usePaymentsContext();
1620
+ const { currencies, isLoadingCurrencies } = useRootPaymentsContext();
1621
+ const form = useForm({
1622
+ resolver: zodResolver(PaymentCreateSchema),
1623
+ defaultValues: {
1624
+ amount_usd: 10,
1625
+ currency_code: "USDT"
1626
+ }
1627
+ });
1628
+ const currenciesList = useMemo(() => {
1629
+ const data = currencies?.currencies || currencies?.results || currencies || [];
1630
+ return Array.isArray(data) ? data : [];
1631
+ }, [currencies]);
1632
+ const currencyOptions = useMemo(() => {
1633
+ return currenciesList.filter((curr) => curr.is_enabled !== false).map((curr) => ({
1634
+ code: curr.code || curr.currency_code || curr.symbol,
1635
+ name: curr.name || curr.code || curr.currency_code,
1636
+ usd_rate: curr.usd_rate || curr.rate || 1,
1637
+ network: curr.network || null
1638
+ }));
1639
+ }, [currenciesList]);
1640
+ const calculateCryptoAmount = useMemo(() => {
1641
+ const amountUsd = form.watch("amount_usd");
1642
+ const currencyCode = form.watch("currency_code");
1643
+ const currency = currencyOptions.find((c) => c.code === currencyCode);
1644
+ if (!currency || !currency.usd_rate || !amountUsd) {
1645
+ return null;
1646
+ }
1647
+ const cryptoAmount = amountUsd / currency.usd_rate;
1648
+ return {
1649
+ amount: cryptoAmount,
1650
+ currency: currency.code,
1651
+ rate: currency.usd_rate,
1652
+ network: currency.network
1653
+ };
1654
+ }, [form.watch("amount_usd"), form.watch("currency_code"), currencyOptions]);
1655
+ useEffect(() => {
1656
+ const handleOpen = () => setOpen(true);
1657
+ const handleClose2 = () => setOpen(false);
1658
+ window.addEventListener(PAYMENT_EVENTS.OPEN_CREATE_PAYMENT_DIALOG, handleOpen);
1659
+ window.addEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
1660
+ return () => {
1661
+ window.removeEventListener(PAYMENT_EVENTS.OPEN_CREATE_PAYMENT_DIALOG, handleOpen);
1662
+ window.removeEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
1663
+ };
1664
+ }, []);
1665
+ const handleClose = () => {
1666
+ setOpen(false);
1667
+ form.reset();
1619
1668
  };
1620
- const formatDate = (dateStr) => {
1621
- if (!dateStr) return "No transactions yet";
1669
+ useEffect(() => {
1670
+ if (currencyOptions.length > 0 && !form.getValues("currency_code")) {
1671
+ form.setValue("currency_code", currencyOptions[0].code);
1672
+ }
1673
+ }, [currencyOptions, form]);
1674
+ const handleSubmit = async (data) => {
1622
1675
  try {
1623
- return new Date(dateStr).toLocaleDateString("en-US", {
1624
- year: "numeric",
1625
- month: "short",
1626
- day: "numeric"
1627
- });
1628
- } catch {
1629
- return "Invalid date";
1676
+ setIsSubmitting(true);
1677
+ const result = await createPayment();
1678
+ handleClose();
1679
+ closePaymentsDialog();
1680
+ const paymentData = result;
1681
+ const paymentId = paymentData?.payment?.id || paymentData?.id;
1682
+ if (paymentId) {
1683
+ openPaymentDetailsDialog(String(paymentId));
1684
+ }
1685
+ } catch (error) {
1686
+ paymentsLogger.error("Failed to create payment:", error);
1687
+ } finally {
1688
+ setIsSubmitting(false);
1630
1689
  }
1631
1690
  };
1632
- if (isLoadingBalance) {
1633
- return /* @__PURE__ */ jsxs(Card, { children: [
1634
- /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center justify-between", children: [
1635
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1636
- /* @__PURE__ */ jsx(Wallet, { className: "h-5 w-5" }),
1637
- "Account Balance"
1691
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-md", children: [
1692
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
1693
+ /* @__PURE__ */ jsx(DialogTitle, { children: "Create Payment" }),
1694
+ /* @__PURE__ */ jsx(DialogDescription, { children: "Create a new payment to add funds to your account." })
1695
+ ] }),
1696
+ /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsxs("form", { onSubmit: form.handleSubmit(handleSubmit), className: "space-y-4", children: [
1697
+ /* @__PURE__ */ jsx(
1698
+ FormField,
1699
+ {
1700
+ control: form.control,
1701
+ name: "amount_usd",
1702
+ render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
1703
+ /* @__PURE__ */ jsx(FormLabel, { children: "Amount (USD)" }),
1704
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
1705
+ Input,
1706
+ {
1707
+ type: "number",
1708
+ step: "0.01",
1709
+ min: "0.01",
1710
+ placeholder: "10.00",
1711
+ ...field,
1712
+ onChange: (e) => field.onChange(parseFloat(e.target.value) || 0)
1713
+ }
1714
+ ) }),
1715
+ /* @__PURE__ */ jsx(FormDescription, { children: "The amount you want to pay in USD." }),
1716
+ /* @__PURE__ */ jsx(FormMessage, {})
1717
+ ] })
1718
+ }
1719
+ ),
1720
+ /* @__PURE__ */ jsx(
1721
+ FormField,
1722
+ {
1723
+ control: form.control,
1724
+ name: "currency_code",
1725
+ render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
1726
+ /* @__PURE__ */ jsx(FormLabel, { children: "Currency" }),
1727
+ /* @__PURE__ */ jsxs(
1728
+ Select,
1729
+ {
1730
+ onValueChange: field.onChange,
1731
+ defaultValue: field.value,
1732
+ disabled: isLoadingCurrencies,
1733
+ children: [
1734
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select currency..." }) }) }),
1735
+ /* @__PURE__ */ jsx(SelectContent, { children: currencyOptions.map((curr) => /* @__PURE__ */ jsx(SelectItem, { value: curr.code, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1736
+ /* @__PURE__ */ jsx(TokenIcon, { symbol: curr.code, size: 16 }),
1737
+ /* @__PURE__ */ jsx("span", { children: curr.code }),
1738
+ curr.network && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
1739
+ "(",
1740
+ curr.network,
1741
+ ")"
1742
+ ] })
1743
+ ] }) }, curr.code)) })
1744
+ ]
1745
+ }
1746
+ ),
1747
+ /* @__PURE__ */ jsx(FormDescription, { children: "The cryptocurrency to use for payment." }),
1748
+ /* @__PURE__ */ jsx(FormMessage, {})
1749
+ ] })
1750
+ }
1751
+ ),
1752
+ calculateCryptoAmount && /* @__PURE__ */ jsxs("div", { className: "rounded-sm bg-muted p-4 space-y-3", children: [
1753
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1754
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "You will send" }),
1755
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1756
+ /* @__PURE__ */ jsx(TokenIcon, { symbol: calculateCryptoAmount.currency, size: 16 }),
1757
+ /* @__PURE__ */ jsxs("span", { className: "font-mono font-semibold", children: [
1758
+ calculateCryptoAmount.amount.toFixed(8),
1759
+ " ",
1760
+ calculateCryptoAmount.currency
1761
+ ] })
1762
+ ] })
1638
1763
  ] }),
1639
- /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-20" })
1640
- ] }) }),
1641
- /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
1642
- /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-32" }),
1643
- /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-48" })
1644
- ] })
1645
- ] });
1646
- }
1647
- const balanceData = balance?.balance || balance;
1648
- const amountUsd = balanceData?.amount_usd ?? 0;
1649
- const totalDeposited = balanceData?.total_deposited ?? 0;
1650
- const totalWithdrawn = balanceData?.total_withdrawn ?? 0;
1651
- const lastTransactionAt = balanceData?.last_transaction_at;
1652
- const isEmpty = amountUsd === 0 && totalDeposited === 0;
1653
- return /* @__PURE__ */ jsxs(Card, { children: [
1654
- /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center justify-between", children: [
1655
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1656
- /* @__PURE__ */ jsx(Wallet, { className: "h-5 w-5" }),
1657
- "Account Balance"
1658
- ] }),
1659
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1660
- /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: refreshBalance, children: /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4" }) }),
1661
- /* @__PURE__ */ jsxs(Button, { size: "sm", onClick: () => openCreatePaymentDialog(), children: [
1662
- /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-2" }),
1663
- "Add Funds"
1664
- ] })
1665
- ] })
1666
- ] }) }),
1667
- /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
1668
- /* @__PURE__ */ jsxs("div", { children: [
1669
- /* @__PURE__ */ jsx("div", { className: "text-4xl font-bold", children: formatCurrency(amountUsd) }),
1670
- /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground mt-1", children: [
1671
- "Available balance \u2022 Last updated ",
1672
- formatDate(lastTransactionAt)
1673
- ] })
1674
- ] }),
1675
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4 pt-4 border-t", children: [
1676
- /* @__PURE__ */ jsxs("div", { children: [
1677
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Total Deposited" }),
1678
- /* @__PURE__ */ jsx("p", { className: "text-lg font-semibold text-green-600", children: formatCurrency(totalDeposited) })
1764
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1765
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "You will receive" }),
1766
+ /* @__PURE__ */ jsxs("span", { className: "text-lg font-bold", children: [
1767
+ "$",
1768
+ form.watch("amount_usd")?.toFixed(2),
1769
+ " USD"
1770
+ ] })
1679
1771
  ] }),
1680
- /* @__PURE__ */ jsxs("div", { children: [
1681
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Total Withdrawn" }),
1682
- /* @__PURE__ */ jsx("p", { className: "text-lg font-semibold text-red-600", children: formatCurrency(totalWithdrawn) })
1683
- ] })
1772
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-xs", children: [
1773
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Rate" }),
1774
+ /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
1775
+ "1 ",
1776
+ calculateCryptoAmount.currency,
1777
+ " = $",
1778
+ calculateCryptoAmount.rate?.toFixed(2)
1779
+ ] })
1780
+ ] }),
1781
+ calculateCryptoAmount.network && /* @__PURE__ */ jsx("div", { className: "border-t pt-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1782
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Network" }),
1783
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: calculateCryptoAmount.network })
1784
+ ] }) })
1684
1785
  ] }),
1685
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1686
- /* @__PURE__ */ jsx(Badge, { variant: !isEmpty ? "default" : "secondary", children: !isEmpty ? "Active" : "New Account" }),
1687
- isEmpty && /* @__PURE__ */ jsx(Badge, { variant: "outline", children: "Empty Balance" })
1786
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [
1787
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: handleClose, disabled: isSubmitting, children: "Cancel" }),
1788
+ /* @__PURE__ */ jsx(Button, { type: "submit", disabled: isSubmitting || currencyOptions.length === 0, children: isSubmitting ? /* @__PURE__ */ jsxs(Fragment, { children: [
1789
+ /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4 mr-2 animate-spin" }),
1790
+ "Creating..."
1791
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1792
+ /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-2" }),
1793
+ "Create Payment"
1794
+ ] }) })
1795
+ ] })
1796
+ ] }) })
1797
+ ] }) });
1798
+ };
1799
+ var PaymentDetailsDialog = () => {
1800
+ const [open, setOpen] = useState(false);
1801
+ const [paymentId, setPaymentId] = useState(null);
1802
+ const [timeLeft, setTimeLeft] = useState("");
1803
+ const shouldFetch = open && !!paymentId;
1804
+ const { data: payment, isLoading, error, mutate } = usePaymentsPaymentsRetrieve(
1805
+ shouldFetch ? paymentId : "",
1806
+ apiPayments
1807
+ );
1808
+ useEffect(() => {
1809
+ const handleOpen = (event) => {
1810
+ const customEvent = event;
1811
+ setPaymentId(customEvent.detail.id);
1812
+ setOpen(true);
1813
+ };
1814
+ const handleClose2 = () => {
1815
+ setOpen(false);
1816
+ setPaymentId(null);
1817
+ };
1818
+ window.addEventListener(PAYMENT_EVENTS.OPEN_PAYMENT_DETAILS_DIALOG, handleOpen);
1819
+ window.addEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
1820
+ return () => {
1821
+ window.removeEventListener(PAYMENT_EVENTS.OPEN_PAYMENT_DETAILS_DIALOG, handleOpen);
1822
+ window.removeEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
1823
+ };
1824
+ }, []);
1825
+ const handleClose = () => {
1826
+ setOpen(false);
1827
+ setPaymentId(null);
1828
+ };
1829
+ useEffect(() => {
1830
+ if (!payment?.expires_at) return;
1831
+ const updateTimeLeft = () => {
1832
+ const now = moment();
1833
+ const expires = moment.utc(payment.expires_at);
1834
+ const diff = expires.diff(now);
1835
+ if (diff <= 0) {
1836
+ setTimeLeft("Expired");
1837
+ return;
1838
+ }
1839
+ const duration = moment.duration(diff);
1840
+ const hours = Math.floor(duration.asHours());
1841
+ const minutes = duration.minutes();
1842
+ const seconds = duration.seconds();
1843
+ setTimeLeft(`${hours}h ${minutes}m ${seconds}s`);
1844
+ };
1845
+ updateTimeLeft();
1846
+ const interval = setInterval(updateTimeLeft, 1e3);
1847
+ return () => clearInterval(interval);
1848
+ }, [payment?.expires_at]);
1849
+ const getStatusInfo = () => {
1850
+ switch (payment?.status?.toLowerCase()) {
1851
+ case "pending":
1852
+ return { icon: Clock, color: "text-yellow-500", bg: "bg-yellow-500/10" };
1853
+ case "completed":
1854
+ case "success":
1855
+ return { icon: CheckCircle2, color: "text-green-500", bg: "bg-green-500/10" };
1856
+ case "failed":
1857
+ case "error":
1858
+ return { icon: XCircle, color: "text-red-500", bg: "bg-red-500/10" };
1859
+ case "expired":
1860
+ return { icon: AlertCircle, color: "text-gray-500", bg: "bg-gray-500/10" };
1861
+ case "confirming":
1862
+ return { icon: RefreshCw, color: "text-blue-500", bg: "bg-blue-500/10" };
1863
+ default:
1864
+ return { icon: Clock, color: "text-gray-500", bg: "bg-gray-500/10" };
1865
+ }
1866
+ };
1867
+ if (!open) return null;
1868
+ if (isLoading) {
1869
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-lg", children: [
1870
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
1871
+ /* @__PURE__ */ jsx(DialogTitle, { children: "Payment Details" }),
1872
+ /* @__PURE__ */ jsx(DialogDescription, { children: "Loading payment information..." })
1873
+ ] }),
1874
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx(RefreshCw, { className: "h-8 w-8 animate-spin text-muted-foreground" }) })
1875
+ ] }) });
1876
+ }
1877
+ if (shouldFetch && !isLoading && (error || !payment)) {
1878
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-lg", children: [
1879
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
1880
+ /* @__PURE__ */ jsx(DialogTitle, { children: "Payment Details" }),
1881
+ /* @__PURE__ */ jsx(DialogDescription, { children: "Failed to load payment information" })
1882
+ ] }),
1883
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-12 space-y-4", children: [
1884
+ /* @__PURE__ */ jsx(XCircle, { className: "h-12 w-12 text-destructive" }),
1885
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: error ? `Error: ${error}` : "Payment not found" }),
1886
+ /* @__PURE__ */ jsx(Button, { onClick: () => mutate(), children: "Try Again" })
1887
+ ] })
1888
+ ] }) });
1889
+ }
1890
+ const statusInfo = getStatusInfo();
1891
+ const StatusIcon = statusInfo.icon;
1892
+ const qrCodeUrl = payment.pay_address ? `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(payment.pay_address)}` : null;
1893
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-lg", children: [
1894
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
1895
+ /* @__PURE__ */ jsx(DialogTitle, { children: "Payment Details" }),
1896
+ /* @__PURE__ */ jsx(DialogDescription, { children: "Send cryptocurrency to complete your payment" })
1897
+ ] }),
1898
+ /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
1899
+ /* @__PURE__ */ jsxs("div", { className: `flex items-center gap-3 p-4 rounded-sm ${statusInfo.bg}`, children: [
1900
+ /* @__PURE__ */ jsx(StatusIcon, { className: `h-5 w-5 ${statusInfo.color}` }),
1901
+ /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
1902
+ /* @__PURE__ */ jsx("div", { className: "font-semibold capitalize", children: payment.status }),
1903
+ payment.status === "pending" && timeLeft && /* @__PURE__ */ jsxs("div", { className: "text-sm text-muted-foreground", children: [
1904
+ "Expires in ",
1905
+ timeLeft
1906
+ ] })
1907
+ ] })
1908
+ ] }),
1909
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
1910
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-4 bg-muted rounded-sm", children: [
1911
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Amount to send" }),
1912
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1913
+ /* @__PURE__ */ jsx(TokenIcon, { symbol: String(payment.currency_code || "BTC"), size: 20 }),
1914
+ /* @__PURE__ */ jsxs("span", { className: "font-mono font-bold text-lg", children: [
1915
+ payment.pay_amount || "0.00000000",
1916
+ " ",
1917
+ payment.currency_code
1918
+ ] })
1919
+ ] })
1920
+ ] }),
1921
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4", children: [
1922
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Equivalent to" }),
1923
+ /* @__PURE__ */ jsxs("span", { className: "font-semibold text-lg", children: [
1924
+ "$",
1925
+ parseFloat(payment.amount_usd || "0").toFixed(2),
1926
+ " USD"
1927
+ ] })
1928
+ ] }),
1929
+ payment.internal_payment_id && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4", children: [
1930
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Payment Order #" }),
1931
+ /* @__PURE__ */ jsx("span", { className: "font-mono font-medium", children: payment.internal_payment_id })
1932
+ ] }),
1933
+ payment.currency_network && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4", children: [
1934
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Network" }),
1935
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: payment.currency_network })
1936
+ ] })
1937
+ ] }),
1938
+ qrCodeUrl && payment.status === "pending" && /* @__PURE__ */ jsx("div", { className: "flex justify-center p-6 bg-white rounded-sm", children: /* @__PURE__ */ jsx("img", { src: qrCodeUrl, alt: "Payment QR Code", className: "w-48 h-48" }) }),
1939
+ payment.pay_address && payment.status === "pending" && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1940
+ /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Payment Address" }),
1941
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1942
+ /* @__PURE__ */ jsx("div", { className: "flex-1 p-3 bg-muted rounded-sm font-mono text-sm break-all", children: payment.pay_address }),
1943
+ /* @__PURE__ */ jsx(CopyButton, { value: payment.pay_address, variant: "outline" })
1944
+ ] })
1945
+ ] }),
1946
+ payment.transaction_hash && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1947
+ /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Transaction Hash" }),
1948
+ /* @__PURE__ */ jsx("div", { className: "p-3 bg-muted rounded-sm font-mono text-sm break-all", children: payment.transaction_hash })
1949
+ ] }),
1950
+ payment.payment_url && payment.status === "pending" && /* @__PURE__ */ jsxs(
1951
+ Button,
1952
+ {
1953
+ variant: "outline",
1954
+ className: "w-full",
1955
+ onClick: () => window.open(payment.payment_url, "_blank"),
1956
+ children: [
1957
+ /* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4 mr-2" }),
1958
+ "Open in Payment Provider"
1959
+ ]
1960
+ }
1961
+ ),
1962
+ /* @__PURE__ */ jsxs("div", { className: "pt-4 border-t space-y-2 text-xs text-muted-foreground", children: [
1963
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
1964
+ /* @__PURE__ */ jsx("span", { children: "Payment ID" }),
1965
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: payment.id })
1966
+ ] }),
1967
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
1968
+ /* @__PURE__ */ jsx("span", { children: "Created" }),
1969
+ /* @__PURE__ */ jsx("span", { children: moment.utc(payment.created_at).local().format("MMM D, YYYY HH:mm") })
1970
+ ] }),
1971
+ payment.confirmations_count !== void 0 && /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
1972
+ /* @__PURE__ */ jsx("span", { children: "Confirmations" }),
1973
+ /* @__PURE__ */ jsx("span", { children: payment.confirmations_count })
1974
+ ] })
1975
+ ] })
1976
+ ] }),
1977
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [
1978
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: handleClose, children: "Close" }),
1979
+ /* @__PURE__ */ jsxs(Button, { onClick: () => mutate(), variant: "ghost", size: "sm", children: [
1980
+ /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4 mr-2" }),
1981
+ "Refresh"
1688
1982
  ] })
1689
1983
  ] })
1690
- ] });
1984
+ ] }) });
1691
1985
  };
1692
- var RecentPayments = () => {
1693
- const { payments, isLoadingPayments } = useOverviewContext();
1986
+ var BalanceCard = () => {
1987
+ const {
1988
+ balance,
1989
+ isLoadingBalance,
1990
+ refreshBalance
1991
+ } = useOverviewContext();
1694
1992
  const formatCurrency = (amount) => {
1695
1993
  if (amount === null || amount === void 0) return "$0.00";
1696
- const numAmount = typeof amount === "string" ? parseFloat(amount) : amount;
1697
1994
  return new Intl.NumberFormat("en-US", {
1698
1995
  style: "currency",
1699
1996
  currency: "USD",
1700
1997
  minimumFractionDigits: 2
1701
- }).format(numAmount);
1702
- };
1703
- const getRelativeTime = (date) => {
1704
- if (!date) return "N/A";
1705
- const now = /* @__PURE__ */ new Date();
1706
- const target = new Date(date);
1707
- const diffInSeconds = Math.floor((now.getTime() - target.getTime()) / 1e3);
1708
- if (diffInSeconds < 60) return "Just now";
1709
- if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
1710
- if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
1711
- return `${Math.floor(diffInSeconds / 86400)}d ago`;
1998
+ }).format(amount);
1712
1999
  };
1713
- const getStatusVariant = (status) => {
1714
- switch (status?.toLowerCase()) {
1715
- case "completed":
1716
- case "success":
1717
- return "default";
1718
- case "pending":
1719
- case "confirming":
1720
- return "secondary";
1721
- case "failed":
1722
- case "error":
1723
- case "expired":
1724
- return "destructive";
1725
- default:
1726
- return "outline";
2000
+ const formatDate = (dateStr) => {
2001
+ if (!dateStr) return "No transactions yet";
2002
+ try {
2003
+ return moment.utc(dateStr).local().format("MMM D, YYYY");
2004
+ } catch {
2005
+ return "Invalid date";
1727
2006
  }
1728
2007
  };
1729
- if (isLoadingPayments) {
2008
+ if (isLoadingBalance) {
1730
2009
  return /* @__PURE__ */ jsxs(Card, { children: [
1731
- /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center gap-2", children: [
1732
- /* @__PURE__ */ jsx(History, { className: "h-5 w-5" }),
1733
- "Recent Payments"
1734
- ] }) }),
1735
- /* @__PURE__ */ jsx(CardContent, { className: "space-y-3", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-3 border rounded-sm", children: [
1736
- /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1737
- /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-32" }),
1738
- /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-24" })
2010
+ /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center justify-between", children: [
2011
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2012
+ /* @__PURE__ */ jsx(Wallet, { className: "h-5 w-5" }),
2013
+ "Account Balance"
1739
2014
  ] }),
1740
- /* @__PURE__ */ jsx(Skeleton, { className: "h-6 w-16" })
1741
- ] }, i)) })
2015
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-20" })
2016
+ ] }) }),
2017
+ /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
2018
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-32" }),
2019
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-48" })
2020
+ ] })
1742
2021
  ] });
1743
2022
  }
1744
- const recentPaymentsList = payments?.results?.slice(0, 5) || [];
2023
+ const balanceData = balance?.balance || balance;
2024
+ const amountUsd = balanceData?.amount_usd ?? 0;
2025
+ const totalDeposited = balanceData?.total_deposited ?? 0;
2026
+ const totalWithdrawn = balanceData?.total_withdrawn ?? 0;
2027
+ const lastTransactionAt = balanceData?.last_transaction_at;
2028
+ const isEmpty = amountUsd === 0 && totalDeposited === 0;
1745
2029
  return /* @__PURE__ */ jsxs(Card, { children: [
1746
2030
  /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center justify-between", children: [
1747
2031
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1748
- /* @__PURE__ */ jsx(History, { className: "h-5 w-5" }),
1749
- "Recent Payments"
2032
+ /* @__PURE__ */ jsx(Wallet, { className: "h-5 w-5" }),
2033
+ "Account Balance"
1750
2034
  ] }),
1751
- /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", children: [
1752
- "View All",
1753
- /* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4 ml-2" })
1754
- ] })
1755
- ] }) }),
2035
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2036
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: refreshBalance, children: /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4" }) }),
2037
+ /* @__PURE__ */ jsxs(Button, { size: "sm", onClick: () => openCreatePaymentDialog(), children: [
2038
+ /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-2" }),
2039
+ "Add Funds"
2040
+ ] })
2041
+ ] })
2042
+ ] }) }),
2043
+ /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
2044
+ /* @__PURE__ */ jsxs("div", { children: [
2045
+ /* @__PURE__ */ jsx("div", { className: "text-4xl font-bold", children: formatCurrency(amountUsd) }),
2046
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground mt-1", children: [
2047
+ "Available balance \u2022 Last updated ",
2048
+ formatDate(lastTransactionAt)
2049
+ ] })
2050
+ ] }),
2051
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4 pt-4 border-t", children: [
2052
+ /* @__PURE__ */ jsxs("div", { children: [
2053
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Total Deposited" }),
2054
+ /* @__PURE__ */ jsx("p", { className: "text-lg font-semibold text-green-600", children: formatCurrency(totalDeposited) })
2055
+ ] }),
2056
+ /* @__PURE__ */ jsxs("div", { children: [
2057
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Total Withdrawn" }),
2058
+ /* @__PURE__ */ jsx("p", { className: "text-lg font-semibold text-red-600", children: formatCurrency(totalWithdrawn) })
2059
+ ] })
2060
+ ] }),
2061
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2062
+ /* @__PURE__ */ jsx(Badge, { variant: !isEmpty ? "default" : "secondary", children: !isEmpty ? "Active" : "New Account" }),
2063
+ isEmpty && /* @__PURE__ */ jsx(Badge, { variant: "outline", children: "Empty Balance" })
2064
+ ] })
2065
+ ] })
2066
+ ] });
2067
+ };
2068
+ var RecentPayments = () => {
2069
+ const { payments, isLoadingPayments } = useOverviewContext();
2070
+ const formatCurrency = (amount) => {
2071
+ if (amount === null || amount === void 0) return "$0.00";
2072
+ const numAmount = typeof amount === "string" ? parseFloat(amount) : amount;
2073
+ return new Intl.NumberFormat("en-US", {
2074
+ style: "currency",
2075
+ currency: "USD",
2076
+ minimumFractionDigits: 2
2077
+ }).format(numAmount);
2078
+ };
2079
+ const getRelativeTime = (date) => {
2080
+ if (!date) return "N/A";
2081
+ const m = moment.utc(date).local();
2082
+ const now = moment();
2083
+ const diffInSeconds = now.diff(m, "seconds");
2084
+ if (diffInSeconds < 60) return "Just now";
2085
+ if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
2086
+ if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
2087
+ return `${Math.floor(diffInSeconds / 86400)}d ago`;
2088
+ };
2089
+ const getStatusVariant = (status) => {
2090
+ switch (status?.toLowerCase()) {
2091
+ case "completed":
2092
+ case "success":
2093
+ return "default";
2094
+ case "pending":
2095
+ case "confirming":
2096
+ return "secondary";
2097
+ case "failed":
2098
+ case "error":
2099
+ case "expired":
2100
+ return "destructive";
2101
+ default:
2102
+ return "outline";
2103
+ }
2104
+ };
2105
+ if (isLoadingPayments) {
2106
+ return /* @__PURE__ */ jsxs(Card, { children: [
2107
+ /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center gap-2", children: [
2108
+ /* @__PURE__ */ jsx(History, { className: "h-5 w-5" }),
2109
+ "Recent Payments"
2110
+ ] }) }),
2111
+ /* @__PURE__ */ jsx(CardContent, { className: "space-y-3", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-3 border rounded-sm", children: [
2112
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
2113
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-32" }),
2114
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-24" })
2115
+ ] }),
2116
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-6 w-16" })
2117
+ ] }, i)) })
2118
+ ] });
2119
+ }
2120
+ const recentPaymentsList = payments?.results?.slice(0, 5) || [];
2121
+ return /* @__PURE__ */ jsxs(Card, { children: [
2122
+ /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center justify-between", children: [
2123
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2124
+ /* @__PURE__ */ jsx(History, { className: "h-5 w-5" }),
2125
+ "Recent Payments"
2126
+ ] }),
2127
+ /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", children: [
2128
+ "View All",
2129
+ /* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4 ml-2" })
2130
+ ] })
2131
+ ] }) }),
1756
2132
  /* @__PURE__ */ jsx(CardContent, { children: recentPaymentsList.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-8 text-muted-foreground", children: [
1757
2133
  /* @__PURE__ */ jsx(History, { className: "h-12 w-12 mx-auto mb-4 opacity-50" }),
1758
2134
  /* @__PURE__ */ jsx("p", { children: "No recent payments" }),
@@ -1810,14 +2186,18 @@ var PaymentsList = () => {
1810
2186
  };
1811
2187
  const getRelativeTime = (date) => {
1812
2188
  if (!date) return "N/A";
1813
- const now = /* @__PURE__ */ new Date();
1814
- const target = new Date(date);
1815
- const diffInSeconds = Math.floor((now.getTime() - target.getTime()) / 1e3);
2189
+ const m = moment.utc(date).local();
2190
+ const now = moment();
2191
+ const diffInSeconds = now.diff(m, "seconds");
1816
2192
  if (diffInSeconds < 60) return "Just now";
1817
2193
  if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
1818
2194
  if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
1819
2195
  return `${Math.floor(diffInSeconds / 86400)}d ago`;
1820
2196
  };
2197
+ const formatDate = (date) => {
2198
+ if (!date) return "N/A";
2199
+ return moment.utc(date).local().format("MMM D, YYYY");
2200
+ };
1821
2201
  const getStatusVariant = (status) => {
1822
2202
  switch (status?.toLowerCase()) {
1823
2203
  case "completed":
@@ -1840,11 +2220,21 @@ var PaymentsList = () => {
1840
2220
  const handleStatusFilter = (status) => {
1841
2221
  setStatusFilter(status);
1842
2222
  };
2223
+ const truncateId = (id) => {
2224
+ if (!id) return "N/A";
2225
+ const str = id.toString();
2226
+ return str.length > 8 ? `${str.slice(0, 8)}...` : str;
2227
+ };
1843
2228
  const filteredPayments = paymentsList.filter((payment) => {
1844
2229
  const matchesSearch = searchTerm ? payment.id?.toLowerCase().includes(searchTerm.toLowerCase()) || payment.status?.toLowerCase().includes(searchTerm.toLowerCase()) || payment.currency_code?.toLowerCase().includes(searchTerm.toLowerCase()) : true;
1845
2230
  const matchesStatus = statusFilter !== "all" ? payment.status?.toLowerCase() === statusFilter.toLowerCase() : true;
1846
2231
  return matchesSearch && matchesStatus;
1847
- });
2232
+ }).map((payment) => ({
2233
+ ...payment,
2234
+ formattedDate: formatDate(payment.created_at),
2235
+ relativeTime: getRelativeTime(payment.created_at),
2236
+ truncatedId: truncateId(payment.id)
2237
+ }));
1848
2238
  return /* @__PURE__ */ jsxs(Card, { children: [
1849
2239
  /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center justify-between", children: [
1850
2240
  /* @__PURE__ */ jsx("span", { children: "Payment History" }),
@@ -1920,14 +2310,14 @@ var PaymentsList = () => {
1920
2310
  onClick: () => openPaymentDetailsDialog(String(payment.id)),
1921
2311
  children: [
1922
2312
  /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs("div", { children: [
1923
- /* @__PURE__ */ jsx("div", { className: "font-medium", children: payment.created_at ? new Date(payment.created_at).toLocaleDateString() : "N/A" }),
1924
- /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: getRelativeTime(payment.created_at) })
2313
+ /* @__PURE__ */ jsx("div", { className: "font-medium", children: payment.formattedDate }),
2314
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: payment.relativeTime })
1925
2315
  ] }) }),
1926
2316
  /* @__PURE__ */ jsx(TableCell, { className: "font-mono font-semibold", children: formatCurrency(payment.amount_usd) }),
1927
2317
  /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Badge, { variant: "outline", children: payment.currency_code || "USD" }) }),
1928
2318
  /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Badge, { variant: getStatusVariant(payment.status), children: payment.status }) }),
1929
2319
  /* @__PURE__ */ jsx(TableCell, { className: "text-sm text-muted-foreground", children: "NowPayments" }),
1930
- /* @__PURE__ */ jsx(TableCell, { className: "font-mono text-sm text-muted-foreground", children: payment.id ? `${payment.id.toString().slice(0, 8)}...` : "N/A" }),
2320
+ /* @__PURE__ */ jsx(TableCell, { className: "font-mono text-sm text-muted-foreground", children: payment.truncatedId }),
1931
2321
  /* @__PURE__ */ jsx(TableCell, { className: "text-right", children: /* @__PURE__ */ jsx(
1932
2322
  Button,
1933
2323
  {
@@ -1980,22 +2370,16 @@ var TransactionsList = () => {
1980
2370
  const formatDate = (date) => {
1981
2371
  if (!date) return "N/A";
1982
2372
  try {
1983
- return new Date(date).toLocaleString("en-US", {
1984
- year: "numeric",
1985
- month: "short",
1986
- day: "numeric",
1987
- hour: "2-digit",
1988
- minute: "2-digit"
1989
- });
2373
+ return moment.utc(date).local().format("MMM D, YYYY hh:mm A");
1990
2374
  } catch {
1991
2375
  return "Invalid date";
1992
2376
  }
1993
2377
  };
1994
2378
  const getRelativeTime = (date) => {
1995
2379
  if (!date) return "N/A";
1996
- const now = /* @__PURE__ */ new Date();
1997
- const target = new Date(date);
1998
- const diffInSeconds = Math.floor((now.getTime() - target.getTime()) / 1e3);
2380
+ const m = moment.utc(date).local();
2381
+ const now = moment();
2382
+ const diffInSeconds = now.diff(m, "seconds");
1999
2383
  if (diffInSeconds < 60) return "Just now";
2000
2384
  if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
2001
2385
  if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
@@ -2025,11 +2409,22 @@ var TransactionsList = () => {
2025
2409
  setTypeFilter(type);
2026
2410
  await refreshTransactions();
2027
2411
  };
2412
+ const truncateId = (id) => {
2413
+ if (!id) return "N/A";
2414
+ const str = id.toString();
2415
+ return str.length > 8 ? `${str.slice(0, 8)}...` : str;
2416
+ };
2028
2417
  const filteredTransactions = transactionsList.filter((transaction) => {
2029
2418
  const matchesSearch = searchTerm ? transaction.id?.toString().toLowerCase().includes(searchTerm.toLowerCase()) || transaction.description?.toLowerCase().includes(searchTerm.toLowerCase()) || transaction.type?.toLowerCase().includes(searchTerm.toLowerCase()) : true;
2030
2419
  const matchesType = typeFilter !== "all" ? transaction.type?.toLowerCase() === typeFilter.toLowerCase() : true;
2031
2420
  return matchesSearch && matchesType;
2032
- });
2421
+ }).map((transaction) => ({
2422
+ ...transaction,
2423
+ isDeposit: transaction.type?.toLowerCase() === "deposit" || transaction.type?.toLowerCase() === "credit",
2424
+ formattedDate: formatDate(transaction.created_at || transaction.timestamp),
2425
+ relativeTime: getRelativeTime(transaction.created_at || transaction.timestamp),
2426
+ truncatedRef: truncateId(transaction.reference || transaction.payment_id)
2427
+ }));
2033
2428
  if (isLoadingTransactions) {
2034
2429
  return /* @__PURE__ */ jsxs(Card, { children: [
2035
2430
  /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center gap-2", children: [
@@ -2095,26 +2490,23 @@ var TransactionsList = () => {
2095
2490
  /* @__PURE__ */ jsx(TableHead, { children: "Description" }),
2096
2491
  /* @__PURE__ */ jsx(TableHead, { children: "Reference" })
2097
2492
  ] }) }),
2098
- /* @__PURE__ */ jsx(TableBody, { children: filteredTransactions.map((transaction, index) => {
2099
- const isDeposit = transaction.type?.toLowerCase() === "deposit" || transaction.type?.toLowerCase() === "credit";
2100
- return /* @__PURE__ */ jsxs(TableRow, { children: [
2101
- /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs("div", { children: [
2102
- /* @__PURE__ */ jsx("div", { className: "font-medium", children: formatDate(transaction.created_at || transaction.timestamp) }),
2103
- /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: getRelativeTime(transaction.created_at || transaction.timestamp) })
2104
- ] }) }),
2105
- /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2106
- getTypeIcon(transaction.type),
2107
- /* @__PURE__ */ jsx(Badge, { variant: getTypeVariant(transaction.type), children: transaction.type || "Unknown" })
2108
- ] }) }),
2109
- /* @__PURE__ */ jsx(TableCell, { className: "font-mono font-semibold", children: /* @__PURE__ */ jsxs("span", { className: isDeposit ? "text-green-600" : "text-red-600", children: [
2110
- isDeposit ? "+" : "-",
2111
- formatCurrency(Math.abs(transaction.amount || transaction.amount_usd || 0))
2112
- ] }) }),
2113
- /* @__PURE__ */ jsx(TableCell, { className: "font-mono", children: formatCurrency(transaction.balance_after || 0) }),
2114
- /* @__PURE__ */ jsx(TableCell, { className: "text-sm", children: transaction.description || transaction.note || "No description" }),
2115
- /* @__PURE__ */ jsx(TableCell, { className: "font-mono text-sm text-muted-foreground", children: transaction.reference || transaction.payment_id ? `${(transaction.reference || transaction.payment_id).toString().slice(0, 8)}...` : "N/A" })
2116
- ] }, transaction.id || index);
2117
- }) })
2493
+ /* @__PURE__ */ jsx(TableBody, { children: filteredTransactions.map((transaction, index) => /* @__PURE__ */ jsxs(TableRow, { children: [
2494
+ /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs("div", { children: [
2495
+ /* @__PURE__ */ jsx("div", { className: "font-medium", children: transaction.formattedDate }),
2496
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: transaction.relativeTime })
2497
+ ] }) }),
2498
+ /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2499
+ getTypeIcon(transaction.type),
2500
+ /* @__PURE__ */ jsx(Badge, { variant: getTypeVariant(transaction.type), children: transaction.type || "Unknown" })
2501
+ ] }) }),
2502
+ /* @__PURE__ */ jsx(TableCell, { className: "font-mono font-semibold", children: /* @__PURE__ */ jsxs("span", { className: transaction.isDeposit ? "text-green-600" : "text-red-600", children: [
2503
+ transaction.isDeposit ? "+" : "-",
2504
+ formatCurrency(Math.abs(transaction.amount || transaction.amount_usd || 0))
2505
+ ] }) }),
2506
+ /* @__PURE__ */ jsx(TableCell, { className: "font-mono", children: formatCurrency(transaction.balance_after || 0) }),
2507
+ /* @__PURE__ */ jsx(TableCell, { className: "text-sm", children: transaction.description || transaction.note || "No description" }),
2508
+ /* @__PURE__ */ jsx(TableCell, { className: "font-mono text-sm text-muted-foreground", children: transaction.truncatedRef })
2509
+ ] }, transaction.id || index)) })
2118
2510
  ] }) })
2119
2511
  ] })
2120
2512
  ] });
@@ -2122,384 +2514,6 @@ var TransactionsList = () => {
2122
2514
  var TransactionsView = () => {
2123
2515
  return /* @__PURE__ */ jsx("div", { className: "space-y-6", children: /* @__PURE__ */ jsx(TransactionsList, {}) });
2124
2516
  };
2125
- var isDevelopment = process.env.NODE_ENV === "development";
2126
- var logger = createConsola({
2127
- level: isDevelopment ? 4 : 1
2128
- }).withTag("ext-payments");
2129
- var paymentsLogger = logger;
2130
- var PaymentCreateSchema = z.object({
2131
- amount_usd: z.number().min(0.01, "Amount must be at least $0.01"),
2132
- currency_code: z.string().min(1, "Please select a currency")
2133
- });
2134
- var CreatePaymentDialog = () => {
2135
- const [open, setOpen] = useState(false);
2136
- const [isSubmitting, setIsSubmitting] = useState(false);
2137
- const { createPayment } = usePaymentsContext();
2138
- const { currencies, isLoadingCurrencies } = useRootPaymentsContext();
2139
- const form = useForm({
2140
- resolver: zodResolver(PaymentCreateSchema),
2141
- defaultValues: {
2142
- amount_usd: 10,
2143
- currency_code: "USDT"
2144
- }
2145
- });
2146
- const currenciesList = useMemo(() => {
2147
- const data = currencies?.currencies || currencies?.results || currencies || [];
2148
- return Array.isArray(data) ? data : [];
2149
- }, [currencies]);
2150
- const currencyOptions = useMemo(() => {
2151
- return currenciesList.filter((curr) => curr.is_enabled !== false).map((curr) => ({
2152
- code: curr.code || curr.currency_code || curr.symbol,
2153
- name: curr.name || curr.code || curr.currency_code,
2154
- usd_rate: curr.usd_rate || curr.rate || 1,
2155
- network: curr.network || null
2156
- }));
2157
- }, [currenciesList]);
2158
- const calculateCryptoAmount = useMemo(() => {
2159
- const amountUsd = form.watch("amount_usd");
2160
- const currencyCode = form.watch("currency_code");
2161
- const currency = currencyOptions.find((c) => c.code === currencyCode);
2162
- if (!currency || !currency.usd_rate || !amountUsd) {
2163
- return null;
2164
- }
2165
- const cryptoAmount = amountUsd / currency.usd_rate;
2166
- return {
2167
- amount: cryptoAmount,
2168
- currency: currency.code,
2169
- rate: currency.usd_rate,
2170
- network: currency.network
2171
- };
2172
- }, [form.watch("amount_usd"), form.watch("currency_code"), currencyOptions]);
2173
- useEffect(() => {
2174
- const handleOpen = () => setOpen(true);
2175
- const handleClose2 = () => setOpen(false);
2176
- window.addEventListener(PAYMENT_EVENTS.OPEN_CREATE_PAYMENT_DIALOG, handleOpen);
2177
- window.addEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
2178
- return () => {
2179
- window.removeEventListener(PAYMENT_EVENTS.OPEN_CREATE_PAYMENT_DIALOG, handleOpen);
2180
- window.removeEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
2181
- };
2182
- }, []);
2183
- const handleClose = () => {
2184
- setOpen(false);
2185
- form.reset();
2186
- };
2187
- useEffect(() => {
2188
- if (currencyOptions.length > 0 && !form.getValues("currency_code")) {
2189
- form.setValue("currency_code", currencyOptions[0].code);
2190
- }
2191
- }, [currencyOptions, form]);
2192
- const handleSubmit = async (data) => {
2193
- try {
2194
- setIsSubmitting(true);
2195
- const result = await createPayment();
2196
- handleClose();
2197
- closePaymentsDialog();
2198
- const paymentData = result;
2199
- const paymentId = paymentData?.payment?.id || paymentData?.id;
2200
- if (paymentId) {
2201
- openPaymentDetailsDialog(String(paymentId));
2202
- }
2203
- } catch (error) {
2204
- paymentsLogger.error("Failed to create payment:", error);
2205
- } finally {
2206
- setIsSubmitting(false);
2207
- }
2208
- };
2209
- return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-md", children: [
2210
- /* @__PURE__ */ jsxs(DialogHeader, { children: [
2211
- /* @__PURE__ */ jsx(DialogTitle, { children: "Create Payment" }),
2212
- /* @__PURE__ */ jsx(DialogDescription, { children: "Create a new payment to add funds to your account." })
2213
- ] }),
2214
- /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsxs("form", { onSubmit: form.handleSubmit(handleSubmit), className: "space-y-4", children: [
2215
- /* @__PURE__ */ jsx(
2216
- FormField,
2217
- {
2218
- control: form.control,
2219
- name: "amount_usd",
2220
- render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
2221
- /* @__PURE__ */ jsx(FormLabel, { children: "Amount (USD)" }),
2222
- /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
2223
- Input,
2224
- {
2225
- type: "number",
2226
- step: "0.01",
2227
- min: "0.01",
2228
- placeholder: "10.00",
2229
- ...field,
2230
- onChange: (e) => field.onChange(parseFloat(e.target.value) || 0)
2231
- }
2232
- ) }),
2233
- /* @__PURE__ */ jsx(FormDescription, { children: "The amount you want to pay in USD." }),
2234
- /* @__PURE__ */ jsx(FormMessage, {})
2235
- ] })
2236
- }
2237
- ),
2238
- /* @__PURE__ */ jsx(
2239
- FormField,
2240
- {
2241
- control: form.control,
2242
- name: "currency_code",
2243
- render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
2244
- /* @__PURE__ */ jsx(FormLabel, { children: "Currency" }),
2245
- /* @__PURE__ */ jsxs(
2246
- Select,
2247
- {
2248
- onValueChange: field.onChange,
2249
- defaultValue: field.value,
2250
- disabled: isLoadingCurrencies,
2251
- children: [
2252
- /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select currency..." }) }) }),
2253
- /* @__PURE__ */ jsx(SelectContent, { children: currencyOptions.map((curr) => /* @__PURE__ */ jsx(SelectItem, { value: curr.code, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2254
- /* @__PURE__ */ jsx(TokenIcon, { symbol: curr.code, size: 16 }),
2255
- /* @__PURE__ */ jsx("span", { children: curr.code }),
2256
- curr.network && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
2257
- "(",
2258
- curr.network,
2259
- ")"
2260
- ] })
2261
- ] }) }, curr.code)) })
2262
- ]
2263
- }
2264
- ),
2265
- /* @__PURE__ */ jsx(FormDescription, { children: "The cryptocurrency to use for payment." }),
2266
- /* @__PURE__ */ jsx(FormMessage, {})
2267
- ] })
2268
- }
2269
- ),
2270
- calculateCryptoAmount && /* @__PURE__ */ jsxs("div", { className: "rounded-sm bg-muted p-4 space-y-3", children: [
2271
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
2272
- /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "You will send" }),
2273
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2274
- /* @__PURE__ */ jsx(TokenIcon, { symbol: calculateCryptoAmount.currency, size: 16 }),
2275
- /* @__PURE__ */ jsxs("span", { className: "font-mono font-semibold", children: [
2276
- calculateCryptoAmount.amount.toFixed(8),
2277
- " ",
2278
- calculateCryptoAmount.currency
2279
- ] })
2280
- ] })
2281
- ] }),
2282
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
2283
- /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "You will receive" }),
2284
- /* @__PURE__ */ jsxs("span", { className: "text-lg font-bold", children: [
2285
- "$",
2286
- form.watch("amount_usd")?.toFixed(2),
2287
- " USD"
2288
- ] })
2289
- ] }),
2290
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-xs", children: [
2291
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Rate" }),
2292
- /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
2293
- "1 ",
2294
- calculateCryptoAmount.currency,
2295
- " = $",
2296
- calculateCryptoAmount.rate?.toFixed(2)
2297
- ] })
2298
- ] }),
2299
- calculateCryptoAmount.network && /* @__PURE__ */ jsx("div", { className: "border-t pt-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
2300
- /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Network" }),
2301
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: calculateCryptoAmount.network })
2302
- ] }) })
2303
- ] }),
2304
- /* @__PURE__ */ jsxs(DialogFooter, { children: [
2305
- /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: handleClose, disabled: isSubmitting, children: "Cancel" }),
2306
- /* @__PURE__ */ jsx(Button, { type: "submit", disabled: isSubmitting || currencyOptions.length === 0, children: isSubmitting ? /* @__PURE__ */ jsxs(Fragment, { children: [
2307
- /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4 mr-2 animate-spin" }),
2308
- "Creating..."
2309
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
2310
- /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-2" }),
2311
- "Create Payment"
2312
- ] }) })
2313
- ] })
2314
- ] }) })
2315
- ] }) });
2316
- };
2317
- var PaymentDetailsDialog = () => {
2318
- const [open, setOpen] = useState(false);
2319
- const [paymentId, setPaymentId] = useState(null);
2320
- const [timeLeft, setTimeLeft] = useState("");
2321
- const shouldFetch = open && !!paymentId;
2322
- const { data: payment, isLoading, error, mutate } = usePaymentsPaymentsRetrieve(
2323
- shouldFetch ? paymentId : "",
2324
- apiPayments
2325
- );
2326
- useEffect(() => {
2327
- const handleOpen = (event) => {
2328
- const customEvent = event;
2329
- setPaymentId(customEvent.detail.id);
2330
- setOpen(true);
2331
- };
2332
- const handleClose2 = () => {
2333
- setOpen(false);
2334
- setPaymentId(null);
2335
- };
2336
- window.addEventListener(PAYMENT_EVENTS.OPEN_PAYMENT_DETAILS_DIALOG, handleOpen);
2337
- window.addEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
2338
- return () => {
2339
- window.removeEventListener(PAYMENT_EVENTS.OPEN_PAYMENT_DETAILS_DIALOG, handleOpen);
2340
- window.removeEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
2341
- };
2342
- }, []);
2343
- const handleClose = () => {
2344
- setOpen(false);
2345
- setPaymentId(null);
2346
- };
2347
- useEffect(() => {
2348
- if (!payment?.expires_at) return;
2349
- const updateTimeLeft = () => {
2350
- const now = (/* @__PURE__ */ new Date()).getTime();
2351
- const expires = new Date(payment.expires_at).getTime();
2352
- const diff = expires - now;
2353
- if (diff <= 0) {
2354
- setTimeLeft("Expired");
2355
- return;
2356
- }
2357
- const hours = Math.floor(diff / (1e3 * 60 * 60));
2358
- const minutes = Math.floor(diff % (1e3 * 60 * 60) / (1e3 * 60));
2359
- const seconds = Math.floor(diff % (1e3 * 60) / 1e3);
2360
- setTimeLeft(`${hours}h ${minutes}m ${seconds}s`);
2361
- };
2362
- updateTimeLeft();
2363
- const interval = setInterval(updateTimeLeft, 1e3);
2364
- return () => clearInterval(interval);
2365
- }, [payment?.expires_at]);
2366
- const getStatusInfo = () => {
2367
- switch (payment?.status?.toLowerCase()) {
2368
- case "pending":
2369
- return { icon: Clock, color: "text-yellow-500", bg: "bg-yellow-500/10" };
2370
- case "completed":
2371
- case "success":
2372
- return { icon: CheckCircle2, color: "text-green-500", bg: "bg-green-500/10" };
2373
- case "failed":
2374
- case "error":
2375
- return { icon: XCircle, color: "text-red-500", bg: "bg-red-500/10" };
2376
- case "expired":
2377
- return { icon: AlertCircle, color: "text-gray-500", bg: "bg-gray-500/10" };
2378
- case "confirming":
2379
- return { icon: RefreshCw, color: "text-blue-500", bg: "bg-blue-500/10" };
2380
- default:
2381
- return { icon: Clock, color: "text-gray-500", bg: "bg-gray-500/10" };
2382
- }
2383
- };
2384
- if (!open) return null;
2385
- if (isLoading) {
2386
- return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-lg", children: [
2387
- /* @__PURE__ */ jsxs(DialogHeader, { children: [
2388
- /* @__PURE__ */ jsx(DialogTitle, { children: "Payment Details" }),
2389
- /* @__PURE__ */ jsx(DialogDescription, { children: "Loading payment information..." })
2390
- ] }),
2391
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx(RefreshCw, { className: "h-8 w-8 animate-spin text-muted-foreground" }) })
2392
- ] }) });
2393
- }
2394
- if (shouldFetch && !isLoading && (error || !payment)) {
2395
- return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-lg", children: [
2396
- /* @__PURE__ */ jsxs(DialogHeader, { children: [
2397
- /* @__PURE__ */ jsx(DialogTitle, { children: "Payment Details" }),
2398
- /* @__PURE__ */ jsx(DialogDescription, { children: "Failed to load payment information" })
2399
- ] }),
2400
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-12 space-y-4", children: [
2401
- /* @__PURE__ */ jsx(XCircle, { className: "h-12 w-12 text-destructive" }),
2402
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: error ? `Error: ${error}` : "Payment not found" }),
2403
- /* @__PURE__ */ jsx(Button, { onClick: () => mutate(), children: "Try Again" })
2404
- ] })
2405
- ] }) });
2406
- }
2407
- const statusInfo = getStatusInfo();
2408
- const StatusIcon = statusInfo.icon;
2409
- const qrCodeUrl = payment.pay_address ? `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(payment.pay_address)}` : null;
2410
- return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-lg", children: [
2411
- /* @__PURE__ */ jsxs(DialogHeader, { children: [
2412
- /* @__PURE__ */ jsx(DialogTitle, { children: "Payment Details" }),
2413
- /* @__PURE__ */ jsx(DialogDescription, { children: "Send cryptocurrency to complete your payment" })
2414
- ] }),
2415
- /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
2416
- /* @__PURE__ */ jsxs("div", { className: `flex items-center gap-3 p-4 rounded-sm ${statusInfo.bg}`, children: [
2417
- /* @__PURE__ */ jsx(StatusIcon, { className: `h-5 w-5 ${statusInfo.color}` }),
2418
- /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
2419
- /* @__PURE__ */ jsx("div", { className: "font-semibold capitalize", children: payment.status }),
2420
- payment.status === "pending" && timeLeft && /* @__PURE__ */ jsxs("div", { className: "text-sm text-muted-foreground", children: [
2421
- "Expires in ",
2422
- timeLeft
2423
- ] })
2424
- ] })
2425
- ] }),
2426
- /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
2427
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-4 bg-muted rounded-sm", children: [
2428
- /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Amount to send" }),
2429
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2430
- /* @__PURE__ */ jsx(TokenIcon, { symbol: String(payment.currency_code || "BTC"), size: 20 }),
2431
- /* @__PURE__ */ jsxs("span", { className: "font-mono font-bold text-lg", children: [
2432
- payment.pay_amount || "0.00000000",
2433
- " ",
2434
- payment.currency_code
2435
- ] })
2436
- ] })
2437
- ] }),
2438
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4", children: [
2439
- /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Equivalent to" }),
2440
- /* @__PURE__ */ jsxs("span", { className: "font-semibold text-lg", children: [
2441
- "$",
2442
- parseFloat(payment.amount_usd || "0").toFixed(2),
2443
- " USD"
2444
- ] })
2445
- ] }),
2446
- payment.internal_payment_id && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4", children: [
2447
- /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Payment Order #" }),
2448
- /* @__PURE__ */ jsx("span", { className: "font-mono font-medium", children: payment.internal_payment_id })
2449
- ] }),
2450
- payment.currency_network && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4", children: [
2451
- /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Network" }),
2452
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: payment.currency_network })
2453
- ] })
2454
- ] }),
2455
- qrCodeUrl && payment.status === "pending" && /* @__PURE__ */ jsx("div", { className: "flex justify-center p-6 bg-white rounded-sm", children: /* @__PURE__ */ jsx("img", { src: qrCodeUrl, alt: "Payment QR Code", className: "w-48 h-48" }) }),
2456
- payment.pay_address && payment.status === "pending" && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
2457
- /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Payment Address" }),
2458
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2459
- /* @__PURE__ */ jsx("div", { className: "flex-1 p-3 bg-muted rounded-sm font-mono text-sm break-all", children: payment.pay_address }),
2460
- /* @__PURE__ */ jsx(CopyButton, { value: payment.pay_address, variant: "outline" })
2461
- ] })
2462
- ] }),
2463
- payment.transaction_hash && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
2464
- /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Transaction Hash" }),
2465
- /* @__PURE__ */ jsx("div", { className: "p-3 bg-muted rounded-sm font-mono text-sm break-all", children: payment.transaction_hash })
2466
- ] }),
2467
- payment.payment_url && payment.status === "pending" && /* @__PURE__ */ jsxs(
2468
- Button,
2469
- {
2470
- variant: "outline",
2471
- className: "w-full",
2472
- onClick: () => window.open(payment.payment_url, "_blank"),
2473
- children: [
2474
- /* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4 mr-2" }),
2475
- "Open in Payment Provider"
2476
- ]
2477
- }
2478
- ),
2479
- /* @__PURE__ */ jsxs("div", { className: "pt-4 border-t space-y-2 text-xs text-muted-foreground", children: [
2480
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
2481
- /* @__PURE__ */ jsx("span", { children: "Payment ID" }),
2482
- /* @__PURE__ */ jsx("span", { className: "font-mono", children: payment.id })
2483
- ] }),
2484
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
2485
- /* @__PURE__ */ jsx("span", { children: "Created" }),
2486
- /* @__PURE__ */ jsx("span", { children: new Date(payment.created_at).toLocaleString() })
2487
- ] }),
2488
- payment.confirmations_count !== void 0 && /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
2489
- /* @__PURE__ */ jsx("span", { children: "Confirmations" }),
2490
- /* @__PURE__ */ jsx("span", { children: payment.confirmations_count })
2491
- ] })
2492
- ] })
2493
- ] }),
2494
- /* @__PURE__ */ jsxs(DialogFooter, { children: [
2495
- /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: handleClose, children: "Close" }),
2496
- /* @__PURE__ */ jsxs(Button, { onClick: () => mutate(), variant: "ghost", size: "sm", children: [
2497
- /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4 mr-2" }),
2498
- "Refresh"
2499
- ] })
2500
- ] })
2501
- ] }) });
2502
- };
2503
2517
  var PaymentsLayout = () => {
2504
2518
  return /* @__PURE__ */ jsx(RootPaymentsProvider, { children: /* @__PURE__ */ jsxs("div", { className: "h-full p-6 space-y-6", children: [
2505
2519
  /* @__PURE__ */ jsxs("div", { children: [
@@ -2606,7 +2620,8 @@ var package_default = {
2606
2620
  "p-retry": "^7.0.0",
2607
2621
  react: "^18 || ^19",
2608
2622
  swr: "^2.3.7",
2609
- zod: "^4.1.13"
2623
+ zod: "^4.1.13",
2624
+ moment: "^2.30.1"
2610
2625
  },
2611
2626
  devDependencies: {
2612
2627
  "@djangocfg/api": "workspace:*",