@djangocfg/ext-payments 1.0.6 → 1.0.7

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 (44) hide show
  1. package/dist/config.cjs +2 -1
  2. package/dist/config.js +2 -1
  3. package/dist/hooks.cjs +558 -542
  4. package/dist/hooks.js +557 -542
  5. package/dist/index.cjs +558 -542
  6. package/dist/index.d.cts +0 -97
  7. package/dist/index.d.ts +0 -97
  8. package/dist/index.js +557 -542
  9. package/package.json +9 -8
  10. package/src/api/generated/ext_payments/CLAUDE.md +76 -0
  11. package/src/api/generated/ext_payments/_utils/fetchers/ext_payments__payments.ts +1 -8
  12. package/src/api/generated/ext_payments/_utils/fetchers/index.ts +1 -8
  13. package/src/api/generated/ext_payments/_utils/hooks/ext_payments__payments.ts +1 -8
  14. package/src/api/generated/ext_payments/_utils/hooks/index.ts +1 -8
  15. package/src/api/generated/ext_payments/_utils/schemas/index.ts +1 -8
  16. package/src/api/generated/ext_payments/api-instance.ts +1 -8
  17. package/src/api/generated/ext_payments/enums.ts +1 -8
  18. package/src/api/generated/ext_payments/errors.ts +1 -8
  19. package/src/api/generated/ext_payments/ext_payments__payments/index.ts +1 -8
  20. package/src/api/generated/ext_payments/ext_payments__payments/models.ts +1 -8
  21. package/src/api/generated/ext_payments/http.ts +1 -8
  22. package/src/api/generated/ext_payments/index.ts +1 -8
  23. package/src/api/generated/ext_payments/logger.ts +1 -8
  24. package/src/api/generated/ext_payments/retry.ts +1 -8
  25. package/src/api/generated/ext_payments/storage.ts +1 -8
  26. package/src/api/generated/ext_payments/validation-events.ts +1 -8
  27. package/src/api/index.ts +2 -1
  28. package/src/config.ts +1 -0
  29. package/src/contexts/BalancesContext.tsx +2 -1
  30. package/src/contexts/CurrenciesContext.tsx +2 -1
  31. package/src/contexts/OverviewContext.tsx +5 -5
  32. package/src/contexts/PaymentsContext.tsx +6 -5
  33. package/src/contexts/PaymentsExtensionProvider.tsx +3 -2
  34. package/src/contexts/RootPaymentsContext.tsx +2 -1
  35. package/src/layouts/PaymentsLayout/PaymentsLayout.tsx +5 -7
  36. package/src/layouts/PaymentsLayout/components/CreatePaymentDialog.tsx +10 -27
  37. package/src/layouts/PaymentsLayout/components/PaymentDetailsDialog.tsx +15 -18
  38. package/src/layouts/PaymentsLayout/views/overview/components/BalanceCard.tsx +6 -13
  39. package/src/layouts/PaymentsLayout/views/overview/components/RecentPayments.tsx +8 -11
  40. package/src/layouts/PaymentsLayout/views/overview/index.tsx +1 -0
  41. package/src/layouts/PaymentsLayout/views/payments/components/PaymentsList.tsx +43 -42
  42. package/src/layouts/PaymentsLayout/views/payments/index.tsx +1 -0
  43. package/src/layouts/PaymentsLayout/views/transactions/components/TransactionsList.tsx +71 -84
  44. package/src/layouts/PaymentsLayout/views/transactions/index.tsx +1 -0
@@ -6,6 +6,7 @@
6
6
  'use client';
7
7
 
8
8
  import React from 'react';
9
+
9
10
  import { BalanceCard, RecentPayments } from './components';
10
11
 
11
12
  export const OverviewView: React.FC = () => {
@@ -5,31 +5,16 @@
5
5
 
6
6
  'use client';
7
7
 
8
+ import { ExternalLink, Filter, Plus, RefreshCw, Search } from 'lucide-react';
9
+ import moment from 'moment';
8
10
  import React, { useState } from 'react';
11
+
9
12
  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,
13
+ Badge, Button, Card, CardContent, CardHeader, CardTitle, Input, Select, SelectContent,
14
+ SelectItem, SelectTrigger, SelectValue, Skeleton, StaticPagination, Table, TableBody, TableCell,
15
+ TableHead, TableHeader, TableRow, useDRFPagination
31
16
  } from '@djangocfg/ui-nextjs';
32
- import { Plus, Search, Filter, RefreshCw, ExternalLink } from 'lucide-react';
17
+
33
18
  import { apiPayments } from '../../../../../api';
34
19
  import { usePaymentsPaymentsList } from '../../../../../api/generated/ext_payments/_utils/hooks';
35
20
  import { openCreatePaymentDialog, openPaymentDetailsDialog } from '../../../events';
@@ -65,9 +50,9 @@ export const PaymentsList: React.FC = () => {
65
50
  const getRelativeTime = (date: string | null | undefined): string => {
66
51
  if (!date) return 'N/A';
67
52
 
68
- const now = new Date();
69
- const target = new Date(date);
70
- const diffInSeconds = Math.floor((now.getTime() - target.getTime()) / 1000);
53
+ const m = moment.utc(date).local();
54
+ const now = moment();
55
+ const diffInSeconds = now.diff(m, 'seconds');
71
56
 
72
57
  if (diffInSeconds < 60) return 'Just now';
73
58
  if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
@@ -75,6 +60,11 @@ export const PaymentsList: React.FC = () => {
75
60
  return `${Math.floor(diffInSeconds / 86400)}d ago`;
76
61
  };
77
62
 
63
+ const formatDate = (date: string | null | undefined): string => {
64
+ if (!date) return 'N/A';
65
+ return moment.utc(date).local().format('MMM D, YYYY');
66
+ };
67
+
78
68
  const getStatusVariant = (
79
69
  status: string | null | undefined
80
70
  ): 'default' | 'destructive' | 'outline' | 'secondary' => {
@@ -104,21 +94,34 @@ export const PaymentsList: React.FC = () => {
104
94
  // Client-side filtering only
105
95
  };
106
96
 
97
+ // Helper to truncate ID
98
+ const truncateId = (id: string | number | null | undefined): string => {
99
+ if (!id) return 'N/A';
100
+ const str = id.toString();
101
+ return str.length > 8 ? `${str.slice(0, 8)}...` : str;
102
+ };
107
103
 
108
- // Filter payments client-side for now (until API supports filtering)
109
- const filteredPayments = paymentsList.filter((payment) => {
110
- const matchesSearch = searchTerm
111
- ? payment.id?.toLowerCase().includes(searchTerm.toLowerCase()) ||
112
- payment.status?.toLowerCase().includes(searchTerm.toLowerCase()) ||
113
- payment.currency_code?.toLowerCase().includes(searchTerm.toLowerCase())
114
- : true;
104
+ // Filter and prepare payments with pre-computed fields
105
+ const filteredPayments = paymentsList
106
+ .filter((payment) => {
107
+ const matchesSearch = searchTerm
108
+ ? payment.id?.toLowerCase().includes(searchTerm.toLowerCase()) ||
109
+ payment.status?.toLowerCase().includes(searchTerm.toLowerCase()) ||
110
+ payment.currency_code?.toLowerCase().includes(searchTerm.toLowerCase())
111
+ : true;
115
112
 
116
- const matchesStatus = statusFilter !== 'all'
117
- ? payment.status?.toLowerCase() === statusFilter.toLowerCase()
118
- : true;
113
+ const matchesStatus = statusFilter !== 'all'
114
+ ? payment.status?.toLowerCase() === statusFilter.toLowerCase()
115
+ : true;
119
116
 
120
- return matchesSearch && matchesStatus;
121
- });
117
+ return matchesSearch && matchesStatus;
118
+ })
119
+ .map((payment) => ({
120
+ ...payment,
121
+ formattedDate: formatDate(payment.created_at),
122
+ relativeTime: getRelativeTime(payment.created_at),
123
+ truncatedId: truncateId(payment.id),
124
+ }));
122
125
 
123
126
  return (
124
127
  <Card>
@@ -221,12 +224,10 @@ export const PaymentsList: React.FC = () => {
221
224
  <TableCell>
222
225
  <div>
223
226
  <div className="font-medium">
224
- {payment.created_at
225
- ? new Date(payment.created_at).toLocaleDateString()
226
- : 'N/A'}
227
+ {payment.formattedDate}
227
228
  </div>
228
229
  <div className="text-sm text-muted-foreground">
229
- {getRelativeTime(payment.created_at)}
230
+ {payment.relativeTime}
230
231
  </div>
231
232
  </div>
232
233
  </TableCell>
@@ -243,7 +244,7 @@ export const PaymentsList: React.FC = () => {
243
244
  NowPayments
244
245
  </TableCell>
245
246
  <TableCell className="font-mono text-sm text-muted-foreground">
246
- {payment.id ? `${payment.id.toString().slice(0, 8)}...` : 'N/A'}
247
+ {payment.truncatedId}
247
248
  </TableCell>
248
249
  <TableCell className="text-right">
249
250
  <Button
@@ -6,6 +6,7 @@
6
6
  'use client';
7
7
 
8
8
  import React from 'react';
9
+
9
10
  import { PaymentsList } from './components';
10
11
 
11
12
  export const PaymentsView: React.FC = () => {
@@ -5,29 +5,16 @@
5
5
 
6
6
  'use client';
7
7
 
8
+ import { ArrowDownLeft, ArrowUpRight, Filter, History, RefreshCw, Search } from 'lucide-react';
9
+ import moment from 'moment';
8
10
  import React, { useState } from 'react';
11
+
9
12
  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,
13
+ Badge, Button, Card, CardContent, CardHeader, CardTitle, Input, Select, SelectContent,
14
+ SelectItem, SelectTrigger, SelectValue, Skeleton, Table, TableBody, TableCell, TableHead,
15
+ TableHeader, TableRow
29
16
  } from '@djangocfg/ui-nextjs';
30
- import { History, Search, Filter, RefreshCw, ArrowUpRight, ArrowDownLeft } from 'lucide-react';
17
+
31
18
  import { useOverviewContext } from '../../../../../contexts';
32
19
 
33
20
  export const TransactionsList: React.FC = () => {
@@ -55,13 +42,7 @@ export const TransactionsList: React.FC = () => {
55
42
  const formatDate = (date: string | null | undefined): string => {
56
43
  if (!date) return 'N/A';
57
44
  try {
58
- return new Date(date).toLocaleString('en-US', {
59
- year: 'numeric',
60
- month: 'short',
61
- day: 'numeric',
62
- hour: '2-digit',
63
- minute: '2-digit',
64
- });
45
+ return moment.utc(date).local().format('MMM D, YYYY hh:mm A');
65
46
  } catch {
66
47
  return 'Invalid date';
67
48
  }
@@ -70,9 +51,9 @@ export const TransactionsList: React.FC = () => {
70
51
  const getRelativeTime = (date: string | null | undefined): string => {
71
52
  if (!date) return 'N/A';
72
53
 
73
- const now = new Date();
74
- const target = new Date(date);
75
- const diffInSeconds = Math.floor((now.getTime() - target.getTime()) / 1000);
54
+ const m = moment.utc(date).local();
55
+ const now = moment();
56
+ const diffInSeconds = now.diff(m, 'seconds');
76
57
 
77
58
  if (diffInSeconds < 60) return 'Just now';
78
59
  if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
@@ -114,20 +95,35 @@ export const TransactionsList: React.FC = () => {
114
95
  await refreshTransactions();
115
96
  };
116
97
 
117
- // Filter transactions client-side
118
- const filteredTransactions = transactionsList.filter((transaction: any) => {
119
- const matchesSearch = searchTerm
120
- ? transaction.id?.toString().toLowerCase().includes(searchTerm.toLowerCase()) ||
121
- transaction.description?.toLowerCase().includes(searchTerm.toLowerCase()) ||
122
- transaction.type?.toLowerCase().includes(searchTerm.toLowerCase())
123
- : true;
98
+ // Helper to truncate ID
99
+ const truncateId = (id: string | number | null | undefined): string => {
100
+ if (!id) return 'N/A';
101
+ const str = id.toString();
102
+ return str.length > 8 ? `${str.slice(0, 8)}...` : str;
103
+ };
104
+
105
+ // Filter and prepare transactions
106
+ const filteredTransactions = transactionsList
107
+ .filter((transaction: any) => {
108
+ const matchesSearch = searchTerm
109
+ ? transaction.id?.toString().toLowerCase().includes(searchTerm.toLowerCase()) ||
110
+ transaction.description?.toLowerCase().includes(searchTerm.toLowerCase()) ||
111
+ transaction.type?.toLowerCase().includes(searchTerm.toLowerCase())
112
+ : true;
124
113
 
125
- const matchesType = typeFilter !== 'all'
126
- ? transaction.type?.toLowerCase() === typeFilter.toLowerCase()
127
- : true;
114
+ const matchesType = typeFilter !== 'all'
115
+ ? transaction.type?.toLowerCase() === typeFilter.toLowerCase()
116
+ : true;
128
117
 
129
- return matchesSearch && matchesType;
130
- });
118
+ return matchesSearch && matchesType;
119
+ })
120
+ .map((transaction: any) => ({
121
+ ...transaction,
122
+ isDeposit: transaction.type?.toLowerCase() === 'deposit' || transaction.type?.toLowerCase() === 'credit',
123
+ formattedDate: formatDate(transaction.created_at || transaction.timestamp),
124
+ relativeTime: getRelativeTime(transaction.created_at || transaction.timestamp),
125
+ truncatedRef: truncateId(transaction.reference || transaction.payment_id),
126
+ }));
131
127
 
132
128
  if (isLoadingTransactions) {
133
129
  return (
@@ -221,48 +217,39 @@ export const TransactionsList: React.FC = () => {
221
217
  </TableRow>
222
218
  </TableHeader>
223
219
  <TableBody>
224
- {filteredTransactions.map((transaction: any, index: number) => {
225
- const isDeposit = transaction.type?.toLowerCase() === 'deposit' || transaction.type?.toLowerCase() === 'credit';
226
- return (
227
- <TableRow key={transaction.id || index}>
228
- <TableCell>
229
- <div>
230
- <div className="font-medium">
231
- {formatDate(transaction.created_at || transaction.timestamp)}
232
- </div>
233
- <div className="text-sm text-muted-foreground">
234
- {getRelativeTime(transaction.created_at || transaction.timestamp)}
235
- </div>
236
- </div>
237
- </TableCell>
238
- <TableCell>
239
- <div className="flex items-center gap-2">
240
- {getTypeIcon(transaction.type)}
241
- <Badge variant={getTypeVariant(transaction.type)}>
242
- {transaction.type || 'Unknown'}
243
- </Badge>
244
- </div>
245
- </TableCell>
246
- <TableCell className="font-mono font-semibold">
247
- <span className={isDeposit ? 'text-green-600' : 'text-red-600'}>
248
- {isDeposit ? '+' : '-'}
249
- {formatCurrency(Math.abs(transaction.amount || transaction.amount_usd || 0))}
250
- </span>
251
- </TableCell>
252
- <TableCell className="font-mono">
253
- {formatCurrency(transaction.balance_after || 0)}
254
- </TableCell>
255
- <TableCell className="text-sm">
256
- {transaction.description || transaction.note || 'No description'}
257
- </TableCell>
258
- <TableCell className="font-mono text-sm text-muted-foreground">
259
- {transaction.reference || transaction.payment_id
260
- ? `${(transaction.reference || transaction.payment_id).toString().slice(0, 8)}...`
261
- : 'N/A'}
262
- </TableCell>
263
- </TableRow>
264
- );
265
- })}
220
+ {filteredTransactions.map((transaction: any, index: number) => (
221
+ <TableRow key={transaction.id || index}>
222
+ <TableCell>
223
+ <div>
224
+ <div className="font-medium">{transaction.formattedDate}</div>
225
+ <div className="text-sm text-muted-foreground">{transaction.relativeTime}</div>
226
+ </div>
227
+ </TableCell>
228
+ <TableCell>
229
+ <div className="flex items-center gap-2">
230
+ {getTypeIcon(transaction.type)}
231
+ <Badge variant={getTypeVariant(transaction.type)}>
232
+ {transaction.type || 'Unknown'}
233
+ </Badge>
234
+ </div>
235
+ </TableCell>
236
+ <TableCell className="font-mono font-semibold">
237
+ <span className={transaction.isDeposit ? 'text-green-600' : 'text-red-600'}>
238
+ {transaction.isDeposit ? '+' : '-'}
239
+ {formatCurrency(Math.abs(transaction.amount || transaction.amount_usd || 0))}
240
+ </span>
241
+ </TableCell>
242
+ <TableCell className="font-mono">
243
+ {formatCurrency(transaction.balance_after || 0)}
244
+ </TableCell>
245
+ <TableCell className="text-sm">
246
+ {transaction.description || transaction.note || 'No description'}
247
+ </TableCell>
248
+ <TableCell className="font-mono text-sm text-muted-foreground">
249
+ {transaction.truncatedRef}
250
+ </TableCell>
251
+ </TableRow>
252
+ ))}
266
253
  </TableBody>
267
254
  </Table>
268
255
  </div>
@@ -6,6 +6,7 @@
6
6
  'use client';
7
7
 
8
8
  import React from 'react';
9
+
9
10
  import { TransactionsList } from './components';
10
11
 
11
12
  export const TransactionsView: React.FC = () => {