@djangocfg/layouts 2.1.10 → 2.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/README.md +53 -161
  2. package/package.json +6 -6
  3. package/src/components/RedirectPage/RedirectPage.tsx +1 -1
  4. package/src/index.ts +0 -6
  5. package/src/layouts/AppLayout/AppLayout.tsx +1 -1
  6. package/src/layouts/AppLayout/BaseApp.tsx +1 -1
  7. package/src/layouts/AuthLayout/AuthContext.tsx +1 -1
  8. package/src/layouts/AuthLayout/OAuthCallback.tsx +1 -1
  9. package/src/layouts/AuthLayout/OAuthProviders.tsx +1 -1
  10. package/src/layouts/PrivateLayout/PrivateLayout.tsx +1 -1
  11. package/src/layouts/PrivateLayout/components/PrivateHeader.tsx +1 -1
  12. package/src/layouts/ProfileLayout/ProfileLayout.tsx +2 -2
  13. package/src/layouts/ProfileLayout/components/AvatarSection.tsx +2 -2
  14. package/src/layouts/ProfileLayout/components/ProfileForm.tsx +2 -2
  15. package/src/layouts/PublicLayout/components/PublicMobileDrawer.tsx +1 -1
  16. package/src/layouts/PublicLayout/components/PublicNavigation.tsx +1 -1
  17. package/src/layouts/_components/UserMenu.tsx +1 -1
  18. package/src/layouts/index.ts +0 -2
  19. package/src/snippets/Analytics/useAnalytics.ts +1 -1
  20. package/src/snippets/index.ts +0 -3
  21. package/src/auth/README.md +0 -962
  22. package/src/auth/context/AccountsContext.tsx +0 -240
  23. package/src/auth/context/AuthContext.tsx +0 -604
  24. package/src/auth/context/index.ts +0 -4
  25. package/src/auth/context/types.ts +0 -68
  26. package/src/auth/hooks/index.ts +0 -17
  27. package/src/auth/hooks/useAuthForm.ts +0 -332
  28. package/src/auth/hooks/useAuthGuard.ts +0 -25
  29. package/src/auth/hooks/useAuthRedirect.ts +0 -51
  30. package/src/auth/hooks/useAutoAuth.ts +0 -49
  31. package/src/auth/hooks/useGithubAuth.ts +0 -184
  32. package/src/auth/hooks/useLocalStorage.ts +0 -214
  33. package/src/auth/hooks/useProfileCache.ts +0 -146
  34. package/src/auth/hooks/useSessionStorage.ts +0 -189
  35. package/src/auth/index.ts +0 -10
  36. package/src/auth/middlewares/index.ts +0 -1
  37. package/src/auth/middlewares/proxy.ts +0 -32
  38. package/src/auth/server.ts +0 -6
  39. package/src/auth/utils/errors.ts +0 -34
  40. package/src/auth/utils/index.ts +0 -2
  41. package/src/auth/utils/validation.ts +0 -14
  42. package/src/contexts/LeadsContext.tsx +0 -156
  43. package/src/contexts/NewsletterContext.tsx +0 -263
  44. package/src/contexts/SupportContext.tsx +0 -256
  45. package/src/contexts/index.ts +0 -59
  46. package/src/contexts/knowbase/ChatContext.tsx +0 -174
  47. package/src/contexts/knowbase/DocumentsContext.tsx +0 -304
  48. package/src/contexts/knowbase/SessionsContext.tsx +0 -174
  49. package/src/contexts/knowbase/index.ts +0 -61
  50. package/src/contexts/payments/BalancesContext.tsx +0 -65
  51. package/src/contexts/payments/CurrenciesContext.tsx +0 -66
  52. package/src/contexts/payments/OverviewContext.tsx +0 -174
  53. package/src/contexts/payments/PaymentsContext.tsx +0 -132
  54. package/src/contexts/payments/README.md +0 -201
  55. package/src/contexts/payments/RootPaymentsContext.tsx +0 -68
  56. package/src/contexts/payments/index.ts +0 -50
  57. package/src/layouts/PaymentsLayout/PaymentsLayout.tsx +0 -92
  58. package/src/layouts/PaymentsLayout/components/CreatePaymentDialog.tsx +0 -291
  59. package/src/layouts/PaymentsLayout/components/PaymentDetailsDialog.tsx +0 -290
  60. package/src/layouts/PaymentsLayout/components/index.ts +0 -2
  61. package/src/layouts/PaymentsLayout/events.ts +0 -47
  62. package/src/layouts/PaymentsLayout/index.ts +0 -16
  63. package/src/layouts/PaymentsLayout/types.ts +0 -6
  64. package/src/layouts/PaymentsLayout/views/overview/components/BalanceCard.tsx +0 -128
  65. package/src/layouts/PaymentsLayout/views/overview/components/RecentPayments.tsx +0 -142
  66. package/src/layouts/PaymentsLayout/views/overview/components/index.ts +0 -2
  67. package/src/layouts/PaymentsLayout/views/overview/index.tsx +0 -20
  68. package/src/layouts/PaymentsLayout/views/payments/components/PaymentsList.tsx +0 -276
  69. package/src/layouts/PaymentsLayout/views/payments/components/index.ts +0 -1
  70. package/src/layouts/PaymentsLayout/views/payments/index.tsx +0 -17
  71. package/src/layouts/PaymentsLayout/views/transactions/components/TransactionsList.tsx +0 -273
  72. package/src/layouts/PaymentsLayout/views/transactions/components/index.ts +0 -1
  73. package/src/layouts/PaymentsLayout/views/transactions/index.tsx +0 -17
  74. package/src/layouts/SupportLayout/README.md +0 -91
  75. package/src/layouts/SupportLayout/SupportLayout.tsx +0 -179
  76. package/src/layouts/SupportLayout/components/CreateTicketDialog.tsx +0 -155
  77. package/src/layouts/SupportLayout/components/MessageInput.tsx +0 -92
  78. package/src/layouts/SupportLayout/components/MessageList.tsx +0 -314
  79. package/src/layouts/SupportLayout/components/TicketCard.tsx +0 -96
  80. package/src/layouts/SupportLayout/components/TicketList.tsx +0 -153
  81. package/src/layouts/SupportLayout/components/index.ts +0 -6
  82. package/src/layouts/SupportLayout/context/SupportLayoutContext.tsx +0 -263
  83. package/src/layouts/SupportLayout/context/index.ts +0 -2
  84. package/src/layouts/SupportLayout/events.ts +0 -33
  85. package/src/layouts/SupportLayout/hooks/index.ts +0 -2
  86. package/src/layouts/SupportLayout/hooks/useInfiniteMessages.ts +0 -119
  87. package/src/layouts/SupportLayout/hooks/useInfiniteTickets.ts +0 -92
  88. package/src/layouts/SupportLayout/index.ts +0 -8
  89. package/src/layouts/SupportLayout/types.ts +0 -21
  90. package/src/snippets/Chat/ChatUIContext.tsx +0 -110
  91. package/src/snippets/Chat/ChatWidget.tsx +0 -476
  92. package/src/snippets/Chat/README.md +0 -122
  93. package/src/snippets/Chat/components/MessageInput.tsx +0 -124
  94. package/src/snippets/Chat/components/MessageList.tsx +0 -169
  95. package/src/snippets/Chat/components/SessionList.tsx +0 -192
  96. package/src/snippets/Chat/components/index.ts +0 -9
  97. package/src/snippets/Chat/hooks/index.ts +0 -6
  98. package/src/snippets/Chat/hooks/useInfiniteSessions.ts +0 -82
  99. package/src/snippets/Chat/index.tsx +0 -45
  100. package/src/snippets/Chat/types.ts +0 -80
  101. package/src/snippets/ContactForm/ContactForm.tsx +0 -346
  102. package/src/snippets/ContactForm/ContactFormProvider.tsx +0 -153
  103. package/src/snippets/ContactForm/ContactInfo.tsx +0 -114
  104. package/src/snippets/ContactForm/ContactPage.tsx +0 -131
  105. package/src/snippets/ContactForm/dynamic.tsx +0 -55
  106. package/src/snippets/ContactForm/index.ts +0 -34
  107. package/src/snippets/ContactForm/types.ts +0 -110
@@ -1,128 +0,0 @@
1
- /**
2
- * Balance Card Component (v2.0 - Simplified)
3
- * Display user balance with quick actions
4
- */
5
-
6
- 'use client';
7
-
8
- import React from 'react';
9
- import {
10
- Card,
11
- CardContent,
12
- CardHeader,
13
- CardTitle,
14
- Button,
15
- Badge,
16
- Skeleton,
17
- } from '@djangocfg/ui-nextjs';
18
- import { Wallet, RefreshCw, Plus } from 'lucide-react';
19
- import { useOverviewContext } from '@djangocfg/layouts/contexts';
20
- import { openCreatePaymentDialog } from '../../../events';
21
-
22
- export const BalanceCard: React.FC = () => {
23
- const {
24
- balance,
25
- isLoadingBalance,
26
- refreshBalance
27
- } = useOverviewContext();
28
-
29
- const formatCurrency = (amount?: number | null) => {
30
- if (amount === null || amount === undefined) return '$0.00';
31
- return new Intl.NumberFormat('en-US', {
32
- style: 'currency',
33
- currency: 'USD',
34
- minimumFractionDigits: 2,
35
- }).format(amount);
36
- };
37
-
38
- const formatDate = (dateStr?: string) => {
39
- if (!dateStr) return 'No transactions yet';
40
- try {
41
- return new Date(dateStr).toLocaleDateString('en-US', {
42
- year: 'numeric',
43
- month: 'short',
44
- day: 'numeric',
45
- });
46
- } catch {
47
- return 'Invalid date';
48
- }
49
- };
50
-
51
- if (isLoadingBalance) {
52
- return (
53
- <Card>
54
- <CardHeader>
55
- <CardTitle className="flex items-center justify-between">
56
- <div className="flex items-center gap-2">
57
- <Wallet className="h-5 w-5" />
58
- Account Balance
59
- </div>
60
- <Skeleton className="h-8 w-20" />
61
- </CardTitle>
62
- </CardHeader>
63
- <CardContent className="space-y-4">
64
- <Skeleton className="h-10 w-32" />
65
- <Skeleton className="h-4 w-48" />
66
- </CardContent>
67
- </Card>
68
- );
69
- }
70
-
71
- // Extract balance data from response: { success, balance: { amount_usd, total_deposited, total_withdrawn, last_transaction_at } }
72
- const balanceData = balance?.balance || balance;
73
- const amountUsd = balanceData?.amount_usd ?? 0;
74
- const totalDeposited = balanceData?.total_deposited ?? 0;
75
- const totalWithdrawn = balanceData?.total_withdrawn ?? 0;
76
- const lastTransactionAt = balanceData?.last_transaction_at;
77
- const isEmpty = amountUsd === 0 && totalDeposited === 0;
78
-
79
- return (
80
- <Card>
81
- <CardHeader>
82
- <CardTitle className="flex items-center justify-between">
83
- <div className="flex items-center gap-2">
84
- <Wallet className="h-5 w-5" />
85
- Account Balance
86
- </div>
87
- <div className="flex items-center gap-2">
88
- <Button variant="ghost" size="sm" onClick={refreshBalance}>
89
- <RefreshCw className="h-4 w-4" />
90
- </Button>
91
- <Button size="sm" onClick={() => openCreatePaymentDialog()}>
92
- <Plus className="h-4 w-4 mr-2" />
93
- Add Funds
94
- </Button>
95
- </div>
96
- </CardTitle>
97
- </CardHeader>
98
- <CardContent className="space-y-4">
99
- <div>
100
- <div className="text-4xl font-bold">
101
- {formatCurrency(amountUsd)}
102
- </div>
103
- <p className="text-sm text-muted-foreground mt-1">
104
- Available balance • Last updated {formatDate(lastTransactionAt)}
105
- </p>
106
- </div>
107
-
108
- <div className="grid grid-cols-2 gap-4 pt-4 border-t">
109
- <div>
110
- <p className="text-xs text-muted-foreground">Total Deposited</p>
111
- <p className="text-lg font-semibold text-green-600">{formatCurrency(totalDeposited)}</p>
112
- </div>
113
- <div>
114
- <p className="text-xs text-muted-foreground">Total Withdrawn</p>
115
- <p className="text-lg font-semibold text-red-600">{formatCurrency(totalWithdrawn)}</p>
116
- </div>
117
- </div>
118
-
119
- <div className="flex items-center gap-2">
120
- <Badge variant={!isEmpty ? 'default' : 'secondary'}>
121
- {!isEmpty ? 'Active' : 'New Account'}
122
- </Badge>
123
- {isEmpty && <Badge variant="outline">Empty Balance</Badge>}
124
- </div>
125
- </CardContent>
126
- </Card>
127
- );
128
- };
@@ -1,142 +0,0 @@
1
- /**
2
- * Recent Payments Component (v2.0 - Simplified)
3
- * Display recent payment transactions from payments list
4
- */
5
-
6
- 'use client';
7
-
8
- import React from 'react';
9
- import {
10
- Card,
11
- CardContent,
12
- CardHeader,
13
- CardTitle,
14
- Button,
15
- Badge,
16
- Skeleton,
17
- } from '@djangocfg/ui-nextjs';
18
- import { History, ExternalLink } from 'lucide-react';
19
- import { useOverviewContext } from '@djangocfg/layouts/contexts';
20
- import { openPaymentDetailsDialog } from '../../../events';
21
-
22
- export const RecentPayments: React.FC = () => {
23
- const { payments, isLoadingPayments } = useOverviewContext();
24
-
25
- const formatCurrency = (amount?: number | string | null) => {
26
- if (amount === null || amount === undefined) return '$0.00';
27
- const numAmount = typeof amount === 'string' ? parseFloat(amount) : amount;
28
- return new Intl.NumberFormat('en-US', {
29
- style: 'currency',
30
- currency: 'USD',
31
- minimumFractionDigits: 2,
32
- }).format(numAmount);
33
- };
34
-
35
- const getRelativeTime = (date: string | null | undefined): string => {
36
- if (!date) return 'N/A';
37
-
38
- const now = new Date();
39
- const target = new Date(date);
40
- const diffInSeconds = Math.floor((now.getTime() - target.getTime()) / 1000);
41
-
42
- if (diffInSeconds < 60) return 'Just now';
43
- if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
44
- if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
45
- return `${Math.floor(diffInSeconds / 86400)}d ago`;
46
- };
47
-
48
- const getStatusVariant = (
49
- status: string | null | undefined
50
- ): 'default' | 'destructive' | 'outline' | 'secondary' => {
51
- switch (status?.toLowerCase()) {
52
- case 'completed':
53
- case 'success':
54
- return 'default';
55
- case 'pending':
56
- case 'confirming':
57
- return 'secondary';
58
- case 'failed':
59
- case 'error':
60
- case 'expired':
61
- return 'destructive';
62
- default:
63
- return 'outline';
64
- }
65
- };
66
-
67
- if (isLoadingPayments) {
68
- return (
69
- <Card>
70
- <CardHeader>
71
- <CardTitle className="flex items-center gap-2">
72
- <History className="h-5 w-5" />
73
- Recent Payments
74
- </CardTitle>
75
- </CardHeader>
76
- <CardContent className="space-y-3">
77
- {Array.from({ length: 5 }).map((_, i) => (
78
- <div key={i} className="flex items-center justify-between p-3 border rounded-sm">
79
- <div className="space-y-2">
80
- <Skeleton className="h-4 w-32" />
81
- <Skeleton className="h-3 w-24" />
82
- </div>
83
- <Skeleton className="h-6 w-16" />
84
- </div>
85
- ))}
86
- </CardContent>
87
- </Card>
88
- );
89
- }
90
-
91
- // Get first 5 payments for recent list
92
- const recentPaymentsList = payments?.results?.slice(0, 5) || [];
93
-
94
- return (
95
- <Card>
96
- <CardHeader>
97
- <CardTitle className="flex items-center justify-between">
98
- <div className="flex items-center gap-2">
99
- <History className="h-5 w-5" />
100
- Recent Payments
101
- </div>
102
- <Button variant="ghost" size="sm">
103
- View All
104
- <ExternalLink className="h-4 w-4 ml-2" />
105
- </Button>
106
- </CardTitle>
107
- </CardHeader>
108
- <CardContent>
109
- {recentPaymentsList.length === 0 ? (
110
- <div className="text-center py-8 text-muted-foreground">
111
- <History className="h-12 w-12 mx-auto mb-4 opacity-50" />
112
- <p>No recent payments</p>
113
- <p className="text-sm mt-2">Create your first payment to get started</p>
114
- </div>
115
- ) : (
116
- <div className="space-y-3">
117
- {recentPaymentsList.map((payment) => (
118
- <div
119
- key={payment.id}
120
- className="flex items-center justify-between p-3 border rounded-sm hover:bg-accent cursor-pointer transition-colors"
121
- onClick={() => openPaymentDetailsDialog(String(payment.id))}
122
- >
123
- <div className="flex-1">
124
- <div className="flex items-center gap-2">
125
- <span className="font-medium">{formatCurrency(payment.amount_usd)}</span>
126
- <Badge variant={getStatusVariant(payment.status)} className="text-xs">
127
- {payment.status}
128
- </Badge>
129
- </div>
130
- <p className="text-sm text-muted-foreground">
131
- {getRelativeTime(payment.created_at)} • {payment.currency_code || 'USD'}
132
- </p>
133
- </div>
134
- <ExternalLink className="h-4 w-4 text-muted-foreground" />
135
- </div>
136
- ))}
137
- </div>
138
- )}
139
- </CardContent>
140
- </Card>
141
- );
142
- };
@@ -1,2 +0,0 @@
1
- export { BalanceCard } from './BalanceCard';
2
- export { RecentPayments } from './RecentPayments';
@@ -1,20 +0,0 @@
1
- /**
2
- * Overview View (v2.0 - Simplified)
3
- * Dashboard with balance and recent payments
4
- */
5
-
6
- 'use client';
7
-
8
- import React from 'react';
9
- import { BalanceCard, RecentPayments } from './components';
10
-
11
- export const OverviewView: React.FC = () => {
12
- return (
13
- <div className="space-y-6">
14
- <div className="grid gap-6 lg:grid-cols-2">
15
- <BalanceCard />
16
- <RecentPayments />
17
- </div>
18
- </div>
19
- );
20
- };
@@ -1,276 +0,0 @@
1
- /**
2
- * Payments List Component (v2.0 - Simplified)
3
- * Display paginated list of payments with filters
4
- */
5
-
6
- 'use client';
7
-
8
- import React, { useState } from 'react';
9
- import {
10
- Card,
11
- CardContent,
12
- CardHeader,
13
- CardTitle,
14
- Table,
15
- TableBody,
16
- TableCell,
17
- TableHead,
18
- TableHeader,
19
- TableRow,
20
- Button,
21
- Badge,
22
- Input,
23
- Select,
24
- SelectContent,
25
- SelectItem,
26
- SelectTrigger,
27
- SelectValue,
28
- Skeleton,
29
- useDRFPagination,
30
- StaticPagination,
31
- } from '@djangocfg/ui-nextjs';
32
- import { Plus, Search, Filter, RefreshCw, ExternalLink } from 'lucide-react';
33
- import { api, Hooks } from '@djangocfg/api';
34
- import { openCreatePaymentDialog, openPaymentDetailsDialog } from '../../../events';
35
-
36
- export const PaymentsList: React.FC = () => {
37
- // Local pagination state
38
- const pagination = useDRFPagination(1, 20);
39
-
40
- // Fetch payments with pagination
41
- const {
42
- data: payments,
43
- error,
44
- isLoading: isLoadingPayments,
45
- mutate: refreshPayments,
46
- } = Hooks.usePaymentsPaymentsList(pagination.params, api as any);
47
-
48
- const paymentsList = payments?.results || [];
49
- const totalCount = payments?.count || 0;
50
-
51
- const [searchTerm, setSearchTerm] = useState('');
52
- const [statusFilter, setStatusFilter] = useState<string>('all');
53
-
54
- const formatCurrency = (amount?: number | string | null) => {
55
- if (amount === null || amount === undefined) return '$0.00';
56
- const numAmount = typeof amount === 'string' ? parseFloat(amount) : amount;
57
- return new Intl.NumberFormat('en-US', {
58
- style: 'currency',
59
- currency: 'USD',
60
- minimumFractionDigits: 2,
61
- }).format(numAmount);
62
- };
63
-
64
- const getRelativeTime = (date: string | null | undefined): string => {
65
- if (!date) return 'N/A';
66
-
67
- const now = new Date();
68
- const target = new Date(date);
69
- const diffInSeconds = Math.floor((now.getTime() - target.getTime()) / 1000);
70
-
71
- if (diffInSeconds < 60) return 'Just now';
72
- if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
73
- if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
74
- return `${Math.floor(diffInSeconds / 86400)}d ago`;
75
- };
76
-
77
- const getStatusVariant = (
78
- status: string | null | undefined
79
- ): 'default' | 'destructive' | 'outline' | 'secondary' => {
80
- switch (status?.toLowerCase()) {
81
- case 'completed':
82
- case 'success':
83
- return 'default';
84
- case 'pending':
85
- case 'confirming':
86
- return 'secondary';
87
- case 'failed':
88
- case 'error':
89
- case 'expired':
90
- return 'destructive';
91
- default:
92
- return 'outline';
93
- }
94
- };
95
-
96
- const handleSearch = (value: string) => {
97
- setSearchTerm(value);
98
- // Client-side filtering only
99
- };
100
-
101
- const handleStatusFilter = (status: string) => {
102
- setStatusFilter(status);
103
- // Client-side filtering only
104
- };
105
-
106
-
107
- // Filter payments client-side for now (until API supports filtering)
108
- const filteredPayments = paymentsList.filter((payment) => {
109
- const matchesSearch = searchTerm
110
- ? payment.id?.toLowerCase().includes(searchTerm.toLowerCase()) ||
111
- payment.status?.toLowerCase().includes(searchTerm.toLowerCase()) ||
112
- payment.currency_code?.toLowerCase().includes(searchTerm.toLowerCase())
113
- : true;
114
-
115
- const matchesStatus = statusFilter !== 'all'
116
- ? payment.status?.toLowerCase() === statusFilter.toLowerCase()
117
- : true;
118
-
119
- return matchesSearch && matchesStatus;
120
- });
121
-
122
- return (
123
- <Card>
124
- <CardHeader>
125
- <CardTitle className="flex items-center justify-between">
126
- <span>Payment History</span>
127
- <div className="flex items-center gap-2">
128
- <Button variant="outline" size="sm" onClick={() => refreshPayments()} disabled={isLoadingPayments}>
129
- <RefreshCw className={`h-4 w-4 mr-2 ${isLoadingPayments ? 'animate-spin' : ''}`} />
130
- Refresh
131
- </Button>
132
- <Button size="sm" onClick={() => openCreatePaymentDialog()}>
133
- <Plus className="h-4 w-4 mr-2" />
134
- New Payment
135
- </Button>
136
- </div>
137
- </CardTitle>
138
- </CardHeader>
139
-
140
- <CardContent className="space-y-4">
141
- {/* Filters */}
142
- <div className="flex flex-col sm:flex-row gap-4">
143
- <div className="relative flex-1">
144
- <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
145
- <Input
146
- placeholder="Search by ID, status, or currency..."
147
- value={searchTerm}
148
- onChange={(e) => handleSearch(e.target.value)}
149
- className="pl-10"
150
- />
151
- </div>
152
-
153
- <Select value={statusFilter} onValueChange={handleStatusFilter}>
154
- <SelectTrigger className="w-full sm:w-48">
155
- <Filter className="h-4 w-4 mr-2" />
156
- <SelectValue placeholder="Filter by status" />
157
- </SelectTrigger>
158
- <SelectContent>
159
- <SelectItem value="all">All Statuses</SelectItem>
160
- <SelectItem value="completed">Completed</SelectItem>
161
- <SelectItem value="pending">Pending</SelectItem>
162
- <SelectItem value="confirming">Confirming</SelectItem>
163
- <SelectItem value="failed">Failed</SelectItem>
164
- <SelectItem value="expired">Expired</SelectItem>
165
- </SelectContent>
166
- </Select>
167
- </div>
168
-
169
- {/* Payments Table */}
170
- {isLoadingPayments ? (
171
- <div className="space-y-3">
172
- {Array.from({ length: 5 }).map((_, i) => (
173
- <div key={i} className="flex items-center justify-between p-4 border rounded-sm">
174
- <div className="space-y-2">
175
- <Skeleton className="h-4 w-32" />
176
- <Skeleton className="h-3 w-24" />
177
- </div>
178
- <Skeleton className="h-6 w-16" />
179
- </div>
180
- ))}
181
- </div>
182
- ) : filteredPayments.length === 0 ? (
183
- <div className="text-center py-12">
184
- <div className="w-16 h-16 mx-auto mb-4 bg-muted rounded-full flex items-center justify-center">
185
- <Search className="w-8 h-8 text-muted-foreground" />
186
- </div>
187
- <h3 className="text-lg font-semibold mb-2">No Payments Found</h3>
188
- <p className="text-muted-foreground mb-4">
189
- {searchTerm || statusFilter !== 'all'
190
- ? 'No payments match your current filters'
191
- : "You haven't made any payments yet"}
192
- </p>
193
- <Button onClick={() => openCreatePaymentDialog()}>
194
- <Plus className="h-4 w-4 mr-2" />
195
- Create Payment
196
- </Button>
197
- </div>
198
- ) : (
199
- <>
200
- <div className="rounded-md border">
201
- <Table>
202
- <TableHeader>
203
- <TableRow>
204
- <TableHead>Date</TableHead>
205
- <TableHead>Amount</TableHead>
206
- <TableHead>Currency</TableHead>
207
- <TableHead>Status</TableHead>
208
- <TableHead>Provider</TableHead>
209
- <TableHead>Payment ID</TableHead>
210
- <TableHead className="text-right">Actions</TableHead>
211
- </TableRow>
212
- </TableHeader>
213
- <TableBody>
214
- {filteredPayments.map((payment) => (
215
- <TableRow
216
- key={payment.id}
217
- className="cursor-pointer hover:bg-accent"
218
- onClick={() => openPaymentDetailsDialog(String(payment.id))}
219
- >
220
- <TableCell>
221
- <div>
222
- <div className="font-medium">
223
- {payment.created_at
224
- ? new Date(payment.created_at).toLocaleDateString()
225
- : 'N/A'}
226
- </div>
227
- <div className="text-sm text-muted-foreground">
228
- {getRelativeTime(payment.created_at)}
229
- </div>
230
- </div>
231
- </TableCell>
232
- <TableCell className="font-mono font-semibold">
233
- {formatCurrency(payment.amount_usd)}
234
- </TableCell>
235
- <TableCell>
236
- <Badge variant="outline">{payment.currency_code || 'USD'}</Badge>
237
- </TableCell>
238
- <TableCell>
239
- <Badge variant={getStatusVariant(payment.status)}>{payment.status}</Badge>
240
- </TableCell>
241
- <TableCell className="text-sm text-muted-foreground">
242
- NowPayments
243
- </TableCell>
244
- <TableCell className="font-mono text-sm text-muted-foreground">
245
- {payment.id ? `${payment.id.toString().slice(0, 8)}...` : 'N/A'}
246
- </TableCell>
247
- <TableCell className="text-right">
248
- <Button
249
- variant="ghost"
250
- size="sm"
251
- onClick={(e) => {
252
- e.stopPropagation();
253
- openPaymentDetailsDialog(String(payment.id));
254
- }}
255
- >
256
- <ExternalLink className="h-4 w-4" />
257
- </Button>
258
- </TableCell>
259
- </TableRow>
260
- ))}
261
- </TableBody>
262
- </Table>
263
- </div>
264
-
265
- {/* DRF Pagination */}
266
- <StaticPagination
267
- data={payments}
268
- onPageChange={pagination.setPage}
269
- className="mt-4"
270
- />
271
- </>
272
- )}
273
- </CardContent>
274
- </Card>
275
- );
276
- };
@@ -1 +0,0 @@
1
- export { PaymentsList } from './PaymentsList';
@@ -1,17 +0,0 @@
1
- /**
2
- * Payments View (v2.0 - Simplified)
3
- * List and manage payment transactions
4
- */
5
-
6
- 'use client';
7
-
8
- import React from 'react';
9
- import { PaymentsList } from './components';
10
-
11
- export const PaymentsView: React.FC = () => {
12
- return (
13
- <div className="space-y-6">
14
- <PaymentsList />
15
- </div>
16
- );
17
- };