@djangocfg/layouts 2.1.9 → 2.1.14

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 (106) 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/components/AvatarSection.tsx +2 -2
  13. package/src/layouts/PublicLayout/components/PublicMobileDrawer.tsx +1 -1
  14. package/src/layouts/PublicLayout/components/PublicNavigation.tsx +1 -1
  15. package/src/layouts/_components/UserMenu.tsx +1 -1
  16. package/src/layouts/index.ts +0 -2
  17. package/src/snippets/Analytics/useAnalytics.ts +1 -1
  18. package/src/snippets/McpChat/hooks/useAIChat.ts +16 -3
  19. package/src/snippets/index.ts +0 -3
  20. package/src/auth/README.md +0 -962
  21. package/src/auth/context/AccountsContext.tsx +0 -240
  22. package/src/auth/context/AuthContext.tsx +0 -604
  23. package/src/auth/context/index.ts +0 -4
  24. package/src/auth/context/types.ts +0 -68
  25. package/src/auth/hooks/index.ts +0 -17
  26. package/src/auth/hooks/useAuthForm.ts +0 -332
  27. package/src/auth/hooks/useAuthGuard.ts +0 -25
  28. package/src/auth/hooks/useAuthRedirect.ts +0 -51
  29. package/src/auth/hooks/useAutoAuth.ts +0 -49
  30. package/src/auth/hooks/useGithubAuth.ts +0 -184
  31. package/src/auth/hooks/useLocalStorage.ts +0 -214
  32. package/src/auth/hooks/useProfileCache.ts +0 -146
  33. package/src/auth/hooks/useSessionStorage.ts +0 -189
  34. package/src/auth/index.ts +0 -10
  35. package/src/auth/middlewares/index.ts +0 -1
  36. package/src/auth/middlewares/proxy.ts +0 -32
  37. package/src/auth/server.ts +0 -6
  38. package/src/auth/utils/errors.ts +0 -34
  39. package/src/auth/utils/index.ts +0 -2
  40. package/src/auth/utils/validation.ts +0 -14
  41. package/src/contexts/LeadsContext.tsx +0 -156
  42. package/src/contexts/NewsletterContext.tsx +0 -263
  43. package/src/contexts/SupportContext.tsx +0 -256
  44. package/src/contexts/index.ts +0 -59
  45. package/src/contexts/knowbase/ChatContext.tsx +0 -174
  46. package/src/contexts/knowbase/DocumentsContext.tsx +0 -304
  47. package/src/contexts/knowbase/SessionsContext.tsx +0 -174
  48. package/src/contexts/knowbase/index.ts +0 -61
  49. package/src/contexts/payments/BalancesContext.tsx +0 -65
  50. package/src/contexts/payments/CurrenciesContext.tsx +0 -66
  51. package/src/contexts/payments/OverviewContext.tsx +0 -174
  52. package/src/contexts/payments/PaymentsContext.tsx +0 -132
  53. package/src/contexts/payments/README.md +0 -201
  54. package/src/contexts/payments/RootPaymentsContext.tsx +0 -68
  55. package/src/contexts/payments/index.ts +0 -50
  56. package/src/layouts/PaymentsLayout/PaymentsLayout.tsx +0 -92
  57. package/src/layouts/PaymentsLayout/components/CreatePaymentDialog.tsx +0 -291
  58. package/src/layouts/PaymentsLayout/components/PaymentDetailsDialog.tsx +0 -290
  59. package/src/layouts/PaymentsLayout/components/index.ts +0 -2
  60. package/src/layouts/PaymentsLayout/events.ts +0 -47
  61. package/src/layouts/PaymentsLayout/index.ts +0 -16
  62. package/src/layouts/PaymentsLayout/types.ts +0 -6
  63. package/src/layouts/PaymentsLayout/views/overview/components/BalanceCard.tsx +0 -128
  64. package/src/layouts/PaymentsLayout/views/overview/components/RecentPayments.tsx +0 -142
  65. package/src/layouts/PaymentsLayout/views/overview/components/index.ts +0 -2
  66. package/src/layouts/PaymentsLayout/views/overview/index.tsx +0 -20
  67. package/src/layouts/PaymentsLayout/views/payments/components/PaymentsList.tsx +0 -276
  68. package/src/layouts/PaymentsLayout/views/payments/components/index.ts +0 -1
  69. package/src/layouts/PaymentsLayout/views/payments/index.tsx +0 -17
  70. package/src/layouts/PaymentsLayout/views/transactions/components/TransactionsList.tsx +0 -273
  71. package/src/layouts/PaymentsLayout/views/transactions/components/index.ts +0 -1
  72. package/src/layouts/PaymentsLayout/views/transactions/index.tsx +0 -17
  73. package/src/layouts/SupportLayout/README.md +0 -91
  74. package/src/layouts/SupportLayout/SupportLayout.tsx +0 -179
  75. package/src/layouts/SupportLayout/components/CreateTicketDialog.tsx +0 -155
  76. package/src/layouts/SupportLayout/components/MessageInput.tsx +0 -92
  77. package/src/layouts/SupportLayout/components/MessageList.tsx +0 -314
  78. package/src/layouts/SupportLayout/components/TicketCard.tsx +0 -96
  79. package/src/layouts/SupportLayout/components/TicketList.tsx +0 -153
  80. package/src/layouts/SupportLayout/components/index.ts +0 -6
  81. package/src/layouts/SupportLayout/context/SupportLayoutContext.tsx +0 -263
  82. package/src/layouts/SupportLayout/context/index.ts +0 -2
  83. package/src/layouts/SupportLayout/events.ts +0 -33
  84. package/src/layouts/SupportLayout/hooks/index.ts +0 -2
  85. package/src/layouts/SupportLayout/hooks/useInfiniteMessages.ts +0 -119
  86. package/src/layouts/SupportLayout/hooks/useInfiniteTickets.ts +0 -92
  87. package/src/layouts/SupportLayout/index.ts +0 -8
  88. package/src/layouts/SupportLayout/types.ts +0 -21
  89. package/src/snippets/Chat/ChatUIContext.tsx +0 -110
  90. package/src/snippets/Chat/ChatWidget.tsx +0 -476
  91. package/src/snippets/Chat/README.md +0 -122
  92. package/src/snippets/Chat/components/MessageInput.tsx +0 -124
  93. package/src/snippets/Chat/components/MessageList.tsx +0 -169
  94. package/src/snippets/Chat/components/SessionList.tsx +0 -192
  95. package/src/snippets/Chat/components/index.ts +0 -9
  96. package/src/snippets/Chat/hooks/index.ts +0 -6
  97. package/src/snippets/Chat/hooks/useInfiniteSessions.ts +0 -82
  98. package/src/snippets/Chat/index.tsx +0 -45
  99. package/src/snippets/Chat/types.ts +0 -80
  100. package/src/snippets/ContactForm/ContactForm.tsx +0 -346
  101. package/src/snippets/ContactForm/ContactFormProvider.tsx +0 -153
  102. package/src/snippets/ContactForm/ContactInfo.tsx +0 -114
  103. package/src/snippets/ContactForm/ContactPage.tsx +0 -131
  104. package/src/snippets/ContactForm/dynamic.tsx +0 -55
  105. package/src/snippets/ContactForm/index.ts +0 -34
  106. 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
- };