@djangocfg/ext-payments 1.0.21 → 1.0.23

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.
@@ -13,6 +13,7 @@ import { useForm } from 'react-hook-form';
13
13
  import { z } from 'zod';
14
14
  import { zodResolver } from '@hookform/resolvers/zod';
15
15
 
16
+ import { usePaymentsT } from '../i18n';
16
17
  import {
17
18
  Alert,
18
19
  AlertDescription,
@@ -74,10 +75,30 @@ interface WithdrawSaved {
74
75
  // ─────────────────────────────────────────────────────────────────────────────
75
76
 
76
77
  export function WithdrawSheet({ open, onOpenChange, onSuccess }: WithdrawSheetProps) {
78
+ const pt = usePaymentsT();
77
79
  const { currencies, isLoadingCurrencies, withdraw, balanceAmount } = useWallet();
78
80
  const [isSubmitting, setIsSubmitting] = useState(false);
79
81
  const [error, setError] = useState<string | null>(null);
80
82
 
83
+ // Prepare labels before render
84
+ const labels = useMemo(() => ({
85
+ title: pt('sheets.withdrawTitle'),
86
+ description: pt('sheets.withdrawDescription'),
87
+ amountUsd: pt('form.amountUsd'),
88
+ withdrawAs: pt('form.withdrawAs'),
89
+ walletAddress: pt('form.walletAddress'),
90
+ enterWalletAddress: pt('form.enterWalletAddress'),
91
+ amount: pt('form.amount'),
92
+ serviceFee: pt('estimate.serviceFee'),
93
+ networkFee: pt('estimate.networkFee'),
94
+ youWillReceive: pt('estimate.youWillReceive'),
95
+ calculating: pt('estimate.calculating'),
96
+ insufficientBalance: pt('withdraw.insufficientBalance'),
97
+ approvalWarning: pt('withdraw.approvalWarning'),
98
+ submitting: pt('withdraw.submitting'),
99
+ requestWithdrawal: pt('actions.requestWithdrawal'),
100
+ }), [pt]);
101
+
81
102
  // Remember last used currency and wallet address
82
103
  const [saved, setSaved] = useLocalStorage<WithdrawSaved>(STORAGE_KEY, {
83
104
  currency: '',
@@ -178,9 +199,9 @@ export function WithdrawSheet({ open, onOpenChange, onSuccess }: WithdrawSheetPr
178
199
  <ResponsiveSheet open={open} onOpenChange={handleOpenChange}>
179
200
  <ResponsiveSheetContent className="sm:max-w-md">
180
201
  <ResponsiveSheetHeader>
181
- <ResponsiveSheetTitle>Withdraw</ResponsiveSheetTitle>
202
+ <ResponsiveSheetTitle>{labels.title}</ResponsiveSheetTitle>
182
203
  <ResponsiveSheetDescription>
183
- Withdraw funds to your cryptocurrency wallet
204
+ {labels.description}
184
205
  </ResponsiveSheetDescription>
185
206
  </ResponsiveSheetHeader>
186
207
 
@@ -192,7 +213,7 @@ export function WithdrawSheet({ open, onOpenChange, onSuccess }: WithdrawSheetPr
192
213
  name="amount"
193
214
  render={({ field }) => (
194
215
  <FormItem>
195
- <FormLabel>Amount (USD)</FormLabel>
216
+ <FormLabel>{labels.amountUsd}</FormLabel>
196
217
  <FormControl>
197
218
  <div className="relative">
198
219
  <span className="absolute left-4 top-1/2 -translate-y-1/2 text-muted-foreground text-lg">
@@ -212,7 +233,7 @@ export function WithdrawSheet({ open, onOpenChange, onSuccess }: WithdrawSheetPr
212
233
  <FormMessage />
213
234
  {insufficientBalance && (
214
235
  <p className="text-sm text-destructive mt-1">
215
- Insufficient balance (Available: ${formatUsdAmount(balanceAmount)})
236
+ {labels.insufficientBalance} (Available: ${formatUsdAmount(balanceAmount)})
216
237
  </p>
217
238
  )}
218
239
  </FormItem>
@@ -225,7 +246,7 @@ export function WithdrawSheet({ open, onOpenChange, onSuccess }: WithdrawSheetPr
225
246
  name="currency"
226
247
  render={({ field }) => (
227
248
  <FormItem>
228
- <FormLabel>Withdraw as</FormLabel>
249
+ <FormLabel>{labels.withdrawAs}</FormLabel>
229
250
  <FormControl>
230
251
  <CurrencyCombobox
231
252
  options={currencyOptions}
@@ -245,10 +266,10 @@ export function WithdrawSheet({ open, onOpenChange, onSuccess }: WithdrawSheetPr
245
266
  name="wallet_address"
246
267
  render={({ field }) => (
247
268
  <FormItem>
248
- <FormLabel>Wallet Address</FormLabel>
269
+ <FormLabel>{labels.walletAddress}</FormLabel>
249
270
  <FormControl>
250
271
  <Input
251
- placeholder="Enter your wallet address"
272
+ placeholder={labels.enterWalletAddress}
252
273
  className="font-mono text-sm"
253
274
  {...field}
254
275
  />
@@ -262,33 +283,33 @@ export function WithdrawSheet({ open, onOpenChange, onSuccess }: WithdrawSheetPr
262
283
  {amount >= 10 && selectedCurrency && (
263
284
  <div className="bg-muted rounded-xl p-4 space-y-2">
264
285
  <div className="flex items-center justify-between text-sm">
265
- <span className="text-muted-foreground">Amount</span>
286
+ <span className="text-muted-foreground">{labels.amount}</span>
266
287
  <span>${formatUsdAmount(amount)}</span>
267
288
  </div>
268
289
  {isLoadingEstimate ? (
269
290
  <div className="flex items-center gap-2 text-sm text-muted-foreground py-2">
270
291
  <Loader2 className="h-4 w-4 animate-spin" />
271
- <span>Calculating fees...</span>
292
+ <span>{labels.calculating}</span>
272
293
  </div>
273
294
  ) : estimate ? (
274
295
  <>
275
296
  <div className="flex items-center justify-between text-sm">
276
297
  <span className="text-muted-foreground">
277
- Service fee ({estimate.serviceFeePercent}%)
298
+ {labels.serviceFee} ({estimate.serviceFeePercent}%)
278
299
  </span>
279
300
  <span className="text-destructive">
280
301
  -${formatUsdAmount(estimate.serviceFeeUsd)}
281
302
  </span>
282
303
  </div>
283
304
  <div className="flex items-center justify-between text-sm">
284
- <span className="text-muted-foreground">Network fee</span>
305
+ <span className="text-muted-foreground">{labels.networkFee}</span>
285
306
  <span className="text-destructive">
286
307
  -${formatUsdAmount(estimate.networkFeeUsd)}
287
308
  </span>
288
309
  </div>
289
310
  <div className="border-t pt-2 mt-2">
290
311
  <div className="flex items-center justify-between">
291
- <span className="font-medium">You will receive</span>
312
+ <span className="font-medium">{labels.youWillReceive}</span>
292
313
  <div className="text-right">
293
314
  <div className="font-semibold">
294
315
  ${formatUsdAmount(estimate.amountToReceive)}
@@ -313,7 +334,7 @@ export function WithdrawSheet({ open, onOpenChange, onSuccess }: WithdrawSheetPr
313
334
  <Alert>
314
335
  <AlertCircle className="h-4 w-4" />
315
336
  <AlertDescription>
316
- Withdrawal requests require admin approval. Processing may take 24-48 hours.
337
+ {labels.approvalWarning}
317
338
  </AlertDescription>
318
339
  </Alert>
319
340
 
@@ -341,10 +362,10 @@ export function WithdrawSheet({ open, onOpenChange, onSuccess }: WithdrawSheetPr
341
362
  {isSubmitting ? (
342
363
  <>
343
364
  <RefreshCw className="h-5 w-5 mr-2 animate-spin" />
344
- Submitting...
365
+ {labels.submitting}
345
366
  </>
346
367
  ) : (
347
- 'Request Withdrawal'
368
+ labels.requestWithdrawal
348
369
  )}
349
370
  </Button>
350
371
  </form>
@@ -19,6 +19,7 @@ import {
19
19
  import moment from 'moment';
20
20
  import useSWR from 'swr';
21
21
 
22
+ import { usePaymentsT } from '../i18n';
22
23
  import {
23
24
  Button,
24
25
  CopyButton,
@@ -49,43 +50,37 @@ interface WithdrawalSheetProps {
49
50
  // Status Config
50
51
  // ─────────────────────────────────────────────────────────────────────────────
51
52
 
52
- const statusConfig: Record<string, { icon: any; color: string; bg: string; label: string; animate?: boolean }> = {
53
+ const statusConfig: Record<string, { icon: any; color: string; bg: string; animate?: boolean }> = {
53
54
  pending: {
54
55
  icon: Clock,
55
56
  color: 'text-yellow-500',
56
57
  bg: 'bg-yellow-500/10',
57
- label: 'Pending Approval',
58
58
  },
59
59
  approved: {
60
60
  icon: CheckCircle2,
61
61
  color: 'text-blue-500',
62
62
  bg: 'bg-blue-500/10',
63
- label: 'Approved',
64
63
  },
65
64
  processing: {
66
65
  icon: RefreshCw,
67
66
  color: 'text-blue-500',
68
67
  bg: 'bg-blue-500/10',
69
- label: 'Processing',
70
68
  animate: true,
71
69
  },
72
70
  completed: {
73
71
  icon: CheckCircle2,
74
72
  color: 'text-green-500',
75
73
  bg: 'bg-green-500/10',
76
- label: 'Completed',
77
74
  },
78
75
  rejected: {
79
76
  icon: XCircle,
80
77
  color: 'text-red-500',
81
78
  bg: 'bg-red-500/10',
82
- label: 'Rejected',
83
79
  },
84
80
  cancelled: {
85
81
  icon: Ban,
86
82
  color: 'text-muted-foreground',
87
83
  bg: 'bg-muted',
88
- label: 'Cancelled',
89
84
  },
90
85
  };
91
86
 
@@ -94,8 +89,45 @@ const statusConfig: Record<string, { icon: any; color: string; bg: string; label
94
89
  // ─────────────────────────────────────────────────────────────────────────────
95
90
 
96
91
  export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: WithdrawalSheetProps) {
92
+ const pt = usePaymentsT();
97
93
  const { getWithdrawalDetails, cancelWithdrawal, refreshWallet } = useWallet();
98
94
 
95
+ // Prepare labels before render
96
+ const labels = useMemo(() => ({
97
+ title: pt('sheets.withdrawalTitle'),
98
+ // Status labels
99
+ pending: pt('withdrawalStatus.pending'),
100
+ approved: pt('withdrawalStatus.approved'),
101
+ processing: pt('withdrawalStatus.processing'),
102
+ completed: pt('withdrawalStatus.completed'),
103
+ rejected: pt('withdrawalStatus.rejected'),
104
+ cancelled: pt('withdrawalStatus.cancelled'),
105
+ // Descriptions
106
+ pendingApproval: pt('withdrawalDescriptions.pendingApproval'),
107
+ processingDesc: pt('withdrawalDescriptions.processing'),
108
+ completedDesc: pt('withdrawalDescriptions.completed'),
109
+ rejectedDesc: pt('withdrawalDescriptions.rejected'),
110
+ cancelledDesc: pt('withdrawalDescriptions.cancelled'),
111
+ // Form
112
+ amount: pt('form.amount'),
113
+ totalFees: pt('estimate.serviceFee'),
114
+ youReceive: pt('estimate.youWillReceive'),
115
+ cryptoAmount: pt('form.amount'),
116
+ destinationWallet: pt('form.walletAddress'),
117
+ transactionHash: pt('form.transactionHash'),
118
+ withdrawalId: pt('form.paymentId'),
119
+ reference: pt('form.orderId'),
120
+ created: pt('form.created'),
121
+ network: pt('form.network'),
122
+ // Actions
123
+ viewOnExplorer: pt('actions.openInPaymentProvider'),
124
+ cancel: pt('actions.cancel'),
125
+ refreshStatus: pt('actions.refreshStatus'),
126
+ tryAgain: pt('actions.tryAgain'),
127
+ // Messages
128
+ failedToLoad: pt('messages.failedToLoadPayment'),
129
+ }), [pt]);
130
+
99
131
  // Fetch withdrawal details when sheet is open
100
132
  const { data: withdrawal, isLoading, error, mutate } = useSWR<WithdrawalDetail>(
101
133
  open && withdrawalId ? ['withdrawal-details', withdrawalId] : null,
@@ -115,13 +147,23 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
115
147
  const isProcessing = s === 'processing' || s === 'approved';
116
148
  const canCancel = isPending;
117
149
 
150
+ // Status label from translations
151
+ const statusLabels: Record<string, string> = {
152
+ pending: labels.pending,
153
+ approved: labels.approved,
154
+ processing: labels.processing,
155
+ completed: labels.completed,
156
+ rejected: labels.rejected,
157
+ cancelled: labels.cancelled,
158
+ };
159
+
118
160
  // Description text
119
161
  let description = '';
120
- if (isPending) description = 'Waiting for admin approval';
121
- else if (isProcessing) description = 'Your withdrawal is being processed';
122
- else if (isCompleted) description = 'Withdrawal completed successfully';
123
- else if (isRejected) description = 'Withdrawal was rejected';
124
- else if (isCancelled) description = 'Withdrawal was cancelled';
162
+ if (isPending) description = labels.pendingApproval;
163
+ else if (isProcessing) description = labels.processingDesc;
164
+ else if (isCompleted) description = labels.completedDesc;
165
+ else if (isRejected) description = labels.rejectedDesc;
166
+ else if (isCancelled) description = labels.cancelledDesc;
125
167
 
126
168
  // Formatted values
127
169
  const amountUsd = withdrawal?.amount_usd ? `$${parseFloat(withdrawal.amount_usd).toFixed(2)}` : '';
@@ -137,6 +179,7 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
137
179
  return {
138
180
  status: s,
139
181
  config,
182
+ statusLabel: statusLabels[s] || statusLabels.pending,
140
183
  isPending,
141
184
  isCompleted,
142
185
  isRejected,
@@ -150,9 +193,9 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
150
193
  createdAt,
151
194
  completedAt,
152
195
  };
153
- }, [withdrawal]);
196
+ }, [withdrawal, labels]);
154
197
 
155
- const { config, canCancel, description, amountUsd, finalAmountUsd, totalFeeUsd, createdAt, completedAt } = displayData;
198
+ const { config, statusLabel, canCancel, description, amountUsd, finalAmountUsd, totalFeeUsd, createdAt, completedAt } = displayData;
156
199
  const StatusIcon = config.icon;
157
200
 
158
201
  // Handle cancel
@@ -171,7 +214,7 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
171
214
  <ResponsiveSheet open={open} onOpenChange={onOpenChange}>
172
215
  <ResponsiveSheetContent className="sm:max-w-lg">
173
216
  <ResponsiveSheetHeader>
174
- <ResponsiveSheetTitle>Withdrawal Details</ResponsiveSheetTitle>
217
+ <ResponsiveSheetTitle>{labels.title}</ResponsiveSheetTitle>
175
218
  <ResponsiveSheetDescription>{description}</ResponsiveSheetDescription>
176
219
  </ResponsiveSheetHeader>
177
220
 
@@ -187,8 +230,8 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
187
230
  {error && (
188
231
  <div className="flex flex-col items-center justify-center py-12">
189
232
  <XCircle className="h-12 w-12 text-destructive mb-4" />
190
- <p className="text-sm text-muted-foreground mb-4">Failed to load withdrawal</p>
191
- <Button onClick={() => mutate()}>Try Again</Button>
233
+ <p className="text-sm text-muted-foreground mb-4">{labels.failedToLoad}</p>
234
+ <Button onClick={() => mutate()}>{labels.tryAgain}</Button>
192
235
  </div>
193
236
  )}
194
237
 
@@ -198,7 +241,7 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
198
241
  <div className={cn('flex items-center gap-3 p-4 rounded-xl', config.bg)}>
199
242
  <StatusIcon className={cn('h-6 w-6', config.color, config.animate && 'animate-spin')} />
200
243
  <div className="flex-1">
201
- <div className="font-semibold">{config.label}</div>
244
+ <div className="font-semibold">{statusLabel}</div>
202
245
  {withdrawal.admin_notes && (
203
246
  <div className="text-sm text-muted-foreground">{withdrawal.admin_notes}</div>
204
247
  )}
@@ -208,17 +251,17 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
208
251
  {/* Amount Breakdown */}
209
252
  <div className="bg-muted rounded-xl p-4 space-y-3">
210
253
  <div className="flex items-center justify-between">
211
- <span className="text-muted-foreground">Amount</span>
254
+ <span className="text-muted-foreground">{labels.amount}</span>
212
255
  <span className="font-semibold">{amountUsd}</span>
213
256
  </div>
214
257
  {totalFeeUsd && (
215
258
  <div className="flex items-center justify-between text-sm">
216
- <span className="text-muted-foreground">Total fees</span>
259
+ <span className="text-muted-foreground">{labels.totalFees}</span>
217
260
  <span className="text-destructive">-{totalFeeUsd}</span>
218
261
  </div>
219
262
  )}
220
263
  <div className="flex items-center justify-between pt-2 border-t">
221
- <span className="text-muted-foreground">You receive</span>
264
+ <span className="text-muted-foreground">{labels.youReceive}</span>
222
265
  <div className="flex items-center gap-2">
223
266
  <TokenIcon symbol={withdrawal.currency_code} size={24} />
224
267
  <span className="font-mono font-bold text-lg">
@@ -228,7 +271,7 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
228
271
  </div>
229
272
  {withdrawal.crypto_amount && (
230
273
  <div className="flex items-center justify-between text-sm">
231
- <span className="text-muted-foreground">Crypto amount</span>
274
+ <span className="text-muted-foreground">{labels.cryptoAmount}</span>
232
275
  <span className="font-mono">{withdrawal.crypto_amount} {withdrawal.currency_token}</span>
233
276
  </div>
234
277
  )}
@@ -237,7 +280,7 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
237
280
  {/* Wallet Address */}
238
281
  {withdrawal.wallet_address && (
239
282
  <div className="space-y-2">
240
- <label className="text-sm font-medium">Destination Wallet</label>
283
+ <label className="text-sm font-medium">{labels.destinationWallet}</label>
241
284
  <div className="flex items-center gap-2">
242
285
  <div className="flex-1 p-3 bg-muted rounded-xl font-mono text-sm break-all">
243
286
  {withdrawal.wallet_address}
@@ -250,7 +293,7 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
250
293
  {/* Transaction Hash (if completed) */}
251
294
  {withdrawal.transaction_hash && (
252
295
  <div className="space-y-2">
253
- <label className="text-sm font-medium">Transaction Hash</label>
296
+ <label className="text-sm font-medium">{labels.transactionHash}</label>
254
297
  <div className="flex items-center gap-2">
255
298
  <div className="flex-1 p-3 bg-muted rounded-xl font-mono text-sm break-all">
256
299
  {withdrawal.transaction_hash}
@@ -268,7 +311,7 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
268
311
  onClick={() => window.open(withdrawal.explorer_link!, '_blank')}
269
312
  >
270
313
  <ExternalLink className="h-4 w-4 mr-2" />
271
- View on Explorer
314
+ {labels.viewOnExplorer}
272
315
  </Button>
273
316
  )}
274
317
 
@@ -280,35 +323,35 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
280
323
  onClick={handleCancel}
281
324
  >
282
325
  <Ban className="h-4 w-4 mr-2" />
283
- Cancel Withdrawal
326
+ {labels.cancel}
284
327
  </Button>
285
328
  )}
286
329
 
287
330
  {/* Metadata */}
288
331
  <div className="space-y-2 text-xs text-muted-foreground pt-4 border-t">
289
332
  <div className="flex justify-between">
290
- <span>Withdrawal ID</span>
333
+ <span>{labels.withdrawalId}</span>
291
334
  <span className="font-mono">{withdrawal.id}</span>
292
335
  </div>
293
336
  {withdrawal.internal_withdrawal_id && (
294
337
  <div className="flex justify-between">
295
- <span>Reference #</span>
338
+ <span>{labels.reference}</span>
296
339
  <span className="font-mono">{withdrawal.internal_withdrawal_id}</span>
297
340
  </div>
298
341
  )}
299
342
  <div className="flex justify-between">
300
- <span>Created</span>
343
+ <span>{labels.created}</span>
301
344
  <span>{createdAt}</span>
302
345
  </div>
303
346
  {completedAt && (
304
347
  <div className="flex justify-between">
305
- <span>Completed</span>
348
+ <span>{labels.completed}</span>
306
349
  <span>{completedAt}</span>
307
350
  </div>
308
351
  )}
309
352
  {withdrawal.currency_network && (
310
353
  <div className="flex justify-between">
311
- <span>Network</span>
354
+ <span>{labels.network}</span>
312
355
  <span>{withdrawal.currency_network}</span>
313
356
  </div>
314
357
  )}
@@ -321,7 +364,7 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
321
364
  onClick={() => mutate()}
322
365
  >
323
366
  <RefreshCw className="h-4 w-4 mr-2" />
324
- Refresh Status
367
+ {labels.refreshStatus}
325
368
  </Button>
326
369
  </div>
327
370
  )}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Payments Extension I18n
3
+ *
4
+ * Self-contained translations - no app configuration needed.
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * import { usePaymentsT } from '@djangocfg/ext-payments/i18n';
9
+ *
10
+ * function MyComponent() {
11
+ * const t = usePaymentsT();
12
+ * return <span>{t('balance.available')}</span>;
13
+ * }
14
+ * ```
15
+ */
16
+
17
+ // Self-contained hook (recommended)
18
+ export { usePaymentsT } from './usePaymentsT';
19
+
20
+ // Types
21
+ export type { PaymentsTranslations, PaymentsLocalKeys } from './types';
22
+
23
+ // Locales (for direct access if needed)
24
+ export { en } from './locales/en';
25
+ export { ru } from './locales/ru';
26
+ export { ko } from './locales/ko';
@@ -0,0 +1,136 @@
1
+ import type { PaymentsTranslations } from '../types';
2
+
3
+ export const en: PaymentsTranslations = {
4
+ balance: {
5
+ available: 'Available Balance',
6
+ totalDeposited: 'Total Deposited',
7
+ totalWithdrawn: 'Total Withdrawn',
8
+ },
9
+
10
+ actions: {
11
+ addFunds: 'Add Funds',
12
+ withdraw: 'Withdraw',
13
+ continue: 'Continue',
14
+ requestWithdrawal: 'Request Withdrawal',
15
+ cancel: 'Cancel',
16
+ close: 'Close',
17
+ copyAddress: 'Copy Address',
18
+ copied: 'Copied!',
19
+ viewAll: 'View All',
20
+ tryAgain: 'Try Again',
21
+ refreshStatus: 'Refresh Status',
22
+ createNewPayment: 'Create New Payment',
23
+ openInPaymentProvider: 'Open in Payment Provider',
24
+ },
25
+
26
+ paymentStatus: {
27
+ waiting: 'Waiting for payment',
28
+ confirming: 'Confirming',
29
+ completed: 'Completed',
30
+ failed: 'Failed',
31
+ expired: 'Expired',
32
+ paymentExpired: 'Payment Expired',
33
+ },
34
+
35
+ withdrawalStatus: {
36
+ pending: 'Pending Approval',
37
+ approved: 'Approved',
38
+ processing: 'Processing',
39
+ completed: 'Completed',
40
+ rejected: 'Rejected',
41
+ cancelled: 'Cancelled',
42
+ },
43
+
44
+ paymentDescriptions: {
45
+ sendCrypto: 'Send cryptocurrency to complete payment',
46
+ expired: 'This payment has expired',
47
+ completed: 'Payment completed successfully',
48
+ failed: 'Payment failed',
49
+ confirming: 'Confirming your payment',
50
+ createNew: 'Please create a new payment to continue',
51
+ },
52
+
53
+ withdrawalDescriptions: {
54
+ pendingApproval: 'Waiting for admin approval',
55
+ processing: 'Your withdrawal is being processed',
56
+ completed: 'Withdrawal completed successfully',
57
+ rejected: 'Withdrawal was rejected',
58
+ cancelled: 'Withdrawal was cancelled',
59
+ },
60
+
61
+ form: {
62
+ amount: 'Amount',
63
+ amountUsd: 'Amount (USD)',
64
+ currency: 'Currency',
65
+ walletAddress: 'Wallet Address',
66
+ selectCurrency: 'Select currency...',
67
+ enterWalletAddress: 'Enter your wallet address',
68
+ search: 'Search...',
69
+ payWith: 'Pay with',
70
+ withdrawAs: 'Withdraw as',
71
+ amountToSend: 'Amount to send',
72
+ equivalent: 'Equivalent',
73
+ network: 'Network',
74
+ paymentAddress: 'Payment Address',
75
+ transactionHash: 'Transaction Hash',
76
+ paymentId: 'Payment ID',
77
+ orderId: 'Order #',
78
+ created: 'Created',
79
+ },
80
+
81
+ validation: {
82
+ minimumDeposit: 'Minimum $1',
83
+ minimumWithdrawal: 'Minimum $10',
84
+ selectCurrency: 'Select a currency',
85
+ invalidWalletAddress: 'Invalid wallet address',
86
+ },
87
+
88
+ messages: {
89
+ paymentCreated: 'Payment created successfully',
90
+ paymentFailed: 'Failed to create payment',
91
+ withdrawalCreated: 'Withdrawal request created',
92
+ withdrawalFailed: 'Failed to create withdrawal request',
93
+ withdrawalCancelled: 'Withdrawal cancelled',
94
+ addressCopied: 'Address copied to clipboard',
95
+ failedToLoadPayment: 'Failed to load payment',
96
+ failedToCreateWithdrawal: 'Failed to create withdrawal request',
97
+ },
98
+
99
+ sheets: {
100
+ addFundsTitle: 'Add Funds',
101
+ addFundsDescription: 'Add funds to your wallet using cryptocurrency',
102
+ withdrawTitle: 'Withdraw',
103
+ withdrawDescription: 'Withdraw funds to your cryptocurrency wallet',
104
+ paymentTitle: 'Payment Details',
105
+ withdrawalTitle: 'Withdrawal Details',
106
+ },
107
+
108
+ activity: {
109
+ title: 'Recent Activity',
110
+ noActivity: 'No Activity Yet',
111
+ deposit: 'Deposit',
112
+ withdrawal: 'Withdrawal',
113
+ payment: 'Payment',
114
+ transactionsWillAppear: 'Your transactions will appear here',
115
+ },
116
+
117
+ estimate: {
118
+ gettingRate: 'Getting rate...',
119
+ calculating: 'Calculating fees...',
120
+ enterAmountToSee: 'Enter amount to see conversion',
121
+ youWillSend: 'You will send',
122
+ youWillReceive: 'You will receive',
123
+ serviceFee: 'Service fee',
124
+ networkFee: 'Network fee',
125
+ rate: 'Rate',
126
+ minimumAmount: 'Minimum amount',
127
+ },
128
+
129
+ withdraw: {
130
+ insufficientBalance: 'Insufficient balance',
131
+ approvalWarning: 'Withdrawal requests require admin approval. Processing may take 24-48 hours.',
132
+ submitting: 'Submitting...',
133
+ creating: 'Creating...',
134
+ expiresIn: 'Expires in',
135
+ },
136
+ };