@djangocfg/ext-payments 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,2735 @@
1
+ 'use strict';
2
+
3
+ var consola = require('consola');
4
+ var pRetry = require('p-retry');
5
+ var zod = require('zod');
6
+ var api = require('@djangocfg/ext-base/api');
7
+ var react = require('react');
8
+ var useSWR = require('swr');
9
+ var jsxRuntime = require('react/jsx-runtime');
10
+ var uiNextjs = require('@djangocfg/ui-nextjs');
11
+ var lucideReact = require('lucide-react');
12
+ var reactHookForm = require('react-hook-form');
13
+ var zod$1 = require('@hookform/resolvers/zod');
14
+ var extBase = require('@djangocfg/ext-base');
15
+
16
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
17
+
18
+ var pRetry__default = /*#__PURE__*/_interopDefault(pRetry);
19
+ var useSWR__default = /*#__PURE__*/_interopDefault(useSWR);
20
+
21
+ var __defProp = Object.defineProperty;
22
+ var __export = (target, all) => {
23
+ for (var name in all)
24
+ __defProp(target, name, { get: all[name], enumerable: true });
25
+ };
26
+
27
+ // src/api/generated/ext_payments/ext_payments__payments/client.ts
28
+ var ExtPaymentsPayments = class {
29
+ client;
30
+ constructor(client) {
31
+ this.client = client;
32
+ }
33
+ /**
34
+ * Get user balance
35
+ *
36
+ * Get current user balance and transaction statistics
37
+ */
38
+ async balanceRetrieve() {
39
+ const response = await this.client.request("GET", "/cfg/payments/balance/");
40
+ return response;
41
+ }
42
+ /**
43
+ * Get available currencies
44
+ *
45
+ * Returns list of available currencies with token+network info
46
+ */
47
+ async currenciesList() {
48
+ const response = await this.client.request("GET", "/cfg/payments/currencies/");
49
+ return response;
50
+ }
51
+ /**
52
+ * ViewSet for payment operations. Endpoints: - GET /payments/ - List
53
+ * user's payments - GET /payments/{id}/ - Get payment details - POST
54
+ * /payments/create/ - Create new payment - GET /payments/{id}/status/ -
55
+ * Check payment status - POST /payments/{id}/confirm/ - Confirm payment
56
+ */
57
+ async paymentsList(...args) {
58
+ const isParamsObject = args.length === 1 && typeof args[0] === "object" && args[0] !== null && !Array.isArray(args[0]);
59
+ let params;
60
+ if (isParamsObject) {
61
+ params = args[0];
62
+ } else {
63
+ params = { page: args[0], page_size: args[1] };
64
+ }
65
+ const response = await this.client.request("GET", "/cfg/payments/payments/", { params });
66
+ return response;
67
+ }
68
+ /**
69
+ * ViewSet for payment operations. Endpoints: - GET /payments/ - List
70
+ * user's payments - GET /payments/{id}/ - Get payment details - POST
71
+ * /payments/create/ - Create new payment - GET /payments/{id}/status/ -
72
+ * Check payment status - POST /payments/{id}/confirm/ - Confirm payment
73
+ */
74
+ async paymentsRetrieve(id) {
75
+ const response = await this.client.request("GET", `/cfg/payments/payments/${id}/`);
76
+ return response;
77
+ }
78
+ /**
79
+ * POST /api/v1/payments/{id}/confirm/ Confirm payment (user clicked "I
80
+ * have paid"). Checks status with provider and creates transaction if
81
+ * completed.
82
+ */
83
+ async paymentsConfirmCreate(id) {
84
+ const response = await this.client.request("POST", `/cfg/payments/payments/${id}/confirm/`);
85
+ return response;
86
+ }
87
+ /**
88
+ * GET /api/v1/payments/{id}/status/?refresh=true Check payment status
89
+ * (with optional refresh from provider). Query params: - refresh: boolean
90
+ * (default: false) - Force refresh from provider
91
+ */
92
+ async paymentsStatusRetrieve(id) {
93
+ const response = await this.client.request("GET", `/cfg/payments/payments/${id}/status/`);
94
+ return response.results || response;
95
+ }
96
+ /**
97
+ * POST /api/v1/payments/create/ Create new payment. Request body: {
98
+ * "amount_usd": "100.00", "currency_code": "USDTTRC20", "description":
99
+ * "Optional description" }
100
+ */
101
+ async paymentsCreateCreate() {
102
+ const response = await this.client.request("POST", "/cfg/payments/payments/create/");
103
+ return response;
104
+ }
105
+ /**
106
+ * Get user transactions
107
+ *
108
+ * Get user transactions with pagination and filtering
109
+ */
110
+ async transactionsList(...args) {
111
+ const isParamsObject = args.length === 1 && typeof args[0] === "object" && args[0] !== null && !Array.isArray(args[0]);
112
+ let params;
113
+ if (isParamsObject) {
114
+ params = args[0];
115
+ } else {
116
+ params = { limit: args[0], offset: args[1], type: args[2] };
117
+ }
118
+ const response = await this.client.request("GET", "/cfg/payments/transactions/", { params });
119
+ return response;
120
+ }
121
+ };
122
+
123
+ // src/api/generated/ext_payments/ext_payments__payments/models.ts
124
+ var models_exports = {};
125
+
126
+ // src/api/generated/ext_payments/http.ts
127
+ var FetchAdapter = class {
128
+ async request(request) {
129
+ const { method, url, headers, body, params, formData } = request;
130
+ let finalUrl = url;
131
+ if (params) {
132
+ const searchParams = new URLSearchParams();
133
+ Object.entries(params).forEach(([key, value]) => {
134
+ if (value !== null && value !== void 0) {
135
+ searchParams.append(key, String(value));
136
+ }
137
+ });
138
+ const queryString = searchParams.toString();
139
+ if (queryString) {
140
+ finalUrl = url.includes("?") ? `${url}&${queryString}` : `${url}?${queryString}`;
141
+ }
142
+ }
143
+ const finalHeaders = { ...headers };
144
+ let requestBody;
145
+ if (formData) {
146
+ requestBody = formData;
147
+ } else if (body) {
148
+ finalHeaders["Content-Type"] = "application/json";
149
+ requestBody = JSON.stringify(body);
150
+ }
151
+ const response = await fetch(finalUrl, {
152
+ method,
153
+ headers: finalHeaders,
154
+ body: requestBody,
155
+ credentials: "include"
156
+ // Include Django session cookies
157
+ });
158
+ let data = null;
159
+ const contentType = response.headers.get("content-type");
160
+ if (response.status !== 204 && contentType?.includes("application/json")) {
161
+ data = await response.json();
162
+ } else if (response.status !== 204) {
163
+ data = await response.text();
164
+ }
165
+ const responseHeaders = {};
166
+ response.headers.forEach((value, key) => {
167
+ responseHeaders[key] = value;
168
+ });
169
+ return {
170
+ data,
171
+ status: response.status,
172
+ statusText: response.statusText,
173
+ headers: responseHeaders
174
+ };
175
+ }
176
+ };
177
+
178
+ // src/api/generated/ext_payments/errors.ts
179
+ var APIError = class extends Error {
180
+ constructor(statusCode, statusText, response, url, message) {
181
+ super(message || `HTTP ${statusCode}: ${statusText}`);
182
+ this.statusCode = statusCode;
183
+ this.statusText = statusText;
184
+ this.response = response;
185
+ this.url = url;
186
+ this.name = "APIError";
187
+ }
188
+ /**
189
+ * Get error details from response.
190
+ * DRF typically returns: { "detail": "Error message" } or { "field": ["error1", "error2"] }
191
+ */
192
+ get details() {
193
+ if (typeof this.response === "object" && this.response !== null) {
194
+ return this.response;
195
+ }
196
+ return null;
197
+ }
198
+ /**
199
+ * Get field-specific validation errors from DRF.
200
+ * Returns: { "field_name": ["error1", "error2"], ... }
201
+ */
202
+ get fieldErrors() {
203
+ const details = this.details;
204
+ if (!details) return null;
205
+ const fieldErrors = {};
206
+ for (const [key, value] of Object.entries(details)) {
207
+ if (Array.isArray(value)) {
208
+ fieldErrors[key] = value;
209
+ }
210
+ }
211
+ return Object.keys(fieldErrors).length > 0 ? fieldErrors : null;
212
+ }
213
+ /**
214
+ * Get single error message from DRF.
215
+ * Checks for "detail", "message", or first field error.
216
+ */
217
+ get errorMessage() {
218
+ const details = this.details;
219
+ if (!details) return this.message;
220
+ if (details.detail) {
221
+ return Array.isArray(details.detail) ? details.detail.join(", ") : String(details.detail);
222
+ }
223
+ if (details.message) {
224
+ return String(details.message);
225
+ }
226
+ const fieldErrors = this.fieldErrors;
227
+ if (fieldErrors) {
228
+ const firstField = Object.keys(fieldErrors)[0];
229
+ if (firstField) {
230
+ return `${firstField}: ${fieldErrors[firstField]?.join(", ")}`;
231
+ }
232
+ }
233
+ return this.message;
234
+ }
235
+ // Helper methods for common HTTP status codes
236
+ get isValidationError() {
237
+ return this.statusCode === 400;
238
+ }
239
+ get isAuthError() {
240
+ return this.statusCode === 401;
241
+ }
242
+ get isPermissionError() {
243
+ return this.statusCode === 403;
244
+ }
245
+ get isNotFoundError() {
246
+ return this.statusCode === 404;
247
+ }
248
+ get isServerError() {
249
+ return this.statusCode >= 500 && this.statusCode < 600;
250
+ }
251
+ };
252
+ var NetworkError = class extends Error {
253
+ constructor(message, url, originalError) {
254
+ super(message);
255
+ this.url = url;
256
+ this.originalError = originalError;
257
+ this.name = "NetworkError";
258
+ }
259
+ };
260
+ var DEFAULT_CONFIG = {
261
+ enabled: process.env.NODE_ENV !== "production",
262
+ logRequests: true,
263
+ logResponses: true,
264
+ logErrors: true,
265
+ logBodies: true,
266
+ logHeaders: false
267
+ };
268
+ var SENSITIVE_HEADERS = [
269
+ "authorization",
270
+ "cookie",
271
+ "set-cookie",
272
+ "x-api-key",
273
+ "x-csrf-token"
274
+ ];
275
+ var APILogger = class {
276
+ config;
277
+ consola;
278
+ constructor(config = {}) {
279
+ this.config = { ...DEFAULT_CONFIG, ...config };
280
+ this.consola = config.consola || consola.createConsola({
281
+ level: this.config.enabled ? 4 : 0
282
+ });
283
+ }
284
+ /**
285
+ * Enable logging
286
+ */
287
+ enable() {
288
+ this.config.enabled = true;
289
+ }
290
+ /**
291
+ * Disable logging
292
+ */
293
+ disable() {
294
+ this.config.enabled = false;
295
+ }
296
+ /**
297
+ * Update configuration
298
+ */
299
+ setConfig(config) {
300
+ this.config = { ...this.config, ...config };
301
+ }
302
+ /**
303
+ * Filter sensitive headers
304
+ */
305
+ filterHeaders(headers) {
306
+ if (!headers) return {};
307
+ const filtered = {};
308
+ Object.keys(headers).forEach((key) => {
309
+ const lowerKey = key.toLowerCase();
310
+ if (SENSITIVE_HEADERS.includes(lowerKey)) {
311
+ filtered[key] = "***";
312
+ } else {
313
+ filtered[key] = headers[key] || "";
314
+ }
315
+ });
316
+ return filtered;
317
+ }
318
+ /**
319
+ * Log request
320
+ */
321
+ logRequest(request) {
322
+ if (!this.config.enabled || !this.config.logRequests) return;
323
+ const { method, url, headers, body } = request;
324
+ this.consola.start(`${method} ${url}`);
325
+ if (this.config.logHeaders && headers) {
326
+ this.consola.debug("Headers:", this.filterHeaders(headers));
327
+ }
328
+ if (this.config.logBodies && body) {
329
+ this.consola.debug("Body:", body);
330
+ }
331
+ }
332
+ /**
333
+ * Log response
334
+ */
335
+ logResponse(request, response) {
336
+ if (!this.config.enabled || !this.config.logResponses) return;
337
+ const { method, url } = request;
338
+ const { status, statusText, data, duration } = response;
339
+ this.consola.success(
340
+ `${method} ${url} ${status} ${statusText} (${duration}ms)`
341
+ );
342
+ if (this.config.logBodies && data) {
343
+ this.consola.debug("Response:", data);
344
+ }
345
+ }
346
+ /**
347
+ * Log error
348
+ */
349
+ logError(request, error) {
350
+ if (!this.config.enabled || !this.config.logErrors) return;
351
+ const { method, url } = request;
352
+ const { message, statusCode, fieldErrors, duration } = error;
353
+ this.consola.error(
354
+ `${method} ${url} ${statusCode || "Network"} Error (${duration}ms)`
355
+ );
356
+ this.consola.error("Message:", message);
357
+ if (fieldErrors && Object.keys(fieldErrors).length > 0) {
358
+ this.consola.error("Field Errors:");
359
+ Object.entries(fieldErrors).forEach(([field, errors]) => {
360
+ errors.forEach((err) => {
361
+ this.consola.error(` \u2022 ${field}: ${err}`);
362
+ });
363
+ });
364
+ }
365
+ }
366
+ /**
367
+ * Log general info
368
+ */
369
+ info(message, ...args) {
370
+ if (!this.config.enabled) return;
371
+ this.consola.info(message, ...args);
372
+ }
373
+ /**
374
+ * Log warning
375
+ */
376
+ warn(message, ...args) {
377
+ if (!this.config.enabled) return;
378
+ this.consola.warn(message, ...args);
379
+ }
380
+ /**
381
+ * Log error
382
+ */
383
+ error(message, ...args) {
384
+ if (!this.config.enabled) return;
385
+ this.consola.error(message, ...args);
386
+ }
387
+ /**
388
+ * Log debug
389
+ */
390
+ debug(message, ...args) {
391
+ if (!this.config.enabled) return;
392
+ this.consola.debug(message, ...args);
393
+ }
394
+ /**
395
+ * Log success
396
+ */
397
+ success(message, ...args) {
398
+ if (!this.config.enabled) return;
399
+ this.consola.success(message, ...args);
400
+ }
401
+ /**
402
+ * Create a sub-logger with prefix
403
+ */
404
+ withTag(tag) {
405
+ return this.consola.withTag(tag);
406
+ }
407
+ };
408
+ new APILogger();
409
+ var DEFAULT_RETRY_CONFIG = {
410
+ retries: 3,
411
+ factor: 2,
412
+ minTimeout: 1e3,
413
+ maxTimeout: 6e4,
414
+ randomize: true,
415
+ onFailedAttempt: () => {
416
+ }
417
+ };
418
+ function shouldRetry(error) {
419
+ if (error instanceof NetworkError) {
420
+ return true;
421
+ }
422
+ if (error instanceof APIError) {
423
+ const status = error.statusCode;
424
+ if (status >= 500 && status < 600) {
425
+ return true;
426
+ }
427
+ if (status === 429) {
428
+ return true;
429
+ }
430
+ return false;
431
+ }
432
+ return true;
433
+ }
434
+ async function withRetry(fn, config) {
435
+ const finalConfig = { ...DEFAULT_RETRY_CONFIG, ...config };
436
+ return pRetry__default.default(
437
+ async () => {
438
+ try {
439
+ return await fn();
440
+ } catch (error) {
441
+ if (!shouldRetry(error)) {
442
+ throw new pRetry.AbortError(error);
443
+ }
444
+ throw error;
445
+ }
446
+ },
447
+ {
448
+ retries: finalConfig.retries,
449
+ factor: finalConfig.factor,
450
+ minTimeout: finalConfig.minTimeout,
451
+ maxTimeout: finalConfig.maxTimeout,
452
+ randomize: finalConfig.randomize,
453
+ onFailedAttempt: finalConfig.onFailedAttempt ? (error) => {
454
+ const pRetryError = error;
455
+ finalConfig.onFailedAttempt({
456
+ error: pRetryError,
457
+ attemptNumber: pRetryError.attemptNumber,
458
+ retriesLeft: pRetryError.retriesLeft
459
+ });
460
+ } : void 0
461
+ }
462
+ );
463
+ }
464
+
465
+ // src/api/generated/ext_payments/client.ts
466
+ var APIClient = class {
467
+ baseUrl;
468
+ httpClient;
469
+ logger = null;
470
+ retryConfig = null;
471
+ // Sub-clients
472
+ ext_payments_payments;
473
+ constructor(baseUrl, options) {
474
+ this.baseUrl = baseUrl.replace(/\/$/, "");
475
+ this.httpClient = options?.httpClient || new FetchAdapter();
476
+ if (options?.loggerConfig !== void 0) {
477
+ this.logger = new APILogger(options.loggerConfig);
478
+ }
479
+ if (options?.retryConfig !== void 0) {
480
+ this.retryConfig = options.retryConfig;
481
+ }
482
+ this.ext_payments_payments = new ExtPaymentsPayments(this);
483
+ }
484
+ /**
485
+ * Get CSRF token from cookies (for SessionAuthentication).
486
+ *
487
+ * Returns null if cookie doesn't exist (JWT-only auth).
488
+ */
489
+ getCsrfToken() {
490
+ const name = "csrftoken";
491
+ const value = `; ${document.cookie}`;
492
+ const parts = value.split(`; ${name}=`);
493
+ if (parts.length === 2) {
494
+ return parts.pop()?.split(";").shift() || null;
495
+ }
496
+ return null;
497
+ }
498
+ /**
499
+ * Make HTTP request with Django CSRF and session handling.
500
+ * Automatically retries on network errors and 5xx server errors.
501
+ */
502
+ async request(method, path, options) {
503
+ if (this.retryConfig) {
504
+ return withRetry(() => this._makeRequest(method, path, options), {
505
+ ...this.retryConfig,
506
+ onFailedAttempt: (info) => {
507
+ if (this.logger) {
508
+ this.logger.warn(
509
+ `Retry attempt ${info.attemptNumber}/${info.retriesLeft + info.attemptNumber} for ${method} ${path}: ${info.error.message}`
510
+ );
511
+ }
512
+ this.retryConfig?.onFailedAttempt?.(info);
513
+ }
514
+ });
515
+ }
516
+ return this._makeRequest(method, path, options);
517
+ }
518
+ /**
519
+ * Internal request method (without retry wrapper).
520
+ * Used by request() method with optional retry logic.
521
+ */
522
+ async _makeRequest(method, path, options) {
523
+ const url = this.baseUrl ? `${this.baseUrl}${path}` : path;
524
+ const startTime = Date.now();
525
+ const headers = {
526
+ ...options?.headers || {}
527
+ };
528
+ if (!options?.formData && !headers["Content-Type"]) {
529
+ headers["Content-Type"] = "application/json";
530
+ }
531
+ if (this.logger) {
532
+ this.logger.logRequest({
533
+ method,
534
+ url,
535
+ headers,
536
+ body: options?.formData || options?.body,
537
+ timestamp: startTime
538
+ });
539
+ }
540
+ try {
541
+ const response = await this.httpClient.request({
542
+ method,
543
+ url,
544
+ headers,
545
+ params: options?.params,
546
+ body: options?.body,
547
+ formData: options?.formData
548
+ });
549
+ const duration = Date.now() - startTime;
550
+ if (response.status >= 400) {
551
+ const error = new APIError(
552
+ response.status,
553
+ response.statusText,
554
+ response.data,
555
+ url
556
+ );
557
+ if (this.logger) {
558
+ this.logger.logError(
559
+ {
560
+ method,
561
+ url,
562
+ headers,
563
+ body: options?.formData || options?.body,
564
+ timestamp: startTime
565
+ },
566
+ {
567
+ message: error.message,
568
+ statusCode: response.status,
569
+ duration,
570
+ timestamp: Date.now()
571
+ }
572
+ );
573
+ }
574
+ throw error;
575
+ }
576
+ if (this.logger) {
577
+ this.logger.logResponse(
578
+ {
579
+ method,
580
+ url,
581
+ headers,
582
+ body: options?.formData || options?.body,
583
+ timestamp: startTime
584
+ },
585
+ {
586
+ status: response.status,
587
+ statusText: response.statusText,
588
+ data: response.data,
589
+ duration,
590
+ timestamp: Date.now()
591
+ }
592
+ );
593
+ }
594
+ return response.data;
595
+ } catch (error) {
596
+ const duration = Date.now() - startTime;
597
+ if (error instanceof APIError) {
598
+ throw error;
599
+ }
600
+ const isCORSError = error instanceof TypeError && (error.message.toLowerCase().includes("cors") || error.message.toLowerCase().includes("failed to fetch") || error.message.toLowerCase().includes("network request failed"));
601
+ if (this.logger) {
602
+ if (isCORSError) {
603
+ this.logger.error(`\u{1F6AB} CORS Error: ${method} ${url}`);
604
+ this.logger.error(` \u2192 ${error instanceof Error ? error.message : String(error)}`);
605
+ this.logger.error(` \u2192 Configure security_domains parameter on the server`);
606
+ } else {
607
+ this.logger.error(`\u26A0\uFE0F Network Error: ${method} ${url}`);
608
+ this.logger.error(` \u2192 ${error instanceof Error ? error.message : String(error)}`);
609
+ }
610
+ }
611
+ if (typeof window !== "undefined") {
612
+ try {
613
+ if (isCORSError) {
614
+ window.dispatchEvent(new CustomEvent("cors-error", {
615
+ detail: {
616
+ url,
617
+ method,
618
+ error: error instanceof Error ? error.message : String(error),
619
+ timestamp: /* @__PURE__ */ new Date()
620
+ },
621
+ bubbles: true,
622
+ cancelable: false
623
+ }));
624
+ } else {
625
+ window.dispatchEvent(new CustomEvent("network-error", {
626
+ detail: {
627
+ url,
628
+ method,
629
+ error: error instanceof Error ? error.message : String(error),
630
+ timestamp: /* @__PURE__ */ new Date()
631
+ },
632
+ bubbles: true,
633
+ cancelable: false
634
+ }));
635
+ }
636
+ } catch (eventError) {
637
+ }
638
+ }
639
+ const networkError = error instanceof Error ? new NetworkError(error.message, url, error) : new NetworkError("Unknown error", url);
640
+ if (this.logger) {
641
+ this.logger.logError(
642
+ {
643
+ method,
644
+ url,
645
+ headers,
646
+ body: options?.formData || options?.body,
647
+ timestamp: startTime
648
+ },
649
+ {
650
+ message: networkError.message,
651
+ duration,
652
+ timestamp: Date.now()
653
+ }
654
+ );
655
+ }
656
+ throw networkError;
657
+ }
658
+ }
659
+ };
660
+
661
+ // src/api/generated/ext_payments/storage.ts
662
+ var LocalStorageAdapter = class {
663
+ logger;
664
+ constructor(logger2) {
665
+ this.logger = logger2;
666
+ }
667
+ getItem(key) {
668
+ try {
669
+ if (typeof window !== "undefined" && window.localStorage) {
670
+ const value = localStorage.getItem(key);
671
+ this.logger?.debug(`LocalStorage.getItem("${key}"): ${value ? "found" : "not found"}`);
672
+ return value;
673
+ }
674
+ this.logger?.warn("LocalStorage not available: window.localStorage is undefined");
675
+ } catch (error) {
676
+ this.logger?.error("LocalStorage.getItem failed:", error);
677
+ }
678
+ return null;
679
+ }
680
+ setItem(key, value) {
681
+ try {
682
+ if (typeof window !== "undefined" && window.localStorage) {
683
+ localStorage.setItem(key, value);
684
+ this.logger?.debug(`LocalStorage.setItem("${key}"): success`);
685
+ } else {
686
+ this.logger?.warn("LocalStorage not available: window.localStorage is undefined");
687
+ }
688
+ } catch (error) {
689
+ this.logger?.error("LocalStorage.setItem failed:", error);
690
+ }
691
+ }
692
+ removeItem(key) {
693
+ try {
694
+ if (typeof window !== "undefined" && window.localStorage) {
695
+ localStorage.removeItem(key);
696
+ this.logger?.debug(`LocalStorage.removeItem("${key}"): success`);
697
+ } else {
698
+ this.logger?.warn("LocalStorage not available: window.localStorage is undefined");
699
+ }
700
+ } catch (error) {
701
+ this.logger?.error("LocalStorage.removeItem failed:", error);
702
+ }
703
+ }
704
+ };
705
+ var CookieStorageAdapter = class {
706
+ logger;
707
+ constructor(logger2) {
708
+ this.logger = logger2;
709
+ }
710
+ getItem(key) {
711
+ try {
712
+ if (typeof document === "undefined") {
713
+ this.logger?.warn("Cookies not available: document is undefined (SSR context?)");
714
+ return null;
715
+ }
716
+ const value = `; ${document.cookie}`;
717
+ const parts = value.split(`; ${key}=`);
718
+ if (parts.length === 2) {
719
+ const result = parts.pop()?.split(";").shift() || null;
720
+ this.logger?.debug(`CookieStorage.getItem("${key}"): ${result ? "found" : "not found"}`);
721
+ return result;
722
+ }
723
+ this.logger?.debug(`CookieStorage.getItem("${key}"): not found`);
724
+ } catch (error) {
725
+ this.logger?.error("CookieStorage.getItem failed:", error);
726
+ }
727
+ return null;
728
+ }
729
+ setItem(key, value) {
730
+ try {
731
+ if (typeof document !== "undefined") {
732
+ document.cookie = `${key}=${value}; path=/; max-age=31536000`;
733
+ this.logger?.debug(`CookieStorage.setItem("${key}"): success`);
734
+ } else {
735
+ this.logger?.warn("Cookies not available: document is undefined (SSR context?)");
736
+ }
737
+ } catch (error) {
738
+ this.logger?.error("CookieStorage.setItem failed:", error);
739
+ }
740
+ }
741
+ removeItem(key) {
742
+ try {
743
+ if (typeof document !== "undefined") {
744
+ document.cookie = `${key}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
745
+ this.logger?.debug(`CookieStorage.removeItem("${key}"): success`);
746
+ } else {
747
+ this.logger?.warn("Cookies not available: document is undefined (SSR context?)");
748
+ }
749
+ } catch (error) {
750
+ this.logger?.error("CookieStorage.removeItem failed:", error);
751
+ }
752
+ }
753
+ };
754
+ var MemoryStorageAdapter = class {
755
+ storage = /* @__PURE__ */ new Map();
756
+ logger;
757
+ constructor(logger2) {
758
+ this.logger = logger2;
759
+ }
760
+ getItem(key) {
761
+ const value = this.storage.get(key) || null;
762
+ this.logger?.debug(`MemoryStorage.getItem("${key}"): ${value ? "found" : "not found"}`);
763
+ return value;
764
+ }
765
+ setItem(key, value) {
766
+ this.storage.set(key, value);
767
+ this.logger?.debug(`MemoryStorage.setItem("${key}"): success`);
768
+ }
769
+ removeItem(key) {
770
+ this.storage.delete(key);
771
+ this.logger?.debug(`MemoryStorage.removeItem("${key}"): success`);
772
+ }
773
+ };
774
+
775
+ // src/api/generated/ext_payments/enums.ts
776
+ var enums_exports = {};
777
+ __export(enums_exports, {
778
+ PaymentDetailStatus: () => PaymentDetailStatus,
779
+ PaymentListStatus: () => PaymentListStatus,
780
+ TransactionTransactionType: () => TransactionTransactionType
781
+ });
782
+ var PaymentDetailStatus = /* @__PURE__ */ ((PaymentDetailStatus2) => {
783
+ PaymentDetailStatus2["PENDING"] = "pending";
784
+ PaymentDetailStatus2["CONFIRMING"] = "confirming";
785
+ PaymentDetailStatus2["CONFIRMED"] = "confirmed";
786
+ PaymentDetailStatus2["COMPLETED"] = "completed";
787
+ PaymentDetailStatus2["PARTIALLY_PAID"] = "partially_paid";
788
+ PaymentDetailStatus2["FAILED"] = "failed";
789
+ PaymentDetailStatus2["EXPIRED"] = "expired";
790
+ PaymentDetailStatus2["CANCELLED"] = "cancelled";
791
+ return PaymentDetailStatus2;
792
+ })(PaymentDetailStatus || {});
793
+ var PaymentListStatus = /* @__PURE__ */ ((PaymentListStatus2) => {
794
+ PaymentListStatus2["PENDING"] = "pending";
795
+ PaymentListStatus2["CONFIRMING"] = "confirming";
796
+ PaymentListStatus2["CONFIRMED"] = "confirmed";
797
+ PaymentListStatus2["COMPLETED"] = "completed";
798
+ PaymentListStatus2["PARTIALLY_PAID"] = "partially_paid";
799
+ PaymentListStatus2["FAILED"] = "failed";
800
+ PaymentListStatus2["EXPIRED"] = "expired";
801
+ PaymentListStatus2["CANCELLED"] = "cancelled";
802
+ return PaymentListStatus2;
803
+ })(PaymentListStatus || {});
804
+ var TransactionTransactionType = /* @__PURE__ */ ((TransactionTransactionType2) => {
805
+ TransactionTransactionType2["DEPOSIT"] = "deposit";
806
+ TransactionTransactionType2["WITHDRAWAL"] = "withdrawal";
807
+ TransactionTransactionType2["PAYMENT"] = "payment";
808
+ TransactionTransactionType2["REFUND"] = "refund";
809
+ TransactionTransactionType2["FEE"] = "fee";
810
+ TransactionTransactionType2["BONUS"] = "bonus";
811
+ TransactionTransactionType2["ADJUSTMENT"] = "adjustment";
812
+ return TransactionTransactionType2;
813
+ })(TransactionTransactionType || {});
814
+
815
+ // src/api/generated/ext_payments/_utils/schemas/index.ts
816
+ var schemas_exports = {};
817
+ __export(schemas_exports, {
818
+ BalanceSchema: () => BalanceSchema,
819
+ CurrencySchema: () => CurrencySchema,
820
+ PaginatedPaymentListListSchema: () => PaginatedPaymentListListSchema,
821
+ PaymentDetailSchema: () => PaymentDetailSchema,
822
+ PaymentListSchema: () => PaymentListSchema,
823
+ TransactionSchema: () => TransactionSchema
824
+ });
825
+ var BalanceSchema = zod.z.object({
826
+ balance_usd: zod.z.string(),
827
+ balance_display: zod.z.string(),
828
+ total_deposited: zod.z.string(),
829
+ total_withdrawn: zod.z.string(),
830
+ last_transaction_at: zod.z.iso.datetime().nullable()
831
+ });
832
+ var CurrencySchema = zod.z.object({
833
+ code: zod.z.string(),
834
+ name: zod.z.string(),
835
+ token: zod.z.string(),
836
+ network: zod.z.string().nullable(),
837
+ display_name: zod.z.string(),
838
+ symbol: zod.z.string(),
839
+ decimal_places: zod.z.int(),
840
+ is_active: zod.z.boolean(),
841
+ min_amount_usd: zod.z.string(),
842
+ sort_order: zod.z.int()
843
+ });
844
+ var PaymentListSchema = zod.z.object({
845
+ id: zod.z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i),
846
+ internal_payment_id: zod.z.string(),
847
+ amount_usd: zod.z.string(),
848
+ currency_code: zod.z.string(),
849
+ currency_token: zod.z.string(),
850
+ status: zod.z.nativeEnum(PaymentListStatus),
851
+ status_display: zod.z.string(),
852
+ created_at: zod.z.iso.datetime(),
853
+ completed_at: zod.z.iso.datetime().nullable()
854
+ });
855
+
856
+ // src/api/generated/ext_payments/_utils/schemas/PaginatedPaymentListList.schema.ts
857
+ var PaginatedPaymentListListSchema = zod.z.object({
858
+ count: zod.z.int(),
859
+ page: zod.z.int(),
860
+ pages: zod.z.int(),
861
+ page_size: zod.z.int(),
862
+ has_next: zod.z.boolean(),
863
+ has_previous: zod.z.boolean(),
864
+ next_page: zod.z.int().nullable().optional(),
865
+ previous_page: zod.z.int().nullable().optional(),
866
+ results: zod.z.array(PaymentListSchema)
867
+ });
868
+ var PaymentDetailSchema = zod.z.object({
869
+ id: zod.z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i),
870
+ internal_payment_id: zod.z.string(),
871
+ amount_usd: zod.z.string(),
872
+ currency_code: zod.z.string(),
873
+ currency_name: zod.z.string(),
874
+ currency_token: zod.z.string(),
875
+ currency_network: zod.z.string(),
876
+ pay_amount: zod.z.string().nullable(),
877
+ actual_amount: zod.z.string().nullable(),
878
+ actual_amount_usd: zod.z.string().nullable(),
879
+ status: zod.z.nativeEnum(PaymentDetailStatus),
880
+ status_display: zod.z.string(),
881
+ pay_address: zod.z.string().nullable(),
882
+ qr_code_url: zod.z.string().nullable(),
883
+ payment_url: zod.z.url().nullable(),
884
+ transaction_hash: zod.z.string().nullable(),
885
+ explorer_link: zod.z.string().nullable(),
886
+ confirmations_count: zod.z.int(),
887
+ expires_at: zod.z.iso.datetime().nullable(),
888
+ completed_at: zod.z.iso.datetime().nullable(),
889
+ created_at: zod.z.iso.datetime(),
890
+ is_completed: zod.z.boolean(),
891
+ is_failed: zod.z.boolean(),
892
+ is_expired: zod.z.boolean(),
893
+ description: zod.z.string()
894
+ });
895
+ var TransactionSchema = zod.z.object({
896
+ id: zod.z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i),
897
+ transaction_type: zod.z.nativeEnum(TransactionTransactionType),
898
+ type_display: zod.z.string(),
899
+ amount_usd: zod.z.string(),
900
+ amount_display: zod.z.string(),
901
+ balance_after: zod.z.string(),
902
+ payment_id: zod.z.string().nullable(),
903
+ description: zod.z.string(),
904
+ created_at: zod.z.iso.datetime()
905
+ });
906
+
907
+ // src/api/generated/ext_payments/validation-events.ts
908
+ function dispatchValidationError(detail) {
909
+ if (typeof window === "undefined") {
910
+ return;
911
+ }
912
+ try {
913
+ const event = new CustomEvent("zod-validation-error", {
914
+ detail,
915
+ bubbles: true,
916
+ cancelable: false
917
+ });
918
+ window.dispatchEvent(event);
919
+ } catch (error) {
920
+ console.warn("Failed to dispatch validation error event:", error);
921
+ }
922
+ }
923
+ function onValidationError(callback) {
924
+ if (typeof window === "undefined") {
925
+ return () => {
926
+ };
927
+ }
928
+ const handler = (event) => {
929
+ if (event instanceof CustomEvent) {
930
+ callback(event.detail);
931
+ }
932
+ };
933
+ window.addEventListener("zod-validation-error", handler);
934
+ return () => {
935
+ window.removeEventListener("zod-validation-error", handler);
936
+ };
937
+ }
938
+ function formatZodError(error) {
939
+ const issues = error.issues.map((issue, index) => {
940
+ const path = issue.path.join(".") || "root";
941
+ const parts = [`${index + 1}. ${path}: ${issue.message}`];
942
+ if ("expected" in issue && issue.expected) {
943
+ parts.push(` Expected: ${issue.expected}`);
944
+ }
945
+ if ("received" in issue && issue.received) {
946
+ parts.push(` Received: ${issue.received}`);
947
+ }
948
+ return parts.join("\n");
949
+ });
950
+ return issues.join("\n");
951
+ }
952
+
953
+ // src/api/generated/ext_payments/_utils/fetchers/index.ts
954
+ var fetchers_exports = {};
955
+ __export(fetchers_exports, {
956
+ createPaymentsPaymentsConfirmCreate: () => createPaymentsPaymentsConfirmCreate,
957
+ createPaymentsPaymentsCreateCreate: () => createPaymentsPaymentsCreateCreate,
958
+ getPaymentsBalanceRetrieve: () => getPaymentsBalanceRetrieve,
959
+ getPaymentsCurrenciesList: () => getPaymentsCurrenciesList,
960
+ getPaymentsPaymentsList: () => getPaymentsPaymentsList,
961
+ getPaymentsPaymentsRetrieve: () => getPaymentsPaymentsRetrieve,
962
+ getPaymentsPaymentsStatusRetrieve: () => getPaymentsPaymentsStatusRetrieve,
963
+ getPaymentsTransactionsList: () => getPaymentsTransactionsList
964
+ });
965
+
966
+ // src/api/generated/ext_payments/api-instance.ts
967
+ var globalAPI = null;
968
+ function getAPIInstance() {
969
+ if (!globalAPI) {
970
+ throw new Error(
971
+ 'API not configured. Call configureAPI() with your base URL before using fetchers or hooks.\n\nExample:\n import { configureAPI } from "./api-instance"\n configureAPI({ baseUrl: "https://api.example.com" })'
972
+ );
973
+ }
974
+ return globalAPI;
975
+ }
976
+ function isAPIConfigured() {
977
+ return globalAPI !== null;
978
+ }
979
+ function configureAPI(config) {
980
+ globalAPI = new API(config.baseUrl, config.options);
981
+ if (config.token) {
982
+ globalAPI.setToken(config.token, config.refreshToken);
983
+ }
984
+ return globalAPI;
985
+ }
986
+ function reconfigureAPI(updates) {
987
+ const instance = getAPIInstance();
988
+ if (updates.baseUrl) {
989
+ instance.setBaseUrl(updates.baseUrl);
990
+ }
991
+ if (updates.token) {
992
+ instance.setToken(updates.token, updates.refreshToken);
993
+ }
994
+ return instance;
995
+ }
996
+ function clearAPITokens() {
997
+ const instance = getAPIInstance();
998
+ instance.clearTokens();
999
+ }
1000
+ function resetAPI() {
1001
+ if (globalAPI) {
1002
+ globalAPI.clearTokens();
1003
+ }
1004
+ globalAPI = null;
1005
+ }
1006
+
1007
+ // src/api/generated/ext_payments/_utils/fetchers/ext_payments__payments.ts
1008
+ async function getPaymentsBalanceRetrieve(client) {
1009
+ const api = client || getAPIInstance();
1010
+ const response = await api.ext_payments_payments.balanceRetrieve();
1011
+ try {
1012
+ return BalanceSchema.parse(response);
1013
+ } catch (error) {
1014
+ consola.consola.error("\u274C Zod Validation Failed");
1015
+ consola.consola.box(`getPaymentsBalanceRetrieve
1016
+ Path: /cfg/payments/balance/
1017
+ Method: GET`);
1018
+ if (error instanceof Error && "issues" in error && Array.isArray(error.issues)) {
1019
+ consola.consola.error("Validation Issues:");
1020
+ error.issues.forEach((issue, index) => {
1021
+ consola.consola.error(` ${index + 1}. ${issue.path.join(".") || "root"}`);
1022
+ consola.consola.error(` \u251C\u2500 Message: ${issue.message}`);
1023
+ if (issue.expected) consola.consola.error(` \u251C\u2500 Expected: ${issue.expected}`);
1024
+ if (issue.received) consola.consola.error(` \u2514\u2500 Received: ${issue.received}`);
1025
+ });
1026
+ }
1027
+ consola.consola.error("Response data:", response);
1028
+ if (typeof window !== "undefined" && error instanceof Error && "issues" in error) {
1029
+ try {
1030
+ const event = new CustomEvent("zod-validation-error", {
1031
+ detail: {
1032
+ operation: "getPaymentsBalanceRetrieve",
1033
+ path: "/cfg/payments/balance/",
1034
+ method: "GET",
1035
+ error,
1036
+ response,
1037
+ timestamp: /* @__PURE__ */ new Date()
1038
+ },
1039
+ bubbles: true,
1040
+ cancelable: false
1041
+ });
1042
+ window.dispatchEvent(event);
1043
+ } catch (eventError) {
1044
+ consola.consola.warn("Failed to dispatch validation error event:", eventError);
1045
+ }
1046
+ }
1047
+ throw error;
1048
+ }
1049
+ }
1050
+ async function getPaymentsCurrenciesList(client) {
1051
+ const api = client || getAPIInstance();
1052
+ const response = await api.ext_payments_payments.currenciesList();
1053
+ return response;
1054
+ }
1055
+ async function getPaymentsPaymentsList(params, client) {
1056
+ const api = client || getAPIInstance();
1057
+ const response = await api.ext_payments_payments.paymentsList(params?.page, params?.page_size);
1058
+ try {
1059
+ return PaginatedPaymentListListSchema.parse(response);
1060
+ } catch (error) {
1061
+ consola.consola.error("\u274C Zod Validation Failed");
1062
+ consola.consola.box(`getPaymentsPaymentsList
1063
+ Path: /cfg/payments/payments/
1064
+ Method: GET`);
1065
+ if (error instanceof Error && "issues" in error && Array.isArray(error.issues)) {
1066
+ consola.consola.error("Validation Issues:");
1067
+ error.issues.forEach((issue, index) => {
1068
+ consola.consola.error(` ${index + 1}. ${issue.path.join(".") || "root"}`);
1069
+ consola.consola.error(` \u251C\u2500 Message: ${issue.message}`);
1070
+ if (issue.expected) consola.consola.error(` \u251C\u2500 Expected: ${issue.expected}`);
1071
+ if (issue.received) consola.consola.error(` \u2514\u2500 Received: ${issue.received}`);
1072
+ });
1073
+ }
1074
+ consola.consola.error("Response data:", response);
1075
+ if (typeof window !== "undefined" && error instanceof Error && "issues" in error) {
1076
+ try {
1077
+ const event = new CustomEvent("zod-validation-error", {
1078
+ detail: {
1079
+ operation: "getPaymentsPaymentsList",
1080
+ path: "/cfg/payments/payments/",
1081
+ method: "GET",
1082
+ error,
1083
+ response,
1084
+ timestamp: /* @__PURE__ */ new Date()
1085
+ },
1086
+ bubbles: true,
1087
+ cancelable: false
1088
+ });
1089
+ window.dispatchEvent(event);
1090
+ } catch (eventError) {
1091
+ consola.consola.warn("Failed to dispatch validation error event:", eventError);
1092
+ }
1093
+ }
1094
+ throw error;
1095
+ }
1096
+ }
1097
+ async function getPaymentsPaymentsRetrieve(id, client) {
1098
+ const api = client || getAPIInstance();
1099
+ const response = await api.ext_payments_payments.paymentsRetrieve(id);
1100
+ try {
1101
+ return PaymentDetailSchema.parse(response);
1102
+ } catch (error) {
1103
+ consola.consola.error("\u274C Zod Validation Failed");
1104
+ consola.consola.box(`getPaymentsPaymentsRetrieve
1105
+ Path: /cfg/payments/payments/{id}/
1106
+ Method: GET`);
1107
+ if (error instanceof Error && "issues" in error && Array.isArray(error.issues)) {
1108
+ consola.consola.error("Validation Issues:");
1109
+ error.issues.forEach((issue, index) => {
1110
+ consola.consola.error(` ${index + 1}. ${issue.path.join(".") || "root"}`);
1111
+ consola.consola.error(` \u251C\u2500 Message: ${issue.message}`);
1112
+ if (issue.expected) consola.consola.error(` \u251C\u2500 Expected: ${issue.expected}`);
1113
+ if (issue.received) consola.consola.error(` \u2514\u2500 Received: ${issue.received}`);
1114
+ });
1115
+ }
1116
+ consola.consola.error("Response data:", response);
1117
+ if (typeof window !== "undefined" && error instanceof Error && "issues" in error) {
1118
+ try {
1119
+ const event = new CustomEvent("zod-validation-error", {
1120
+ detail: {
1121
+ operation: "getPaymentsPaymentsRetrieve",
1122
+ path: "/cfg/payments/payments/{id}/",
1123
+ method: "GET",
1124
+ error,
1125
+ response,
1126
+ timestamp: /* @__PURE__ */ new Date()
1127
+ },
1128
+ bubbles: true,
1129
+ cancelable: false
1130
+ });
1131
+ window.dispatchEvent(event);
1132
+ } catch (eventError) {
1133
+ consola.consola.warn("Failed to dispatch validation error event:", eventError);
1134
+ }
1135
+ }
1136
+ throw error;
1137
+ }
1138
+ }
1139
+ async function createPaymentsPaymentsConfirmCreate(id, client) {
1140
+ const api = client || getAPIInstance();
1141
+ const response = await api.ext_payments_payments.paymentsConfirmCreate(id);
1142
+ try {
1143
+ return PaymentListSchema.parse(response);
1144
+ } catch (error) {
1145
+ consola.consola.error("\u274C Zod Validation Failed");
1146
+ consola.consola.box(`createPaymentsPaymentsConfirmCreate
1147
+ Path: /cfg/payments/payments/{id}/confirm/
1148
+ Method: POST`);
1149
+ if (error instanceof Error && "issues" in error && Array.isArray(error.issues)) {
1150
+ consola.consola.error("Validation Issues:");
1151
+ error.issues.forEach((issue, index) => {
1152
+ consola.consola.error(` ${index + 1}. ${issue.path.join(".") || "root"}`);
1153
+ consola.consola.error(` \u251C\u2500 Message: ${issue.message}`);
1154
+ if (issue.expected) consola.consola.error(` \u251C\u2500 Expected: ${issue.expected}`);
1155
+ if (issue.received) consola.consola.error(` \u2514\u2500 Received: ${issue.received}`);
1156
+ });
1157
+ }
1158
+ consola.consola.error("Response data:", response);
1159
+ if (typeof window !== "undefined" && error instanceof Error && "issues" in error) {
1160
+ try {
1161
+ const event = new CustomEvent("zod-validation-error", {
1162
+ detail: {
1163
+ operation: "createPaymentsPaymentsConfirmCreate",
1164
+ path: "/cfg/payments/payments/{id}/confirm/",
1165
+ method: "POST",
1166
+ error,
1167
+ response,
1168
+ timestamp: /* @__PURE__ */ new Date()
1169
+ },
1170
+ bubbles: true,
1171
+ cancelable: false
1172
+ });
1173
+ window.dispatchEvent(event);
1174
+ } catch (eventError) {
1175
+ consola.consola.warn("Failed to dispatch validation error event:", eventError);
1176
+ }
1177
+ }
1178
+ throw error;
1179
+ }
1180
+ }
1181
+ async function getPaymentsPaymentsStatusRetrieve(id, client) {
1182
+ const api = client || getAPIInstance();
1183
+ const response = await api.ext_payments_payments.paymentsStatusRetrieve(id);
1184
+ try {
1185
+ return PaymentListSchema.parse(response);
1186
+ } catch (error) {
1187
+ consola.consola.error("\u274C Zod Validation Failed");
1188
+ consola.consola.box(`getPaymentsPaymentsStatusRetrieve
1189
+ Path: /cfg/payments/payments/{id}/status/
1190
+ Method: GET`);
1191
+ if (error instanceof Error && "issues" in error && Array.isArray(error.issues)) {
1192
+ consola.consola.error("Validation Issues:");
1193
+ error.issues.forEach((issue, index) => {
1194
+ consola.consola.error(` ${index + 1}. ${issue.path.join(".") || "root"}`);
1195
+ consola.consola.error(` \u251C\u2500 Message: ${issue.message}`);
1196
+ if (issue.expected) consola.consola.error(` \u251C\u2500 Expected: ${issue.expected}`);
1197
+ if (issue.received) consola.consola.error(` \u2514\u2500 Received: ${issue.received}`);
1198
+ });
1199
+ }
1200
+ consola.consola.error("Response data:", response);
1201
+ if (typeof window !== "undefined" && error instanceof Error && "issues" in error) {
1202
+ try {
1203
+ const event = new CustomEvent("zod-validation-error", {
1204
+ detail: {
1205
+ operation: "getPaymentsPaymentsStatusRetrieve",
1206
+ path: "/cfg/payments/payments/{id}/status/",
1207
+ method: "GET",
1208
+ error,
1209
+ response,
1210
+ timestamp: /* @__PURE__ */ new Date()
1211
+ },
1212
+ bubbles: true,
1213
+ cancelable: false
1214
+ });
1215
+ window.dispatchEvent(event);
1216
+ } catch (eventError) {
1217
+ consola.consola.warn("Failed to dispatch validation error event:", eventError);
1218
+ }
1219
+ }
1220
+ throw error;
1221
+ }
1222
+ }
1223
+ async function createPaymentsPaymentsCreateCreate(client) {
1224
+ const api = client || getAPIInstance();
1225
+ const response = await api.ext_payments_payments.paymentsCreateCreate();
1226
+ try {
1227
+ return PaymentListSchema.parse(response);
1228
+ } catch (error) {
1229
+ consola.consola.error("\u274C Zod Validation Failed");
1230
+ consola.consola.box(`createPaymentsPaymentsCreateCreate
1231
+ Path: /cfg/payments/payments/create/
1232
+ Method: POST`);
1233
+ if (error instanceof Error && "issues" in error && Array.isArray(error.issues)) {
1234
+ consola.consola.error("Validation Issues:");
1235
+ error.issues.forEach((issue, index) => {
1236
+ consola.consola.error(` ${index + 1}. ${issue.path.join(".") || "root"}`);
1237
+ consola.consola.error(` \u251C\u2500 Message: ${issue.message}`);
1238
+ if (issue.expected) consola.consola.error(` \u251C\u2500 Expected: ${issue.expected}`);
1239
+ if (issue.received) consola.consola.error(` \u2514\u2500 Received: ${issue.received}`);
1240
+ });
1241
+ }
1242
+ consola.consola.error("Response data:", response);
1243
+ if (typeof window !== "undefined" && error instanceof Error && "issues" in error) {
1244
+ try {
1245
+ const event = new CustomEvent("zod-validation-error", {
1246
+ detail: {
1247
+ operation: "createPaymentsPaymentsCreateCreate",
1248
+ path: "/cfg/payments/payments/create/",
1249
+ method: "POST",
1250
+ error,
1251
+ response,
1252
+ timestamp: /* @__PURE__ */ new Date()
1253
+ },
1254
+ bubbles: true,
1255
+ cancelable: false
1256
+ });
1257
+ window.dispatchEvent(event);
1258
+ } catch (eventError) {
1259
+ consola.consola.warn("Failed to dispatch validation error event:", eventError);
1260
+ }
1261
+ }
1262
+ throw error;
1263
+ }
1264
+ }
1265
+ async function getPaymentsTransactionsList(params, client) {
1266
+ const api = client || getAPIInstance();
1267
+ const response = await api.ext_payments_payments.transactionsList(params?.limit, params?.offset, params?.type);
1268
+ return response;
1269
+ }
1270
+
1271
+ // src/api/generated/ext_payments/index.ts
1272
+ var TOKEN_KEY = "auth_token";
1273
+ var REFRESH_TOKEN_KEY = "refresh_token";
1274
+ var API = class {
1275
+ baseUrl;
1276
+ _client;
1277
+ _token = null;
1278
+ _refreshToken = null;
1279
+ storage;
1280
+ options;
1281
+ // Sub-clients
1282
+ ext_payments_payments;
1283
+ constructor(baseUrl, options) {
1284
+ this.baseUrl = baseUrl;
1285
+ this.options = options;
1286
+ const logger2 = options?.loggerConfig ? new APILogger(options.loggerConfig) : void 0;
1287
+ this.storage = options?.storage || new LocalStorageAdapter(logger2);
1288
+ this._loadTokensFromStorage();
1289
+ this._client = new APIClient(this.baseUrl, {
1290
+ retryConfig: this.options?.retryConfig,
1291
+ loggerConfig: this.options?.loggerConfig
1292
+ });
1293
+ this._injectAuthHeader();
1294
+ this.ext_payments_payments = this._client.ext_payments_payments;
1295
+ }
1296
+ _loadTokensFromStorage() {
1297
+ this._token = this.storage.getItem(TOKEN_KEY);
1298
+ this._refreshToken = this.storage.getItem(REFRESH_TOKEN_KEY);
1299
+ }
1300
+ _reinitClients() {
1301
+ this._client = new APIClient(this.baseUrl, {
1302
+ retryConfig: this.options?.retryConfig,
1303
+ loggerConfig: this.options?.loggerConfig
1304
+ });
1305
+ this._injectAuthHeader();
1306
+ this.ext_payments_payments = this._client.ext_payments_payments;
1307
+ }
1308
+ _injectAuthHeader() {
1309
+ const originalRequest = this._client.request.bind(this._client);
1310
+ this._client.request = async (method, path, options) => {
1311
+ const token = this.getToken();
1312
+ const mergedOptions = {
1313
+ ...options,
1314
+ headers: {
1315
+ ...options?.headers || {},
1316
+ ...token ? { "Authorization": `Bearer ${token}` } : {}
1317
+ }
1318
+ };
1319
+ return originalRequest(method, path, mergedOptions);
1320
+ };
1321
+ }
1322
+ /**
1323
+ * Get current JWT token
1324
+ */
1325
+ getToken() {
1326
+ return this.storage.getItem(TOKEN_KEY);
1327
+ }
1328
+ /**
1329
+ * Get current refresh token
1330
+ */
1331
+ getRefreshToken() {
1332
+ return this.storage.getItem(REFRESH_TOKEN_KEY);
1333
+ }
1334
+ /**
1335
+ * Set JWT token and refresh token
1336
+ * @param token - JWT access token
1337
+ * @param refreshToken - JWT refresh token (optional)
1338
+ */
1339
+ setToken(token, refreshToken) {
1340
+ this._token = token;
1341
+ this.storage.setItem(TOKEN_KEY, token);
1342
+ if (refreshToken) {
1343
+ this._refreshToken = refreshToken;
1344
+ this.storage.setItem(REFRESH_TOKEN_KEY, refreshToken);
1345
+ }
1346
+ this._reinitClients();
1347
+ }
1348
+ /**
1349
+ * Clear all tokens
1350
+ */
1351
+ clearTokens() {
1352
+ this._token = null;
1353
+ this._refreshToken = null;
1354
+ this.storage.removeItem(TOKEN_KEY);
1355
+ this.storage.removeItem(REFRESH_TOKEN_KEY);
1356
+ this._reinitClients();
1357
+ }
1358
+ /**
1359
+ * Check if user is authenticated
1360
+ */
1361
+ isAuthenticated() {
1362
+ return !!this.getToken();
1363
+ }
1364
+ /**
1365
+ * Update base URL and reinitialize clients
1366
+ * @param url - New base URL
1367
+ */
1368
+ setBaseUrl(url) {
1369
+ this.baseUrl = url;
1370
+ this._reinitClients();
1371
+ }
1372
+ /**
1373
+ * Get current base URL
1374
+ */
1375
+ getBaseUrl() {
1376
+ return this.baseUrl;
1377
+ }
1378
+ /**
1379
+ * Get OpenAPI schema path
1380
+ * @returns Path to the OpenAPI schema JSON file
1381
+ *
1382
+ * Note: The OpenAPI schema is available in the schema.json file.
1383
+ * You can load it dynamically using:
1384
+ * ```typescript
1385
+ * const schema = await fetch('./schema.json').then(r => r.json());
1386
+ * // or using fs in Node.js:
1387
+ * // const schema = JSON.parse(fs.readFileSync('./schema.json', 'utf-8'));
1388
+ * ```
1389
+ */
1390
+ getSchemaPath() {
1391
+ return "./schema.json";
1392
+ }
1393
+ };
1394
+ var apiPayments = api.createExtensionAPI(API);
1395
+ function usePaymentsBalanceRetrieve(client) {
1396
+ return useSWR__default.default(
1397
+ "cfg-payments-balance",
1398
+ () => getPaymentsBalanceRetrieve(client)
1399
+ );
1400
+ }
1401
+ function usePaymentsCurrenciesList(client) {
1402
+ return useSWR__default.default(
1403
+ "cfg-payments-currencies",
1404
+ () => getPaymentsCurrenciesList(client)
1405
+ );
1406
+ }
1407
+ function usePaymentsPaymentsList(params, client) {
1408
+ return useSWR__default.default(
1409
+ params ? ["cfg-payments-payments", params] : "cfg-payments-payments",
1410
+ () => getPaymentsPaymentsList(params, client)
1411
+ );
1412
+ }
1413
+ function usePaymentsPaymentsRetrieve(id, client) {
1414
+ return useSWR__default.default(
1415
+ ["cfg-payments-payment", id],
1416
+ () => getPaymentsPaymentsRetrieve(id, client)
1417
+ );
1418
+ }
1419
+ function useCreatePaymentsPaymentsConfirmCreate() {
1420
+ const { mutate } = useSWR.useSWRConfig();
1421
+ return async (id, client) => {
1422
+ const result = await createPaymentsPaymentsConfirmCreate(id, client);
1423
+ mutate("cfg-payments-payments-confirm");
1424
+ return result;
1425
+ };
1426
+ }
1427
+ function useCreatePaymentsPaymentsCreateCreate() {
1428
+ const { mutate } = useSWR.useSWRConfig();
1429
+ return async (client) => {
1430
+ const result = await createPaymentsPaymentsCreateCreate(client);
1431
+ mutate("cfg-payments-payments");
1432
+ return result;
1433
+ };
1434
+ }
1435
+ function usePaymentsTransactionsList(params, client) {
1436
+ return useSWR__default.default(
1437
+ params ? ["cfg-payments-transactions", params] : "cfg-payments-transactions",
1438
+ () => getPaymentsTransactionsList(params, client)
1439
+ );
1440
+ }
1441
+ var PaymentsContext = react.createContext(void 0);
1442
+ function PaymentsProvider({ children }) {
1443
+ const {
1444
+ data: payments,
1445
+ error: paymentsError,
1446
+ isLoading: isLoadingPayments,
1447
+ mutate: mutatePayments
1448
+ } = usePaymentsPaymentsList({ page: 1, page_size: 1 }, apiPayments);
1449
+ const refreshPayments = async () => {
1450
+ await mutatePayments();
1451
+ };
1452
+ const createPaymentMutation = useCreatePaymentsPaymentsCreateCreate();
1453
+ const confirmPaymentMutation = useCreatePaymentsPaymentsConfirmCreate();
1454
+ const getPayment = async (id) => {
1455
+ return getPaymentsPaymentsRetrieve(id, apiPayments);
1456
+ };
1457
+ const createPayment = async () => {
1458
+ const result = await createPaymentMutation(apiPayments);
1459
+ await refreshPayments();
1460
+ return result;
1461
+ };
1462
+ const confirmPayment = async (id) => {
1463
+ const result = await confirmPaymentMutation(id, apiPayments);
1464
+ await refreshPayments();
1465
+ return result;
1466
+ };
1467
+ const checkPaymentStatus = async (id) => {
1468
+ return getPaymentsPaymentsStatusRetrieve(id, apiPayments);
1469
+ };
1470
+ const value = {
1471
+ payments,
1472
+ isLoadingPayments,
1473
+ paymentsError,
1474
+ refreshPayments,
1475
+ getPayment,
1476
+ createPayment,
1477
+ confirmPayment,
1478
+ checkPaymentStatus
1479
+ };
1480
+ return /* @__PURE__ */ jsxRuntime.jsx(PaymentsContext.Provider, { value, children });
1481
+ }
1482
+ function usePaymentsContext() {
1483
+ const context = react.useContext(PaymentsContext);
1484
+ if (!context) {
1485
+ throw new Error("usePaymentsContext must be used within PaymentsProvider");
1486
+ }
1487
+ return context;
1488
+ }
1489
+ react.createContext(void 0);
1490
+ react.createContext(void 0);
1491
+ var OverviewContext = react.createContext(void 0);
1492
+ function OverviewProvider({ children }) {
1493
+ const swrConfig = {
1494
+ revalidateOnFocus: false,
1495
+ revalidateOnReconnect: false,
1496
+ revalidateIfStale: false
1497
+ };
1498
+ const {
1499
+ data: balance,
1500
+ error: balanceError,
1501
+ isLoading: isLoadingBalance,
1502
+ mutate: mutateBalance
1503
+ } = usePaymentsBalanceRetrieve(apiPayments);
1504
+ const {
1505
+ data: payments,
1506
+ error: paymentsError,
1507
+ isLoading: isLoadingPayments,
1508
+ mutate: mutatePayments
1509
+ } = usePaymentsPaymentsList({}, apiPayments);
1510
+ const {
1511
+ data: transactions,
1512
+ error: transactionsError,
1513
+ isLoading: isLoadingTransactions,
1514
+ mutate: mutateTransactions
1515
+ } = usePaymentsTransactionsList({}, apiPayments);
1516
+ const createPaymentMutation = useCreatePaymentsPaymentsCreateCreate();
1517
+ const isLoadingOverview = isLoadingBalance || isLoadingPayments || isLoadingTransactions;
1518
+ const overviewError = balanceError || paymentsError || transactionsError;
1519
+ const refreshBalance = async () => {
1520
+ await mutateBalance();
1521
+ };
1522
+ const refreshPayments = async () => {
1523
+ await mutatePayments();
1524
+ };
1525
+ const refreshTransactions = async () => {
1526
+ await mutateTransactions();
1527
+ };
1528
+ const refreshOverview = async () => {
1529
+ await Promise.all([
1530
+ mutateBalance(),
1531
+ mutatePayments(),
1532
+ mutateTransactions()
1533
+ ]);
1534
+ };
1535
+ const createPayment = async () => {
1536
+ const result = await createPaymentMutation(apiPayments);
1537
+ await refreshOverview();
1538
+ return result;
1539
+ };
1540
+ const value = {
1541
+ balance,
1542
+ isLoadingBalance,
1543
+ balanceError,
1544
+ refreshBalance,
1545
+ payments,
1546
+ isLoadingPayments,
1547
+ paymentsError,
1548
+ refreshPayments,
1549
+ transactions,
1550
+ isLoadingTransactions,
1551
+ transactionsError,
1552
+ refreshTransactions,
1553
+ createPayment,
1554
+ isLoadingOverview,
1555
+ overviewError,
1556
+ refreshOverview
1557
+ };
1558
+ return /* @__PURE__ */ jsxRuntime.jsx(useSWR.SWRConfig, { value: swrConfig, children: /* @__PURE__ */ jsxRuntime.jsx(OverviewContext.Provider, { value, children }) });
1559
+ }
1560
+ function useOverviewContext() {
1561
+ const context = react.useContext(OverviewContext);
1562
+ if (!context) {
1563
+ throw new Error("useOverviewContext must be used within OverviewProvider");
1564
+ }
1565
+ return context;
1566
+ }
1567
+ var RootPaymentsContext = react.createContext(void 0);
1568
+ function RootPaymentsProvider({ children }) {
1569
+ const {
1570
+ data: currencies,
1571
+ error: currenciesError,
1572
+ isLoading: isLoadingCurrencies,
1573
+ mutate: mutateCurrencies
1574
+ } = usePaymentsCurrenciesList(apiPayments);
1575
+ const refreshCurrencies = async () => {
1576
+ await mutateCurrencies();
1577
+ };
1578
+ const value = {
1579
+ currencies,
1580
+ isLoadingCurrencies,
1581
+ currenciesError,
1582
+ refreshCurrencies
1583
+ };
1584
+ return /* @__PURE__ */ jsxRuntime.jsx(RootPaymentsContext.Provider, { value, children });
1585
+ }
1586
+ function useRootPaymentsContext() {
1587
+ const context = react.useContext(RootPaymentsContext);
1588
+ if (!context) {
1589
+ throw new Error("useRootPaymentsContext must be used within RootPaymentsProvider");
1590
+ }
1591
+ return context;
1592
+ }
1593
+
1594
+ // src/layouts/PaymentsLayout/events.ts
1595
+ var PAYMENT_EVENTS = {
1596
+ OPEN_CREATE_PAYMENT_DIALOG: "payments:open-create-payment",
1597
+ OPEN_PAYMENT_DETAILS_DIALOG: "payments:open-payment-details",
1598
+ CLOSE_DIALOG: "payments:close-dialog"
1599
+ };
1600
+ var openCreatePaymentDialog = () => {
1601
+ window.dispatchEvent(new Event(PAYMENT_EVENTS.OPEN_CREATE_PAYMENT_DIALOG));
1602
+ };
1603
+ var openPaymentDetailsDialog = (id) => {
1604
+ window.dispatchEvent(
1605
+ new CustomEvent(PAYMENT_EVENTS.OPEN_PAYMENT_DETAILS_DIALOG, {
1606
+ detail: { id }
1607
+ })
1608
+ );
1609
+ };
1610
+ var closePaymentsDialog = () => {
1611
+ window.dispatchEvent(new Event(PAYMENT_EVENTS.CLOSE_DIALOG));
1612
+ };
1613
+ var BalanceCard = () => {
1614
+ const {
1615
+ balance,
1616
+ isLoadingBalance,
1617
+ refreshBalance
1618
+ } = useOverviewContext();
1619
+ const formatCurrency = (amount) => {
1620
+ if (amount === null || amount === void 0) return "$0.00";
1621
+ return new Intl.NumberFormat("en-US", {
1622
+ style: "currency",
1623
+ currency: "USD",
1624
+ minimumFractionDigits: 2
1625
+ }).format(amount);
1626
+ };
1627
+ const formatDate = (dateStr) => {
1628
+ if (!dateStr) return "No transactions yet";
1629
+ try {
1630
+ return new Date(dateStr).toLocaleDateString("en-US", {
1631
+ year: "numeric",
1632
+ month: "short",
1633
+ day: "numeric"
1634
+ });
1635
+ } catch {
1636
+ return "Invalid date";
1637
+ }
1638
+ };
1639
+ if (isLoadingBalance) {
1640
+ return /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.Card, { children: [
1641
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.CardTitle, { className: "flex items-center justify-between", children: [
1642
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1643
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Wallet, { className: "h-5 w-5" }),
1644
+ "Account Balance"
1645
+ ] }),
1646
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Skeleton, { className: "h-8 w-20" })
1647
+ ] }) }),
1648
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.CardContent, { className: "space-y-4", children: [
1649
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Skeleton, { className: "h-10 w-32" }),
1650
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Skeleton, { className: "h-4 w-48" })
1651
+ ] })
1652
+ ] });
1653
+ }
1654
+ const balanceData = balance?.balance || balance;
1655
+ const amountUsd = balanceData?.amount_usd ?? 0;
1656
+ const totalDeposited = balanceData?.total_deposited ?? 0;
1657
+ const totalWithdrawn = balanceData?.total_withdrawn ?? 0;
1658
+ const lastTransactionAt = balanceData?.last_transaction_at;
1659
+ const isEmpty = amountUsd === 0 && totalDeposited === 0;
1660
+ return /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.Card, { children: [
1661
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.CardTitle, { className: "flex items-center justify-between", children: [
1662
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1663
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Wallet, { className: "h-5 w-5" }),
1664
+ "Account Balance"
1665
+ ] }),
1666
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1667
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Button, { variant: "ghost", size: "sm", onClick: refreshBalance, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "h-4 w-4" }) }),
1668
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.Button, { size: "sm", onClick: () => openCreatePaymentDialog(), children: [
1669
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-4 w-4 mr-2" }),
1670
+ "Add Funds"
1671
+ ] })
1672
+ ] })
1673
+ ] }) }),
1674
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.CardContent, { className: "space-y-4", children: [
1675
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1676
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-4xl font-bold", children: formatCurrency(amountUsd) }),
1677
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground mt-1", children: [
1678
+ "Available balance \u2022 Last updated ",
1679
+ formatDate(lastTransactionAt)
1680
+ ] })
1681
+ ] }),
1682
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-4 pt-4 border-t", children: [
1683
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1684
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Total Deposited" }),
1685
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg font-semibold text-green-600", children: formatCurrency(totalDeposited) })
1686
+ ] }),
1687
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1688
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Total Withdrawn" }),
1689
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg font-semibold text-red-600", children: formatCurrency(totalWithdrawn) })
1690
+ ] })
1691
+ ] }),
1692
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1693
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Badge, { variant: !isEmpty ? "default" : "secondary", children: !isEmpty ? "Active" : "New Account" }),
1694
+ isEmpty && /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Badge, { variant: "outline", children: "Empty Balance" })
1695
+ ] })
1696
+ ] })
1697
+ ] });
1698
+ };
1699
+ var RecentPayments = () => {
1700
+ const { payments, isLoadingPayments } = useOverviewContext();
1701
+ const formatCurrency = (amount) => {
1702
+ if (amount === null || amount === void 0) return "$0.00";
1703
+ const numAmount = typeof amount === "string" ? parseFloat(amount) : amount;
1704
+ return new Intl.NumberFormat("en-US", {
1705
+ style: "currency",
1706
+ currency: "USD",
1707
+ minimumFractionDigits: 2
1708
+ }).format(numAmount);
1709
+ };
1710
+ const getRelativeTime = (date) => {
1711
+ if (!date) return "N/A";
1712
+ const now = /* @__PURE__ */ new Date();
1713
+ const target = new Date(date);
1714
+ const diffInSeconds = Math.floor((now.getTime() - target.getTime()) / 1e3);
1715
+ if (diffInSeconds < 60) return "Just now";
1716
+ if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
1717
+ if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
1718
+ return `${Math.floor(diffInSeconds / 86400)}d ago`;
1719
+ };
1720
+ const getStatusVariant = (status) => {
1721
+ switch (status?.toLowerCase()) {
1722
+ case "completed":
1723
+ case "success":
1724
+ return "default";
1725
+ case "pending":
1726
+ case "confirming":
1727
+ return "secondary";
1728
+ case "failed":
1729
+ case "error":
1730
+ case "expired":
1731
+ return "destructive";
1732
+ default:
1733
+ return "outline";
1734
+ }
1735
+ };
1736
+ if (isLoadingPayments) {
1737
+ return /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.Card, { children: [
1738
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.CardTitle, { className: "flex items-center gap-2", children: [
1739
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "h-5 w-5" }),
1740
+ "Recent Payments"
1741
+ ] }) }),
1742
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.CardContent, { className: "space-y-3", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-3 border rounded-sm", children: [
1743
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1744
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Skeleton, { className: "h-4 w-32" }),
1745
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Skeleton, { className: "h-3 w-24" })
1746
+ ] }),
1747
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Skeleton, { className: "h-6 w-16" })
1748
+ ] }, i)) })
1749
+ ] });
1750
+ }
1751
+ const recentPaymentsList = payments?.results?.slice(0, 5) || [];
1752
+ return /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.Card, { children: [
1753
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.CardTitle, { className: "flex items-center justify-between", children: [
1754
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1755
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "h-5 w-5" }),
1756
+ "Recent Payments"
1757
+ ] }),
1758
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.Button, { variant: "ghost", size: "sm", children: [
1759
+ "View All",
1760
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-4 w-4 ml-2" })
1761
+ ] })
1762
+ ] }) }),
1763
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.CardContent, { children: recentPaymentsList.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-8 text-muted-foreground", children: [
1764
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "h-12 w-12 mx-auto mb-4 opacity-50" }),
1765
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: "No recent payments" }),
1766
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm mt-2", children: "Create your first payment to get started" })
1767
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: recentPaymentsList.map((payment) => /* @__PURE__ */ jsxRuntime.jsxs(
1768
+ "div",
1769
+ {
1770
+ className: "flex items-center justify-between p-3 border rounded-sm hover:bg-accent cursor-pointer transition-colors",
1771
+ onClick: () => openPaymentDetailsDialog(String(payment.id)),
1772
+ children: [
1773
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
1774
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1775
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: formatCurrency(payment.amount_usd) }),
1776
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Badge, { variant: getStatusVariant(payment.status), className: "text-xs", children: payment.status })
1777
+ ] }),
1778
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
1779
+ getRelativeTime(payment.created_at),
1780
+ " \u2022 ",
1781
+ payment.currency_code || "USD"
1782
+ ] })
1783
+ ] }),
1784
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-4 w-4 text-muted-foreground" })
1785
+ ]
1786
+ },
1787
+ payment.id
1788
+ )) }) })
1789
+ ] });
1790
+ };
1791
+ var OverviewView = () => {
1792
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-6 lg:grid-cols-2", children: [
1793
+ /* @__PURE__ */ jsxRuntime.jsx(BalanceCard, {}),
1794
+ /* @__PURE__ */ jsxRuntime.jsx(RecentPayments, {})
1795
+ ] }) });
1796
+ };
1797
+ var PaymentsList = () => {
1798
+ const pagination = uiNextjs.useDRFPagination(1, 20);
1799
+ const {
1800
+ data: payments,
1801
+ error,
1802
+ isLoading: isLoadingPayments,
1803
+ mutate: refreshPayments
1804
+ } = usePaymentsPaymentsList(pagination.params, apiPayments);
1805
+ const paymentsList = payments?.results || [];
1806
+ payments?.count || 0;
1807
+ const [searchTerm, setSearchTerm] = react.useState("");
1808
+ const [statusFilter, setStatusFilter] = react.useState("all");
1809
+ const formatCurrency = (amount) => {
1810
+ if (amount === null || amount === void 0) return "$0.00";
1811
+ const numAmount = typeof amount === "string" ? parseFloat(amount) : amount;
1812
+ return new Intl.NumberFormat("en-US", {
1813
+ style: "currency",
1814
+ currency: "USD",
1815
+ minimumFractionDigits: 2
1816
+ }).format(numAmount);
1817
+ };
1818
+ const getRelativeTime = (date) => {
1819
+ if (!date) return "N/A";
1820
+ const now = /* @__PURE__ */ new Date();
1821
+ const target = new Date(date);
1822
+ const diffInSeconds = Math.floor((now.getTime() - target.getTime()) / 1e3);
1823
+ if (diffInSeconds < 60) return "Just now";
1824
+ if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
1825
+ if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
1826
+ return `${Math.floor(diffInSeconds / 86400)}d ago`;
1827
+ };
1828
+ const getStatusVariant = (status) => {
1829
+ switch (status?.toLowerCase()) {
1830
+ case "completed":
1831
+ case "success":
1832
+ return "default";
1833
+ case "pending":
1834
+ case "confirming":
1835
+ return "secondary";
1836
+ case "failed":
1837
+ case "error":
1838
+ case "expired":
1839
+ return "destructive";
1840
+ default:
1841
+ return "outline";
1842
+ }
1843
+ };
1844
+ const handleSearch = (value) => {
1845
+ setSearchTerm(value);
1846
+ };
1847
+ const handleStatusFilter = (status) => {
1848
+ setStatusFilter(status);
1849
+ };
1850
+ const filteredPayments = paymentsList.filter((payment) => {
1851
+ const matchesSearch = searchTerm ? payment.id?.toLowerCase().includes(searchTerm.toLowerCase()) || payment.status?.toLowerCase().includes(searchTerm.toLowerCase()) || payment.currency_code?.toLowerCase().includes(searchTerm.toLowerCase()) : true;
1852
+ const matchesStatus = statusFilter !== "all" ? payment.status?.toLowerCase() === statusFilter.toLowerCase() : true;
1853
+ return matchesSearch && matchesStatus;
1854
+ });
1855
+ return /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.Card, { children: [
1856
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.CardTitle, { className: "flex items-center justify-between", children: [
1857
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Payment History" }),
1858
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1859
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.Button, { variant: "outline", size: "sm", onClick: () => refreshPayments(), disabled: isLoadingPayments, children: [
1860
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: `h-4 w-4 mr-2 ${isLoadingPayments ? "animate-spin" : ""}` }),
1861
+ "Refresh"
1862
+ ] }),
1863
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.Button, { size: "sm", onClick: () => openCreatePaymentDialog(), children: [
1864
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-4 w-4 mr-2" }),
1865
+ "New Payment"
1866
+ ] })
1867
+ ] })
1868
+ ] }) }),
1869
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.CardContent, { className: "space-y-4", children: [
1870
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col sm:flex-row gap-4", children: [
1871
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-1", children: [
1872
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
1873
+ /* @__PURE__ */ jsxRuntime.jsx(
1874
+ uiNextjs.Input,
1875
+ {
1876
+ placeholder: "Search by ID, status, or currency...",
1877
+ value: searchTerm,
1878
+ onChange: (e) => handleSearch(e.target.value),
1879
+ className: "pl-10"
1880
+ }
1881
+ )
1882
+ ] }),
1883
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.Select, { value: statusFilter, onValueChange: handleStatusFilter, children: [
1884
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.SelectTrigger, { className: "w-full sm:w-48", children: [
1885
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Filter, { className: "h-4 w-4 mr-2" }),
1886
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.SelectValue, { placeholder: "Filter by status" })
1887
+ ] }),
1888
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.SelectContent, { children: [
1889
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.SelectItem, { value: "all", children: "All Statuses" }),
1890
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.SelectItem, { value: "completed", children: "Completed" }),
1891
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.SelectItem, { value: "pending", children: "Pending" }),
1892
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.SelectItem, { value: "confirming", children: "Confirming" }),
1893
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.SelectItem, { value: "failed", children: "Failed" }),
1894
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.SelectItem, { value: "expired", children: "Expired" })
1895
+ ] })
1896
+ ] })
1897
+ ] }),
1898
+ isLoadingPayments ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-4 border rounded-sm", children: [
1899
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1900
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Skeleton, { className: "h-4 w-32" }),
1901
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Skeleton, { className: "h-3 w-24" })
1902
+ ] }),
1903
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Skeleton, { className: "h-6 w-16" })
1904
+ ] }, i)) }) : filteredPayments.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-12", children: [
1905
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-16 h-16 mx-auto mb-4 bg-muted rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "w-8 h-8 text-muted-foreground" }) }),
1906
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold mb-2", children: "No Payments Found" }),
1907
+ /* @__PURE__ */ jsxRuntime.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" }),
1908
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.Button, { onClick: () => openCreatePaymentDialog(), children: [
1909
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-4 w-4 mr-2" }),
1910
+ "Create Payment"
1911
+ ] })
1912
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1913
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.Table, { children: [
1914
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.TableRow, { children: [
1915
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableHead, { children: "Date" }),
1916
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableHead, { children: "Amount" }),
1917
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableHead, { children: "Currency" }),
1918
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableHead, { children: "Status" }),
1919
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableHead, { children: "Provider" }),
1920
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableHead, { children: "Payment ID" }),
1921
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableHead, { className: "text-right", children: "Actions" })
1922
+ ] }) }),
1923
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableBody, { children: filteredPayments.map((payment) => /* @__PURE__ */ jsxRuntime.jsxs(
1924
+ uiNextjs.TableRow,
1925
+ {
1926
+ className: "cursor-pointer hover:bg-accent",
1927
+ onClick: () => openPaymentDetailsDialog(String(payment.id)),
1928
+ children: [
1929
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableCell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1930
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children: payment.created_at ? new Date(payment.created_at).toLocaleDateString() : "N/A" }),
1931
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-muted-foreground", children: getRelativeTime(payment.created_at) })
1932
+ ] }) }),
1933
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableCell, { className: "font-mono font-semibold", children: formatCurrency(payment.amount_usd) }),
1934
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableCell, { children: /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Badge, { variant: "outline", children: payment.currency_code || "USD" }) }),
1935
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableCell, { children: /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Badge, { variant: getStatusVariant(payment.status), children: payment.status }) }),
1936
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableCell, { className: "text-sm text-muted-foreground", children: "NowPayments" }),
1937
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableCell, { className: "font-mono text-sm text-muted-foreground", children: payment.id ? `${payment.id.toString().slice(0, 8)}...` : "N/A" }),
1938
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableCell, { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsx(
1939
+ uiNextjs.Button,
1940
+ {
1941
+ variant: "ghost",
1942
+ size: "sm",
1943
+ onClick: (e) => {
1944
+ e.stopPropagation();
1945
+ openPaymentDetailsDialog(String(payment.id));
1946
+ },
1947
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-4 w-4" })
1948
+ }
1949
+ ) })
1950
+ ]
1951
+ },
1952
+ payment.id
1953
+ )) })
1954
+ ] }) }),
1955
+ /* @__PURE__ */ jsxRuntime.jsx(
1956
+ uiNextjs.StaticPagination,
1957
+ {
1958
+ data: payments,
1959
+ onPageChange: pagination.setPage,
1960
+ className: "mt-4"
1961
+ }
1962
+ )
1963
+ ] })
1964
+ ] })
1965
+ ] });
1966
+ };
1967
+ var PaymentsView = () => {
1968
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-6", children: /* @__PURE__ */ jsxRuntime.jsx(PaymentsList, {}) });
1969
+ };
1970
+ var TransactionsList = () => {
1971
+ const {
1972
+ transactions,
1973
+ isLoadingTransactions,
1974
+ refreshTransactions
1975
+ } = useOverviewContext();
1976
+ const [searchTerm, setSearchTerm] = react.useState("");
1977
+ const [typeFilter, setTypeFilter] = react.useState("all");
1978
+ const transactionsList = transactions?.results || transactions?.transactions || [];
1979
+ const formatCurrency = (amount) => {
1980
+ if (amount === null || amount === void 0) return "$0.00";
1981
+ return new Intl.NumberFormat("en-US", {
1982
+ style: "currency",
1983
+ currency: "USD",
1984
+ minimumFractionDigits: 2
1985
+ }).format(amount);
1986
+ };
1987
+ const formatDate = (date) => {
1988
+ if (!date) return "N/A";
1989
+ try {
1990
+ return new Date(date).toLocaleString("en-US", {
1991
+ year: "numeric",
1992
+ month: "short",
1993
+ day: "numeric",
1994
+ hour: "2-digit",
1995
+ minute: "2-digit"
1996
+ });
1997
+ } catch {
1998
+ return "Invalid date";
1999
+ }
2000
+ };
2001
+ const getRelativeTime = (date) => {
2002
+ if (!date) return "N/A";
2003
+ const now = /* @__PURE__ */ new Date();
2004
+ const target = new Date(date);
2005
+ const diffInSeconds = Math.floor((now.getTime() - target.getTime()) / 1e3);
2006
+ if (diffInSeconds < 60) return "Just now";
2007
+ if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
2008
+ if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
2009
+ return `${Math.floor(diffInSeconds / 86400)}d ago`;
2010
+ };
2011
+ const getTypeVariant = (type) => {
2012
+ switch (type?.toLowerCase()) {
2013
+ case "deposit":
2014
+ case "credit":
2015
+ return "default";
2016
+ case "withdrawal":
2017
+ case "debit":
2018
+ return "destructive";
2019
+ default:
2020
+ return "outline";
2021
+ }
2022
+ };
2023
+ const getTypeIcon = (type) => {
2024
+ const isDeposit = type?.toLowerCase() === "deposit" || type?.toLowerCase() === "credit";
2025
+ return isDeposit ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownLeft, { className: "h-4 w-4 text-green-600" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { className: "h-4 w-4 text-red-600" });
2026
+ };
2027
+ const handleSearch = async (value) => {
2028
+ setSearchTerm(value);
2029
+ await refreshTransactions();
2030
+ };
2031
+ const handleTypeFilter = async (type) => {
2032
+ setTypeFilter(type);
2033
+ await refreshTransactions();
2034
+ };
2035
+ const filteredTransactions = transactionsList.filter((transaction) => {
2036
+ const matchesSearch = searchTerm ? transaction.id?.toString().toLowerCase().includes(searchTerm.toLowerCase()) || transaction.description?.toLowerCase().includes(searchTerm.toLowerCase()) || transaction.type?.toLowerCase().includes(searchTerm.toLowerCase()) : true;
2037
+ const matchesType = typeFilter !== "all" ? transaction.type?.toLowerCase() === typeFilter.toLowerCase() : true;
2038
+ return matchesSearch && matchesType;
2039
+ });
2040
+ if (isLoadingTransactions) {
2041
+ return /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.Card, { children: [
2042
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.CardTitle, { className: "flex items-center gap-2", children: [
2043
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "h-5 w-5" }),
2044
+ "Transaction History"
2045
+ ] }) }),
2046
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.CardContent, { className: "space-y-3", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-4 border rounded-sm", children: [
2047
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
2048
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Skeleton, { className: "h-4 w-32" }),
2049
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Skeleton, { className: "h-3 w-24" })
2050
+ ] }),
2051
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Skeleton, { className: "h-6 w-16" })
2052
+ ] }, i)) })
2053
+ ] });
2054
+ }
2055
+ return /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.Card, { children: [
2056
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.CardTitle, { className: "flex items-center justify-between", children: [
2057
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2058
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "h-5 w-5" }),
2059
+ "Transaction History"
2060
+ ] }),
2061
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.Button, { variant: "outline", size: "sm", onClick: refreshTransactions, disabled: isLoadingTransactions, children: [
2062
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: `h-4 w-4 mr-2 ${isLoadingTransactions ? "animate-spin" : ""}` }),
2063
+ "Refresh"
2064
+ ] })
2065
+ ] }) }),
2066
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.CardContent, { className: "space-y-4", children: [
2067
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col sm:flex-row gap-4", children: [
2068
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-1", children: [
2069
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
2070
+ /* @__PURE__ */ jsxRuntime.jsx(
2071
+ uiNextjs.Input,
2072
+ {
2073
+ placeholder: "Search by ID, description, or type...",
2074
+ value: searchTerm,
2075
+ onChange: (e) => handleSearch(e.target.value),
2076
+ className: "pl-10"
2077
+ }
2078
+ )
2079
+ ] }),
2080
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.Select, { value: typeFilter, onValueChange: handleTypeFilter, children: [
2081
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.SelectTrigger, { className: "w-full sm:w-48", children: [
2082
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Filter, { className: "h-4 w-4 mr-2" }),
2083
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.SelectValue, { placeholder: "Filter by type" })
2084
+ ] }),
2085
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.SelectContent, { children: [
2086
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.SelectItem, { value: "all", children: "All Types" }),
2087
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.SelectItem, { value: "deposit", children: "Deposits" }),
2088
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.SelectItem, { value: "withdrawal", children: "Withdrawals" })
2089
+ ] })
2090
+ ] })
2091
+ ] }),
2092
+ filteredTransactions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-12", children: [
2093
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-16 h-16 mx-auto mb-4 bg-muted rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "w-8 h-8 text-muted-foreground" }) }),
2094
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold mb-2", children: "No Transactions Found" }),
2095
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: searchTerm || typeFilter !== "all" ? "No transactions match your current filters" : "You don't have any transactions yet" })
2096
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.Table, { children: [
2097
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.TableRow, { children: [
2098
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableHead, { children: "Date & Time" }),
2099
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableHead, { children: "Type" }),
2100
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableHead, { children: "Amount" }),
2101
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableHead, { children: "Balance After" }),
2102
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableHead, { children: "Description" }),
2103
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableHead, { children: "Reference" })
2104
+ ] }) }),
2105
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableBody, { children: filteredTransactions.map((transaction, index) => {
2106
+ const isDeposit = transaction.type?.toLowerCase() === "deposit" || transaction.type?.toLowerCase() === "credit";
2107
+ return /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.TableRow, { children: [
2108
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableCell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2109
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children: formatDate(transaction.created_at || transaction.timestamp) }),
2110
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-muted-foreground", children: getRelativeTime(transaction.created_at || transaction.timestamp) })
2111
+ ] }) }),
2112
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableCell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2113
+ getTypeIcon(transaction.type),
2114
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Badge, { variant: getTypeVariant(transaction.type), children: transaction.type || "Unknown" })
2115
+ ] }) }),
2116
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableCell, { className: "font-mono font-semibold", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: isDeposit ? "text-green-600" : "text-red-600", children: [
2117
+ isDeposit ? "+" : "-",
2118
+ formatCurrency(Math.abs(transaction.amount || transaction.amount_usd || 0))
2119
+ ] }) }),
2120
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableCell, { className: "font-mono", children: formatCurrency(transaction.balance_after || 0) }),
2121
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableCell, { className: "text-sm", children: transaction.description || transaction.note || "No description" }),
2122
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TableCell, { className: "font-mono text-sm text-muted-foreground", children: transaction.reference || transaction.payment_id ? `${(transaction.reference || transaction.payment_id).toString().slice(0, 8)}...` : "N/A" })
2123
+ ] }, transaction.id || index);
2124
+ }) })
2125
+ ] }) })
2126
+ ] })
2127
+ ] });
2128
+ };
2129
+ var TransactionsView = () => {
2130
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-6", children: /* @__PURE__ */ jsxRuntime.jsx(TransactionsList, {}) });
2131
+ };
2132
+ var isDevelopment = process.env.NODE_ENV === "development";
2133
+ var logger = consola.createConsola({
2134
+ level: isDevelopment ? 4 : 1
2135
+ }).withTag("ext-payments");
2136
+ var paymentsLogger = logger;
2137
+ var PaymentCreateSchema = zod.z.object({
2138
+ amount_usd: zod.z.number().min(0.01, "Amount must be at least $0.01"),
2139
+ currency_code: zod.z.string().min(1, "Please select a currency")
2140
+ });
2141
+ var CreatePaymentDialog = () => {
2142
+ const [open, setOpen] = react.useState(false);
2143
+ const [isSubmitting, setIsSubmitting] = react.useState(false);
2144
+ const { createPayment } = usePaymentsContext();
2145
+ const { currencies, isLoadingCurrencies } = useRootPaymentsContext();
2146
+ const form = reactHookForm.useForm({
2147
+ resolver: zod$1.zodResolver(PaymentCreateSchema),
2148
+ defaultValues: {
2149
+ amount_usd: 10,
2150
+ currency_code: "USDT"
2151
+ }
2152
+ });
2153
+ const currenciesList = react.useMemo(() => {
2154
+ const data = currencies?.currencies || currencies?.results || currencies || [];
2155
+ return Array.isArray(data) ? data : [];
2156
+ }, [currencies]);
2157
+ const currencyOptions = react.useMemo(() => {
2158
+ return currenciesList.filter((curr) => curr.is_enabled !== false).map((curr) => ({
2159
+ code: curr.code || curr.currency_code || curr.symbol,
2160
+ name: curr.name || curr.code || curr.currency_code,
2161
+ usd_rate: curr.usd_rate || curr.rate || 1,
2162
+ network: curr.network || null
2163
+ }));
2164
+ }, [currenciesList]);
2165
+ const calculateCryptoAmount = react.useMemo(() => {
2166
+ const amountUsd = form.watch("amount_usd");
2167
+ const currencyCode = form.watch("currency_code");
2168
+ const currency = currencyOptions.find((c) => c.code === currencyCode);
2169
+ if (!currency || !currency.usd_rate || !amountUsd) {
2170
+ return null;
2171
+ }
2172
+ const cryptoAmount = amountUsd / currency.usd_rate;
2173
+ return {
2174
+ amount: cryptoAmount,
2175
+ currency: currency.code,
2176
+ rate: currency.usd_rate,
2177
+ network: currency.network
2178
+ };
2179
+ }, [form.watch("amount_usd"), form.watch("currency_code"), currencyOptions]);
2180
+ react.useEffect(() => {
2181
+ const handleOpen = () => setOpen(true);
2182
+ const handleClose2 = () => setOpen(false);
2183
+ window.addEventListener(PAYMENT_EVENTS.OPEN_CREATE_PAYMENT_DIALOG, handleOpen);
2184
+ window.addEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
2185
+ return () => {
2186
+ window.removeEventListener(PAYMENT_EVENTS.OPEN_CREATE_PAYMENT_DIALOG, handleOpen);
2187
+ window.removeEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
2188
+ };
2189
+ }, []);
2190
+ const handleClose = () => {
2191
+ setOpen(false);
2192
+ form.reset();
2193
+ };
2194
+ react.useEffect(() => {
2195
+ if (currencyOptions.length > 0 && !form.getValues("currency_code")) {
2196
+ form.setValue("currency_code", currencyOptions[0].code);
2197
+ }
2198
+ }, [currencyOptions, form]);
2199
+ const handleSubmit = async (data) => {
2200
+ try {
2201
+ setIsSubmitting(true);
2202
+ const result = await createPayment();
2203
+ handleClose();
2204
+ closePaymentsDialog();
2205
+ const paymentData = result;
2206
+ const paymentId = paymentData?.payment?.id || paymentData?.id;
2207
+ if (paymentId) {
2208
+ openPaymentDetailsDialog(String(paymentId));
2209
+ }
2210
+ } catch (error) {
2211
+ paymentsLogger.error("Failed to create payment:", error);
2212
+ } finally {
2213
+ setIsSubmitting(false);
2214
+ }
2215
+ };
2216
+ return /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.DialogContent, { className: "sm:max-w-md", children: [
2217
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.DialogHeader, { children: [
2218
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.DialogTitle, { children: "Create Payment" }),
2219
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.DialogDescription, { children: "Create a new payment to add funds to your account." })
2220
+ ] }),
2221
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Form, { ...form, children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: form.handleSubmit(handleSubmit), className: "space-y-4", children: [
2222
+ /* @__PURE__ */ jsxRuntime.jsx(
2223
+ uiNextjs.FormField,
2224
+ {
2225
+ control: form.control,
2226
+ name: "amount_usd",
2227
+ render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.FormItem, { children: [
2228
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.FormLabel, { children: "Amount (USD)" }),
2229
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
2230
+ uiNextjs.Input,
2231
+ {
2232
+ type: "number",
2233
+ step: "0.01",
2234
+ min: "0.01",
2235
+ placeholder: "10.00",
2236
+ ...field,
2237
+ onChange: (e) => field.onChange(parseFloat(e.target.value) || 0)
2238
+ }
2239
+ ) }),
2240
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.FormDescription, { children: "The amount you want to pay in USD." }),
2241
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.FormMessage, {})
2242
+ ] })
2243
+ }
2244
+ ),
2245
+ /* @__PURE__ */ jsxRuntime.jsx(
2246
+ uiNextjs.FormField,
2247
+ {
2248
+ control: form.control,
2249
+ name: "currency_code",
2250
+ render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.FormItem, { children: [
2251
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.FormLabel, { children: "Currency" }),
2252
+ /* @__PURE__ */ jsxRuntime.jsxs(
2253
+ uiNextjs.Select,
2254
+ {
2255
+ onValueChange: field.onChange,
2256
+ defaultValue: field.value,
2257
+ disabled: isLoadingCurrencies,
2258
+ children: [
2259
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.SelectTrigger, { children: /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.SelectValue, { placeholder: "Select currency..." }) }) }),
2260
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.SelectContent, { children: currencyOptions.map((curr) => /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.SelectItem, { value: curr.code, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2261
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TokenIcon, { symbol: curr.code, size: 16 }),
2262
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: curr.code }),
2263
+ curr.network && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: [
2264
+ "(",
2265
+ curr.network,
2266
+ ")"
2267
+ ] })
2268
+ ] }) }, curr.code)) })
2269
+ ]
2270
+ }
2271
+ ),
2272
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.FormDescription, { children: "The cryptocurrency to use for payment." }),
2273
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.FormMessage, {})
2274
+ ] })
2275
+ }
2276
+ ),
2277
+ calculateCryptoAmount && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm bg-muted p-4 space-y-3", children: [
2278
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
2279
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "You will send" }),
2280
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2281
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TokenIcon, { symbol: calculateCryptoAmount.currency, size: 16 }),
2282
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono font-semibold", children: [
2283
+ calculateCryptoAmount.amount.toFixed(8),
2284
+ " ",
2285
+ calculateCryptoAmount.currency
2286
+ ] })
2287
+ ] })
2288
+ ] }),
2289
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
2290
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "You will receive" }),
2291
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-lg font-bold", children: [
2292
+ "$",
2293
+ form.watch("amount_usd")?.toFixed(2),
2294
+ " USD"
2295
+ ] })
2296
+ ] }),
2297
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-xs", children: [
2298
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Rate" }),
2299
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
2300
+ "1 ",
2301
+ calculateCryptoAmount.currency,
2302
+ " = $",
2303
+ calculateCryptoAmount.rate?.toFixed(2)
2304
+ ] })
2305
+ ] }),
2306
+ calculateCryptoAmount.network && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t pt-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
2307
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Network" }),
2308
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: calculateCryptoAmount.network })
2309
+ ] }) })
2310
+ ] }),
2311
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.DialogFooter, { children: [
2312
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Button, { type: "button", variant: "outline", onClick: handleClose, disabled: isSubmitting, children: "Cancel" }),
2313
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Button, { type: "submit", disabled: isSubmitting || currencyOptions.length === 0, children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2314
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "h-4 w-4 mr-2 animate-spin" }),
2315
+ "Creating..."
2316
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2317
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-4 w-4 mr-2" }),
2318
+ "Create Payment"
2319
+ ] }) })
2320
+ ] })
2321
+ ] }) })
2322
+ ] }) });
2323
+ };
2324
+ var PaymentDetailsDialog = () => {
2325
+ const [open, setOpen] = react.useState(false);
2326
+ const [paymentId, setPaymentId] = react.useState(null);
2327
+ const [timeLeft, setTimeLeft] = react.useState("");
2328
+ const shouldFetch = open && !!paymentId;
2329
+ const { data: payment, isLoading, error, mutate } = usePaymentsPaymentsRetrieve(
2330
+ shouldFetch ? paymentId : "",
2331
+ apiPayments
2332
+ );
2333
+ react.useEffect(() => {
2334
+ const handleOpen = (event) => {
2335
+ const customEvent = event;
2336
+ setPaymentId(customEvent.detail.id);
2337
+ setOpen(true);
2338
+ };
2339
+ const handleClose2 = () => {
2340
+ setOpen(false);
2341
+ setPaymentId(null);
2342
+ };
2343
+ window.addEventListener(PAYMENT_EVENTS.OPEN_PAYMENT_DETAILS_DIALOG, handleOpen);
2344
+ window.addEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
2345
+ return () => {
2346
+ window.removeEventListener(PAYMENT_EVENTS.OPEN_PAYMENT_DETAILS_DIALOG, handleOpen);
2347
+ window.removeEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
2348
+ };
2349
+ }, []);
2350
+ const handleClose = () => {
2351
+ setOpen(false);
2352
+ setPaymentId(null);
2353
+ };
2354
+ react.useEffect(() => {
2355
+ if (!payment?.expires_at) return;
2356
+ const updateTimeLeft = () => {
2357
+ const now = (/* @__PURE__ */ new Date()).getTime();
2358
+ const expires = new Date(payment.expires_at).getTime();
2359
+ const diff = expires - now;
2360
+ if (diff <= 0) {
2361
+ setTimeLeft("Expired");
2362
+ return;
2363
+ }
2364
+ const hours = Math.floor(diff / (1e3 * 60 * 60));
2365
+ const minutes = Math.floor(diff % (1e3 * 60 * 60) / (1e3 * 60));
2366
+ const seconds = Math.floor(diff % (1e3 * 60) / 1e3);
2367
+ setTimeLeft(`${hours}h ${minutes}m ${seconds}s`);
2368
+ };
2369
+ updateTimeLeft();
2370
+ const interval = setInterval(updateTimeLeft, 1e3);
2371
+ return () => clearInterval(interval);
2372
+ }, [payment?.expires_at]);
2373
+ const getStatusInfo = () => {
2374
+ switch (payment?.status?.toLowerCase()) {
2375
+ case "pending":
2376
+ return { icon: lucideReact.Clock, color: "text-yellow-500", bg: "bg-yellow-500/10" };
2377
+ case "completed":
2378
+ case "success":
2379
+ return { icon: lucideReact.CheckCircle2, color: "text-green-500", bg: "bg-green-500/10" };
2380
+ case "failed":
2381
+ case "error":
2382
+ return { icon: lucideReact.XCircle, color: "text-red-500", bg: "bg-red-500/10" };
2383
+ case "expired":
2384
+ return { icon: lucideReact.AlertCircle, color: "text-gray-500", bg: "bg-gray-500/10" };
2385
+ case "confirming":
2386
+ return { icon: lucideReact.RefreshCw, color: "text-blue-500", bg: "bg-blue-500/10" };
2387
+ default:
2388
+ return { icon: lucideReact.Clock, color: "text-gray-500", bg: "bg-gray-500/10" };
2389
+ }
2390
+ };
2391
+ if (!open) return null;
2392
+ if (isLoading) {
2393
+ return /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.DialogContent, { className: "sm:max-w-lg", children: [
2394
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.DialogHeader, { children: [
2395
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.DialogTitle, { children: "Payment Details" }),
2396
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.DialogDescription, { children: "Loading payment information..." })
2397
+ ] }),
2398
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "h-8 w-8 animate-spin text-muted-foreground" }) })
2399
+ ] }) });
2400
+ }
2401
+ if (shouldFetch && !isLoading && (error || !payment)) {
2402
+ return /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.DialogContent, { className: "sm:max-w-lg", children: [
2403
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.DialogHeader, { children: [
2404
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.DialogTitle, { children: "Payment Details" }),
2405
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.DialogDescription, { children: "Failed to load payment information" })
2406
+ ] }),
2407
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center py-12 space-y-4", children: [
2408
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XCircle, { className: "h-12 w-12 text-destructive" }),
2409
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: error ? `Error: ${error}` : "Payment not found" }),
2410
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Button, { onClick: () => mutate(), children: "Try Again" })
2411
+ ] })
2412
+ ] }) });
2413
+ }
2414
+ const statusInfo = getStatusInfo();
2415
+ const StatusIcon = statusInfo.icon;
2416
+ const qrCodeUrl = payment.pay_address ? `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(payment.pay_address)}` : null;
2417
+ return /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.DialogContent, { className: "sm:max-w-lg", children: [
2418
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.DialogHeader, { children: [
2419
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.DialogTitle, { children: "Payment Details" }),
2420
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.DialogDescription, { children: "Send cryptocurrency to complete your payment" })
2421
+ ] }),
2422
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
2423
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center gap-3 p-4 rounded-sm ${statusInfo.bg}`, children: [
2424
+ /* @__PURE__ */ jsxRuntime.jsx(StatusIcon, { className: `h-5 w-5 ${statusInfo.color}` }),
2425
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
2426
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold capitalize", children: payment.status }),
2427
+ payment.status === "pending" && timeLeft && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm text-muted-foreground", children: [
2428
+ "Expires in ",
2429
+ timeLeft
2430
+ ] })
2431
+ ] })
2432
+ ] }),
2433
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
2434
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-4 bg-muted rounded-sm", children: [
2435
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Amount to send" }),
2436
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2437
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TokenIcon, { symbol: String(payment.currency_code || "BTC"), size: 20 }),
2438
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono font-bold text-lg", children: [
2439
+ payment.pay_amount || "0.00000000",
2440
+ " ",
2441
+ payment.currency_code
2442
+ ] })
2443
+ ] })
2444
+ ] }),
2445
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4", children: [
2446
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Equivalent to" }),
2447
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-semibold text-lg", children: [
2448
+ "$",
2449
+ parseFloat(payment.amount_usd || "0").toFixed(2),
2450
+ " USD"
2451
+ ] })
2452
+ ] }),
2453
+ payment.internal_payment_id && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4", children: [
2454
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Payment Order #" }),
2455
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-medium", children: payment.internal_payment_id })
2456
+ ] }),
2457
+ payment.currency_network && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4", children: [
2458
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Network" }),
2459
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: payment.currency_network })
2460
+ ] })
2461
+ ] }),
2462
+ qrCodeUrl && payment.status === "pending" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center p-6 bg-white rounded-sm", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: qrCodeUrl, alt: "Payment QR Code", className: "w-48 h-48" }) }),
2463
+ payment.pay_address && payment.status === "pending" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
2464
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: "Payment Address" }),
2465
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2466
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 p-3 bg-muted rounded-sm font-mono text-sm break-all", children: payment.pay_address }),
2467
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.CopyButton, { value: payment.pay_address, variant: "outline" })
2468
+ ] })
2469
+ ] }),
2470
+ payment.transaction_hash && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
2471
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: "Transaction Hash" }),
2472
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3 bg-muted rounded-sm font-mono text-sm break-all", children: payment.transaction_hash })
2473
+ ] }),
2474
+ payment.payment_url && payment.status === "pending" && /* @__PURE__ */ jsxRuntime.jsxs(
2475
+ uiNextjs.Button,
2476
+ {
2477
+ variant: "outline",
2478
+ className: "w-full",
2479
+ onClick: () => window.open(payment.payment_url, "_blank"),
2480
+ children: [
2481
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-4 w-4 mr-2" }),
2482
+ "Open in Payment Provider"
2483
+ ]
2484
+ }
2485
+ ),
2486
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pt-4 border-t space-y-2 text-xs text-muted-foreground", children: [
2487
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between", children: [
2488
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Payment ID" }),
2489
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: payment.id })
2490
+ ] }),
2491
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between", children: [
2492
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Created" }),
2493
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: new Date(payment.created_at).toLocaleString() })
2494
+ ] }),
2495
+ payment.confirmations_count !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between", children: [
2496
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Confirmations" }),
2497
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: payment.confirmations_count })
2498
+ ] })
2499
+ ] })
2500
+ ] }),
2501
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.DialogFooter, { children: [
2502
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.Button, { variant: "outline", onClick: handleClose, children: "Close" }),
2503
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.Button, { onClick: () => mutate(), variant: "ghost", size: "sm", children: [
2504
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "h-4 w-4 mr-2" }),
2505
+ "Refresh"
2506
+ ] })
2507
+ ] })
2508
+ ] }) });
2509
+ };
2510
+ var PaymentsLayout = () => {
2511
+ return /* @__PURE__ */ jsxRuntime.jsx(RootPaymentsProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full p-6 space-y-6", children: [
2512
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2513
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-3xl font-bold tracking-tight", children: "Payments" }),
2514
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: "Manage your payments, balance, and transaction history" })
2515
+ ] }),
2516
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.Tabs, { defaultValue: "overview", className: "space-y-6", children: [
2517
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.TabsList, { className: "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground", children: [
2518
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.TabsTrigger, { value: "overview", className: "inline-flex items-center gap-2 px-3 py-1.5", children: [
2519
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Wallet, { className: "h-4 w-4" }),
2520
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: "Overview" })
2521
+ ] }),
2522
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.TabsTrigger, { value: "payments", className: "inline-flex items-center gap-2 px-3 py-1.5", children: [
2523
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CreditCard, { className: "h-4 w-4" }),
2524
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: "Payments" })
2525
+ ] }),
2526
+ /* @__PURE__ */ jsxRuntime.jsxs(uiNextjs.TabsTrigger, { value: "transactions", className: "inline-flex items-center gap-2 px-3 py-1.5", children: [
2527
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "h-4 w-4" }),
2528
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: "Transactions" })
2529
+ ] })
2530
+ ] }),
2531
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TabsContent, { value: "overview", className: "space-y-6", children: /* @__PURE__ */ jsxRuntime.jsx(OverviewProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(PaymentsProvider, { children: [
2532
+ /* @__PURE__ */ jsxRuntime.jsx(OverviewView, {}),
2533
+ /* @__PURE__ */ jsxRuntime.jsx(CreatePaymentDialog, {})
2534
+ ] }) }) }),
2535
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TabsContent, { value: "payments", className: "space-y-6", children: /* @__PURE__ */ jsxRuntime.jsxs(PaymentsProvider, { children: [
2536
+ /* @__PURE__ */ jsxRuntime.jsx(PaymentsView, {}),
2537
+ /* @__PURE__ */ jsxRuntime.jsx(CreatePaymentDialog, {})
2538
+ ] }) }),
2539
+ /* @__PURE__ */ jsxRuntime.jsx(uiNextjs.TabsContent, { value: "transactions", className: "space-y-6", children: /* @__PURE__ */ jsxRuntime.jsx(OverviewProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(TransactionsView, {}) }) })
2540
+ ] }),
2541
+ /* @__PURE__ */ jsxRuntime.jsx(PaymentDetailsDialog, {})
2542
+ ] }) });
2543
+ };
2544
+
2545
+ // package.json
2546
+ var package_default = {
2547
+ name: "@djangocfg/ext-payments",
2548
+ version: "1.0.3",
2549
+ description: "Payments system extension for DjangoCFG",
2550
+ keywords: [
2551
+ "django",
2552
+ "djangocfg",
2553
+ "extension",
2554
+ "payments",
2555
+ "stripe",
2556
+ "billing",
2557
+ "subscription",
2558
+ "typescript",
2559
+ "react"
2560
+ ],
2561
+ author: {
2562
+ name: "DjangoCFG",
2563
+ url: "https://djangocfg.com"
2564
+ },
2565
+ homepage: "https://hub.djangocfg.com/extensions/djangocfg-ext-payments",
2566
+ repository: {
2567
+ type: "git",
2568
+ url: "https://github.com/markolofsen/django-cfg.git",
2569
+ directory: "extensions/payments"
2570
+ },
2571
+ bugs: {
2572
+ url: "https://github.com/markolofsen/django-cfg/issues"
2573
+ },
2574
+ license: "MIT",
2575
+ type: "module",
2576
+ main: "./dist/index.cjs",
2577
+ module: "./dist/index.js",
2578
+ types: "./dist/index.d.ts",
2579
+ exports: {
2580
+ ".": {
2581
+ types: "./dist/index.d.ts",
2582
+ import: "./dist/index.js",
2583
+ require: "./dist/index.cjs"
2584
+ },
2585
+ "./hooks": {
2586
+ types: "./dist/hooks.d.ts",
2587
+ import: "./dist/hooks.js",
2588
+ require: "./dist/hooks.cjs"
2589
+ },
2590
+ "./config": {
2591
+ types: "./dist/config.d.ts",
2592
+ import: "./dist/config.js",
2593
+ require: "./dist/config.cjs"
2594
+ }
2595
+ },
2596
+ files: [
2597
+ "dist",
2598
+ "src",
2599
+ "preview.png"
2600
+ ],
2601
+ scripts: {
2602
+ build: "tsup",
2603
+ dev: "tsup --watch",
2604
+ check: "tsc --noEmit"
2605
+ },
2606
+ peerDependencies: {
2607
+ "@djangocfg/api": "workspace:*",
2608
+ "@djangocfg/ext-base": "workspace:*",
2609
+ "@djangocfg/ui-nextjs": "workspace:*",
2610
+ consola: "^3.4.2",
2611
+ "lucide-react": "^0.545.0",
2612
+ next: "^15.5.7",
2613
+ "p-retry": "^7.0.0",
2614
+ react: "^18 || ^19",
2615
+ swr: "^2.3.7",
2616
+ zod: "^4.1.13"
2617
+ },
2618
+ devDependencies: {
2619
+ "@djangocfg/api": "workspace:*",
2620
+ "@djangocfg/ext-base": "workspace:*",
2621
+ "@djangocfg/typescript-config": "workspace:*",
2622
+ "@types/node": "^24.7.2",
2623
+ "@types/react": "^19.0.0",
2624
+ consola: "^3.4.2",
2625
+ "p-retry": "^7.0.0",
2626
+ swr: "^2.3.7",
2627
+ tsup: "^8.5.0",
2628
+ typescript: "^5.9.3"
2629
+ }
2630
+ };
2631
+
2632
+ // src/config.ts
2633
+ var extensionConfig = extBase.createExtensionConfig(package_default, {
2634
+ name: "payments",
2635
+ displayName: "Payments & Billing",
2636
+ category: "payments",
2637
+ features: [
2638
+ "Multiple payment providers",
2639
+ "Stripe integration",
2640
+ "Cryptocurrency payments (NowPayments)",
2641
+ "Subscription management",
2642
+ "Payment tracking",
2643
+ "Invoice generation"
2644
+ ],
2645
+ minVersion: "2.0.0",
2646
+ examples: [
2647
+ {
2648
+ title: "Stripe Payment Form",
2649
+ description: "Accept payments with Stripe",
2650
+ code: `import { PaymentForm, usePayment } from '@djangocfg/ext-payments';
2651
+
2652
+ export default function CheckoutPage() {
2653
+ const { processPayment, isProcessing } = usePayment();
2654
+
2655
+ return (
2656
+ <PaymentForm
2657
+ amount={9900}
2658
+ currency="usd"
2659
+ onSuccess={(paymentIntent) => {
2660
+ console.log('Payment successful!', paymentIntent);
2661
+ }}
2662
+ />
2663
+ );
2664
+ }`,
2665
+ language: "tsx"
2666
+ },
2667
+ {
2668
+ title: "Cryptocurrency Payment",
2669
+ description: "Accept crypto payments via NowPayments",
2670
+ code: `import { CryptoPayment } from '@djangocfg/ext-payments';
2671
+
2672
+ export default function CryptoCheckout() {
2673
+ return (
2674
+ <CryptoPayment
2675
+ amount={100}
2676
+ currency="USDT"
2677
+ onPaymentCreated={(payment) => {
2678
+ console.log('Payment created:', payment.paymentUrl);
2679
+ }}
2680
+ />
2681
+ );
2682
+ }`,
2683
+ language: "tsx"
2684
+ }
2685
+ ]
2686
+ });
2687
+
2688
+ exports.API = API;
2689
+ exports.APIClient = APIClient;
2690
+ exports.APIError = APIError;
2691
+ exports.APILogger = APILogger;
2692
+ exports.BalanceSchema = BalanceSchema;
2693
+ exports.CookieStorageAdapter = CookieStorageAdapter;
2694
+ exports.CurrencySchema = CurrencySchema;
2695
+ exports.DEFAULT_RETRY_CONFIG = DEFAULT_RETRY_CONFIG;
2696
+ exports.Enums = enums_exports;
2697
+ exports.ExtPaymentsPaymentsTypes = models_exports;
2698
+ exports.FetchAdapter = FetchAdapter;
2699
+ exports.Fetchers = fetchers_exports;
2700
+ exports.LocalStorageAdapter = LocalStorageAdapter;
2701
+ exports.MemoryStorageAdapter = MemoryStorageAdapter;
2702
+ exports.NetworkError = NetworkError;
2703
+ exports.PAYMENT_EVENTS = PAYMENT_EVENTS;
2704
+ exports.PaginatedPaymentListListSchema = PaginatedPaymentListListSchema;
2705
+ exports.PaymentDetailSchema = PaymentDetailSchema;
2706
+ exports.PaymentListSchema = PaymentListSchema;
2707
+ exports.PaymentsLayout = PaymentsLayout;
2708
+ exports.REFRESH_TOKEN_KEY = REFRESH_TOKEN_KEY;
2709
+ exports.Schemas = schemas_exports;
2710
+ exports.TOKEN_KEY = TOKEN_KEY;
2711
+ exports.TransactionSchema = TransactionSchema;
2712
+ exports.apiPayments = apiPayments;
2713
+ exports.clearAPITokens = clearAPITokens;
2714
+ exports.closePaymentsDialog = closePaymentsDialog;
2715
+ exports.configureAPI = configureAPI;
2716
+ exports.createPaymentsPaymentsConfirmCreate = createPaymentsPaymentsConfirmCreate;
2717
+ exports.createPaymentsPaymentsCreateCreate = createPaymentsPaymentsCreateCreate;
2718
+ exports.dispatchValidationError = dispatchValidationError;
2719
+ exports.extensionConfig = extensionConfig;
2720
+ exports.formatZodError = formatZodError;
2721
+ exports.getAPIInstance = getAPIInstance;
2722
+ exports.getPaymentsBalanceRetrieve = getPaymentsBalanceRetrieve;
2723
+ exports.getPaymentsCurrenciesList = getPaymentsCurrenciesList;
2724
+ exports.getPaymentsPaymentsList = getPaymentsPaymentsList;
2725
+ exports.getPaymentsPaymentsRetrieve = getPaymentsPaymentsRetrieve;
2726
+ exports.getPaymentsPaymentsStatusRetrieve = getPaymentsPaymentsStatusRetrieve;
2727
+ exports.getPaymentsTransactionsList = getPaymentsTransactionsList;
2728
+ exports.isAPIConfigured = isAPIConfigured;
2729
+ exports.onValidationError = onValidationError;
2730
+ exports.openCreatePaymentDialog = openCreatePaymentDialog;
2731
+ exports.openPaymentDetailsDialog = openPaymentDetailsDialog;
2732
+ exports.reconfigureAPI = reconfigureAPI;
2733
+ exports.resetAPI = resetAPI;
2734
+ exports.shouldRetry = shouldRetry;
2735
+ exports.withRetry = withRetry;