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