@djangocfg/ext-payments 1.0.13 → 1.0.17

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 (59) hide show
  1. package/dist/config.cjs +5 -8
  2. package/dist/config.js +5 -8
  3. package/dist/hooks.cjs +1 -1
  4. package/dist/hooks.js +1 -1
  5. package/dist/index.cjs +1085 -1107
  6. package/dist/index.d.cts +480 -41
  7. package/dist/index.d.ts +480 -41
  8. package/dist/index.js +1037 -1093
  9. package/package.json +13 -16
  10. package/src/api/generated/ext_payments/CLAUDE.md +7 -3
  11. package/src/api/generated/ext_payments/_utils/fetchers/ext_payments__payments.ts +237 -5
  12. package/src/api/generated/ext_payments/_utils/hooks/ext_payments__payments.ts +71 -3
  13. package/src/api/generated/ext_payments/_utils/schemas/PaginatedWithdrawalListList.schema.ts +24 -0
  14. package/src/api/generated/ext_payments/_utils/schemas/PaymentCreateRequest.schema.ts +21 -0
  15. package/src/api/generated/ext_payments/_utils/schemas/WithdrawalCreateRequest.schema.ts +21 -0
  16. package/src/api/generated/ext_payments/_utils/schemas/WithdrawalDetail.schema.ts +42 -0
  17. package/src/api/generated/ext_payments/_utils/schemas/WithdrawalList.schema.ts +29 -0
  18. package/src/api/generated/ext_payments/_utils/schemas/index.ts +5 -0
  19. package/src/api/generated/ext_payments/enums.ts +36 -0
  20. package/src/api/generated/ext_payments/ext_payments__payments/client.ts +58 -5
  21. package/src/api/generated/ext_payments/ext_payments__payments/models.ts +141 -0
  22. package/src/api/generated/ext_payments/schema.json +579 -3
  23. package/src/components/ActivityItem.tsx +118 -0
  24. package/src/components/ActivityList.tsx +93 -0
  25. package/src/components/AddFundsSheet.tsx +258 -0
  26. package/src/components/BalanceHero.tsx +102 -0
  27. package/src/components/PaymentSheet.tsx +290 -0
  28. package/src/components/ResponsiveSheet.tsx +151 -0
  29. package/src/components/WithdrawSheet.tsx +329 -0
  30. package/src/components/index.ts +18 -0
  31. package/src/contexts/WalletContext.tsx +355 -0
  32. package/src/contexts/index.ts +12 -45
  33. package/src/index.ts +6 -18
  34. package/src/contexts/BalancesContext.tsx +0 -63
  35. package/src/contexts/CurrenciesContext.tsx +0 -64
  36. package/src/contexts/OverviewContext.tsx +0 -173
  37. package/src/contexts/PaymentsContext.tsx +0 -122
  38. package/src/contexts/PaymentsExtensionProvider.tsx +0 -56
  39. package/src/contexts/README.md +0 -201
  40. package/src/contexts/RootPaymentsContext.tsx +0 -66
  41. package/src/contexts/types.ts +0 -40
  42. package/src/hooks/index.ts +0 -20
  43. package/src/layouts/PaymentsLayout/PaymentsLayout.tsx +0 -90
  44. package/src/layouts/PaymentsLayout/components/CreatePaymentDialog.tsx +0 -274
  45. package/src/layouts/PaymentsLayout/components/PaymentDetailsDialog.tsx +0 -287
  46. package/src/layouts/PaymentsLayout/components/index.ts +0 -2
  47. package/src/layouts/PaymentsLayout/events.ts +0 -47
  48. package/src/layouts/PaymentsLayout/index.ts +0 -16
  49. package/src/layouts/PaymentsLayout/types.ts +0 -6
  50. package/src/layouts/PaymentsLayout/views/overview/components/BalanceCard.tsx +0 -121
  51. package/src/layouts/PaymentsLayout/views/overview/components/RecentPayments.tsx +0 -139
  52. package/src/layouts/PaymentsLayout/views/overview/components/index.ts +0 -2
  53. package/src/layouts/PaymentsLayout/views/overview/index.tsx +0 -21
  54. package/src/layouts/PaymentsLayout/views/payments/components/PaymentsList.tsx +0 -279
  55. package/src/layouts/PaymentsLayout/views/payments/components/index.ts +0 -1
  56. package/src/layouts/PaymentsLayout/views/payments/index.tsx +0 -18
  57. package/src/layouts/PaymentsLayout/views/transactions/components/TransactionsList.tsx +0 -260
  58. package/src/layouts/PaymentsLayout/views/transactions/components/index.ts +0 -1
  59. package/src/layouts/PaymentsLayout/views/transactions/index.tsx +0 -18
package/dist/index.js CHANGED
@@ -2,15 +2,16 @@ import { createConsola, consola } from 'consola';
2
2
  import pRetry, { AbortError } from 'p-retry';
3
3
  import { z } from 'zod';
4
4
  import { initializeExtensionAPI, 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, Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from '@djangocfg/ui-core';
7
- import { createContext, useState, useMemo, useEffect, useContext } from 'react';
8
- import useSWR, { SWRConfig, useSWRConfig } from 'swr';
9
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
+ import { Plus, ArrowUpRight, RefreshCw, AlertCircle, XCircle, CheckCircle2, Loader2, Clock, ArrowDownLeft, History, ChevronRight, ExternalLink } from 'lucide-react';
6
+ import { Skeleton, Button, TokenIcon, ResponsiveSheet, ResponsiveSheetContent, ResponsiveSheetHeader, ResponsiveSheetTitle, ResponsiveSheetDescription, Form, FormField, FormItem, FormLabel, FormControl, Input, FormMessage, Combobox, Alert, AlertDescription, CopyButton, useIsMobile, Drawer, Dialog, DrawerContent, DialogContent, DrawerHeader, DialogHeader, DrawerTitle, DialogTitle, DrawerDescription, DialogDescription, DrawerFooter, DialogFooter } from '@djangocfg/ui-core';
7
+ import { cn } from '@djangocfg/ui-core/lib';
8
+ import * as React2 from 'react';
9
+ import { createContext, useState, useMemo, useCallback, useEffect, useContext } from 'react';
10
+ import useSWR2 from 'swr';
11
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
12
+ import moment2 from 'moment';
10
13
  import { useForm } from 'react-hook-form';
11
14
  import { zodResolver } from '@hookform/resolvers/zod';
12
- import moment from 'moment';
13
- import { useDRFPagination, StaticPagination } from '@djangocfg/ui-nextjs/components';
14
15
  import { createExtensionConfig } from '@djangocfg/ext-base';
15
16
 
16
17
  var __defProp = Object.defineProperty;
@@ -89,12 +90,12 @@ var ExtPaymentsPayments = class {
89
90
  return response.results || response;
90
91
  }
91
92
  /**
92
- * POST /api/v1/payments/create/ Create new payment. Request body: {
93
- * "amount_usd": "100.00", "currency_code": "USDTTRC20", "description":
94
- * "Optional description" }
93
+ * Create payment
94
+ *
95
+ * Create a new payment with specified amount and currency
95
96
  */
96
- async paymentsCreateCreate() {
97
- const response = await this.client.request("POST", "/cfg/payments/payments/create/");
97
+ async paymentsCreateCreate(data) {
98
+ const response = await this.client.request("POST", "/cfg/payments/payments/create/", { body: data });
98
99
  return response;
99
100
  }
100
101
  /**
@@ -113,6 +114,51 @@ var ExtPaymentsPayments = class {
113
114
  const response = await this.client.request("GET", "/cfg/payments/transactions/", { params });
114
115
  return response;
115
116
  }
117
+ /**
118
+ * ViewSet for withdrawal operations. Endpoints: - GET /withdrawals/ - List
119
+ * user's withdrawal requests - GET /withdrawals/{id}/ - Get withdrawal
120
+ * details - POST /withdrawals/create/ - Create withdrawal request - POST
121
+ * /withdrawals/{id}/cancel/ - Cancel pending withdrawal
122
+ */
123
+ async withdrawalsList(...args) {
124
+ const isParamsObject = args.length === 1 && typeof args[0] === "object" && args[0] !== null && !Array.isArray(args[0]);
125
+ let params;
126
+ if (isParamsObject) {
127
+ params = args[0];
128
+ } else {
129
+ params = { page: args[0], page_size: args[1] };
130
+ }
131
+ const response = await this.client.request("GET", "/cfg/payments/withdrawals/", { params });
132
+ return response;
133
+ }
134
+ /**
135
+ * ViewSet for withdrawal operations. Endpoints: - GET /withdrawals/ - List
136
+ * user's withdrawal requests - GET /withdrawals/{id}/ - Get withdrawal
137
+ * details - POST /withdrawals/create/ - Create withdrawal request - POST
138
+ * /withdrawals/{id}/cancel/ - Cancel pending withdrawal
139
+ */
140
+ async withdrawalsRetrieve(id) {
141
+ const response = await this.client.request("GET", `/cfg/payments/withdrawals/${id}/`);
142
+ return response;
143
+ }
144
+ /**
145
+ * Cancel withdrawal request
146
+ *
147
+ * Cancel a pending withdrawal request
148
+ */
149
+ async withdrawalsCancelCreate(id) {
150
+ const response = await this.client.request("POST", `/cfg/payments/withdrawals/${id}/cancel/`);
151
+ return response;
152
+ }
153
+ /**
154
+ * Create withdrawal request
155
+ *
156
+ * Create a new withdrawal request (requires admin approval)
157
+ */
158
+ async withdrawalsCreateCreate(data) {
159
+ const response = await this.client.request("POST", "/cfg/payments/withdrawals/create/", { body: data });
160
+ return response;
161
+ }
116
162
  };
117
163
 
118
164
  // src/api/generated/ext_payments/ext_payments__payments/models.ts
@@ -675,8 +721,8 @@ var APIClient = class {
675
721
  // src/api/generated/ext_payments/storage.ts
676
722
  var LocalStorageAdapter = class {
677
723
  logger;
678
- constructor(logger2) {
679
- this.logger = logger2;
724
+ constructor(logger) {
725
+ this.logger = logger;
680
726
  }
681
727
  getItem(key) {
682
728
  try {
@@ -718,8 +764,8 @@ var LocalStorageAdapter = class {
718
764
  };
719
765
  var CookieStorageAdapter = class {
720
766
  logger;
721
- constructor(logger2) {
722
- this.logger = logger2;
767
+ constructor(logger) {
768
+ this.logger = logger;
723
769
  }
724
770
  getItem(key) {
725
771
  try {
@@ -768,8 +814,8 @@ var CookieStorageAdapter = class {
768
814
  var MemoryStorageAdapter = class {
769
815
  storage = /* @__PURE__ */ new Map();
770
816
  logger;
771
- constructor(logger2) {
772
- this.logger = logger2;
817
+ constructor(logger) {
818
+ this.logger = logger;
773
819
  }
774
820
  getItem(key) {
775
821
  const value = this.storage.get(key) || null;
@@ -791,7 +837,9 @@ var enums_exports = {};
791
837
  __export(enums_exports, {
792
838
  PaymentDetailStatus: () => PaymentDetailStatus,
793
839
  PaymentListStatus: () => PaymentListStatus,
794
- TransactionTransactionType: () => TransactionTransactionType
840
+ TransactionTransactionType: () => TransactionTransactionType,
841
+ WithdrawalDetailStatus: () => WithdrawalDetailStatus,
842
+ WithdrawalListStatus: () => WithdrawalListStatus
795
843
  });
796
844
  var PaymentDetailStatus = /* @__PURE__ */ ((PaymentDetailStatus2) => {
797
845
  PaymentDetailStatus2["PENDING"] = "pending";
@@ -825,6 +873,24 @@ var TransactionTransactionType = /* @__PURE__ */ ((TransactionTransactionType2)
825
873
  TransactionTransactionType2["ADJUSTMENT"] = "adjustment";
826
874
  return TransactionTransactionType2;
827
875
  })(TransactionTransactionType || {});
876
+ var WithdrawalDetailStatus = /* @__PURE__ */ ((WithdrawalDetailStatus2) => {
877
+ WithdrawalDetailStatus2["PENDING"] = "pending";
878
+ WithdrawalDetailStatus2["APPROVED"] = "approved";
879
+ WithdrawalDetailStatus2["PROCESSING"] = "processing";
880
+ WithdrawalDetailStatus2["COMPLETED"] = "completed";
881
+ WithdrawalDetailStatus2["REJECTED"] = "rejected";
882
+ WithdrawalDetailStatus2["CANCELLED"] = "cancelled";
883
+ return WithdrawalDetailStatus2;
884
+ })(WithdrawalDetailStatus || {});
885
+ var WithdrawalListStatus = /* @__PURE__ */ ((WithdrawalListStatus2) => {
886
+ WithdrawalListStatus2["PENDING"] = "pending";
887
+ WithdrawalListStatus2["APPROVED"] = "approved";
888
+ WithdrawalListStatus2["PROCESSING"] = "processing";
889
+ WithdrawalListStatus2["COMPLETED"] = "completed";
890
+ WithdrawalListStatus2["REJECTED"] = "rejected";
891
+ WithdrawalListStatus2["CANCELLED"] = "cancelled";
892
+ return WithdrawalListStatus2;
893
+ })(WithdrawalListStatus || {});
828
894
 
829
895
  // src/api/generated/ext_payments/_utils/schemas/index.ts
830
896
  var schemas_exports = {};
@@ -832,9 +898,14 @@ __export(schemas_exports, {
832
898
  BalanceSchema: () => BalanceSchema,
833
899
  CurrencySchema: () => CurrencySchema,
834
900
  PaginatedPaymentListListSchema: () => PaginatedPaymentListListSchema,
901
+ PaginatedWithdrawalListListSchema: () => PaginatedWithdrawalListListSchema,
902
+ PaymentCreateRequestSchema: () => PaymentCreateRequestSchema,
835
903
  PaymentDetailSchema: () => PaymentDetailSchema,
836
904
  PaymentListSchema: () => PaymentListSchema,
837
- TransactionSchema: () => TransactionSchema
905
+ TransactionSchema: () => TransactionSchema,
906
+ WithdrawalCreateRequestSchema: () => WithdrawalCreateRequestSchema,
907
+ WithdrawalDetailSchema: () => WithdrawalDetailSchema,
908
+ WithdrawalListSchema: () => WithdrawalListSchema
838
909
  });
839
910
  var BalanceSchema = z.object({
840
911
  balance_usd: z.string(),
@@ -879,6 +950,36 @@ var PaginatedPaymentListListSchema = z.object({
879
950
  previous_page: z.int().nullable().optional(),
880
951
  results: z.array(PaymentListSchema)
881
952
  });
953
+ var WithdrawalListSchema = z.object({
954
+ id: z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i),
955
+ internal_withdrawal_id: z.string(),
956
+ amount_usd: z.string(),
957
+ final_amount_usd: z.string(),
958
+ currency_code: z.string(),
959
+ currency_token: z.string(),
960
+ status: z.nativeEnum(WithdrawalListStatus),
961
+ status_display: z.string(),
962
+ created_at: z.iso.datetime(),
963
+ completed_at: z.iso.datetime().nullable()
964
+ });
965
+
966
+ // src/api/generated/ext_payments/_utils/schemas/PaginatedWithdrawalListList.schema.ts
967
+ var PaginatedWithdrawalListListSchema = z.object({
968
+ count: z.int(),
969
+ page: z.int(),
970
+ pages: z.int(),
971
+ page_size: z.int(),
972
+ has_next: z.boolean(),
973
+ has_previous: z.boolean(),
974
+ next_page: z.int().nullable().optional(),
975
+ previous_page: z.int().nullable().optional(),
976
+ results: z.array(WithdrawalListSchema)
977
+ });
978
+ var PaymentCreateRequestSchema = z.object({
979
+ amount_usd: z.string(),
980
+ currency_code: z.string().min(1).max(20),
981
+ description: z.string().max(500).optional()
982
+ });
882
983
  var PaymentDetailSchema = z.object({
883
984
  id: z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i),
884
985
  internal_payment_id: z.string(),
@@ -917,6 +1018,36 @@ var TransactionSchema = z.object({
917
1018
  description: z.string(),
918
1019
  created_at: z.iso.datetime()
919
1020
  });
1021
+ var WithdrawalCreateRequestSchema = z.object({
1022
+ amount_usd: z.string(),
1023
+ currency_code: z.string().min(1).max(20),
1024
+ wallet_address: z.string().min(1).max(255)
1025
+ });
1026
+ var WithdrawalDetailSchema = z.object({
1027
+ id: z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i),
1028
+ internal_withdrawal_id: z.string(),
1029
+ amount_usd: z.string(),
1030
+ currency_code: z.string(),
1031
+ currency_name: z.string(),
1032
+ currency_token: z.string(),
1033
+ currency_network: z.string(),
1034
+ wallet_address: z.string(),
1035
+ network_fee_usd: z.string(),
1036
+ service_fee_usd: z.string(),
1037
+ total_fee_usd: z.string(),
1038
+ final_amount_usd: z.string(),
1039
+ crypto_amount: z.string().nullable(),
1040
+ status: z.nativeEnum(WithdrawalDetailStatus),
1041
+ status_display: z.string(),
1042
+ transaction_hash: z.string().nullable(),
1043
+ explorer_link: z.string().nullable(),
1044
+ admin_notes: z.string(),
1045
+ created_at: z.iso.datetime(),
1046
+ approved_at: z.iso.datetime().nullable(),
1047
+ completed_at: z.iso.datetime().nullable(),
1048
+ rejected_at: z.iso.datetime().nullable(),
1049
+ cancelled_at: z.iso.datetime().nullable()
1050
+ });
920
1051
 
921
1052
  // src/api/generated/ext_payments/validation-events.ts
922
1053
  function dispatchValidationError(detail) {
@@ -969,12 +1100,16 @@ var fetchers_exports = {};
969
1100
  __export(fetchers_exports, {
970
1101
  createPaymentsPaymentsConfirmCreate: () => createPaymentsPaymentsConfirmCreate,
971
1102
  createPaymentsPaymentsCreateCreate: () => createPaymentsPaymentsCreateCreate,
1103
+ createPaymentsWithdrawalsCancelCreate: () => createPaymentsWithdrawalsCancelCreate,
1104
+ createPaymentsWithdrawalsCreateCreate: () => createPaymentsWithdrawalsCreateCreate,
972
1105
  getPaymentsBalanceRetrieve: () => getPaymentsBalanceRetrieve,
973
1106
  getPaymentsCurrenciesList: () => getPaymentsCurrenciesList,
974
1107
  getPaymentsPaymentsList: () => getPaymentsPaymentsList,
975
1108
  getPaymentsPaymentsRetrieve: () => getPaymentsPaymentsRetrieve,
976
1109
  getPaymentsPaymentsStatusRetrieve: () => getPaymentsPaymentsStatusRetrieve,
977
- getPaymentsTransactionsList: () => getPaymentsTransactionsList
1110
+ getPaymentsTransactionsList: () => getPaymentsTransactionsList,
1111
+ getPaymentsWithdrawalsList: () => getPaymentsWithdrawalsList,
1112
+ getPaymentsWithdrawalsRetrieve: () => getPaymentsWithdrawalsRetrieve
978
1113
  });
979
1114
 
980
1115
  // src/api/generated/ext_payments/api-instance.ts
@@ -1247,11 +1382,11 @@ Method: GET`);
1247
1382
  throw error;
1248
1383
  }
1249
1384
  }
1250
- async function createPaymentsPaymentsCreateCreate(client) {
1385
+ async function createPaymentsPaymentsCreateCreate(data, client) {
1251
1386
  const api = client || getAPIInstance();
1252
- const response = await api.ext_payments_payments.paymentsCreateCreate();
1387
+ const response = await api.ext_payments_payments.paymentsCreateCreate(data);
1253
1388
  try {
1254
- return PaymentListSchema.parse(response);
1389
+ return PaymentDetailSchema.parse(response);
1255
1390
  } catch (error) {
1256
1391
  consola.error("\u274C Zod Validation Failed");
1257
1392
  consola.box(`createPaymentsPaymentsCreateCreate
@@ -1294,6 +1429,174 @@ async function getPaymentsTransactionsList(params, client) {
1294
1429
  const response = await api.ext_payments_payments.transactionsList(params?.limit, params?.offset, params?.type);
1295
1430
  return response;
1296
1431
  }
1432
+ async function getPaymentsWithdrawalsList(params, client) {
1433
+ const api = client || getAPIInstance();
1434
+ const response = await api.ext_payments_payments.withdrawalsList(params?.page, params?.page_size);
1435
+ try {
1436
+ return PaginatedWithdrawalListListSchema.parse(response);
1437
+ } catch (error) {
1438
+ consola.error("\u274C Zod Validation Failed");
1439
+ consola.box(`getPaymentsWithdrawalsList
1440
+ Path: /cfg/payments/withdrawals/
1441
+ Method: GET`);
1442
+ if (error instanceof Error && "issues" in error && Array.isArray(error.issues)) {
1443
+ consola.error("Validation Issues:");
1444
+ error.issues.forEach((issue, index) => {
1445
+ consola.error(` ${index + 1}. ${issue.path.join(".") || "root"}`);
1446
+ consola.error(` \u251C\u2500 Message: ${issue.message}`);
1447
+ if (issue.expected) consola.error(` \u251C\u2500 Expected: ${issue.expected}`);
1448
+ if (issue.received) consola.error(` \u2514\u2500 Received: ${issue.received}`);
1449
+ });
1450
+ }
1451
+ consola.error("Response data:", response);
1452
+ if (typeof window !== "undefined" && error instanceof Error && "issues" in error) {
1453
+ try {
1454
+ const event = new CustomEvent("zod-validation-error", {
1455
+ detail: {
1456
+ operation: "getPaymentsWithdrawalsList",
1457
+ path: "/cfg/payments/withdrawals/",
1458
+ method: "GET",
1459
+ error,
1460
+ response,
1461
+ timestamp: /* @__PURE__ */ new Date()
1462
+ },
1463
+ bubbles: true,
1464
+ cancelable: false
1465
+ });
1466
+ window.dispatchEvent(event);
1467
+ } catch (eventError) {
1468
+ consola.warn("Failed to dispatch validation error event:", eventError);
1469
+ }
1470
+ }
1471
+ throw error;
1472
+ }
1473
+ }
1474
+ async function getPaymentsWithdrawalsRetrieve(id, client) {
1475
+ const api = client || getAPIInstance();
1476
+ const response = await api.ext_payments_payments.withdrawalsRetrieve(id);
1477
+ try {
1478
+ return WithdrawalDetailSchema.parse(response);
1479
+ } catch (error) {
1480
+ consola.error("\u274C Zod Validation Failed");
1481
+ consola.box(`getPaymentsWithdrawalsRetrieve
1482
+ Path: /cfg/payments/withdrawals/{id}/
1483
+ Method: GET`);
1484
+ if (error instanceof Error && "issues" in error && Array.isArray(error.issues)) {
1485
+ consola.error("Validation Issues:");
1486
+ error.issues.forEach((issue, index) => {
1487
+ consola.error(` ${index + 1}. ${issue.path.join(".") || "root"}`);
1488
+ consola.error(` \u251C\u2500 Message: ${issue.message}`);
1489
+ if (issue.expected) consola.error(` \u251C\u2500 Expected: ${issue.expected}`);
1490
+ if (issue.received) consola.error(` \u2514\u2500 Received: ${issue.received}`);
1491
+ });
1492
+ }
1493
+ consola.error("Response data:", response);
1494
+ if (typeof window !== "undefined" && error instanceof Error && "issues" in error) {
1495
+ try {
1496
+ const event = new CustomEvent("zod-validation-error", {
1497
+ detail: {
1498
+ operation: "getPaymentsWithdrawalsRetrieve",
1499
+ path: "/cfg/payments/withdrawals/{id}/",
1500
+ method: "GET",
1501
+ error,
1502
+ response,
1503
+ timestamp: /* @__PURE__ */ new Date()
1504
+ },
1505
+ bubbles: true,
1506
+ cancelable: false
1507
+ });
1508
+ window.dispatchEvent(event);
1509
+ } catch (eventError) {
1510
+ consola.warn("Failed to dispatch validation error event:", eventError);
1511
+ }
1512
+ }
1513
+ throw error;
1514
+ }
1515
+ }
1516
+ async function createPaymentsWithdrawalsCancelCreate(id, client) {
1517
+ const api = client || getAPIInstance();
1518
+ const response = await api.ext_payments_payments.withdrawalsCancelCreate(id);
1519
+ try {
1520
+ return WithdrawalDetailSchema.parse(response);
1521
+ } catch (error) {
1522
+ consola.error("\u274C Zod Validation Failed");
1523
+ consola.box(`createPaymentsWithdrawalsCancelCreate
1524
+ Path: /cfg/payments/withdrawals/{id}/cancel/
1525
+ Method: POST`);
1526
+ if (error instanceof Error && "issues" in error && Array.isArray(error.issues)) {
1527
+ consola.error("Validation Issues:");
1528
+ error.issues.forEach((issue, index) => {
1529
+ consola.error(` ${index + 1}. ${issue.path.join(".") || "root"}`);
1530
+ consola.error(` \u251C\u2500 Message: ${issue.message}`);
1531
+ if (issue.expected) consola.error(` \u251C\u2500 Expected: ${issue.expected}`);
1532
+ if (issue.received) consola.error(` \u2514\u2500 Received: ${issue.received}`);
1533
+ });
1534
+ }
1535
+ consola.error("Response data:", response);
1536
+ if (typeof window !== "undefined" && error instanceof Error && "issues" in error) {
1537
+ try {
1538
+ const event = new CustomEvent("zod-validation-error", {
1539
+ detail: {
1540
+ operation: "createPaymentsWithdrawalsCancelCreate",
1541
+ path: "/cfg/payments/withdrawals/{id}/cancel/",
1542
+ method: "POST",
1543
+ error,
1544
+ response,
1545
+ timestamp: /* @__PURE__ */ new Date()
1546
+ },
1547
+ bubbles: true,
1548
+ cancelable: false
1549
+ });
1550
+ window.dispatchEvent(event);
1551
+ } catch (eventError) {
1552
+ consola.warn("Failed to dispatch validation error event:", eventError);
1553
+ }
1554
+ }
1555
+ throw error;
1556
+ }
1557
+ }
1558
+ async function createPaymentsWithdrawalsCreateCreate(data, client) {
1559
+ const api = client || getAPIInstance();
1560
+ const response = await api.ext_payments_payments.withdrawalsCreateCreate(data);
1561
+ try {
1562
+ return WithdrawalDetailSchema.parse(response);
1563
+ } catch (error) {
1564
+ consola.error("\u274C Zod Validation Failed");
1565
+ consola.box(`createPaymentsWithdrawalsCreateCreate
1566
+ Path: /cfg/payments/withdrawals/create/
1567
+ Method: POST`);
1568
+ if (error instanceof Error && "issues" in error && Array.isArray(error.issues)) {
1569
+ consola.error("Validation Issues:");
1570
+ error.issues.forEach((issue, index) => {
1571
+ consola.error(` ${index + 1}. ${issue.path.join(".") || "root"}`);
1572
+ consola.error(` \u251C\u2500 Message: ${issue.message}`);
1573
+ if (issue.expected) consola.error(` \u251C\u2500 Expected: ${issue.expected}`);
1574
+ if (issue.received) consola.error(` \u2514\u2500 Received: ${issue.received}`);
1575
+ });
1576
+ }
1577
+ consola.error("Response data:", response);
1578
+ if (typeof window !== "undefined" && error instanceof Error && "issues" in error) {
1579
+ try {
1580
+ const event = new CustomEvent("zod-validation-error", {
1581
+ detail: {
1582
+ operation: "createPaymentsWithdrawalsCreateCreate",
1583
+ path: "/cfg/payments/withdrawals/create/",
1584
+ method: "POST",
1585
+ error,
1586
+ response,
1587
+ timestamp: /* @__PURE__ */ new Date()
1588
+ },
1589
+ bubbles: true,
1590
+ cancelable: false
1591
+ });
1592
+ window.dispatchEvent(event);
1593
+ } catch (eventError) {
1594
+ consola.warn("Failed to dispatch validation error event:", eventError);
1595
+ }
1596
+ }
1597
+ throw error;
1598
+ }
1599
+ }
1297
1600
 
1298
1601
  // src/api/generated/ext_payments/index.ts
1299
1602
  var TOKEN_KEY = "auth_token";
@@ -1310,8 +1613,8 @@ var API = class {
1310
1613
  constructor(baseUrl, options) {
1311
1614
  this.baseUrl = baseUrl;
1312
1615
  this.options = options;
1313
- const logger2 = options?.loggerConfig ? new APILogger(options.loggerConfig) : void 0;
1314
- this.storage = options?.storage || new LocalStorageAdapter(logger2);
1616
+ const logger = options?.loggerConfig ? new APILogger(options.loggerConfig) : void 0;
1617
+ this.storage = options?.storage || new LocalStorageAdapter(logger);
1315
1618
  this._loadTokensFromStorage();
1316
1619
  this._client = new APIClient(this.baseUrl, {
1317
1620
  retryConfig: this.options?.retryConfig,
@@ -1422,333 +1725,296 @@ var API = class {
1422
1725
  };
1423
1726
  initializeExtensionAPI(configureAPI);
1424
1727
  var apiPayments = createExtensionAPI(API);
1425
- function usePaymentsBalanceRetrieve(client) {
1426
- return useSWR(
1427
- "cfg-payments-balance",
1428
- () => getPaymentsBalanceRetrieve(client)
1429
- );
1430
- }
1431
- function usePaymentsCurrenciesList(client) {
1432
- return useSWR(
1433
- "cfg-payments-currencies",
1434
- () => getPaymentsCurrenciesList(client)
1435
- );
1436
- }
1437
- function usePaymentsPaymentsList(params, client) {
1438
- return useSWR(
1439
- params ? ["cfg-payments-payments", params] : "cfg-payments-payments",
1440
- () => getPaymentsPaymentsList(params, client)
1441
- );
1442
- }
1443
- function usePaymentsPaymentsRetrieve(id, client) {
1444
- return useSWR(
1445
- ["cfg-payments-payment", id],
1446
- () => getPaymentsPaymentsRetrieve(id, client)
1447
- );
1448
- }
1449
- function useCreatePaymentsPaymentsConfirmCreate() {
1450
- const { mutate } = useSWRConfig();
1451
- return async (id, client) => {
1452
- const result = await createPaymentsPaymentsConfirmCreate(id, client);
1453
- mutate("cfg-payments-payments-confirm");
1454
- return result;
1455
- };
1456
- }
1457
- function useCreatePaymentsPaymentsCreateCreate() {
1458
- const { mutate } = useSWRConfig();
1459
- return async (client) => {
1460
- const result = await createPaymentsPaymentsCreateCreate(client);
1461
- mutate("cfg-payments-payments");
1462
- return result;
1463
- };
1464
- }
1465
- function usePaymentsTransactionsList(params, client) {
1466
- return useSWR(
1467
- params ? ["cfg-payments-transactions", params] : "cfg-payments-transactions",
1468
- () => getPaymentsTransactionsList(params, client)
1469
- );
1470
- }
1471
- var PaymentsContext = createContext(void 0);
1472
- function PaymentsProvider({ children }) {
1473
- const {
1474
- data: payments,
1475
- error: paymentsError,
1476
- isLoading: isLoadingPayments,
1477
- mutate: mutatePayments
1478
- } = usePaymentsPaymentsList({ page: 1, page_size: 1 }, apiPayments);
1479
- const refreshPayments = async () => {
1480
- await mutatePayments();
1481
- };
1482
- const createPaymentMutation = useCreatePaymentsPaymentsCreateCreate();
1483
- const confirmPaymentMutation = useCreatePaymentsPaymentsConfirmCreate();
1484
- const getPayment = async (id) => {
1485
- return getPaymentsPaymentsRetrieve(id, apiPayments);
1486
- };
1487
- const createPayment = async () => {
1488
- const result = await createPaymentMutation(apiPayments);
1489
- await refreshPayments();
1490
- return result;
1491
- };
1492
- const confirmPayment = async (id) => {
1493
- const result = await confirmPaymentMutation(id, apiPayments);
1494
- await refreshPayments();
1495
- return result;
1496
- };
1497
- const checkPaymentStatus = async (id) => {
1498
- return getPaymentsPaymentsStatusRetrieve(id, apiPayments);
1499
- };
1500
- const value = {
1501
- payments,
1502
- isLoadingPayments,
1503
- paymentsError,
1504
- refreshPayments,
1505
- getPayment,
1506
- createPayment,
1507
- confirmPayment,
1508
- checkPaymentStatus
1509
- };
1510
- return /* @__PURE__ */ jsx(PaymentsContext.Provider, { value, children });
1511
- }
1512
- function usePaymentsContext() {
1513
- const context = useContext(PaymentsContext);
1728
+ var WalletContext = createContext(void 0);
1729
+ function useWallet() {
1730
+ const context = useContext(WalletContext);
1514
1731
  if (!context) {
1515
- throw new Error("usePaymentsContext must be used within PaymentsProvider");
1732
+ throw new Error("useWallet must be used within WalletProvider");
1516
1733
  }
1517
1734
  return context;
1518
1735
  }
1519
- createContext(void 0);
1520
- createContext(void 0);
1521
- var OverviewContext = createContext(void 0);
1522
- function OverviewProvider({ children }) {
1523
- const swrConfig = {
1524
- revalidateOnFocus: false,
1525
- revalidateOnReconnect: false,
1526
- revalidateIfStale: false
1527
- };
1528
- const {
1529
- data: balance,
1530
- error: balanceError,
1531
- isLoading: isLoadingBalance,
1532
- mutate: mutateBalance
1533
- } = usePaymentsBalanceRetrieve(apiPayments);
1534
- const {
1535
- data: payments,
1536
- error: paymentsError,
1537
- isLoading: isLoadingPayments,
1538
- mutate: mutatePayments
1539
- } = usePaymentsPaymentsList({}, apiPayments);
1540
- const {
1541
- data: transactions,
1542
- error: transactionsError,
1543
- isLoading: isLoadingTransactions,
1544
- mutate: mutateTransactions
1545
- } = usePaymentsTransactionsList({}, apiPayments);
1546
- const createPaymentMutation = useCreatePaymentsPaymentsCreateCreate();
1547
- const isLoadingOverview = isLoadingBalance || isLoadingPayments || isLoadingTransactions;
1548
- const overviewError = balanceError || paymentsError || transactionsError;
1549
- const refreshBalance = async () => {
1550
- await mutateBalance();
1551
- };
1552
- const refreshPayments = async () => {
1553
- await mutatePayments();
1554
- };
1555
- const refreshTransactions = async () => {
1556
- await mutateTransactions();
1557
- };
1558
- const refreshOverview = async () => {
1559
- await Promise.all([
1560
- mutateBalance(),
1561
- mutatePayments(),
1562
- mutateTransactions()
1563
- ]);
1564
- };
1565
- const createPayment = async () => {
1566
- const result = await createPaymentMutation(apiPayments);
1567
- await refreshOverview();
1568
- return result;
1569
- };
1570
- const value = {
1571
- balance,
1572
- isLoadingBalance,
1573
- balanceError,
1574
- refreshBalance,
1575
- payments,
1576
- isLoadingPayments,
1577
- paymentsError,
1578
- refreshPayments,
1579
- transactions,
1580
- isLoadingTransactions,
1581
- transactionsError,
1582
- refreshTransactions,
1583
- createPayment,
1584
- isLoadingOverview,
1585
- overviewError,
1586
- refreshOverview
1587
- };
1588
- return /* @__PURE__ */ jsx(SWRConfig, { value: swrConfig, children: /* @__PURE__ */ jsx(OverviewContext.Provider, { value, children }) });
1736
+ function BalanceHero({ onAddFunds, onWithdraw, className }) {
1737
+ const { balance, balanceAmount, isLoadingBalance, refreshWallet } = useWallet();
1738
+ const formattedBalance = new Intl.NumberFormat("en-US", {
1739
+ style: "currency",
1740
+ currency: "USD",
1741
+ minimumFractionDigits: 2,
1742
+ maximumFractionDigits: 2
1743
+ }).format(balanceAmount);
1744
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col items-center py-16 px-4", className), children: [
1745
+ /* @__PURE__ */ jsx("div", { className: "text-center mb-6", children: isLoadingBalance ? /* @__PURE__ */ jsxs(Fragment, { children: [
1746
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-12 w-48 mx-auto mb-2" }),
1747
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-24 mx-auto" })
1748
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1749
+ /* @__PURE__ */ jsx("h1", { className: "text-5xl font-bold tracking-tight tabular-nums", children: formattedBalance }),
1750
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-1", children: "Available Balance" })
1751
+ ] }) }),
1752
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
1753
+ /* @__PURE__ */ jsxs(
1754
+ Button,
1755
+ {
1756
+ size: "lg",
1757
+ onClick: onAddFunds,
1758
+ className: "rounded-full px-6",
1759
+ children: [
1760
+ /* @__PURE__ */ jsx(Plus, { className: "h-5 w-5 mr-2" }),
1761
+ "Add Funds"
1762
+ ]
1763
+ }
1764
+ ),
1765
+ /* @__PURE__ */ jsxs(
1766
+ Button,
1767
+ {
1768
+ size: "lg",
1769
+ variant: "outline",
1770
+ onClick: onWithdraw,
1771
+ className: "rounded-full px-6",
1772
+ children: [
1773
+ /* @__PURE__ */ jsx(ArrowUpRight, { className: "h-5 w-5 mr-2" }),
1774
+ "Withdraw"
1775
+ ]
1776
+ }
1777
+ ),
1778
+ /* @__PURE__ */ jsx(
1779
+ Button,
1780
+ {
1781
+ size: "icon",
1782
+ variant: "ghost",
1783
+ onClick: () => refreshWallet(),
1784
+ className: "rounded-full",
1785
+ children: /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4" })
1786
+ }
1787
+ )
1788
+ ] }),
1789
+ balance && !isLoadingBalance && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-6 mt-6 text-sm text-muted-foreground", children: [
1790
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
1791
+ /* @__PURE__ */ jsxs("span", { className: "block font-medium text-foreground", children: [
1792
+ "$",
1793
+ parseFloat(balance.total_deposited || "0").toFixed(2)
1794
+ ] }),
1795
+ /* @__PURE__ */ jsx("span", { children: "Total Deposited" })
1796
+ ] }),
1797
+ /* @__PURE__ */ jsx("div", { className: "h-8 w-px bg-border" }),
1798
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
1799
+ /* @__PURE__ */ jsxs("span", { className: "block font-medium text-foreground", children: [
1800
+ "$",
1801
+ parseFloat(balance.total_withdrawn || "0").toFixed(2)
1802
+ ] }),
1803
+ /* @__PURE__ */ jsx("span", { children: "Total Withdrawn" })
1804
+ ] })
1805
+ ] })
1806
+ ] });
1589
1807
  }
1590
- function useOverviewContext() {
1591
- const context = useContext(OverviewContext);
1592
- if (!context) {
1593
- throw new Error("useOverviewContext must be used within OverviewProvider");
1808
+ var statusConfig = {
1809
+ pending: {
1810
+ icon: Clock,
1811
+ color: "text-yellow-500",
1812
+ bg: "bg-yellow-500/10"
1813
+ },
1814
+ confirming: {
1815
+ icon: Loader2,
1816
+ color: "text-blue-500",
1817
+ bg: "bg-blue-500/10",
1818
+ animate: true
1819
+ },
1820
+ completed: {
1821
+ icon: CheckCircle2,
1822
+ color: "text-green-500",
1823
+ bg: "bg-green-500/10"
1824
+ },
1825
+ failed: {
1826
+ icon: XCircle,
1827
+ color: "text-red-500",
1828
+ bg: "bg-red-500/10"
1829
+ },
1830
+ expired: {
1831
+ icon: AlertCircle,
1832
+ color: "text-muted-foreground",
1833
+ bg: "bg-muted"
1594
1834
  }
1595
- return context;
1596
- }
1597
- var RootPaymentsContext = createContext(void 0);
1598
- function RootPaymentsProvider({ children }) {
1599
- const {
1600
- data: currencies,
1601
- error: currenciesError,
1602
- isLoading: isLoadingCurrencies,
1603
- mutate: mutateCurrencies
1604
- } = usePaymentsCurrenciesList(apiPayments);
1605
- const refreshCurrencies = async () => {
1606
- await mutateCurrencies();
1607
- };
1608
- const value = {
1609
- currencies,
1610
- isLoadingCurrencies,
1611
- currenciesError,
1612
- refreshCurrencies
1613
- };
1614
- return /* @__PURE__ */ jsx(RootPaymentsContext.Provider, { value, children });
1835
+ };
1836
+ function ActivityItem({ item, onClick }) {
1837
+ const config = statusConfig[item.status];
1838
+ const StatusIcon = config.icon;
1839
+ const isPositive = item.type === "payment" || item.type === "deposit";
1840
+ const DirectionIcon = isPositive ? ArrowDownLeft : ArrowUpRight;
1841
+ const relativeTime = moment2(item.createdAt).fromNow();
1842
+ return /* @__PURE__ */ jsxs(
1843
+ "button",
1844
+ {
1845
+ onClick,
1846
+ className: cn(
1847
+ "w-full flex items-center gap-4 p-4 rounded-xl",
1848
+ "cursor-pointer",
1849
+ "hover:bg-accent active:bg-accent/80 transition-colors",
1850
+ "text-left"
1851
+ ),
1852
+ children: [
1853
+ /* @__PURE__ */ jsx("div", { className: cn(
1854
+ "flex items-center justify-center w-10 h-10 rounded-full",
1855
+ isPositive ? "bg-green-500/10" : "bg-red-500/10"
1856
+ ), children: item.currency ? /* @__PURE__ */ jsx(TokenIcon, { symbol: item.currency, size: 24 }) : /* @__PURE__ */ jsx(DirectionIcon, { className: cn(
1857
+ "h-5 w-5",
1858
+ isPositive ? "text-green-500" : "text-red-500"
1859
+ ) }) }),
1860
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
1861
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx("span", { className: "font-medium truncate", children: item.description }) }),
1862
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
1863
+ /* @__PURE__ */ jsx("span", { children: relativeTime }),
1864
+ item.status !== "completed" && /* @__PURE__ */ jsxs(Fragment, { children: [
1865
+ /* @__PURE__ */ jsx("span", { children: "\xB7" }),
1866
+ /* @__PURE__ */ jsxs("span", { className: cn("flex items-center gap-1", config.color), children: [
1867
+ /* @__PURE__ */ jsx(StatusIcon, { className: cn("h-3 w-3", config.animate && "animate-spin") }),
1868
+ item.statusDisplay
1869
+ ] })
1870
+ ] })
1871
+ ] })
1872
+ ] }),
1873
+ /* @__PURE__ */ jsxs("div", { className: "text-right", children: [
1874
+ /* @__PURE__ */ jsx("span", { className: cn(
1875
+ "font-semibold tabular-nums",
1876
+ isPositive ? "text-green-600 dark:text-green-400" : "text-foreground"
1877
+ ), children: item.amountDisplay }),
1878
+ item.status === "completed" && /* @__PURE__ */ jsx(CheckCircle2, { className: "h-4 w-4 text-green-500 ml-2 inline-block" })
1879
+ ] })
1880
+ ]
1881
+ }
1882
+ );
1615
1883
  }
1616
- function useRootPaymentsContext() {
1617
- const context = useContext(RootPaymentsContext);
1618
- if (!context) {
1619
- throw new Error("useRootPaymentsContext must be used within RootPaymentsProvider");
1884
+ function ActivityList({
1885
+ onItemClick,
1886
+ onViewAll,
1887
+ limit = 10,
1888
+ className
1889
+ }) {
1890
+ const { activity, isLoadingActivity, hasMoreActivity } = useWallet();
1891
+ const displayedActivity = limit ? activity.slice(0, limit) : activity;
1892
+ if (isLoadingActivity) {
1893
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-2", className), children: [
1894
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between px-4 py-2", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-32" }) }),
1895
+ [1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 p-4", children: [
1896
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-10 rounded-full" }),
1897
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-2", children: [
1898
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-32" }),
1899
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-24" })
1900
+ ] }),
1901
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-16" })
1902
+ ] }, i))
1903
+ ] });
1620
1904
  }
1621
- return context;
1905
+ if (activity.length === 0) {
1906
+ return /* @__PURE__ */ jsxs("div", { className: cn("text-center py-12", className), children: [
1907
+ /* @__PURE__ */ jsx("div", { className: "inline-flex items-center justify-center w-16 h-16 rounded-full bg-muted mb-4", children: /* @__PURE__ */ jsx(History, { className: "h-8 w-8 text-muted-foreground" }) }),
1908
+ /* @__PURE__ */ jsx("h3", { className: "font-semibold mb-1", children: "No Activity Yet" }),
1909
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Your transactions will appear here" })
1910
+ ] });
1911
+ }
1912
+ return /* @__PURE__ */ jsxs("div", { className: cn("pt-6", className), children: [
1913
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-2", children: [
1914
+ /* @__PURE__ */ jsx("h2", { className: "font-semibold text-lg", children: "Recent Activity" }),
1915
+ hasMoreActivity && onViewAll && /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", onClick: onViewAll, className: "text-primary", children: [
1916
+ "View All",
1917
+ /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4 ml-1" })
1918
+ ] })
1919
+ ] }),
1920
+ /* @__PURE__ */ jsx("div", { className: "divide-y divide-border/50", children: displayedActivity.map((item) => /* @__PURE__ */ jsx(
1921
+ ActivityItem,
1922
+ {
1923
+ item,
1924
+ onClick: () => onItemClick?.(item)
1925
+ },
1926
+ item.id
1927
+ )) })
1928
+ ] });
1622
1929
  }
1623
- var isDevelopment = process.env.NODE_ENV === "development";
1624
- var logger = createConsola({
1625
- level: isDevelopment ? 4 : 1
1626
- }).withTag("ext-payments");
1627
- var paymentsLogger = logger;
1628
-
1629
- // src/layouts/PaymentsLayout/events.ts
1630
- var PAYMENT_EVENTS = {
1631
- OPEN_CREATE_PAYMENT_DIALOG: "payments:open-create-payment",
1632
- OPEN_PAYMENT_DETAILS_DIALOG: "payments:open-payment-details",
1633
- CLOSE_DIALOG: "payments:close-dialog"
1634
- };
1635
- var openCreatePaymentDialog = () => {
1636
- window.dispatchEvent(new Event(PAYMENT_EVENTS.OPEN_CREATE_PAYMENT_DIALOG));
1637
- };
1638
- var openPaymentDetailsDialog = (id) => {
1639
- window.dispatchEvent(
1640
- new CustomEvent(PAYMENT_EVENTS.OPEN_PAYMENT_DETAILS_DIALOG, {
1641
- detail: { id }
1642
- })
1643
- );
1644
- };
1645
- var closePaymentsDialog = () => {
1646
- window.dispatchEvent(new Event(PAYMENT_EVENTS.CLOSE_DIALOG));
1647
- };
1648
- var PaymentCreateSchema = z.object({
1649
- amount_usd: z.number().min(0.01, "Amount must be at least $0.01"),
1650
- currency_code: z.string().min(1, "Please select a currency")
1930
+ var AddFundsSchema = z.object({
1931
+ amount: z.number().min(1, "Minimum $1.00"),
1932
+ currency: z.string().min(1, "Select a currency")
1651
1933
  });
1652
- var CreatePaymentDialog = () => {
1653
- const [open, setOpen] = useState(false);
1934
+ function AddFundsSheet({ open, onOpenChange, onSuccess }) {
1935
+ const { currencies, isLoadingCurrencies, addFunds } = useWallet();
1654
1936
  const [isSubmitting, setIsSubmitting] = useState(false);
1655
- const { createPayment } = usePaymentsContext();
1656
- const { currencies, isLoadingCurrencies } = useRootPaymentsContext();
1937
+ const [error, setError] = useState(null);
1657
1938
  const form = useForm({
1658
- resolver: zodResolver(PaymentCreateSchema),
1939
+ resolver: zodResolver(AddFundsSchema),
1659
1940
  defaultValues: {
1660
- amount_usd: 10,
1661
- currency_code: "USDT"
1941
+ amount: 100,
1942
+ currency: ""
1662
1943
  }
1663
1944
  });
1664
- const currenciesList = useMemo(() => {
1665
- const data = currencies?.currencies || currencies?.results || currencies || [];
1666
- return Array.isArray(data) ? data : [];
1667
- }, [currencies]);
1668
1945
  const currencyOptions = useMemo(() => {
1669
- return currenciesList.filter((curr) => curr.is_enabled !== false).map((curr) => ({
1670
- code: curr.code || curr.currency_code || curr.symbol,
1671
- name: curr.name || curr.code || curr.currency_code,
1672
- usd_rate: curr.usd_rate || curr.rate || 1,
1673
- network: curr.network || null
1946
+ return currencies.map((c) => ({
1947
+ value: c.code,
1948
+ label: c.network ? `${c.code} (${c.network})` : c.code,
1949
+ rate: c.rate,
1950
+ network: c.network
1674
1951
  }));
1675
- }, [currenciesList]);
1676
- const calculateCryptoAmount = useMemo(() => {
1677
- const amountUsd = form.watch("amount_usd");
1678
- const currencyCode = form.watch("currency_code");
1679
- const currency = currencyOptions.find((c) => c.code === currencyCode);
1680
- if (!currency || !currency.usd_rate || !amountUsd) {
1681
- return null;
1682
- }
1683
- const cryptoAmount = amountUsd / currency.usd_rate;
1684
- return {
1685
- amount: cryptoAmount,
1686
- currency: currency.code,
1687
- rate: currency.usd_rate,
1688
- network: currency.network
1689
- };
1690
- }, [form.watch("amount_usd"), form.watch("currency_code"), currencyOptions]);
1691
- useEffect(() => {
1692
- const handleOpen = () => setOpen(true);
1693
- const handleClose2 = () => setOpen(false);
1694
- window.addEventListener(PAYMENT_EVENTS.OPEN_CREATE_PAYMENT_DIALOG, handleOpen);
1695
- window.addEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
1696
- return () => {
1697
- window.removeEventListener(PAYMENT_EVENTS.OPEN_CREATE_PAYMENT_DIALOG, handleOpen);
1698
- window.removeEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
1699
- };
1700
- }, []);
1701
- const handleClose = () => {
1702
- setOpen(false);
1703
- form.reset();
1704
- };
1705
- useEffect(() => {
1706
- if (currencyOptions.length > 0 && !form.getValues("currency_code")) {
1707
- form.setValue("currency_code", currencyOptions[0].code);
1952
+ }, [currencies]);
1953
+ useMemo(() => {
1954
+ if (currencyOptions.length > 0 && !form.getValues("currency")) {
1955
+ const usdt = currencyOptions.find((c) => c.value.includes("USDT"));
1956
+ form.setValue("currency", usdt?.value || currencyOptions[0].value);
1708
1957
  }
1709
1958
  }, [currencyOptions, form]);
1710
- const handleSubmit = async (data) => {
1959
+ const selectedCurrency = currencyOptions.find((c) => c.value === form.watch("currency"));
1960
+ const cryptoAmount = useMemo(() => {
1961
+ const amount = form.watch("amount");
1962
+ if (!selectedCurrency?.rate || !amount) return null;
1963
+ return amount / selectedCurrency.rate;
1964
+ }, [form.watch("amount"), selectedCurrency]);
1965
+ const handleSubmit = useCallback(async (data) => {
1711
1966
  try {
1712
1967
  setIsSubmitting(true);
1713
- const result = await createPayment();
1714
- handleClose();
1715
- closePaymentsDialog();
1716
- const paymentData = result;
1717
- const paymentId = paymentData?.payment?.id || paymentData?.id;
1718
- if (paymentId) {
1719
- openPaymentDetailsDialog(String(paymentId));
1720
- }
1721
- } catch (error) {
1722
- paymentsLogger.error("Failed to create payment:", error);
1968
+ setError(null);
1969
+ const result = await addFunds({
1970
+ amount_usd: String(data.amount),
1971
+ currency_code: data.currency
1972
+ });
1973
+ form.reset();
1974
+ onOpenChange(false);
1975
+ onSuccess?.(result);
1976
+ } catch (err) {
1977
+ const message = err?.response?.data?.message || err?.response?.data?.detail || err?.message || "Failed to create payment";
1978
+ setError(message);
1723
1979
  } finally {
1724
1980
  setIsSubmitting(false);
1725
1981
  }
1726
- };
1727
- return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-md", children: [
1728
- /* @__PURE__ */ jsxs(DialogHeader, { children: [
1729
- /* @__PURE__ */ jsx(DialogTitle, { children: "Create Payment" }),
1730
- /* @__PURE__ */ jsx(DialogDescription, { children: "Create a new payment to add funds to your account." })
1982
+ }, [addFunds, form, onOpenChange, onSuccess]);
1983
+ const handleOpenChange = useCallback((open2) => {
1984
+ if (!open2) {
1985
+ setError(null);
1986
+ form.reset();
1987
+ }
1988
+ onOpenChange(open2);
1989
+ }, [form, onOpenChange]);
1990
+ return /* @__PURE__ */ jsx(ResponsiveSheet, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs(ResponsiveSheetContent, { className: "sm:max-w-md", children: [
1991
+ /* @__PURE__ */ jsxs(ResponsiveSheetHeader, { children: [
1992
+ /* @__PURE__ */ jsx(ResponsiveSheetTitle, { children: "Add Funds" }),
1993
+ /* @__PURE__ */ jsx(ResponsiveSheetDescription, { children: "Add funds to your wallet using cryptocurrency" })
1731
1994
  ] }),
1732
- /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsxs("form", { onSubmit: form.handleSubmit(handleSubmit), className: "space-y-4", children: [
1995
+ /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsxs("form", { onSubmit: form.handleSubmit(handleSubmit), className: "space-y-6 p-4 sm:p-0 sm:mt-4", children: [
1733
1996
  /* @__PURE__ */ jsx(
1734
1997
  FormField,
1735
1998
  {
1736
1999
  control: form.control,
1737
- name: "amount_usd",
2000
+ name: "amount",
1738
2001
  render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
1739
2002
  /* @__PURE__ */ jsx(FormLabel, { children: "Amount (USD)" }),
1740
- /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
1741
- Input,
1742
- {
1743
- type: "number",
1744
- step: "0.01",
1745
- min: "0.01",
1746
- placeholder: "10.00",
1747
- ...field,
1748
- onChange: (e) => field.onChange(parseFloat(e.target.value) || 0)
1749
- }
1750
- ) }),
1751
- /* @__PURE__ */ jsx(FormDescription, { children: "The amount you want to pay in USD." }),
2003
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
2004
+ /* @__PURE__ */ jsx("span", { className: "absolute left-4 top-1/2 -translate-y-1/2 text-muted-foreground text-lg", children: "$" }),
2005
+ /* @__PURE__ */ jsx(
2006
+ Input,
2007
+ {
2008
+ type: "number",
2009
+ step: "0.01",
2010
+ min: "1",
2011
+ placeholder: "100.00",
2012
+ className: "pl-8 text-2xl h-14 font-semibold",
2013
+ ...field,
2014
+ onChange: (e) => field.onChange(parseFloat(e.target.value) || 0)
2015
+ }
2016
+ )
2017
+ ] }) }),
1752
2018
  /* @__PURE__ */ jsx(FormMessage, {})
1753
2019
  ] })
1754
2020
  }
@@ -1757,122 +2023,344 @@ var CreatePaymentDialog = () => {
1757
2023
  FormField,
1758
2024
  {
1759
2025
  control: form.control,
1760
- name: "currency_code",
2026
+ name: "currency",
1761
2027
  render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
1762
- /* @__PURE__ */ jsx(FormLabel, { children: "Currency" }),
1763
- /* @__PURE__ */ jsxs(
1764
- Select,
2028
+ /* @__PURE__ */ jsx(FormLabel, { children: "Pay with" }),
2029
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
2030
+ Combobox,
1765
2031
  {
2032
+ options: currencyOptions,
2033
+ value: field.value,
1766
2034
  onValueChange: field.onChange,
1767
- defaultValue: field.value,
2035
+ placeholder: "Select currency...",
2036
+ searchPlaceholder: "Search...",
1768
2037
  disabled: isLoadingCurrencies,
1769
- children: [
1770
- /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select currency..." }) }) }),
1771
- /* @__PURE__ */ jsx(SelectContent, { children: currencyOptions.map((curr) => /* @__PURE__ */ jsx(SelectItem, { value: curr.code, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1772
- /* @__PURE__ */ jsx(TokenIcon, { symbol: curr.code, size: 16 }),
1773
- /* @__PURE__ */ jsx("span", { children: curr.code }),
1774
- curr.network && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
1775
- "(",
1776
- curr.network,
1777
- ")"
1778
- ] })
1779
- ] }) }, curr.code)) })
1780
- ]
2038
+ className: "h-14",
2039
+ renderOption: (option) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 flex-1", children: [
2040
+ /* @__PURE__ */ jsx(TokenIcon, { symbol: option.value, size: 24 }),
2041
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: option.label })
2042
+ ] }),
2043
+ renderValue: (option) => option && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
2044
+ /* @__PURE__ */ jsx(TokenIcon, { symbol: option.value, size: 24 }),
2045
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: option.label })
2046
+ ] })
1781
2047
  }
1782
- ),
1783
- /* @__PURE__ */ jsx(FormDescription, { children: "The cryptocurrency to use for payment." }),
2048
+ ) }),
1784
2049
  /* @__PURE__ */ jsx(FormMessage, {})
1785
2050
  ] })
1786
2051
  }
1787
2052
  ),
1788
- calculateCryptoAmount && /* @__PURE__ */ jsxs("div", { className: "rounded-sm bg-muted p-4 space-y-3", children: [
2053
+ cryptoAmount !== null && selectedCurrency && /* @__PURE__ */ jsxs("div", { className: "bg-muted rounded-xl p-4 space-y-2", children: [
1789
2054
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1790
- /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "You will send" }),
2055
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "You will send" }),
1791
2056
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1792
- /* @__PURE__ */ jsx(TokenIcon, { symbol: calculateCryptoAmount.currency, size: 16 }),
2057
+ /* @__PURE__ */ jsx(TokenIcon, { symbol: selectedCurrency.value, size: 20 }),
1793
2058
  /* @__PURE__ */ jsxs("span", { className: "font-mono font-semibold", children: [
1794
- calculateCryptoAmount.amount.toFixed(8),
2059
+ cryptoAmount.toFixed(8),
1795
2060
  " ",
1796
- calculateCryptoAmount.currency
2061
+ selectedCurrency.value
1797
2062
  ] })
1798
2063
  ] })
1799
2064
  ] }),
1800
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1801
- /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "You will receive" }),
1802
- /* @__PURE__ */ jsxs("span", { className: "text-lg font-bold", children: [
2065
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm text-muted-foreground", children: [
2066
+ /* @__PURE__ */ jsx("span", { children: "Rate" }),
2067
+ /* @__PURE__ */ jsxs("span", { children: [
2068
+ "1 ",
2069
+ selectedCurrency.value,
2070
+ " = $",
2071
+ selectedCurrency.rate.toFixed(2)
2072
+ ] })
2073
+ ] })
2074
+ ] }),
2075
+ error && /* @__PURE__ */ jsx(Alert, { variant: "destructive", children: /* @__PURE__ */ jsx(AlertDescription, { children: error }) }),
2076
+ /* @__PURE__ */ jsx(
2077
+ Button,
2078
+ {
2079
+ type: "submit",
2080
+ size: "lg",
2081
+ className: "w-full h-14 text-lg rounded-xl",
2082
+ disabled: isSubmitting || currencyOptions.length === 0,
2083
+ children: isSubmitting ? /* @__PURE__ */ jsxs(Fragment, { children: [
2084
+ /* @__PURE__ */ jsx(RefreshCw, { className: "h-5 w-5 mr-2 animate-spin" }),
2085
+ "Creating..."
2086
+ ] }) : "Continue"
2087
+ }
2088
+ )
2089
+ ] }) })
2090
+ ] }) });
2091
+ }
2092
+ var WithdrawSchema = z.object({
2093
+ amount: z.number().min(10, "Minimum $10.00"),
2094
+ currency: z.string().min(1, "Select a currency"),
2095
+ wallet_address: z.string().min(26, "Invalid wallet address")
2096
+ });
2097
+ var SERVICE_FEE_PERCENT = 0.01;
2098
+ var NETWORK_FEE_USD = 1;
2099
+ function WithdrawSheet({ open, onOpenChange, onSuccess }) {
2100
+ const { currencies, isLoadingCurrencies, withdraw, balanceAmount } = useWallet();
2101
+ const [isSubmitting, setIsSubmitting] = useState(false);
2102
+ const [error, setError] = useState(null);
2103
+ const form = useForm({
2104
+ resolver: zodResolver(WithdrawSchema),
2105
+ defaultValues: {
2106
+ amount: 10,
2107
+ currency: "",
2108
+ wallet_address: ""
2109
+ }
2110
+ });
2111
+ const currencyOptions = useMemo(() => {
2112
+ return currencies.map((c) => ({
2113
+ value: c.code,
2114
+ label: c.network ? `${c.code} (${c.network})` : c.code,
2115
+ rate: c.rate,
2116
+ network: c.network
2117
+ }));
2118
+ }, [currencies]);
2119
+ useMemo(() => {
2120
+ if (currencyOptions.length > 0 && !form.getValues("currency")) {
2121
+ const usdt = currencyOptions.find((c) => c.value.includes("USDT"));
2122
+ form.setValue("currency", usdt?.value || currencyOptions[0].value);
2123
+ }
2124
+ }, [currencyOptions, form]);
2125
+ const selectedCurrency = currencyOptions.find((c) => c.value === form.watch("currency"));
2126
+ const amount = form.watch("amount") || 0;
2127
+ const feeBreakdown = useMemo(() => {
2128
+ const serviceFee = amount * SERVICE_FEE_PERCENT;
2129
+ const networkFee = NETWORK_FEE_USD;
2130
+ const totalFee = serviceFee + networkFee;
2131
+ const finalAmount = Math.max(0, amount - totalFee);
2132
+ const cryptoAmount = selectedCurrency?.rate ? finalAmount / selectedCurrency.rate : null;
2133
+ return {
2134
+ serviceFee,
2135
+ networkFee,
2136
+ totalFee,
2137
+ finalAmount,
2138
+ cryptoAmount
2139
+ };
2140
+ }, [amount, selectedCurrency]);
2141
+ const insufficientBalance = amount > balanceAmount;
2142
+ const handleSubmit = useCallback(async (data) => {
2143
+ try {
2144
+ setIsSubmitting(true);
2145
+ setError(null);
2146
+ const result = await withdraw({
2147
+ amount_usd: String(data.amount),
2148
+ currency_code: data.currency,
2149
+ wallet_address: data.wallet_address
2150
+ });
2151
+ form.reset();
2152
+ onOpenChange(false);
2153
+ onSuccess?.(result);
2154
+ } catch (err) {
2155
+ const message = err?.response?.data?.error || err?.response?.data?.message || err?.response?.data?.detail || err?.message || "Failed to create withdrawal request";
2156
+ setError(message);
2157
+ } finally {
2158
+ setIsSubmitting(false);
2159
+ }
2160
+ }, [withdraw, form, onOpenChange, onSuccess]);
2161
+ const handleOpenChange = useCallback((open2) => {
2162
+ if (!open2) {
2163
+ setError(null);
2164
+ form.reset();
2165
+ }
2166
+ onOpenChange(open2);
2167
+ }, [form, onOpenChange]);
2168
+ return /* @__PURE__ */ jsx(ResponsiveSheet, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs(ResponsiveSheetContent, { className: "sm:max-w-md", children: [
2169
+ /* @__PURE__ */ jsxs(ResponsiveSheetHeader, { children: [
2170
+ /* @__PURE__ */ jsx(ResponsiveSheetTitle, { children: "Withdraw" }),
2171
+ /* @__PURE__ */ jsx(ResponsiveSheetDescription, { children: "Withdraw funds to your cryptocurrency wallet" })
2172
+ ] }),
2173
+ /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsxs("form", { onSubmit: form.handleSubmit(handleSubmit), className: "space-y-6 p-4 sm:p-0 sm:mt-4", children: [
2174
+ /* @__PURE__ */ jsx(
2175
+ FormField,
2176
+ {
2177
+ control: form.control,
2178
+ name: "amount",
2179
+ render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
2180
+ /* @__PURE__ */ jsx(FormLabel, { children: "Amount (USD)" }),
2181
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
2182
+ /* @__PURE__ */ jsx("span", { className: "absolute left-4 top-1/2 -translate-y-1/2 text-muted-foreground text-lg", children: "$" }),
2183
+ /* @__PURE__ */ jsx(
2184
+ Input,
2185
+ {
2186
+ type: "number",
2187
+ step: "0.01",
2188
+ min: "10",
2189
+ placeholder: "10.00",
2190
+ className: "pl-8 text-2xl h-14 font-semibold",
2191
+ ...field,
2192
+ onChange: (e) => field.onChange(parseFloat(e.target.value) || 0)
2193
+ }
2194
+ )
2195
+ ] }) }),
2196
+ /* @__PURE__ */ jsx(FormMessage, {}),
2197
+ insufficientBalance && /* @__PURE__ */ jsxs("p", { className: "text-sm text-destructive mt-1", children: [
2198
+ "Insufficient balance (Available: $",
2199
+ balanceAmount.toFixed(2),
2200
+ ")"
2201
+ ] })
2202
+ ] })
2203
+ }
2204
+ ),
2205
+ /* @__PURE__ */ jsx(
2206
+ FormField,
2207
+ {
2208
+ control: form.control,
2209
+ name: "currency",
2210
+ render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
2211
+ /* @__PURE__ */ jsx(FormLabel, { children: "Withdraw as" }),
2212
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
2213
+ Combobox,
2214
+ {
2215
+ options: currencyOptions,
2216
+ value: field.value,
2217
+ onValueChange: field.onChange,
2218
+ placeholder: "Select currency...",
2219
+ searchPlaceholder: "Search...",
2220
+ disabled: isLoadingCurrencies,
2221
+ className: "h-14",
2222
+ renderOption: (option) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 flex-1", children: [
2223
+ /* @__PURE__ */ jsx(TokenIcon, { symbol: option.value, size: 24 }),
2224
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: option.label })
2225
+ ] }),
2226
+ renderValue: (option) => option && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
2227
+ /* @__PURE__ */ jsx(TokenIcon, { symbol: option.value, size: 24 }),
2228
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: option.label })
2229
+ ] })
2230
+ }
2231
+ ) }),
2232
+ /* @__PURE__ */ jsx(FormMessage, {})
2233
+ ] })
2234
+ }
2235
+ ),
2236
+ /* @__PURE__ */ jsx(
2237
+ FormField,
2238
+ {
2239
+ control: form.control,
2240
+ name: "wallet_address",
2241
+ render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
2242
+ /* @__PURE__ */ jsx(FormLabel, { children: "Wallet Address" }),
2243
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
2244
+ Input,
2245
+ {
2246
+ placeholder: "Enter your wallet address",
2247
+ className: "font-mono text-sm",
2248
+ ...field
2249
+ }
2250
+ ) }),
2251
+ /* @__PURE__ */ jsx(FormMessage, {})
2252
+ ] })
2253
+ }
2254
+ ),
2255
+ amount >= 10 && selectedCurrency && /* @__PURE__ */ jsxs("div", { className: "bg-muted rounded-xl p-4 space-y-2", children: [
2256
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
2257
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Amount" }),
2258
+ /* @__PURE__ */ jsxs("span", { children: [
1803
2259
  "$",
1804
- form.watch("amount_usd")?.toFixed(2),
1805
- " USD"
2260
+ amount.toFixed(2)
1806
2261
  ] })
1807
2262
  ] }),
1808
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-xs", children: [
1809
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Rate" }),
1810
- /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
1811
- "1 ",
1812
- calculateCryptoAmount.currency,
1813
- " = $",
1814
- calculateCryptoAmount.rate?.toFixed(2)
2263
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
2264
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Service fee (1%)" }),
2265
+ /* @__PURE__ */ jsxs("span", { className: "text-destructive", children: [
2266
+ "-$",
2267
+ feeBreakdown.serviceFee.toFixed(2)
2268
+ ] })
2269
+ ] }),
2270
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
2271
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Network fee" }),
2272
+ /* @__PURE__ */ jsxs("span", { className: "text-destructive", children: [
2273
+ "-$",
2274
+ feeBreakdown.networkFee.toFixed(2)
1815
2275
  ] })
1816
2276
  ] }),
1817
- calculateCryptoAmount.network && /* @__PURE__ */ jsx("div", { className: "border-t pt-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1818
- /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Network" }),
1819
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: calculateCryptoAmount.network })
2277
+ /* @__PURE__ */ jsx("div", { className: "border-t pt-2 mt-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
2278
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "You will receive" }),
2279
+ /* @__PURE__ */ jsxs("div", { className: "text-right", children: [
2280
+ /* @__PURE__ */ jsxs("div", { className: "font-semibold", children: [
2281
+ "$",
2282
+ feeBreakdown.finalAmount.toFixed(2)
2283
+ ] }),
2284
+ feeBreakdown.cryptoAmount !== null && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
2285
+ /* @__PURE__ */ jsx(TokenIcon, { symbol: selectedCurrency.value, size: 16 }),
2286
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: feeBreakdown.cryptoAmount.toFixed(8) })
2287
+ ] })
2288
+ ] })
1820
2289
  ] }) })
1821
2290
  ] }),
1822
- /* @__PURE__ */ jsxs(DialogFooter, { children: [
1823
- /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: handleClose, disabled: isSubmitting, children: "Cancel" }),
1824
- /* @__PURE__ */ jsx(Button, { type: "submit", disabled: isSubmitting || currencyOptions.length === 0, children: isSubmitting ? /* @__PURE__ */ jsxs(Fragment, { children: [
1825
- /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4 mr-2 animate-spin" }),
1826
- "Creating..."
1827
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1828
- /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-2" }),
1829
- "Create Payment"
1830
- ] }) })
1831
- ] })
2291
+ /* @__PURE__ */ jsxs(Alert, { children: [
2292
+ /* @__PURE__ */ jsx(AlertCircle, { className: "h-4 w-4" }),
2293
+ /* @__PURE__ */ jsx(AlertDescription, { children: "Withdrawal requests require admin approval. Processing may take 24-48 hours." })
2294
+ ] }),
2295
+ error && /* @__PURE__ */ jsx(Alert, { variant: "destructive", children: /* @__PURE__ */ jsx(AlertDescription, { children: error }) }),
2296
+ /* @__PURE__ */ jsx(
2297
+ Button,
2298
+ {
2299
+ type: "submit",
2300
+ size: "lg",
2301
+ className: "w-full h-14 text-lg rounded-xl",
2302
+ disabled: isSubmitting || currencyOptions.length === 0 || insufficientBalance || feeBreakdown.finalAmount <= 0,
2303
+ children: isSubmitting ? /* @__PURE__ */ jsxs(Fragment, { children: [
2304
+ /* @__PURE__ */ jsx(RefreshCw, { className: "h-5 w-5 mr-2 animate-spin" }),
2305
+ "Submitting..."
2306
+ ] }) : "Request Withdrawal"
2307
+ }
2308
+ )
1832
2309
  ] }) })
1833
2310
  ] }) });
2311
+ }
2312
+ var statusConfig2 = {
2313
+ pending: {
2314
+ icon: Clock,
2315
+ color: "text-yellow-500",
2316
+ bg: "bg-yellow-500/10",
2317
+ label: "Waiting for payment"
2318
+ },
2319
+ confirming: {
2320
+ icon: RefreshCw,
2321
+ color: "text-blue-500",
2322
+ bg: "bg-blue-500/10",
2323
+ label: "Confirming",
2324
+ animate: true
2325
+ },
2326
+ completed: {
2327
+ icon: CheckCircle2,
2328
+ color: "text-green-500",
2329
+ bg: "bg-green-500/10",
2330
+ label: "Completed"
2331
+ },
2332
+ failed: {
2333
+ icon: XCircle,
2334
+ color: "text-red-500",
2335
+ bg: "bg-red-500/10",
2336
+ label: "Failed"
2337
+ },
2338
+ expired: {
2339
+ icon: AlertCircle,
2340
+ color: "text-muted-foreground",
2341
+ bg: "bg-muted",
2342
+ label: "Expired"
2343
+ }
1834
2344
  };
1835
- var PaymentDetailsDialog = () => {
1836
- const [open, setOpen] = useState(false);
1837
- const [paymentId, setPaymentId] = useState(null);
2345
+ function PaymentSheet({ paymentId, open, onOpenChange }) {
2346
+ const { getPaymentDetails } = useWallet();
1838
2347
  const [timeLeft, setTimeLeft] = useState("");
1839
- const shouldFetch = open && !!paymentId;
1840
- const { data: payment, isLoading, error, mutate } = usePaymentsPaymentsRetrieve(
1841
- shouldFetch ? paymentId : "",
1842
- apiPayments
2348
+ const { data: payment, isLoading, error, mutate } = useSWR2(
2349
+ open && paymentId ? ["payment-details", paymentId] : null,
2350
+ () => getPaymentDetails(paymentId),
2351
+ { refreshInterval: 1e4 }
1843
2352
  );
1844
- useEffect(() => {
1845
- const handleOpen = (event) => {
1846
- const customEvent = event;
1847
- setPaymentId(customEvent.detail.id);
1848
- setOpen(true);
1849
- };
1850
- const handleClose2 = () => {
1851
- setOpen(false);
1852
- setPaymentId(null);
1853
- };
1854
- window.addEventListener(PAYMENT_EVENTS.OPEN_PAYMENT_DETAILS_DIALOG, handleOpen);
1855
- window.addEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
1856
- return () => {
1857
- window.removeEventListener(PAYMENT_EVENTS.OPEN_PAYMENT_DETAILS_DIALOG, handleOpen);
1858
- window.removeEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
1859
- };
1860
- }, []);
1861
- const handleClose = () => {
1862
- setOpen(false);
1863
- setPaymentId(null);
1864
- };
1865
2353
  useEffect(() => {
1866
2354
  if (!payment?.expires_at) return;
1867
2355
  const updateTimeLeft = () => {
1868
- const now = moment();
1869
- const expires = moment.utc(payment.expires_at);
2356
+ const now = moment2();
2357
+ const expires = moment2.utc(payment.expires_at);
1870
2358
  const diff = expires.diff(now);
1871
2359
  if (diff <= 0) {
1872
2360
  setTimeLeft("Expired");
1873
2361
  return;
1874
2362
  }
1875
- const duration = moment.duration(diff);
2363
+ const duration = moment2.duration(diff);
1876
2364
  const hours = Math.floor(duration.asHours());
1877
2365
  const minutes = duration.minutes();
1878
2366
  const seconds = duration.seconds();
@@ -1882,713 +2370,172 @@ var PaymentDetailsDialog = () => {
1882
2370
  const interval = setInterval(updateTimeLeft, 1e3);
1883
2371
  return () => clearInterval(interval);
1884
2372
  }, [payment?.expires_at]);
1885
- const getStatusInfo = () => {
1886
- switch (payment?.status?.toLowerCase()) {
1887
- case "pending":
1888
- return { icon: Clock, color: "text-yellow-500", bg: "bg-yellow-500/10" };
1889
- case "completed":
1890
- case "success":
1891
- return { icon: CheckCircle2, color: "text-green-500", bg: "bg-green-500/10" };
1892
- case "failed":
1893
- case "error":
1894
- return { icon: XCircle, color: "text-red-500", bg: "bg-red-500/10" };
1895
- case "expired":
1896
- return { icon: AlertCircle, color: "text-gray-500", bg: "bg-gray-500/10" };
1897
- case "confirming":
1898
- return { icon: RefreshCw, color: "text-blue-500", bg: "bg-blue-500/10" };
1899
- default:
1900
- return { icon: Clock, color: "text-gray-500", bg: "bg-gray-500/10" };
1901
- }
1902
- };
1903
- if (!open) return null;
1904
- if (isLoading) {
1905
- return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-lg", children: [
1906
- /* @__PURE__ */ jsxs(DialogHeader, { children: [
1907
- /* @__PURE__ */ jsx(DialogTitle, { children: "Payment Details" }),
1908
- /* @__PURE__ */ jsx(DialogDescription, { children: "Loading payment information..." })
1909
- ] }),
1910
- /* @__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" }) })
1911
- ] }) });
1912
- }
1913
- if (shouldFetch && !isLoading && (error || !payment)) {
1914
- return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-lg", children: [
1915
- /* @__PURE__ */ jsxs(DialogHeader, { children: [
1916
- /* @__PURE__ */ jsx(DialogTitle, { children: "Payment Details" }),
1917
- /* @__PURE__ */ jsx(DialogDescription, { children: "Failed to load payment information" })
2373
+ const status = useMemo(() => {
2374
+ const s = payment?.status?.toLowerCase();
2375
+ if (s === "completed" || s === "success" || s === "finished") return "completed";
2376
+ if (s === "confirming" || s === "partially_paid") return "confirming";
2377
+ if (s === "expired") return "expired";
2378
+ if (s === "failed" || s === "error" || s === "cancelled") return "failed";
2379
+ return "pending";
2380
+ }, [payment?.status]);
2381
+ const config = statusConfig2[status];
2382
+ const StatusIcon = config.icon;
2383
+ const qrCodeUrl = payment?.pay_address ? `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(payment.pay_address)}` : null;
2384
+ const isPending = status === "pending";
2385
+ return /* @__PURE__ */ jsx(ResponsiveSheet, { open, onOpenChange, children: /* @__PURE__ */ jsxs(ResponsiveSheetContent, { className: "sm:max-w-lg", children: [
2386
+ /* @__PURE__ */ jsxs(ResponsiveSheetHeader, { children: [
2387
+ /* @__PURE__ */ jsx(ResponsiveSheetTitle, { children: "Payment Details" }),
2388
+ /* @__PURE__ */ jsx(ResponsiveSheetDescription, { children: isPending ? "Send cryptocurrency to complete payment" : "Payment information" })
2389
+ ] }),
2390
+ /* @__PURE__ */ jsxs("div", { className: "p-4 sm:p-0 sm:mt-4 overflow-y-auto max-h-[70vh]", children: [
2391
+ isLoading && /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
2392
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-48 w-48 rounded-xl" }) }),
2393
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-12 w-full" }),
2394
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-24 w-full" })
1918
2395
  ] }),
1919
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-12 space-y-4", children: [
1920
- /* @__PURE__ */ jsx(XCircle, { className: "h-12 w-12 text-destructive" }),
1921
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: error ? `Error: ${error}` : "Payment not found" }),
2396
+ error && /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-12", children: [
2397
+ /* @__PURE__ */ jsx(XCircle, { className: "h-12 w-12 text-destructive mb-4" }),
2398
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-4", children: "Failed to load payment" }),
1922
2399
  /* @__PURE__ */ jsx(Button, { onClick: () => mutate(), children: "Try Again" })
1923
- ] })
1924
- ] }) });
1925
- }
1926
- const statusInfo = getStatusInfo();
1927
- const StatusIcon = statusInfo.icon;
1928
- const qrCodeUrl = payment.pay_address ? `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(payment.pay_address)}` : null;
1929
- return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-lg", children: [
1930
- /* @__PURE__ */ jsxs(DialogHeader, { children: [
1931
- /* @__PURE__ */ jsx(DialogTitle, { children: "Payment Details" }),
1932
- /* @__PURE__ */ jsx(DialogDescription, { children: "Send cryptocurrency to complete your payment" })
1933
- ] }),
1934
- /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
1935
- /* @__PURE__ */ jsxs("div", { className: `flex items-center gap-3 p-4 rounded-sm ${statusInfo.bg}`, children: [
1936
- /* @__PURE__ */ jsx(StatusIcon, { className: `h-5 w-5 ${statusInfo.color}` }),
1937
- /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
1938
- /* @__PURE__ */ jsx("div", { className: "font-semibold capitalize", children: payment.status }),
1939
- payment.status === "pending" && timeLeft && /* @__PURE__ */ jsxs("div", { className: "text-sm text-muted-foreground", children: [
1940
- "Expires in ",
1941
- timeLeft
1942
- ] })
1943
- ] })
1944
2400
  ] }),
1945
- /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
1946
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-4 bg-muted rounded-sm", children: [
1947
- /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Amount to send" }),
1948
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1949
- /* @__PURE__ */ jsx(TokenIcon, { symbol: String(payment.currency_code || "BTC"), size: 20 }),
1950
- /* @__PURE__ */ jsxs("span", { className: "font-mono font-bold text-lg", children: [
1951
- payment.pay_amount || "0.00000000",
1952
- " ",
1953
- payment.currency_code
2401
+ payment && !isLoading && /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
2402
+ /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-3 p-4 rounded-xl", config.bg), children: [
2403
+ /* @__PURE__ */ jsx(StatusIcon, { className: cn("h-6 w-6", config.color, config.animate && "animate-spin") }),
2404
+ /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
2405
+ /* @__PURE__ */ jsx("div", { className: "font-semibold", children: config.label }),
2406
+ isPending && timeLeft && /* @__PURE__ */ jsxs("div", { className: "text-sm text-muted-foreground", children: [
2407
+ "Expires in ",
2408
+ timeLeft
1954
2409
  ] })
1955
2410
  ] })
1956
2411
  ] }),
1957
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4", children: [
1958
- /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Equivalent to" }),
1959
- /* @__PURE__ */ jsxs("span", { className: "font-semibold text-lg", children: [
1960
- "$",
1961
- parseFloat(payment.amount_usd || "0").toFixed(2),
1962
- " USD"
1963
- ] })
1964
- ] }),
1965
- payment.internal_payment_id && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4", children: [
1966
- /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Payment Order #" }),
1967
- /* @__PURE__ */ jsx("span", { className: "font-mono font-medium", children: payment.internal_payment_id })
1968
- ] }),
1969
- payment.currency_network && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4", children: [
1970
- /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Network" }),
1971
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: payment.currency_network })
1972
- ] })
1973
- ] }),
1974
- 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" }) }),
1975
- payment.pay_address && payment.status === "pending" && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1976
- /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Payment Address" }),
1977
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1978
- /* @__PURE__ */ jsx("div", { className: "flex-1 p-3 bg-muted rounded-sm font-mono text-sm break-all", children: payment.pay_address }),
1979
- /* @__PURE__ */ jsx(CopyButton, { value: payment.pay_address, variant: "outline" })
1980
- ] })
1981
- ] }),
1982
- payment.transaction_hash && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1983
- /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Transaction Hash" }),
1984
- /* @__PURE__ */ jsx("div", { className: "p-3 bg-muted rounded-sm font-mono text-sm break-all", children: payment.transaction_hash })
1985
- ] }),
1986
- payment.payment_url && payment.status === "pending" && /* @__PURE__ */ jsxs(
1987
- Button,
1988
- {
1989
- variant: "outline",
1990
- className: "w-full",
1991
- onClick: () => window.open(payment.payment_url, "_blank"),
1992
- children: [
1993
- /* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4 mr-2" }),
1994
- "Open in Payment Provider"
1995
- ]
1996
- }
1997
- ),
1998
- /* @__PURE__ */ jsxs("div", { className: "pt-4 border-t space-y-2 text-xs text-muted-foreground", children: [
1999
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
2000
- /* @__PURE__ */ jsx("span", { children: "Payment ID" }),
2001
- /* @__PURE__ */ jsx("span", { className: "font-mono", children: payment.id })
2002
- ] }),
2003
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
2004
- /* @__PURE__ */ jsx("span", { children: "Created" }),
2005
- /* @__PURE__ */ jsx("span", { children: moment.utc(payment.created_at).local().format("MMM D, YYYY HH:mm") })
2006
- ] }),
2007
- payment.confirmations_count !== void 0 && /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
2008
- /* @__PURE__ */ jsx("span", { children: "Confirmations" }),
2009
- /* @__PURE__ */ jsx("span", { children: payment.confirmations_count })
2010
- ] })
2011
- ] })
2012
- ] }),
2013
- /* @__PURE__ */ jsxs(DialogFooter, { children: [
2014
- /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: handleClose, children: "Close" }),
2015
- /* @__PURE__ */ jsxs(Button, { onClick: () => mutate(), variant: "ghost", size: "sm", children: [
2016
- /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4 mr-2" }),
2017
- "Refresh"
2018
- ] })
2019
- ] })
2020
- ] }) });
2021
- };
2022
- var BalanceCard = () => {
2023
- const {
2024
- balance,
2025
- isLoadingBalance,
2026
- refreshBalance
2027
- } = useOverviewContext();
2028
- const formatCurrency = (amount) => {
2029
- if (amount === null || amount === void 0) return "$0.00";
2030
- return new Intl.NumberFormat("en-US", {
2031
- style: "currency",
2032
- currency: "USD",
2033
- minimumFractionDigits: 2
2034
- }).format(amount);
2035
- };
2036
- const formatDate = (dateStr) => {
2037
- if (!dateStr) return "No transactions yet";
2038
- try {
2039
- return moment.utc(dateStr).local().format("MMM D, YYYY");
2040
- } catch {
2041
- return "Invalid date";
2042
- }
2043
- };
2044
- if (isLoadingBalance) {
2045
- return /* @__PURE__ */ jsxs(Card, { children: [
2046
- /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center justify-between", children: [
2047
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2048
- /* @__PURE__ */ jsx(Wallet, { className: "h-5 w-5" }),
2049
- "Account Balance"
2050
- ] }),
2051
- /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-20" })
2052
- ] }) }),
2053
- /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
2054
- /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-32" }),
2055
- /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-48" })
2056
- ] })
2057
- ] });
2058
- }
2059
- const balanceData = balance?.balance || balance;
2060
- const amountUsd = balanceData?.amount_usd ?? 0;
2061
- const totalDeposited = balanceData?.total_deposited ?? 0;
2062
- const totalWithdrawn = balanceData?.total_withdrawn ?? 0;
2063
- const lastTransactionAt = balanceData?.last_transaction_at;
2064
- const isEmpty = amountUsd === 0 && totalDeposited === 0;
2065
- return /* @__PURE__ */ jsxs(Card, { children: [
2066
- /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center justify-between", children: [
2067
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2068
- /* @__PURE__ */ jsx(Wallet, { className: "h-5 w-5" }),
2069
- "Account Balance"
2070
- ] }),
2071
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2072
- /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: refreshBalance, children: /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4" }) }),
2073
- /* @__PURE__ */ jsxs(Button, { size: "sm", onClick: () => openCreatePaymentDialog(), children: [
2074
- /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-2" }),
2075
- "Add Funds"
2076
- ] })
2077
- ] })
2078
- ] }) }),
2079
- /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
2080
- /* @__PURE__ */ jsxs("div", { children: [
2081
- /* @__PURE__ */ jsx("div", { className: "text-4xl font-bold", children: formatCurrency(amountUsd) }),
2082
- /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground mt-1", children: [
2083
- "Available balance \u2022 Last updated ",
2084
- formatDate(lastTransactionAt)
2085
- ] })
2086
- ] }),
2087
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4 pt-4 border-t", children: [
2088
- /* @__PURE__ */ jsxs("div", { children: [
2089
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Total Deposited" }),
2090
- /* @__PURE__ */ jsx("p", { className: "text-lg font-semibold text-green-600", children: formatCurrency(totalDeposited) })
2091
- ] }),
2092
- /* @__PURE__ */ jsxs("div", { children: [
2093
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Total Withdrawn" }),
2094
- /* @__PURE__ */ jsx("p", { className: "text-lg font-semibold text-red-600", children: formatCurrency(totalWithdrawn) })
2095
- ] })
2096
- ] }),
2097
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2098
- /* @__PURE__ */ jsx(Badge, { variant: !isEmpty ? "default" : "secondary", children: !isEmpty ? "Active" : "New Account" }),
2099
- isEmpty && /* @__PURE__ */ jsx(Badge, { variant: "outline", children: "Empty Balance" })
2100
- ] })
2101
- ] })
2102
- ] });
2103
- };
2104
- var RecentPayments = () => {
2105
- const { payments, isLoadingPayments } = useOverviewContext();
2106
- const formatCurrency = (amount) => {
2107
- if (amount === null || amount === void 0) return "$0.00";
2108
- const numAmount = typeof amount === "string" ? parseFloat(amount) : amount;
2109
- return new Intl.NumberFormat("en-US", {
2110
- style: "currency",
2111
- currency: "USD",
2112
- minimumFractionDigits: 2
2113
- }).format(numAmount);
2114
- };
2115
- const getRelativeTime = (date) => {
2116
- if (!date) return "N/A";
2117
- const m = moment.utc(date).local();
2118
- const now = moment();
2119
- const diffInSeconds = now.diff(m, "seconds");
2120
- if (diffInSeconds < 60) return "Just now";
2121
- if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
2122
- if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
2123
- return `${Math.floor(diffInSeconds / 86400)}d ago`;
2124
- };
2125
- const getStatusVariant = (status) => {
2126
- switch (status?.toLowerCase()) {
2127
- case "completed":
2128
- case "success":
2129
- return "default";
2130
- case "pending":
2131
- case "confirming":
2132
- return "secondary";
2133
- case "failed":
2134
- case "error":
2135
- case "expired":
2136
- return "destructive";
2137
- default:
2138
- return "outline";
2139
- }
2140
- };
2141
- if (isLoadingPayments) {
2142
- return /* @__PURE__ */ jsxs(Card, { children: [
2143
- /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center gap-2", children: [
2144
- /* @__PURE__ */ jsx(History, { className: "h-5 w-5" }),
2145
- "Recent Payments"
2146
- ] }) }),
2147
- /* @__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: [
2148
- /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
2149
- /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-32" }),
2150
- /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-24" })
2151
- ] }),
2152
- /* @__PURE__ */ jsx(Skeleton, { className: "h-6 w-16" })
2153
- ] }, i)) })
2154
- ] });
2155
- }
2156
- const recentPaymentsList = payments?.results?.slice(0, 5) || [];
2157
- return /* @__PURE__ */ jsxs(Card, { children: [
2158
- /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center justify-between", children: [
2159
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2160
- /* @__PURE__ */ jsx(History, { className: "h-5 w-5" }),
2161
- "Recent Payments"
2162
- ] }),
2163
- /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", children: [
2164
- "View All",
2165
- /* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4 ml-2" })
2166
- ] })
2167
- ] }) }),
2168
- /* @__PURE__ */ jsx(CardContent, { children: recentPaymentsList.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-8 text-muted-foreground", children: [
2169
- /* @__PURE__ */ jsx(History, { className: "h-12 w-12 mx-auto mb-4 opacity-50" }),
2170
- /* @__PURE__ */ jsx("p", { children: "No recent payments" }),
2171
- /* @__PURE__ */ jsx("p", { className: "text-sm mt-2", children: "Create your first payment to get started" })
2172
- ] }) : /* @__PURE__ */ jsx("div", { className: "space-y-3", children: recentPaymentsList.map((payment) => /* @__PURE__ */ jsxs(
2173
- "div",
2174
- {
2175
- className: "flex items-center justify-between p-3 border rounded-sm hover:bg-accent cursor-pointer transition-colors",
2176
- onClick: () => openPaymentDetailsDialog(String(payment.id)),
2177
- children: [
2178
- /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
2412
+ /* @__PURE__ */ jsxs("div", { className: "bg-muted rounded-xl p-4 space-y-3", children: [
2413
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
2414
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Amount to send" }),
2179
2415
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2180
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: formatCurrency(payment.amount_usd) }),
2181
- /* @__PURE__ */ jsx(Badge, { variant: getStatusVariant(payment.status), className: "text-xs", children: payment.status })
2182
- ] }),
2183
- /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
2184
- getRelativeTime(payment.created_at),
2185
- " \u2022 ",
2186
- payment.currency_code || "USD"
2416
+ /* @__PURE__ */ jsx(TokenIcon, { symbol: payment.currency_code, size: 24 }),
2417
+ /* @__PURE__ */ jsxs("span", { className: "font-mono font-bold text-lg", children: [
2418
+ payment.pay_amount,
2419
+ " ",
2420
+ payment.currency_code
2421
+ ] })
2187
2422
  ] })
2188
2423
  ] }),
2189
- /* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4 text-muted-foreground" })
2190
- ]
2191
- },
2192
- payment.id
2193
- )) }) })
2194
- ] });
2195
- };
2196
- var OverviewView = () => {
2197
- return /* @__PURE__ */ jsx("div", { className: "space-y-6", children: /* @__PURE__ */ jsxs("div", { className: "grid gap-6 lg:grid-cols-2", children: [
2198
- /* @__PURE__ */ jsx(BalanceCard, {}),
2199
- /* @__PURE__ */ jsx(RecentPayments, {})
2200
- ] }) });
2201
- };
2202
- var PaymentsList = () => {
2203
- const pagination = useDRFPagination(1, 20);
2204
- const {
2205
- data: payments,
2206
- error,
2207
- isLoading: isLoadingPayments,
2208
- mutate: refreshPayments
2209
- } = usePaymentsPaymentsList(pagination.params, apiPayments);
2210
- const paymentsList = payments?.results || [];
2211
- payments?.count || 0;
2212
- const [searchTerm, setSearchTerm] = useState("");
2213
- const [statusFilter, setStatusFilter] = useState("all");
2214
- const formatCurrency = (amount) => {
2215
- if (amount === null || amount === void 0) return "$0.00";
2216
- const numAmount = typeof amount === "string" ? parseFloat(amount) : amount;
2217
- return new Intl.NumberFormat("en-US", {
2218
- style: "currency",
2219
- currency: "USD",
2220
- minimumFractionDigits: 2
2221
- }).format(numAmount);
2222
- };
2223
- const getRelativeTime = (date) => {
2224
- if (!date) return "N/A";
2225
- const m = moment.utc(date).local();
2226
- const now = moment();
2227
- const diffInSeconds = now.diff(m, "seconds");
2228
- if (diffInSeconds < 60) return "Just now";
2229
- if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
2230
- if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
2231
- return `${Math.floor(diffInSeconds / 86400)}d ago`;
2232
- };
2233
- const formatDate = (date) => {
2234
- if (!date) return "N/A";
2235
- return moment.utc(date).local().format("MMM D, YYYY");
2236
- };
2237
- const getStatusVariant = (status) => {
2238
- switch (status?.toLowerCase()) {
2239
- case "completed":
2240
- case "success":
2241
- return "default";
2242
- case "pending":
2243
- case "confirming":
2244
- return "secondary";
2245
- case "failed":
2246
- case "error":
2247
- case "expired":
2248
- return "destructive";
2249
- default:
2250
- return "outline";
2251
- }
2252
- };
2253
- const handleSearch = (value) => {
2254
- setSearchTerm(value);
2255
- };
2256
- const handleStatusFilter = (status) => {
2257
- setStatusFilter(status);
2258
- };
2259
- const truncateId = (id) => {
2260
- if (!id) return "N/A";
2261
- const str = id.toString();
2262
- return str.length > 8 ? `${str.slice(0, 8)}...` : str;
2263
- };
2264
- const filteredPayments = paymentsList.filter((payment) => {
2265
- const matchesSearch = searchTerm ? payment.id?.toLowerCase().includes(searchTerm.toLowerCase()) || payment.status?.toLowerCase().includes(searchTerm.toLowerCase()) || payment.currency_code?.toLowerCase().includes(searchTerm.toLowerCase()) : true;
2266
- const matchesStatus = statusFilter !== "all" ? payment.status?.toLowerCase() === statusFilter.toLowerCase() : true;
2267
- return matchesSearch && matchesStatus;
2268
- }).map((payment) => ({
2269
- ...payment,
2270
- formattedDate: formatDate(payment.created_at),
2271
- relativeTime: getRelativeTime(payment.created_at),
2272
- truncatedId: truncateId(payment.id)
2273
- }));
2274
- return /* @__PURE__ */ jsxs(Card, { children: [
2275
- /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center justify-between", children: [
2276
- /* @__PURE__ */ jsx("span", { children: "Payment History" }),
2277
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2278
- /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: () => refreshPayments(), disabled: isLoadingPayments, children: [
2279
- /* @__PURE__ */ jsx(RefreshCw, { className: `h-4 w-4 mr-2 ${isLoadingPayments ? "animate-spin" : ""}` }),
2280
- "Refresh"
2424
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
2425
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Equivalent" }),
2426
+ /* @__PURE__ */ jsxs("span", { className: "font-semibold", children: [
2427
+ "$",
2428
+ parseFloat(payment.amount_usd).toFixed(2),
2429
+ " USD"
2430
+ ] })
2431
+ ] }),
2432
+ payment.currency_network && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm pt-2 border-t", children: [
2433
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Network" }),
2434
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: payment.currency_network })
2435
+ ] })
2281
2436
  ] }),
2282
- /* @__PURE__ */ jsxs(Button, { size: "sm", onClick: () => openCreatePaymentDialog(), children: [
2283
- /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-2" }),
2284
- "New Payment"
2285
- ] })
2286
- ] })
2287
- ] }) }),
2288
- /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
2289
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row gap-4", children: [
2290
- /* @__PURE__ */ jsxs("div", { className: "relative flex-1", children: [
2291
- /* @__PURE__ */ jsx(Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
2292
- /* @__PURE__ */ jsx(
2293
- Input,
2294
- {
2295
- placeholder: "Search by ID, status, or currency...",
2296
- value: searchTerm,
2297
- onChange: (e) => handleSearch(e.target.value),
2298
- className: "pl-10"
2299
- }
2300
- )
2437
+ qrCodeUrl && isPending && /* @__PURE__ */ jsx("div", { className: "flex justify-center p-6 bg-white rounded-xl", children: /* @__PURE__ */ jsx("img", { src: qrCodeUrl, alt: "Payment QR Code", className: "w-48 h-48" }) }),
2438
+ payment.pay_address && isPending && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
2439
+ /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Payment Address" }),
2440
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2441
+ /* @__PURE__ */ jsx("div", { className: "flex-1 p-3 bg-muted rounded-xl font-mono text-sm break-all", children: payment.pay_address }),
2442
+ /* @__PURE__ */ jsx(CopyButton, { value: payment.pay_address, variant: "outline", className: "shrink-0" })
2443
+ ] })
2444
+ ] }),
2445
+ payment.transaction_hash && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
2446
+ /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Transaction Hash" }),
2447
+ /* @__PURE__ */ jsx("div", { className: "p-3 bg-muted rounded-xl font-mono text-sm break-all", children: payment.transaction_hash })
2301
2448
  ] }),
2302
- /* @__PURE__ */ jsxs(Select, { value: statusFilter, onValueChange: handleStatusFilter, children: [
2303
- /* @__PURE__ */ jsxs(SelectTrigger, { className: "w-full sm:w-48", children: [
2304
- /* @__PURE__ */ jsx(Filter, { className: "h-4 w-4 mr-2" }),
2305
- /* @__PURE__ */ jsx(SelectValue, { placeholder: "Filter by status" })
2449
+ payment.payment_url && isPending && /* @__PURE__ */ jsxs(
2450
+ Button,
2451
+ {
2452
+ variant: "outline",
2453
+ className: "w-full",
2454
+ onClick: () => window.open(payment.payment_url, "_blank"),
2455
+ children: [
2456
+ /* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4 mr-2" }),
2457
+ "Open in Payment Provider"
2458
+ ]
2459
+ }
2460
+ ),
2461
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2 text-xs text-muted-foreground pt-4 border-t", children: [
2462
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
2463
+ /* @__PURE__ */ jsx("span", { children: "Payment ID" }),
2464
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: payment.id })
2465
+ ] }),
2466
+ payment.internal_payment_id && /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
2467
+ /* @__PURE__ */ jsx("span", { children: "Order #" }),
2468
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: payment.internal_payment_id })
2306
2469
  ] }),
2307
- /* @__PURE__ */ jsxs(SelectContent, { children: [
2308
- /* @__PURE__ */ jsx(SelectItem, { value: "all", children: "All Statuses" }),
2309
- /* @__PURE__ */ jsx(SelectItem, { value: "completed", children: "Completed" }),
2310
- /* @__PURE__ */ jsx(SelectItem, { value: "pending", children: "Pending" }),
2311
- /* @__PURE__ */ jsx(SelectItem, { value: "confirming", children: "Confirming" }),
2312
- /* @__PURE__ */ jsx(SelectItem, { value: "failed", children: "Failed" }),
2313
- /* @__PURE__ */ jsx(SelectItem, { value: "expired", children: "Expired" })
2470
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
2471
+ /* @__PURE__ */ jsx("span", { children: "Created" }),
2472
+ /* @__PURE__ */ jsx("span", { children: moment2.utc(payment.created_at).local().format("MMM D, YYYY HH:mm") })
2314
2473
  ] })
2315
- ] })
2316
- ] }),
2317
- isLoadingPayments ? /* @__PURE__ */ jsx("div", { className: "space-y-3", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-4 border rounded-sm", children: [
2318
- /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
2319
- /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-32" }),
2320
- /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-24" })
2321
2474
  ] }),
2322
- /* @__PURE__ */ jsx(Skeleton, { className: "h-6 w-16" })
2323
- ] }, i)) }) : filteredPayments.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-12", children: [
2324
- /* @__PURE__ */ jsx("div", { className: "w-16 h-16 mx-auto mb-4 bg-muted rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsx(Search, { className: "w-8 h-8 text-muted-foreground" }) }),
2325
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: "No Payments Found" }),
2326
- /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mb-4", children: searchTerm || statusFilter !== "all" ? "No payments match your current filters" : "You haven't made any payments yet" }),
2327
- /* @__PURE__ */ jsxs(Button, { onClick: () => openCreatePaymentDialog(), children: [
2328
- /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-2" }),
2329
- "Create Payment"
2330
- ] })
2331
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
2332
- /* @__PURE__ */ jsx("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxs(Table, { children: [
2333
- /* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
2334
- /* @__PURE__ */ jsx(TableHead, { children: "Date" }),
2335
- /* @__PURE__ */ jsx(TableHead, { children: "Amount" }),
2336
- /* @__PURE__ */ jsx(TableHead, { children: "Currency" }),
2337
- /* @__PURE__ */ jsx(TableHead, { children: "Status" }),
2338
- /* @__PURE__ */ jsx(TableHead, { children: "Provider" }),
2339
- /* @__PURE__ */ jsx(TableHead, { children: "Payment ID" }),
2340
- /* @__PURE__ */ jsx(TableHead, { className: "text-right", children: "Actions" })
2341
- ] }) }),
2342
- /* @__PURE__ */ jsx(TableBody, { children: filteredPayments.map((payment) => /* @__PURE__ */ jsxs(
2343
- TableRow,
2344
- {
2345
- className: "cursor-pointer hover:bg-accent",
2346
- onClick: () => openPaymentDetailsDialog(String(payment.id)),
2347
- children: [
2348
- /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs("div", { children: [
2349
- /* @__PURE__ */ jsx("div", { className: "font-medium", children: payment.formattedDate }),
2350
- /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: payment.relativeTime })
2351
- ] }) }),
2352
- /* @__PURE__ */ jsx(TableCell, { className: "font-mono font-semibold", children: formatCurrency(payment.amount_usd) }),
2353
- /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Badge, { variant: "outline", children: payment.currency_code || "USD" }) }),
2354
- /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Badge, { variant: getStatusVariant(payment.status), children: payment.status }) }),
2355
- /* @__PURE__ */ jsx(TableCell, { className: "text-sm text-muted-foreground", children: "NowPayments" }),
2356
- /* @__PURE__ */ jsx(TableCell, { className: "font-mono text-sm text-muted-foreground", children: payment.truncatedId }),
2357
- /* @__PURE__ */ jsx(TableCell, { className: "text-right", children: /* @__PURE__ */ jsx(
2358
- Button,
2359
- {
2360
- variant: "ghost",
2361
- size: "sm",
2362
- onClick: (e) => {
2363
- e.stopPropagation();
2364
- openPaymentDetailsDialog(String(payment.id));
2365
- },
2366
- children: /* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4" })
2367
- }
2368
- ) })
2369
- ]
2370
- },
2371
- payment.id
2372
- )) })
2373
- ] }) }),
2374
- /* @__PURE__ */ jsx(
2375
- StaticPagination,
2475
+ /* @__PURE__ */ jsxs(
2476
+ Button,
2376
2477
  {
2377
- data: payments,
2378
- onPageChange: pagination.setPage,
2379
- className: "mt-4"
2478
+ variant: "ghost",
2479
+ className: "w-full",
2480
+ onClick: () => mutate(),
2481
+ children: [
2482
+ /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4 mr-2" }),
2483
+ "Refresh Status"
2484
+ ]
2380
2485
  }
2381
2486
  )
2382
2487
  ] })
2383
2488
  ] })
2384
- ] });
2385
- };
2386
- var PaymentsView = () => {
2387
- return /* @__PURE__ */ jsx("div", { className: "space-y-6", children: /* @__PURE__ */ jsx(PaymentsList, {}) });
2388
- };
2389
- var TransactionsList = () => {
2390
- const {
2391
- transactions,
2392
- isLoadingTransactions,
2393
- refreshTransactions
2394
- } = useOverviewContext();
2395
- const [searchTerm, setSearchTerm] = useState("");
2396
- const [typeFilter, setTypeFilter] = useState("all");
2397
- const transactionsList = transactions?.results || transactions?.transactions || [];
2398
- const formatCurrency = (amount) => {
2399
- if (amount === null || amount === void 0) return "$0.00";
2400
- return new Intl.NumberFormat("en-US", {
2401
- style: "currency",
2402
- currency: "USD",
2403
- minimumFractionDigits: 2
2404
- }).format(amount);
2405
- };
2406
- const formatDate = (date) => {
2407
- if (!date) return "N/A";
2408
- try {
2409
- return moment.utc(date).local().format("MMM D, YYYY hh:mm A");
2410
- } catch {
2411
- return "Invalid date";
2412
- }
2413
- };
2414
- const getRelativeTime = (date) => {
2415
- if (!date) return "N/A";
2416
- const m = moment.utc(date).local();
2417
- const now = moment();
2418
- const diffInSeconds = now.diff(m, "seconds");
2419
- if (diffInSeconds < 60) return "Just now";
2420
- if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
2421
- if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
2422
- return `${Math.floor(diffInSeconds / 86400)}d ago`;
2423
- };
2424
- const getTypeVariant = (type) => {
2425
- switch (type?.toLowerCase()) {
2426
- case "deposit":
2427
- case "credit":
2428
- return "default";
2429
- case "withdrawal":
2430
- case "debit":
2431
- return "destructive";
2432
- default:
2433
- return "outline";
2434
- }
2435
- };
2436
- const getTypeIcon = (type) => {
2437
- const isDeposit = type?.toLowerCase() === "deposit" || type?.toLowerCase() === "credit";
2438
- return isDeposit ? /* @__PURE__ */ jsx(ArrowDownLeft, { className: "h-4 w-4 text-green-600" }) : /* @__PURE__ */ jsx(ArrowUpRight, { className: "h-4 w-4 text-red-600" });
2439
- };
2440
- const handleSearch = async (value) => {
2441
- setSearchTerm(value);
2442
- await refreshTransactions();
2443
- };
2444
- const handleTypeFilter = async (type) => {
2445
- setTypeFilter(type);
2446
- await refreshTransactions();
2447
- };
2448
- const truncateId = (id) => {
2449
- if (!id) return "N/A";
2450
- const str = id.toString();
2451
- return str.length > 8 ? `${str.slice(0, 8)}...` : str;
2452
- };
2453
- const filteredTransactions = transactionsList.filter((transaction) => {
2454
- const matchesSearch = searchTerm ? transaction.id?.toString().toLowerCase().includes(searchTerm.toLowerCase()) || transaction.description?.toLowerCase().includes(searchTerm.toLowerCase()) || transaction.type?.toLowerCase().includes(searchTerm.toLowerCase()) : true;
2455
- const matchesType = typeFilter !== "all" ? transaction.type?.toLowerCase() === typeFilter.toLowerCase() : true;
2456
- return matchesSearch && matchesType;
2457
- }).map((transaction) => ({
2458
- ...transaction,
2459
- isDeposit: transaction.type?.toLowerCase() === "deposit" || transaction.type?.toLowerCase() === "credit",
2460
- formattedDate: formatDate(transaction.created_at || transaction.timestamp),
2461
- relativeTime: getRelativeTime(transaction.created_at || transaction.timestamp),
2462
- truncatedRef: truncateId(transaction.reference || transaction.payment_id)
2463
- }));
2464
- if (isLoadingTransactions) {
2465
- return /* @__PURE__ */ jsxs(Card, { children: [
2466
- /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center gap-2", children: [
2467
- /* @__PURE__ */ jsx(History, { className: "h-5 w-5" }),
2468
- "Transaction History"
2469
- ] }) }),
2470
- /* @__PURE__ */ jsx(CardContent, { className: "space-y-3", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-4 border rounded-sm", children: [
2471
- /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
2472
- /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-32" }),
2473
- /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-24" })
2474
- ] }),
2475
- /* @__PURE__ */ jsx(Skeleton, { className: "h-6 w-16" })
2476
- ] }, i)) })
2477
- ] });
2478
- }
2479
- return /* @__PURE__ */ jsxs(Card, { children: [
2480
- /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center justify-between", children: [
2481
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2482
- /* @__PURE__ */ jsx(History, { className: "h-5 w-5" }),
2483
- "Transaction History"
2484
- ] }),
2485
- /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: refreshTransactions, disabled: isLoadingTransactions, children: [
2486
- /* @__PURE__ */ jsx(RefreshCw, { className: `h-4 w-4 mr-2 ${isLoadingTransactions ? "animate-spin" : ""}` }),
2487
- "Refresh"
2488
- ] })
2489
- ] }) }),
2490
- /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
2491
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row gap-4", children: [
2492
- /* @__PURE__ */ jsxs("div", { className: "relative flex-1", children: [
2493
- /* @__PURE__ */ jsx(Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
2494
- /* @__PURE__ */ jsx(
2495
- Input,
2496
- {
2497
- placeholder: "Search by ID, description, or type...",
2498
- value: searchTerm,
2499
- onChange: (e) => handleSearch(e.target.value),
2500
- className: "pl-10"
2501
- }
2502
- )
2503
- ] }),
2504
- /* @__PURE__ */ jsxs(Select, { value: typeFilter, onValueChange: handleTypeFilter, children: [
2505
- /* @__PURE__ */ jsxs(SelectTrigger, { className: "w-full sm:w-48", children: [
2506
- /* @__PURE__ */ jsx(Filter, { className: "h-4 w-4 mr-2" }),
2507
- /* @__PURE__ */ jsx(SelectValue, { placeholder: "Filter by type" })
2508
- ] }),
2509
- /* @__PURE__ */ jsxs(SelectContent, { children: [
2510
- /* @__PURE__ */ jsx(SelectItem, { value: "all", children: "All Types" }),
2511
- /* @__PURE__ */ jsx(SelectItem, { value: "deposit", children: "Deposits" }),
2512
- /* @__PURE__ */ jsx(SelectItem, { value: "withdrawal", children: "Withdrawals" })
2513
- ] })
2514
- ] })
2515
- ] }),
2516
- filteredTransactions.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-12", children: [
2517
- /* @__PURE__ */ jsx("div", { className: "w-16 h-16 mx-auto mb-4 bg-muted rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsx(History, { className: "w-8 h-8 text-muted-foreground" }) }),
2518
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: "No Transactions Found" }),
2519
- /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: searchTerm || typeFilter !== "all" ? "No transactions match your current filters" : "You don't have any transactions yet" })
2520
- ] }) : /* @__PURE__ */ jsx("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxs(Table, { children: [
2521
- /* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
2522
- /* @__PURE__ */ jsx(TableHead, { children: "Date & Time" }),
2523
- /* @__PURE__ */ jsx(TableHead, { children: "Type" }),
2524
- /* @__PURE__ */ jsx(TableHead, { children: "Amount" }),
2525
- /* @__PURE__ */ jsx(TableHead, { children: "Balance After" }),
2526
- /* @__PURE__ */ jsx(TableHead, { children: "Description" }),
2527
- /* @__PURE__ */ jsx(TableHead, { children: "Reference" })
2528
- ] }) }),
2529
- /* @__PURE__ */ jsx(TableBody, { children: filteredTransactions.map((transaction, index) => /* @__PURE__ */ jsxs(TableRow, { children: [
2530
- /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs("div", { children: [
2531
- /* @__PURE__ */ jsx("div", { className: "font-medium", children: transaction.formattedDate }),
2532
- /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: transaction.relativeTime })
2533
- ] }) }),
2534
- /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2535
- getTypeIcon(transaction.type),
2536
- /* @__PURE__ */ jsx(Badge, { variant: getTypeVariant(transaction.type), children: transaction.type || "Unknown" })
2537
- ] }) }),
2538
- /* @__PURE__ */ jsx(TableCell, { className: "font-mono font-semibold", children: /* @__PURE__ */ jsxs("span", { className: transaction.isDeposit ? "text-green-600" : "text-red-600", children: [
2539
- transaction.isDeposit ? "+" : "-",
2540
- formatCurrency(Math.abs(transaction.amount || transaction.amount_usd || 0))
2541
- ] }) }),
2542
- /* @__PURE__ */ jsx(TableCell, { className: "font-mono", children: formatCurrency(transaction.balance_after || 0) }),
2543
- /* @__PURE__ */ jsx(TableCell, { className: "text-sm", children: transaction.description || transaction.note || "No description" }),
2544
- /* @__PURE__ */ jsx(TableCell, { className: "font-mono text-sm text-muted-foreground", children: transaction.truncatedRef })
2545
- ] }, transaction.id || index)) })
2546
- ] }) })
2547
- ] })
2548
- ] });
2549
- };
2550
- var TransactionsView = () => {
2551
- return /* @__PURE__ */ jsx("div", { className: "space-y-6", children: /* @__PURE__ */ jsx(TransactionsList, {}) });
2552
- };
2553
- var PaymentsLayout = () => {
2554
- return /* @__PURE__ */ jsx(RootPaymentsProvider, { children: /* @__PURE__ */ jsxs("div", { className: "h-full p-6 space-y-6", children: [
2555
- /* @__PURE__ */ jsxs("div", { children: [
2556
- /* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold tracking-tight", children: "Payments" }),
2557
- /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "Manage your payments, balance, and transaction history" })
2558
- ] }),
2559
- /* @__PURE__ */ jsxs(Tabs, { defaultValue: "overview", className: "space-y-6", children: [
2560
- /* @__PURE__ */ jsxs(TabsList, { className: "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground", children: [
2561
- /* @__PURE__ */ jsxs(TabsTrigger, { value: "overview", className: "inline-flex items-center gap-2 px-3 py-1.5", children: [
2562
- /* @__PURE__ */ jsx(Wallet, { className: "h-4 w-4" }),
2563
- /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Overview" })
2564
- ] }),
2565
- /* @__PURE__ */ jsxs(TabsTrigger, { value: "payments", className: "inline-flex items-center gap-2 px-3 py-1.5", children: [
2566
- /* @__PURE__ */ jsx(CreditCard, { className: "h-4 w-4" }),
2567
- /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Payments" })
2568
- ] }),
2569
- /* @__PURE__ */ jsxs(TabsTrigger, { value: "transactions", className: "inline-flex items-center gap-2 px-3 py-1.5", children: [
2570
- /* @__PURE__ */ jsx(History, { className: "h-4 w-4" }),
2571
- /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Transactions" })
2572
- ] })
2573
- ] }),
2574
- /* @__PURE__ */ jsx(TabsContent, { value: "overview", className: "space-y-6", children: /* @__PURE__ */ jsx(OverviewProvider, { children: /* @__PURE__ */ jsxs(PaymentsProvider, { children: [
2575
- /* @__PURE__ */ jsx(OverviewView, {}),
2576
- /* @__PURE__ */ jsx(CreatePaymentDialog, {})
2577
- ] }) }) }),
2578
- /* @__PURE__ */ jsx(TabsContent, { value: "payments", className: "space-y-6", children: /* @__PURE__ */ jsxs(PaymentsProvider, { children: [
2579
- /* @__PURE__ */ jsx(PaymentsView, {}),
2580
- /* @__PURE__ */ jsx(CreatePaymentDialog, {})
2581
- ] }) }),
2582
- /* @__PURE__ */ jsx(TabsContent, { value: "transactions", className: "space-y-6", children: /* @__PURE__ */ jsx(OverviewProvider, { children: /* @__PURE__ */ jsx(TransactionsView, {}) }) })
2583
- ] }),
2584
- /* @__PURE__ */ jsx(PaymentDetailsDialog, {})
2585
2489
  ] }) });
2586
- };
2490
+ }
2491
+ var ResponsiveSheetContext = React2.createContext({ isMobile: false });
2492
+ function ResponsiveSheet4({ open, onOpenChange, children }) {
2493
+ const isMobile = useIsMobile();
2494
+ if (isMobile) {
2495
+ return /* @__PURE__ */ jsx(ResponsiveSheetContext.Provider, { value: { isMobile: true }, children: /* @__PURE__ */ jsx(Drawer, { open, onOpenChange, children }) });
2496
+ }
2497
+ return /* @__PURE__ */ jsx(ResponsiveSheetContext.Provider, { value: { isMobile: false }, children: /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children }) });
2498
+ }
2499
+ function ResponsiveSheetContent4({ children, className }) {
2500
+ const { isMobile } = React2.useContext(ResponsiveSheetContext);
2501
+ if (isMobile) {
2502
+ return /* @__PURE__ */ jsx(DrawerContent, { className, children });
2503
+ }
2504
+ return /* @__PURE__ */ jsx(DialogContent, { className, children });
2505
+ }
2506
+ function ResponsiveSheetHeader4({ children, className }) {
2507
+ const { isMobile } = React2.useContext(ResponsiveSheetContext);
2508
+ if (isMobile) {
2509
+ return /* @__PURE__ */ jsx(DrawerHeader, { className, children });
2510
+ }
2511
+ return /* @__PURE__ */ jsx(DialogHeader, { className, children });
2512
+ }
2513
+ function ResponsiveSheetTitle4({ children, className }) {
2514
+ const { isMobile } = React2.useContext(ResponsiveSheetContext);
2515
+ if (isMobile) {
2516
+ return /* @__PURE__ */ jsx(DrawerTitle, { className, children });
2517
+ }
2518
+ return /* @__PURE__ */ jsx(DialogTitle, { className, children });
2519
+ }
2520
+ function ResponsiveSheetDescription4({ children, className }) {
2521
+ const { isMobile } = React2.useContext(ResponsiveSheetContext);
2522
+ if (isMobile) {
2523
+ return /* @__PURE__ */ jsx(DrawerDescription, { className, children });
2524
+ }
2525
+ return /* @__PURE__ */ jsx(DialogDescription, { className, children });
2526
+ }
2527
+ function ResponsiveSheetFooter({ children, className }) {
2528
+ const { isMobile } = React2.useContext(ResponsiveSheetContext);
2529
+ if (isMobile) {
2530
+ return /* @__PURE__ */ jsx(DrawerFooter, { className, children });
2531
+ }
2532
+ return /* @__PURE__ */ jsx(DialogFooter, { className, children });
2533
+ }
2587
2534
 
2588
2535
  // package.json
2589
2536
  var package_default = {
2590
2537
  name: "@djangocfg/ext-payments",
2591
- version: "1.0.13",
2538
+ version: "1.0.17",
2592
2539
  description: "Payments system extension for DjangoCFG",
2593
2540
  keywords: [
2594
2541
  "django",
@@ -2625,11 +2572,6 @@ var package_default = {
2625
2572
  import: "./dist/index.js",
2626
2573
  require: "./dist/index.cjs"
2627
2574
  },
2628
- "./hooks": {
2629
- types: "./dist/hooks.d.ts",
2630
- import: "./dist/hooks.js",
2631
- require: "./dist/hooks.cjs"
2632
- },
2633
2575
  "./config": {
2634
2576
  types: "./dist/config.d.ts",
2635
2577
  import: "./dist/config.js",
@@ -2657,8 +2599,10 @@ var package_default = {
2657
2599
  "p-retry": "^7.0.0",
2658
2600
  react: "^19",
2659
2601
  swr: "^2.3.7",
2660
- zod: "^4.1.13",
2661
- moment: "^2.30.1"
2602
+ zod: "^4.3.4",
2603
+ moment: "^2.30.1",
2604
+ "react-hook-form": "^7.69.0",
2605
+ "@hookform/resolvers": "^5.2.2"
2662
2606
  },
2663
2607
  devDependencies: {
2664
2608
  "@djangocfg/api": "workspace:*",
@@ -2731,4 +2675,4 @@ export default function CryptoCheckout() {
2731
2675
  ]
2732
2676
  });
2733
2677
 
2734
- export { API, APIClient, APIError, APILogger, BalanceSchema, CookieStorageAdapter, CurrencySchema, DEFAULT_RETRY_CONFIG, enums_exports as Enums, models_exports as ExtPaymentsPaymentsTypes, FetchAdapter, fetchers_exports as Fetchers, LocalStorageAdapter, MemoryStorageAdapter, NetworkError, PAYMENT_EVENTS, PaginatedPaymentListListSchema, PaymentDetailSchema, PaymentListSchema, PaymentsLayout, REFRESH_TOKEN_KEY, schemas_exports as Schemas, TOKEN_KEY, TransactionSchema, apiPayments, clearAPITokens, closePaymentsDialog, configureAPI, createPaymentsPaymentsConfirmCreate, createPaymentsPaymentsCreateCreate, dispatchValidationError, extensionConfig, formatZodError, getAPIInstance, getPaymentsBalanceRetrieve, getPaymentsCurrenciesList, getPaymentsPaymentsList, getPaymentsPaymentsRetrieve, getPaymentsPaymentsStatusRetrieve, getPaymentsTransactionsList, isAPIConfigured, onValidationError, openCreatePaymentDialog, openPaymentDetailsDialog, reconfigureAPI, resetAPI, shouldRetry, withRetry };
2678
+ export { API, APIClient, APIError, APILogger, ActivityItem, ActivityList, AddFundsSheet, BalanceHero, BalanceSchema, CookieStorageAdapter, CurrencySchema, DEFAULT_RETRY_CONFIG, enums_exports as Enums, models_exports as ExtPaymentsPaymentsTypes, FetchAdapter, fetchers_exports as Fetchers, LocalStorageAdapter, MemoryStorageAdapter, NetworkError, PaginatedPaymentListListSchema, PaginatedWithdrawalListListSchema, PaymentCreateRequestSchema, PaymentDetailSchema, PaymentListSchema, PaymentSheet, REFRESH_TOKEN_KEY, ResponsiveSheet4 as ResponsiveSheet, ResponsiveSheetContent4 as ResponsiveSheetContent, ResponsiveSheetDescription4 as ResponsiveSheetDescription, ResponsiveSheetFooter, ResponsiveSheetHeader4 as ResponsiveSheetHeader, ResponsiveSheetTitle4 as ResponsiveSheetTitle, schemas_exports as Schemas, TOKEN_KEY, TransactionSchema, WithdrawSheet, WithdrawalCreateRequestSchema, WithdrawalDetailSchema, WithdrawalListSchema, apiPayments, clearAPITokens, configureAPI, createPaymentsPaymentsConfirmCreate, createPaymentsPaymentsCreateCreate, createPaymentsWithdrawalsCancelCreate, createPaymentsWithdrawalsCreateCreate, dispatchValidationError, extensionConfig, formatZodError, getAPIInstance, getPaymentsBalanceRetrieve, getPaymentsCurrenciesList, getPaymentsPaymentsList, getPaymentsPaymentsRetrieve, getPaymentsPaymentsStatusRetrieve, getPaymentsTransactionsList, getPaymentsWithdrawalsList, getPaymentsWithdrawalsRetrieve, isAPIConfigured, onValidationError, reconfigureAPI, resetAPI, shouldRetry, withRetry };